huge refactor
This commit is contained in:
parent
03e5a47910
commit
1d4c8455ee
30 changed files with 972 additions and 697 deletions
|
|
@ -1,31 +1,8 @@
|
|||
{ lib, ... }:
|
||||
{
|
||||
inputs,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
azPkgs = inputs.nixpkgs-azure-cli.legacyPackages.${pkgs.stdenv.hostPlatform.system};
|
||||
in
|
||||
{
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
nixfmt-rfc-style
|
||||
lazydocker
|
||||
gh
|
||||
awscli
|
||||
minio-client
|
||||
opentofu
|
||||
python3
|
||||
(azPkgs.azure-cli.withExtensions (
|
||||
with azPkgs.azure-cli.extensions;
|
||||
[
|
||||
# aks-preview
|
||||
# ssh
|
||||
fzf
|
||||
]
|
||||
))
|
||||
yq
|
||||
jq
|
||||
git
|
||||
imports = [
|
||||
./programs/dev
|
||||
];
|
||||
|
||||
features.dev.enable = lib.mkDefault true;
|
||||
}
|
||||
|
|
|
|||
108
moduler/features/README.md
Normal file
108
moduler/features/README.md
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
# Feature Profiles
|
||||
|
||||
This directory provides a profile + overrides model for host configuration.
|
||||
|
||||
## Imports
|
||||
|
||||
Use this in host `imports`:
|
||||
|
||||
```nix
|
||||
(modulesDirectory + /features/standard)
|
||||
```
|
||||
|
||||
`features/standard` imports:
|
||||
|
||||
- `features` profile module
|
||||
- `services/users`
|
||||
- `services/network`
|
||||
- `services/system`
|
||||
- `services/sound`
|
||||
- `programs/base`
|
||||
- `programs/git`
|
||||
- `programs/dev`
|
||||
|
||||
## Profile Selection
|
||||
|
||||
Set one profile per host:
|
||||
|
||||
```nix
|
||||
features.profile = "desktop";
|
||||
```
|
||||
|
||||
Supported values:
|
||||
|
||||
- `custom`
|
||||
- `desktop`
|
||||
- `laptop`
|
||||
- `server`
|
||||
- `camera`
|
||||
|
||||
Profiles set `mkDefault` values, so you can override any option per host.
|
||||
|
||||
## Common Overrides
|
||||
|
||||
### Base packages
|
||||
|
||||
```nix
|
||||
features.base = {
|
||||
enable = true;
|
||||
preset = "minimal";
|
||||
packages.captureEnable = true;
|
||||
};
|
||||
```
|
||||
|
||||
### Dev tools
|
||||
|
||||
```nix
|
||||
features.dev = {
|
||||
enable = true;
|
||||
preset = "minimal";
|
||||
cloud.aws.enable = false;
|
||||
cloud.azure.enable = false;
|
||||
};
|
||||
```
|
||||
|
||||
### Network
|
||||
|
||||
```nix
|
||||
features.network = {
|
||||
enable = true;
|
||||
netbird.enable = false;
|
||||
tooling.enable = false;
|
||||
};
|
||||
```
|
||||
|
||||
### Sound/Bluetooth
|
||||
|
||||
```nix
|
||||
features.sound = {
|
||||
enable = true;
|
||||
bluetooth.enable = false;
|
||||
};
|
||||
```
|
||||
|
||||
### Git defaults
|
||||
|
||||
```nix
|
||||
features.git = {
|
||||
enable = true;
|
||||
userName = "myuser";
|
||||
userEmail = "me@example.com";
|
||||
};
|
||||
```
|
||||
|
||||
### Users
|
||||
|
||||
```nix
|
||||
features.users = {
|
||||
enable = true;
|
||||
name = "fw";
|
||||
fullName = "Fredrik Wastring";
|
||||
extraGroups = [ "wheel" "networkmanager" ];
|
||||
};
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- If you only import `features/default.nix`, profile defaults are applied only for options that exist in imported modules.
|
||||
- `features/standard` is the easiest option for hosts that should expose all common feature knobs.
|
||||
81
moduler/features/default.nix
Normal file
81
moduler/features/default.nix
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
options,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
profile = config.features.profile;
|
||||
has = path: lib.hasAttrByPath path options;
|
||||
setIf = path: value: lib.optionalAttrs (has path) (lib.setAttrByPath path value);
|
||||
in
|
||||
{
|
||||
options.features.profile = mkOption {
|
||||
type = types.enum [
|
||||
"custom"
|
||||
"desktop"
|
||||
"laptop"
|
||||
"server"
|
||||
"camera"
|
||||
];
|
||||
default = "custom";
|
||||
description = "Host feature profile. Use custom for fully explicit per-feature settings.";
|
||||
};
|
||||
|
||||
config = mkMerge [
|
||||
(mkIf (profile == "desktop") (mkMerge [
|
||||
(setIf [ "features" "base" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "base" "preset" ] (mkDefault "full"))
|
||||
(setIf [ "features" "git" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "dev" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "dev" "preset" ] (mkDefault "full"))
|
||||
(setIf [ "features" "users" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "network" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "network" "tooling" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "system" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "system" "preset" ] (mkDefault "desktop"))
|
||||
(setIf [ "features" "sound" "enable" ] (mkDefault true))
|
||||
]))
|
||||
|
||||
(mkIf (profile == "laptop") (mkMerge [
|
||||
(setIf [ "features" "base" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "base" "preset" ] (mkDefault "standard"))
|
||||
(setIf [ "features" "git" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "dev" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "dev" "preset" ] (mkDefault "standard"))
|
||||
(setIf [ "features" "users" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "network" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "network" "tooling" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "system" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "system" "preset" ] (mkDefault "desktop"))
|
||||
(setIf [ "features" "sound" "enable" ] (mkDefault true))
|
||||
]))
|
||||
|
||||
(mkIf (profile == "server") (mkMerge [
|
||||
(setIf [ "features" "users" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "network" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "network" "netbird" "enable" ] (mkDefault false))
|
||||
(setIf [ "features" "network" "tooling" "enable" ] (mkDefault false))
|
||||
(setIf [ "features" "system" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "system" "preset" ] (mkDefault "minimal"))
|
||||
(setIf [ "features" "base" "enable" ] (mkDefault false))
|
||||
(setIf [ "features" "git" "enable" ] (mkDefault false))
|
||||
(setIf [ "features" "dev" "enable" ] (mkDefault false))
|
||||
(setIf [ "features" "sound" "enable" ] (mkDefault false))
|
||||
]))
|
||||
|
||||
(mkIf (profile == "camera") (mkMerge [
|
||||
(setIf [ "features" "users" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "network" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "network" "netbird" "enable" ] (mkDefault false))
|
||||
(setIf [ "features" "network" "tooling" "enable" ] (mkDefault false))
|
||||
(setIf [ "features" "system" "enable" ] (mkDefault true))
|
||||
(setIf [ "features" "system" "preset" ] (mkDefault "minimal"))
|
||||
(setIf [ "features" "base" "enable" ] (mkDefault false))
|
||||
(setIf [ "features" "git" "enable" ] (mkDefault false))
|
||||
(setIf [ "features" "dev" "enable" ] (mkDefault false))
|
||||
(setIf [ "features" "sound" "enable" ] (mkDefault false))
|
||||
]))
|
||||
];
|
||||
}
|
||||
13
moduler/features/standard/default.nix
Normal file
13
moduler/features/standard/default.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{ ... }:
|
||||
{
|
||||
imports = [
|
||||
../default.nix
|
||||
../../services/users
|
||||
../../services/network
|
||||
../../services/system
|
||||
../../services/sound
|
||||
../../programs/base
|
||||
../../programs/git
|
||||
../../programs/dev
|
||||
];
|
||||
}
|
||||
|
|
@ -1,16 +1,8 @@
|
|||
{ pkgs, lib, ... }:
|
||||
{ lib, ... }:
|
||||
{
|
||||
programs.git = {
|
||||
enable = true;
|
||||
config = {
|
||||
user = {
|
||||
name = "fwastring";
|
||||
email = "fredrik@wastring.com";
|
||||
};
|
||||
pull = {
|
||||
rebase = true;
|
||||
};
|
||||
url."git@github.com:".insteadOf = "https://github.com/";
|
||||
};
|
||||
};
|
||||
imports = [
|
||||
./programs/git
|
||||
];
|
||||
|
||||
features.git.enable = lib.mkDefault true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,34 +1,8 @@
|
|||
# This is your system's configuration file.
|
||||
# Use this to configure your system environment (it replaces /etc/nixos/configuration.nix)
|
||||
{ lib, ... }:
|
||||
{
|
||||
inputs,
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
|
||||
services.netbird = {
|
||||
enable = true;
|
||||
ui.enable = true;
|
||||
};
|
||||
|
||||
systemd.services.tailscaled = {
|
||||
after = [ "netbird.service" "network-online.target" ];
|
||||
wants = [ "netbird.service" "network-online.target" ];
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
# networkmanager
|
||||
dnsutils
|
||||
nmap
|
||||
ipcalc
|
||||
# iperf3
|
||||
# networkmanagerapplet
|
||||
|
||||
# (octodns.withProviders (ps: [
|
||||
# octodns-providers.gandi
|
||||
# ]))
|
||||
imports = [
|
||||
./services/network
|
||||
];
|
||||
|
||||
features.network.enable = lib.mkDefault true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,144 +1,8 @@
|
|||
{ lib, ... }:
|
||||
{
|
||||
inputs,
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
services.udev = {
|
||||
extraRules = ''
|
||||
KERNEL=="ttyACM0", MODE:="666"
|
||||
ACTION=="add", KERNEL=="sd[a-e][0-9]", ENV{ID_FS_UUID}=="3039-3932", RUN+="${pkgs.systemd}/bin/systemd-mount --no-block -A -G -o gid=users,fmask=113,dmask=002 /dev/%k /mnt/sdcard"
|
||||
ACTION=="add", KERNEL=="sd[a-e]", ENV{ID_FS_UUID}=="66BA-4EBA", RUN+="${pkgs.systemd}/bin/systemd-mount --no-block -A -G -o gid=users,fmask=113,dmask=002 /dev/%k /mnt/kobo"
|
||||
KERNEL=="uinput", GROUP="input", MODE="0660", OPTIONS+="static_node=uinput"
|
||||
'';
|
||||
packages = with pkgs; [
|
||||
vial
|
||||
via
|
||||
];
|
||||
};
|
||||
home-manager.users.fw = {
|
||||
xdg.mimeApps = {
|
||||
enable = true;
|
||||
defaultApplications = {
|
||||
"text/html" = "librewolf.desktop";
|
||||
"x-scheme-handler/http" = "librewolf.desktop";
|
||||
"x-scheme-handler/https" = "librewolf.desktop";
|
||||
"x-scheme-handler/about" = "librewolf.desktop";
|
||||
"x-scheme-handler/unknown" = "librewolf.desktop";
|
||||
"text/plain" = "nvim.desktop";
|
||||
"text/markdown" = "nvim.desktop";
|
||||
"text/x-markdown" = "nvim.desktop";
|
||||
"application/json" = "nvim.desktop";
|
||||
"application/x-ndjson" = "nvim.desktop";
|
||||
"application/x-yaml" = "nvim.desktop";
|
||||
"text/yaml" = "nvim.desktop";
|
||||
"text/x-shellscript" = "nvim.desktop";
|
||||
"text/x-python" = "nvim.desktop";
|
||||
"text/x-csrc" = "nvim.desktop";
|
||||
"text/x-c++src" = "nvim.desktop";
|
||||
"application/x-sql" = "nvim.desktop";
|
||||
"text/xml" = "nvim.desktop";
|
||||
"application/xml" = "nvim.desktop";
|
||||
"application/pdf" = "org.gnome.Evince.desktop";
|
||||
"image/jpeg" = "feh.desktop";
|
||||
"image/png" = "feh.desktop";
|
||||
"image/gif" = "feh.desktop";
|
||||
"image/webp" = "feh.desktop";
|
||||
"image/tiff" = "feh.desktop";
|
||||
"image/bmp" = "feh.desktop";
|
||||
"image/svg+xml" = "feh.desktop";
|
||||
};
|
||||
};
|
||||
};
|
||||
environment.sessionVariables.DEFAULT_BROWSER = "${pkgs.librewolf}/bin/librewolf";
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
# GUI
|
||||
feishin
|
||||
vscode
|
||||
signal-desktop
|
||||
thunderbird
|
||||
discord
|
||||
slack
|
||||
evince
|
||||
spotify
|
||||
firefox
|
||||
ipcalc
|
||||
vial
|
||||
via
|
||||
remmina
|
||||
brightnessctl
|
||||
speedcrunch
|
||||
opencode
|
||||
quickemu
|
||||
virt-viewer
|
||||
go-passbolt-cli
|
||||
wf-recorder
|
||||
slurp
|
||||
bitwarden-desktop
|
||||
bitwarden-cli
|
||||
lagrange
|
||||
jujutsu
|
||||
rclone
|
||||
|
||||
|
||||
dbeaver-bin
|
||||
(
|
||||
let
|
||||
base = pkgs.appimageTools.defaultFhsEnvArgs;
|
||||
in
|
||||
pkgs.buildFHSEnv (
|
||||
base
|
||||
// {
|
||||
name = "fhs";
|
||||
targetPkgs =
|
||||
pkgs:
|
||||
# pkgs.buildFHSUserEnv provides only a minimal FHS environment,
|
||||
# lacking many basic packages needed by most software.
|
||||
# Therefore, we need to add them manually.
|
||||
#
|
||||
# pkgs.appimageTools provides basic packages required by most software.
|
||||
(base.targetPkgs pkgs)
|
||||
++ (with pkgs; [
|
||||
pkg-config
|
||||
ncurses
|
||||
icu
|
||||
# Feel free to add more packages here if needed.
|
||||
]);
|
||||
profile = "export FHS=1";
|
||||
runScript = "bash";
|
||||
extraOutputsToInstall = [ "dev" ];
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
# TUI
|
||||
codex
|
||||
|
||||
# Browsers
|
||||
librewolf
|
||||
|
||||
# Displaying
|
||||
zathura
|
||||
feh
|
||||
mpv
|
||||
|
||||
# System
|
||||
pavucontrol
|
||||
pulseaudio
|
||||
devour
|
||||
caligula
|
||||
ptouch-print
|
||||
|
||||
# Transforms
|
||||
yt-dlp
|
||||
imagemagick
|
||||
pandoc
|
||||
pinta
|
||||
pastel
|
||||
ffmpeg
|
||||
# darktable
|
||||
imports = [
|
||||
./programs/base
|
||||
];
|
||||
|
||||
features.base.enable = lib.mkDefault true;
|
||||
}
|
||||
|
|
|
|||
245
moduler/programs/base/default.nix
Normal file
245
moduler/programs/base/default.nix
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
fhsEnv =
|
||||
let
|
||||
base = pkgs.appimageTools.defaultFhsEnvArgs;
|
||||
in
|
||||
pkgs.buildFHSEnv (
|
||||
base
|
||||
// {
|
||||
name = "fhs";
|
||||
targetPkgs =
|
||||
pkgs:
|
||||
(base.targetPkgs pkgs)
|
||||
++ (with pkgs; [
|
||||
pkg-config
|
||||
ncurses
|
||||
icu
|
||||
]);
|
||||
profile = "export FHS=1";
|
||||
runScript = "bash";
|
||||
extraOutputsToInstall = [ "dev" ];
|
||||
}
|
||||
);
|
||||
in
|
||||
{
|
||||
options.features.base = {
|
||||
enable = mkEnableOption "enable shared base programs";
|
||||
preset = mkOption {
|
||||
type = types.enum [
|
||||
"minimal"
|
||||
"standard"
|
||||
"full"
|
||||
];
|
||||
default = "standard";
|
||||
description = "Preset for desktop package groups.";
|
||||
};
|
||||
udevEnable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable custom udev rules and device packages.";
|
||||
};
|
||||
mimeEnable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable Home Manager MIME defaults.";
|
||||
};
|
||||
packages = {
|
||||
communicationEnable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Install communication desktop apps.";
|
||||
};
|
||||
mediaEnable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Install media apps.";
|
||||
};
|
||||
browsersEnable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Install browsers.";
|
||||
};
|
||||
captureEnable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Install screen capture tools.";
|
||||
};
|
||||
creativeEnable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Install conversion/creative tools.";
|
||||
};
|
||||
devDesktopEnable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Install desktop dev helper tools and VMs.";
|
||||
};
|
||||
dbeaverEnable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Install dbeaver and FHS shell.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkMerge [
|
||||
(mkIf (config.features.base.preset == "minimal") {
|
||||
features.base.packages.communicationEnable = mkDefault false;
|
||||
features.base.packages.mediaEnable = mkDefault false;
|
||||
features.base.packages.browsersEnable = mkDefault true;
|
||||
features.base.packages.captureEnable = mkDefault false;
|
||||
features.base.packages.creativeEnable = mkDefault false;
|
||||
features.base.packages.devDesktopEnable = mkDefault false;
|
||||
features.base.packages.dbeaverEnable = mkDefault false;
|
||||
})
|
||||
|
||||
(mkIf (config.features.base.preset == "full") {
|
||||
features.base.packages.communicationEnable = mkDefault true;
|
||||
features.base.packages.mediaEnable = mkDefault true;
|
||||
features.base.packages.browsersEnable = mkDefault true;
|
||||
features.base.packages.captureEnable = mkDefault true;
|
||||
features.base.packages.creativeEnable = mkDefault true;
|
||||
features.base.packages.devDesktopEnable = mkDefault true;
|
||||
features.base.packages.dbeaverEnable = mkDefault true;
|
||||
})
|
||||
|
||||
(mkIf config.features.base.enable {
|
||||
services.udev = mkIf config.features.base.udevEnable {
|
||||
extraRules = ''
|
||||
KERNEL=="ttyACM0", MODE:="666"
|
||||
ACTION=="add", KERNEL=="sd[a-e][0-9]", ENV{ID_FS_UUID}=="3039-3932", RUN+="${pkgs.systemd}/bin/systemd-mount --no-block -A -G -o gid=users,fmask=113,dmask=002 /dev/%k /mnt/sdcard"
|
||||
ACTION=="add", KERNEL=="sd[a-e]", ENV{ID_FS_UUID}=="66BA-4EBA", RUN+="${pkgs.systemd}/bin/systemd-mount --no-block -A -G -o gid=users,fmask=113,dmask=002 /dev/%k /mnt/kobo"
|
||||
KERNEL=="uinput", GROUP="input", MODE="0660", OPTIONS+="static_node=uinput"
|
||||
'';
|
||||
packages = with pkgs; [
|
||||
vial
|
||||
via
|
||||
];
|
||||
};
|
||||
|
||||
home-manager.users.fw = mkIf config.features.base.mimeEnable {
|
||||
xdg.mimeApps = {
|
||||
enable = true;
|
||||
defaultApplications = {
|
||||
"text/html" = "librewolf.desktop";
|
||||
"x-scheme-handler/http" = "librewolf.desktop";
|
||||
"x-scheme-handler/https" = "librewolf.desktop";
|
||||
"x-scheme-handler/about" = "librewolf.desktop";
|
||||
"x-scheme-handler/unknown" = "librewolf.desktop";
|
||||
"text/plain" = "nvim.desktop";
|
||||
"text/markdown" = "nvim.desktop";
|
||||
"text/x-markdown" = "nvim.desktop";
|
||||
"application/json" = "nvim.desktop";
|
||||
"application/x-ndjson" = "nvim.desktop";
|
||||
"application/x-yaml" = "nvim.desktop";
|
||||
"text/yaml" = "nvim.desktop";
|
||||
"text/x-shellscript" = "nvim.desktop";
|
||||
"text/x-python" = "nvim.desktop";
|
||||
"text/x-csrc" = "nvim.desktop";
|
||||
"text/x-c++src" = "nvim.desktop";
|
||||
"application/x-sql" = "nvim.desktop";
|
||||
"text/xml" = "nvim.desktop";
|
||||
"application/xml" = "nvim.desktop";
|
||||
"application/pdf" = "org.gnome.Evince.desktop";
|
||||
"image/jpeg" = "feh.desktop";
|
||||
"image/png" = "feh.desktop";
|
||||
"image/gif" = "feh.desktop";
|
||||
"image/webp" = "feh.desktop";
|
||||
"image/tiff" = "feh.desktop";
|
||||
"image/bmp" = "feh.desktop";
|
||||
"image/svg+xml" = "feh.desktop";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
environment.sessionVariables.DEFAULT_BROWSER = "${pkgs.librewolf}/bin/librewolf";
|
||||
|
||||
environment.systemPackages =
|
||||
(with pkgs; [
|
||||
codex
|
||||
ipcalc
|
||||
remmina
|
||||
brightnessctl
|
||||
speedcrunch
|
||||
lagrange
|
||||
jujutsu
|
||||
rclone
|
||||
zathura
|
||||
feh
|
||||
pavucontrol
|
||||
pulseaudio
|
||||
devour
|
||||
caligula
|
||||
ptouch-print
|
||||
])
|
||||
++ optionals config.features.base.packages.communicationEnable (
|
||||
with pkgs;
|
||||
[
|
||||
signal-desktop
|
||||
thunderbird
|
||||
discord
|
||||
slack
|
||||
]
|
||||
)
|
||||
++ optionals config.features.base.packages.mediaEnable (
|
||||
with pkgs;
|
||||
[
|
||||
feishin
|
||||
spotify
|
||||
mpv
|
||||
]
|
||||
)
|
||||
++ optionals config.features.base.packages.browsersEnable (
|
||||
with pkgs;
|
||||
[
|
||||
librewolf
|
||||
firefox
|
||||
]
|
||||
)
|
||||
++ optionals config.features.base.packages.captureEnable (
|
||||
with pkgs;
|
||||
[
|
||||
wf-recorder
|
||||
slurp
|
||||
]
|
||||
)
|
||||
++ optionals config.features.base.packages.creativeEnable (
|
||||
with pkgs;
|
||||
[
|
||||
yt-dlp
|
||||
imagemagick
|
||||
pandoc
|
||||
pinta
|
||||
pastel
|
||||
ffmpeg
|
||||
]
|
||||
)
|
||||
++ optionals config.features.base.packages.devDesktopEnable (
|
||||
with pkgs;
|
||||
[
|
||||
vscode
|
||||
opencode
|
||||
quickemu
|
||||
virt-viewer
|
||||
go-passbolt-cli
|
||||
bitwarden-desktop
|
||||
bitwarden-cli
|
||||
]
|
||||
)
|
||||
++ optionals config.features.base.packages.dbeaverEnable (
|
||||
with pkgs;
|
||||
[
|
||||
dbeaver-bin
|
||||
fhsEnv
|
||||
]
|
||||
);
|
||||
})
|
||||
];
|
||||
}
|
||||
109
moduler/programs/dev/default.nix
Normal file
109
moduler/programs/dev/default.nix
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
{
|
||||
inputs,
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
azPkgs = inputs.nixpkgs-azure-cli.legacyPackages.${pkgs.stdenv.hostPlatform.system};
|
||||
in
|
||||
with lib;
|
||||
{
|
||||
options.features.dev = {
|
||||
enable = mkEnableOption "enable development toolchain";
|
||||
preset = mkOption {
|
||||
type = types.enum [
|
||||
"minimal"
|
||||
"standard"
|
||||
"full"
|
||||
];
|
||||
default = "standard";
|
||||
description = "Preset for development package groups.";
|
||||
};
|
||||
cloud = {
|
||||
aws.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable AWS CLI tools.";
|
||||
};
|
||||
azure.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable Azure CLI tools.";
|
||||
};
|
||||
minio.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable MinIO client.";
|
||||
};
|
||||
};
|
||||
tools = {
|
||||
docker.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable lazydocker.";
|
||||
};
|
||||
python.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable Python runtime package.";
|
||||
};
|
||||
opentofu.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable OpenTofu package.";
|
||||
};
|
||||
git.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable git package in dev toolchain.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkMerge [
|
||||
(mkIf config.features.dev.enable {
|
||||
environment.systemPackages =
|
||||
(with pkgs; [
|
||||
nixfmt-rfc-style
|
||||
gh
|
||||
yq
|
||||
jq
|
||||
])
|
||||
++ optionals config.features.dev.tools.docker.enable (with pkgs; [ lazydocker ])
|
||||
++ optionals config.features.dev.cloud.aws.enable (with pkgs; [ awscli ])
|
||||
++ optionals config.features.dev.cloud.minio.enable (with pkgs; [ minio-client ])
|
||||
++ optionals config.features.dev.tools.opentofu.enable (with pkgs; [ opentofu ])
|
||||
++ optionals config.features.dev.tools.python.enable (with pkgs; [ python3 ])
|
||||
++ optionals config.features.dev.cloud.azure.enable [
|
||||
(azPkgs.azure-cli.withExtensions (
|
||||
with azPkgs.azure-cli.extensions;
|
||||
[
|
||||
fzf
|
||||
]
|
||||
))
|
||||
]
|
||||
++ optionals config.features.dev.tools.git.enable (with pkgs; [ git ]);
|
||||
})
|
||||
|
||||
(mkIf (config.features.dev.preset == "minimal") {
|
||||
features.dev.cloud.aws.enable = mkDefault false;
|
||||
features.dev.cloud.azure.enable = mkDefault false;
|
||||
features.dev.cloud.minio.enable = mkDefault false;
|
||||
features.dev.tools.docker.enable = mkDefault false;
|
||||
features.dev.tools.opentofu.enable = mkDefault false;
|
||||
features.dev.tools.python.enable = mkDefault false;
|
||||
})
|
||||
|
||||
(mkIf (config.features.dev.preset == "full") {
|
||||
features.dev.cloud.aws.enable = mkDefault true;
|
||||
features.dev.cloud.azure.enable = mkDefault true;
|
||||
features.dev.cloud.minio.enable = mkDefault true;
|
||||
features.dev.tools.docker.enable = mkDefault true;
|
||||
features.dev.tools.opentofu.enable = mkDefault true;
|
||||
features.dev.tools.python.enable = mkDefault true;
|
||||
features.dev.tools.git.enable = mkDefault true;
|
||||
})
|
||||
];
|
||||
}
|
||||
45
moduler/programs/git/default.nix
Normal file
45
moduler/programs/git/default.nix
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
{ lib, config, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.features.git = {
|
||||
enable = mkEnableOption "enable git defaults";
|
||||
userName = mkOption {
|
||||
type = types.str;
|
||||
default = "fwastring";
|
||||
description = "Default git user.name.";
|
||||
};
|
||||
userEmail = mkOption {
|
||||
type = types.str;
|
||||
default = "fredrik@wastring.com";
|
||||
description = "Default git user.email.";
|
||||
};
|
||||
pullRebase = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable pull.rebase by default.";
|
||||
};
|
||||
githubSshInsteadOfHttps = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Use SSH for GitHub remotes when cloning with HTTPS URLs.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf config.features.git.enable {
|
||||
programs.git = {
|
||||
enable = true;
|
||||
config = {
|
||||
user = {
|
||||
name = config.features.git.userName;
|
||||
email = config.features.git.userEmail;
|
||||
};
|
||||
pull = {
|
||||
rebase = config.features.git.pullRebase;
|
||||
};
|
||||
}
|
||||
// optionalAttrs config.features.git.githubSshInsteadOfHttps {
|
||||
url."git@github.com:".insteadOf = "https://github.com/";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
69
moduler/services/network/default.nix
Normal file
69
moduler/services/network/default.nix
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
{
|
||||
options.features.network = {
|
||||
enable = mkEnableOption "enable network tooling and VPN services";
|
||||
netbird = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable NetBird service.";
|
||||
};
|
||||
uiEnable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable NetBird UI component.";
|
||||
};
|
||||
};
|
||||
tailscale = {
|
||||
waitForNetbird = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Add netbird ordering to tailscaled unit.";
|
||||
};
|
||||
};
|
||||
tooling = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Install network troubleshooting CLI tools.";
|
||||
};
|
||||
packages = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = with pkgs; [
|
||||
dnsutils
|
||||
nmap
|
||||
ipcalc
|
||||
];
|
||||
description = "Packages installed when network tooling is enabled.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf config.features.network.enable {
|
||||
services.netbird = mkIf config.features.network.netbird.enable {
|
||||
enable = true;
|
||||
ui.enable = config.features.network.netbird.uiEnable;
|
||||
};
|
||||
|
||||
systemd.services.tailscaled =
|
||||
mkIf (config.features.network.tailscale.waitForNetbird && config.features.network.netbird.enable)
|
||||
{
|
||||
after = [
|
||||
"netbird.service"
|
||||
"network-online.target"
|
||||
];
|
||||
wants = [
|
||||
"netbird.service"
|
||||
"network-online.target"
|
||||
];
|
||||
};
|
||||
|
||||
environment.systemPackages = mkIf config.features.network.tooling.enable config.features.network.tooling.packages;
|
||||
};
|
||||
}
|
||||
71
moduler/services/sound/default.nix
Normal file
71
moduler/services/sound/default.nix
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
{ lib, config, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.features.sound = {
|
||||
enable = mkEnableOption "enable sound and bluetooth stack";
|
||||
pipewire = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable PipeWire audio stack.";
|
||||
};
|
||||
alsa32Bit = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable 32-bit ALSA support.";
|
||||
};
|
||||
pulseCompat = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable PulseAudio compatibility through PipeWire.";
|
||||
};
|
||||
};
|
||||
bluetooth = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable Bluetooth subsystem.";
|
||||
};
|
||||
powerOnBoot = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Power on Bluetooth at boot.";
|
||||
};
|
||||
disableHeadsetProfile = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Disable headset profile for Bluetooth devices.";
|
||||
};
|
||||
bluemanEnable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable Blueman service.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf config.features.sound.enable {
|
||||
services.pulseaudio.enable = false;
|
||||
security.rtkit.enable = true;
|
||||
services = {
|
||||
pipewire = {
|
||||
enable = config.features.sound.pipewire.enable;
|
||||
alsa.enable = config.features.sound.pipewire.enable;
|
||||
alsa.support32Bit = config.features.sound.pipewire.alsa32Bit;
|
||||
pulse.enable = config.features.sound.pipewire.pulseCompat;
|
||||
};
|
||||
blueman.enable = config.features.sound.bluetooth.bluemanEnable;
|
||||
};
|
||||
hardware = {
|
||||
bluetooth = mkIf config.features.sound.bluetooth.enable {
|
||||
enable = config.features.sound.bluetooth.enable;
|
||||
powerOnBoot = config.features.sound.bluetooth.powerOnBoot;
|
||||
settings = {
|
||||
General = mkIf config.features.sound.bluetooth.disableHeadsetProfile {
|
||||
Disable = "Headset";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
78
moduler/services/system/default.nix
Normal file
78
moduler/services/system/default.nix
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
{
|
||||
options.features.system = {
|
||||
enable = mkEnableOption "enable shared system utilities";
|
||||
preset = mkOption {
|
||||
type = types.enum [
|
||||
"minimal"
|
||||
"desktop"
|
||||
"ops"
|
||||
];
|
||||
default = "desktop";
|
||||
description = "Package profile for shared system tooling.";
|
||||
};
|
||||
corePackages = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = with pkgs; [
|
||||
sops
|
||||
unzip
|
||||
zip
|
||||
wget
|
||||
htop
|
||||
procps
|
||||
fastfetch
|
||||
bc
|
||||
fzf
|
||||
eza
|
||||
rsync
|
||||
ripgrep
|
||||
fd
|
||||
];
|
||||
description = "Always-installed core system packages.";
|
||||
};
|
||||
desktopPackages = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = with pkgs; [
|
||||
bluez
|
||||
bluez-tools
|
||||
poppler-utils
|
||||
alsa-utils
|
||||
libnotify
|
||||
hyprpicker
|
||||
];
|
||||
description = "Additional packages for desktop-oriented hosts.";
|
||||
};
|
||||
opsPackages = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = with pkgs; [
|
||||
grc
|
||||
lazygit
|
||||
];
|
||||
description = "Additional packages for operations-heavy hosts.";
|
||||
};
|
||||
extras = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = with pkgs; [
|
||||
lolcat
|
||||
fortune
|
||||
cowsay
|
||||
typst
|
||||
];
|
||||
description = "Additional optional packages for all presets except minimal.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf config.features.system.enable {
|
||||
environment.systemPackages =
|
||||
config.features.system.corePackages
|
||||
++ optionals (config.features.system.preset != "minimal") config.features.system.extras
|
||||
++ optionals (config.features.system.preset == "desktop") config.features.system.desktopPackages
|
||||
++ optionals (config.features.system.preset == "ops") config.features.system.opsPackages;
|
||||
};
|
||||
}
|
||||
62
moduler/services/users/default.nix
Normal file
62
moduler/services/users/default.nix
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
{
|
||||
options.features.users = {
|
||||
enable = mkEnableOption "enable default users";
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = "fw";
|
||||
description = "Primary user account name.";
|
||||
};
|
||||
fullName = mkOption {
|
||||
type = types.str;
|
||||
default = "Fredrik Wastring";
|
||||
description = "Primary user full name.";
|
||||
};
|
||||
initialPassword = mkOption {
|
||||
type = types.str;
|
||||
default = "password";
|
||||
description = "Initial password for the primary user.";
|
||||
};
|
||||
extraGroups = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [
|
||||
"networkmanager"
|
||||
"wheel"
|
||||
"audio"
|
||||
"docker"
|
||||
"input"
|
||||
];
|
||||
description = "Additional groups for the primary user.";
|
||||
};
|
||||
sshAuthorizedKeys = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFpJBGPIfPB1BwSG7aoKqwfccyZSaU7J3xpJ8behMp9N fw@core"
|
||||
];
|
||||
description = "SSH authorized keys for the primary user.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf config.features.users.enable {
|
||||
users = {
|
||||
defaultUserShell = pkgs.bash;
|
||||
users = {
|
||||
${config.features.users.name} = {
|
||||
initialPassword = config.features.users.initialPassword;
|
||||
isNormalUser = true;
|
||||
description = config.features.users.fullName;
|
||||
extraGroups = config.features.users.extraGroups;
|
||||
openssh.authorizedKeys = {
|
||||
keys = config.features.users.sshAuthorizedKeys;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -100,6 +100,21 @@ in
|
|||
default = 24;
|
||||
description = "VAAPI quality parameter (lower means better quality, higher CPU/bitrate).";
|
||||
};
|
||||
waitForRtsp = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Wait for the RTSP destination to accept TCP connections before ffmpeg starts.";
|
||||
};
|
||||
waitForRtspTimeoutSec = mkOption {
|
||||
type = types.int;
|
||||
default = 30;
|
||||
description = "Maximum seconds to wait for RTSP destination availability.";
|
||||
};
|
||||
waitForRtspIntervalSec = mkOption {
|
||||
type = types.int;
|
||||
default = 1;
|
||||
description = "Seconds between RTSP availability checks.";
|
||||
};
|
||||
vaapiDriver = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
|
|
@ -209,6 +224,13 @@ in
|
|||
"-rc_mode VBR -b:v ${toString streamCfg.bitrateKbps}k -maxrate ${toString maxrateKbps}k -bufsize ${toString bufsizeKbps}k"
|
||||
else
|
||||
"-rc_mode CQP -qp ${toString streamCfg.vaapiQp}";
|
||||
rtspUrlMatch = builtins.match "rtsp://([^/:]+)(:([0-9]+))?/.*" streamCfg.rtspUrl;
|
||||
rtspHost = if rtspUrlMatch != null then builtins.elemAt rtspUrlMatch 0 else "127.0.0.1";
|
||||
rtspPort =
|
||||
if rtspUrlMatch != null && builtins.elemAt rtspUrlMatch 2 != null then
|
||||
builtins.elemAt rtspUrlMatch 2
|
||||
else
|
||||
"8554";
|
||||
videoCodecArgs =
|
||||
if streamCfg.useVaapi then
|
||||
"-vaapi_device ${streamCfg.vaapiDevice} -vf format=nv12,hwupload -c:v h264_vaapi -profile:v main -level:v 4.1 ${vaapiRateControlArgs} -g ${
|
||||
|
|
@ -230,6 +252,22 @@ in
|
|||
Restart = "always";
|
||||
RestartSec = "2";
|
||||
Environment = optional (streamCfg.vaapiDriver != null) "LIBVA_DRIVER_NAME=${streamCfg.vaapiDriver}";
|
||||
ExecStartPre = optional cfg.waitForRtsp (
|
||||
pkgs.writeShellScript "wait-for-rtsp-${sanitizeName streamName}" ''
|
||||
set -eu
|
||||
retries=${toString cfg.waitForRtspTimeoutSec}
|
||||
interval=${toString cfg.waitForRtspIntervalSec}
|
||||
i=0
|
||||
until ${pkgs.netcat-openbsd}/bin/nc -z -w1 ${rtspHost} ${rtspPort}; do
|
||||
i=$((i + 1))
|
||||
if [ "$i" -ge "$retries" ]; then
|
||||
echo "Timed out waiting for RTSP server at ${rtspHost}:${rtspPort}" >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep "$interval"
|
||||
done
|
||||
''
|
||||
);
|
||||
ExecStart = "${pkgs.ffmpeg}/bin/ffmpeg -hide_banner -loglevel warning -f v4l2 -framerate ${toString streamCfg.framerate} -video_size ${streamCfg.videoSize} -i ${streamCfg.device} ${videoCodecArgs} -f rtsp -rtsp_transport tcp ${streamCfg.rtspUrl}";
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,8 @@
|
|||
{ pkgs, lib, ... }:
|
||||
{ lib, ... }:
|
||||
{
|
||||
services.pulseaudio.enable = false;
|
||||
security.rtkit.enable = true;
|
||||
services = {
|
||||
pipewire = {
|
||||
enable = true;
|
||||
alsa.enable = true;
|
||||
alsa.support32Bit = true;
|
||||
pulse.enable = true;
|
||||
};
|
||||
blueman.enable = true;
|
||||
};
|
||||
hardware = {
|
||||
bluetooth = {
|
||||
enable = true;
|
||||
powerOnBoot = true;
|
||||
settings = {
|
||||
General = {
|
||||
Disable = "Headset";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
imports = [
|
||||
./services/sound
|
||||
];
|
||||
|
||||
features.sound.enable = lib.mkDefault true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,39 +1,8 @@
|
|||
{ lib, ... }:
|
||||
{
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
bluez
|
||||
bluez-tools
|
||||
poppler-utils
|
||||
alsa-utils
|
||||
|
||||
sops
|
||||
libnotify
|
||||
unzip
|
||||
zip
|
||||
wget
|
||||
htop
|
||||
procps
|
||||
grc
|
||||
fastfetch
|
||||
bc
|
||||
|
||||
fzf
|
||||
eza
|
||||
rsync
|
||||
ripgrep
|
||||
fd
|
||||
|
||||
lolcat
|
||||
fortune
|
||||
cowsay
|
||||
|
||||
lazygit
|
||||
hyprpicker
|
||||
typst
|
||||
imports = [
|
||||
./services/system
|
||||
];
|
||||
|
||||
features.system.enable = lib.mkDefault true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,8 @@
|
|||
{ lib, ... }:
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
# sops.secrets.user-password = { };
|
||||
users = {
|
||||
defaultUserShell = pkgs.bash;
|
||||
users = {
|
||||
fw = {
|
||||
# hashedPasswordFile = config.sops.secrets.user-password.path;
|
||||
initialPassword = "password";
|
||||
isNormalUser = true;
|
||||
description = "Fredrik Wastring";
|
||||
extraGroups = [
|
||||
"networkmanager"
|
||||
"wheel"
|
||||
"audio"
|
||||
"docker"
|
||||
"input"
|
||||
];
|
||||
openssh.authorizedKeys = {
|
||||
keys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFpJBGPIfPB1BwSG7aoKqwfccyZSaU7J3xpJ8behMp9N fw@core"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
imports = [
|
||||
./services/users
|
||||
];
|
||||
|
||||
features.users.enable = lib.mkDefault true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue