Compare commits

...

7 commits

Author SHA1 Message Date
müde
a2494f5213 ssh: block sleep while conntections acive 2026-05-03 17:11:13 +02:00
müde
d75e91b7bc group options in my namespace 2026-05-03 16:33:56 +02:00
müde
63ce7eac05 move allowedUnfreePackages into my namespace 2026-05-03 16:32:26 +02:00
müde
d2acd47e71 move some imports to desktop only 2026-05-03 16:30:00 +02:00
müde
7de5751743 distributed builds: add assertions, nix fmt 2026-05-03 16:13:47 +02:00
müde
9bff3f718f ditributed builds: use fqdn if available 2026-05-03 16:04:27 +02:00
müde
c8cfa37bb9 hm modules: gate behind enable options, always import 2026-05-03 15:19:06 +02:00
22 changed files with 211 additions and 98 deletions

View file

@ -26,6 +26,7 @@ in
}; };
forgejo-runner-1 = { forgejo-runner-1 = {
system = "aarch64-linux"; system = "aarch64-linux";
publicFqdn = "forgejo-runner-1.dev.zerforschen.plus";
distributedBuilds = { distributedBuilds = {
isBuilder = true; isBuilder = true;
speedFactor = 1; speedFactor = 1;

View file

@ -23,6 +23,15 @@
]; ];
config = { config = {
my = {
# keep-sorted start
gnome-extensions.enable = true;
nano.enable = true;
templates.enable = true;
zsh.enable = true;
# keep-sorted end
};
programs = { programs = {
home-manager.enable = true; home-manager.enable = true;
fzf.enable = true; fzf.enable = true;

View file

@ -2,6 +2,14 @@
{ {
imports = [ ./vscode.nix ]; imports = [ ./vscode.nix ];
config = { config = {
my = {
# keep-sorted start
nano.enable = true;
templates.enable = true;
zsh.enable = true;
# keep-sorted end
};
home.packages = with pkgs; [ home.packages = with pkgs; [
## Apps ## Apps
telegram-desktop telegram-desktop

View file

@ -18,7 +18,7 @@
}; };
in in
{ {
enable = mkDefaultEnabledOption "gnome extended options"; enable = lib.mkEnableOption "gnome extended options";
appindicator.enable = mkDefaultEnabledOption "appindicator"; appindicator.enable = mkDefaultEnabledOption "appindicator";
caffeine.enable = mkDefaultEnabledOption "caffeine"; caffeine.enable = mkDefaultEnabledOption "caffeine";
tailscale-qs.enable = lib.mkOption { tailscale-qs.enable = lib.mkOption {

View file

@ -1,9 +1,14 @@
{ lib, config, ... }:
{ {
home = { options.my.nano.enable = lib.mkEnableOption "nano editor config";
sessionVariables.EDITOR = "nano";
file.".nanorc".text = '' config = lib.mkIf config.my.nano.enable {
set linenumbers home = {
set mouse sessionVariables.EDITOR = "nano";
''; file.".nanorc".text = ''
set linenumbers
set mouse
'';
};
}; };
} }

View file

@ -1,4 +1,18 @@
{ osConfig, thisDevice, ... }:
{ {
services.tailscale-systray.enable = (thisDevice.isDesktop or false) && osConfig.my.tailscale.enable; lib,
config,
osConfig,
thisDevice,
...
}:
{
options.my.tailscale.enable = lib.mkOption {
type = lib.types.bool;
default = (thisDevice.isDesktop or false) && osConfig.my.tailscale.enable;
description = "Whether to enable the Tailscale system tray applet. Defaults to true on desktops with Tailscale enabled.";
};
config = lib.mkIf config.my.tailscale.enable {
services.tailscale-systray.enable = true;
};
} }

View file

@ -1,12 +1,17 @@
{ lib, config, ... }:
{ {
home.file = { options.my.templates.enable = lib.mkEnableOption "file templates";
"Templates/Empty file".text = "";
"Templates/Empty bash script".text = '' config = lib.mkIf config.my.templates.enable {
#!/usr/bin/env bash home.file = {
# abort on error, undefined variables "Templates/Empty file".text = "";
set -eu "Templates/Empty bash script".text = ''
# print commands before execution #!/usr/bin/env bash
set -x # abort on error, undefined variables
''; set -eu
# print commands before execution
set -x
'';
};
}; };
} }

View file

@ -1,13 +1,18 @@
{ lib, config, ... }:
{ {
programs = { options.my.zsh.enable = lib.mkEnableOption "zsh with basic settings";
command-not-found.enable = true;
dircolors.enable = true;
zsh = { config = lib.mkIf config.my.zsh.enable {
enable = true; programs = {
syntaxHighlighting.enable = true; command-not-found.enable = true;
autosuggestion.enable = true; dircolors.enable = true;
enableVteIntegration = true;
zsh = {
enable = true;
syntaxHighlighting.enable = true;
autosuggestion.enable = true;
enableVteIntegration = true;
};
}; };
}; };
} }

View file

@ -45,10 +45,6 @@ forDevice (
# keep-sorted start # keep-sorted start
home-manager.nixosModules.home-manager home-manager.nixosModules.home-manager
lanzaboote.nixosModules.lanzaboote lanzaboote.nixosModules.lanzaboote
nova-shell.nixosModules.default
servicepoint-cli.nixosModules.default
servicepoint-simulator.nixosModules.default
servicepoint-tanks.nixosModules.default
stylix.nixosModules.stylix stylix.nixosModules.stylix
zerforschen-plus.nixosModules.default zerforschen-plus.nixosModules.default
# keep-sorted end # keep-sorted end
@ -80,15 +76,32 @@ forDevice (
lixIsNix.enable = true; lixIsNix.enable = true;
openssh.enable = true; openssh.enable = true;
overlays.unstable.enable = true; overlays.unstable.enable = true;
overlays.vscodeExtensions.enable = true;
# prometheusNode.enable = true; # prometheusNode.enable = true;
systemdBoot.enable = true; systemdBoot.enable = true;
tailscale.enable = true; tailscale.enable = true;
# keep-sorted end # keep-sorted end
# keep-sorted start
enDe.enable = isDesktop;
firmwareUpdates.enable = isDesktop;
gnome.enable = isDesktop;
kdeconnect.enable = isDesktop;
modernDesktop.enable = isDesktop;
nixLd.enable = isDesktop;
overlays.vscodeExtensions.enable = isDesktop;
quietBoot.enable = isDesktop;
stylix.enable = isDesktop;
# keep-sorted end
}; };
} }
] ]
++ lib.optionals isDesktop [ ++ lib.optionals isDesktop [
inputs.niri.nixosModules.niri
nova-shell.nixosModules.default
servicepoint-cli.nixosModules.default
servicepoint-simulator.nixosModules.default
servicepoint-tanks.nixosModules.default
# Desktop config # Desktop config
{ {
home-manager = { home-manager = {
@ -96,16 +109,7 @@ forDevice (
useGlobalPkgs = true; useGlobalPkgs = true;
useUserPackages = true; useUserPackages = true;
users = home-manager-users; users = home-manager-users;
sharedModules = [ sharedModules = [ { home.stateVersion = "22.11"; } ] ++ builtins.attrValues self.homeModules;
{ home.stateVersion = "22.11"; }
# keep-sorted start
self.homeModules.gnome-extensions
self.homeModules.nano
self.homeModules.tailscale
self.homeModules.templates
self.homeModules.zsh-basics
# keep-sorted end
];
}; };
time.timeZone = "Europe/Berlin"; time.timeZone = "Europe/Berlin";
@ -115,19 +119,6 @@ forDevice (
daemonCPUSchedPolicy = "idle"; daemonCPUSchedPolicy = "idle";
daemonIOSchedClass = "idle"; daemonIOSchedClass = "idle";
}; };
my = {
# keep-sorted start
enDe.enable = true;
firmwareUpdates.enable = true;
gnome.enable = true;
kdeconnect.enable = true;
modernDesktop.enable = true;
nixLd.enable = true;
quietBoot.enable = true;
stylix.enable = true;
# keep-sorted end
};
} }
]; ];
} }

View file

@ -12,7 +12,7 @@ in
{ {
nixpkgs.config.android_sdk.accept_license = true; nixpkgs.config.android_sdk.accept_license = true;
allowedUnfreePackages = [ my.allowedUnfreePackages = [
"android-sdk-cmdline-tools" "android-sdk-cmdline-tools"
"android-sdk-platform-tools" "android-sdk-platform-tools"
"android-sdk-tools" "android-sdk-tools"

View file

@ -5,8 +5,10 @@
}: }:
{ {
my.overlays.unstable.enable = true; my = {
allowedUnfreePackages = [ "claude-code" ]; allowedUnfreePackages = [ "claude-code" ];
overlays.unstable.enable = true;
};
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
unstable.claude-code unstable.claude-code

View file

@ -5,13 +5,17 @@
]; ];
config = { config = {
my.users.muede.enable = true; my = {
my.wineGaming.enable = true; # keep-sorted start
my.steam.enable = true; intelGraphics.enable = true;
my.podman.enable = true; muedeDesktopSettings.enable = true;
my.muedeDesktopSettings.enable = true; podman.enable = true;
my.intelGraphics.enable = true; secureBoot.enable = true;
my.secureBoot.enable = true; steam.enable = true;
users.muede.enable = true;
wineGaming.enable = true;
# keep-sorted end
};
nix.settings.extra-platforms = [ nix.settings.extra-platforms = [
"aarch64-linux" "aarch64-linux"

View file

@ -7,13 +7,17 @@
]; ];
config = { config = {
my.users.muede.enable = true; my = {
my.wineGaming.enable = true; # keep-sorted start
my.steam.enable = true; amdGraphics.enable = true;
my.podman.enable = true; muedeDesktopSettings.enable = true;
my.muedeDesktopSettings.enable = true; podman.enable = true;
my.amdGraphics.enable = true; secureBoot.enable = true;
my.secureBoot.enable = true; steam.enable = true;
users.muede.enable = true;
wineGaming.enable = true;
# keep-sorted end
};
boot.binfmt.emulatedSystems = [ "aarch64-linux" ]; boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
nix.settings.extra-platforms = [ nix.settings.extra-platforms = [

View file

@ -5,10 +5,14 @@
]; ];
config = { config = {
my.users.ronja.enable = true; my = {
my.steam.enable = true; # keep-sorted start
my.wineGaming.enable = true; muedeDesktopSettings.enable = true;
my.muedeDesktopSettings.enable = true; steam.enable = true;
users.ronja.enable = true;
wineGaming.enable = true;
# keep-sorted end
};
# Configure keymap in X11 # Configure keymap in X11
services.xserver.xkb = { services.xserver.xkb = {

View file

@ -1,6 +1,6 @@
{ lib, config, ... }: { lib, config, ... }:
{ {
options.allowedUnfreePackages = lib.mkOption { options.my.allowedUnfreePackages = lib.mkOption {
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
default = [ ]; default = [ ];
example = [ "steam" ]; example = [ "steam" ];
@ -10,7 +10,7 @@
nixpkgs.config = { nixpkgs.config = {
# https://github.com/NixOS/nixpkgs/issues/197325#issuecomment-1579420085 # https://github.com/NixOS/nixpkgs/issues/197325#issuecomment-1579420085
allowUnfreePredicate = lib.mkDefault ( allowUnfreePredicate = lib.mkDefault (
pkg: builtins.elem (lib.getName pkg) config.allowedUnfreePackages pkg: builtins.elem (lib.getName pkg) config.my.allowedUnfreePackages
); );
}; };
}; };

View file

@ -21,23 +21,26 @@ let
_: v: (v.distributedBuilds or { }).isBuilder or false _: v: (v.distributedBuilds or { }).isBuilder or false
) allDevices; ) allDevices;
sshHostname = m: m.publicFqdn or m.hostName;
buildServerKnownHosts = lib.pipe buildServerDevices [ buildServerKnownHosts = lib.pipe buildServerDevices [
(lib.filterAttrs (_: v: v.distributedBuilds ? hostPublicKey)) (lib.filterAttrs (_: v: v.distributedBuilds ? hostPublicKey))
(lib.mapAttrs ( (lib.mapAttrs (
_: v: { name: v: {
publicKey = v.distributedBuilds.hostPublicKey; publicKey = v.distributedBuilds.hostPublicKey;
hostNames = [ (v.publicFqdn or name) ];
} }
)) ))
]; ];
remoteBuildServerDevices = builtins.filter ( remoteBuildServerDevices = builtins.filter (m: m.hostName != config.networking.hostName) (
m: m.hostName != config.networking.hostName lib.mapAttrsToList (name: v: v // { hostName = name; }) buildServerDevices
) (lib.mapAttrsToList (name: v: v // { hostName = name; }) buildServerDevices); );
buildMachines = map ( buildMachines = map (
m: m:
{ {
hostName = m.hostName; hostName = sshHostname m;
systems = [ m.system ]; systems = [ m.system ];
sshUser = buildUser; sshUser = buildUser;
sshKey = clientSshKeyPath; sshKey = clientSshKeyPath;
@ -64,7 +67,23 @@ in
# All machines # All machines
{ {
assertions =
lib.mapAttrsToList (name: v: {
assertion = v.distributedBuilds ? hostPublicKey && v.distributedBuilds ? storeSigningPublicKey;
message = "devices.${name}: isBuilder = true requires distributedBuilds.hostPublicKey and distributedBuilds.storeSigningPublicKey";
}) buildServerDevices
++ lib.mapAttrsToList (name: v: {
assertion = lib.hasPrefix "ssh-" v.distributedBuilds.clientPublicKey;
message = "devices.${name}: distributedBuilds.clientPublicKey must start with 'ssh-'";
}) (lib.filterAttrs (_: v: (v.distributedBuilds or { }) ? clientPublicKey) allDevices)
++ lib.mapAttrsToList (name: v: {
assertion = builtins.match ".+:.+" v.distributedBuilds.storeSigningPublicKey != null;
message = "devices.${name}: distributedBuilds.storeSigningPublicKey must be in '<name>:<base64>' format";
}) (lib.filterAttrs (_: v: (v.distributedBuilds or { }) ? storeSigningPublicKey) allDevices);
nix.settings = { nix.settings = {
#fallback = true;
connect-timeout = 5;
trusted-public-keys = lib.pipe buildServerDevices [ trusted-public-keys = lib.pipe buildServerDevices [
(lib.mapAttrsToList (_: v: v.distributedBuilds.storeSigningPublicKey or null)) (lib.mapAttrsToList (_: v: v.distributedBuilds.storeSigningPublicKey or null))
(builtins.filter (k: k != null)) (builtins.filter (k: k != null))
@ -103,11 +122,20 @@ in
programs.ssh = { programs.ssh = {
knownHosts = buildServerKnownHosts; knownHosts = buildServerKnownHosts;
extraConfig = lib.concatStringsSep "\n" ( extraConfig = lib.concatStringsSep "\n" (
lib.mapAttrsToList (name: _: '' lib.mapAttrsToList (
Match originalhost ${name} user ${buildUser} name: v:
IdentityFile ${clientSshKeyPath} let
IdentitiesOnly yes names = lib.unique [
'') buildServerDevices name
(v.publicFqdn or name)
];
in
''
Match originalhost ${lib.concatStringsSep "," names} user ${buildUser}
IdentityFile ${clientSshKeyPath}
IdentitiesOnly yes
''
) buildServerDevices
); );
}; };
nix = { nix = {
@ -115,7 +143,7 @@ in
buildMachines = buildMachines; buildMachines = buildMachines;
settings = { settings = {
builders-use-substitutes = true; builders-use-substitutes = true;
substituters = map (m: "ssh-ng://${buildUser}@${m.hostName}") ( substituters = map (m: "ssh-ng://${buildUser}@${sshHostname m}") (
builtins.filter (m: m.distributedBuilds ? storeSigningPublicKey) remoteBuildServerDevices builtins.filter (m: m.distributedBuilds ? storeSigningPublicKey) remoteBuildServerDevices
); );
}; };

View file

@ -5,9 +5,9 @@
... ...
}: }:
{ {
options = { options.my.gnome = {
my.gnome.enable = lib.mkEnableOption "GNOME desktop environment"; enable = lib.mkEnableOption "GNOME desktop environment";
my.gnome.keep-default-apps = lib.mkEnableOption "keep gnome default apps"; keep-default-apps = lib.mkEnableOption "keep gnome default apps";
}; };
config = lib.mkIf config.my.gnome.enable ( config = lib.mkIf config.my.gnome.enable (

View file

@ -22,6 +22,6 @@
]; ];
}; };
environment.systemPackages = with pkgs; [ nvtopPackages.intel ]; environment.systemPackages = with pkgs; [ nvtopPackages.intel ];
allowedUnfreePackages = [ "intel-ocl" ]; my.allowedUnfreePackages = [ "intel-ocl" ];
}; };
} }

View file

@ -2,12 +2,9 @@
lib, lib,
config, config,
pkgs, pkgs,
niri,
... ...
}: }:
{ {
imports = [ niri.nixosModules.niri ];
options.my.muedeDesktopSettings.enable = lib.mkEnableOption "muede desktop settings (Firefox, Logitech, RDP)"; options.my.muedeDesktopSettings.enable = lib.mkEnableOption "muede desktop settings (Firefox, Logitech, RDP)";
config = lib.mkIf config.my.muedeDesktopSettings.enable { config = lib.mkIf config.my.muedeDesktopSettings.enable {

View file

@ -1,4 +1,10 @@
{ lib, config, ... }: {
lib,
config,
pkgs,
thisDevice,
...
}:
{ {
options.my.openssh.enable = lib.mkEnableOption "OpenSSH server"; options.my.openssh.enable = lib.mkEnableOption "OpenSSH server";
@ -12,5 +18,35 @@
KbdInteractiveAuthentication = false; KbdInteractiveAuthentication = false;
}; };
}; };
# On desktops, hold a systemd sleep inhibitor while SSH connections are active
security.pam.services.sshd.rules.session.ssh-inhibit = lib.mkIf (thisDevice.isDesktop or false) {
order = 10000;
control = "optional";
modulePath = "${pkgs.pam}/lib/security/pam_exec.so";
args = [
"quiet"
"${pkgs.writeShellScript "ssh-inhibit-pam" ''
PIDFILE="/run/ssh-inhibitor-''${PPID}.pid"
case "''${PAM_TYPE:-}" in
open)
${pkgs.systemd}/bin/systemd-inhibit \
--what=sleep \
--who=sshd \
--why="SSH session active" \
--mode=block \
sleep infinity &
echo $! > "$PIDFILE"
;;
close)
if [ -f "$PIDFILE" ]; then
kill "$(cat "$PIDFILE")" 2>/dev/null || true
rm -f "$PIDFILE"
fi
;;
esac
''}"
];
};
}; };
} }

View file

@ -40,7 +40,7 @@
]; ];
}; };
allowedUnfreePackages = [ my.allowedUnfreePackages = [
"steam" "steam"
"steam-original" "steam-original"
"steam-run" "steam-run"

View file

@ -31,7 +31,7 @@
nix.settings.trusted-users = [ "muede" ]; nix.settings.trusted-users = [ "muede" ];
allowedUnfreePackages = [ my.allowedUnfreePackages = [
"rider" "rider"
"pycharm-professional" "pycharm-professional"
"jetbrains-toolbox" "jetbrains-toolbox"