From 086e091add256d028b27569e6e87555700dbb24b Mon Sep 17 00:00:00 2001 From: Hektor Misplon Date: Fri, 22 May 2026 10:23:22 +0200 Subject: [PATCH] feat(ssh): add enable option --- home/hosts/andromache/default.nix | 1 + home/hosts/astyanax/default.nix | 1 + home/modules/ssh/default.nix | 55 +++++++++++++++++-------------- modules/ssh/authorized-keys.nix | 25 +++++++------- modules/ssh/default.nix | 15 ++++++--- modules/ssh/extract-keys.nix | 50 ++++++++++++++-------------- modules/ssh/hardened-openssh.nix | 4 ++- modules/ssh/known-hosts.nix | 12 ++++--- 8 files changed, 93 insertions(+), 70 deletions(-) diff --git a/home/hosts/andromache/default.nix b/home/hosts/andromache/default.nix index 05dc49c5..cfc69455 100644 --- a/home/hosts/andromache/default.nix +++ b/home/hosts/andromache/default.nix @@ -59,6 +59,7 @@ shell.bash.aliases.lang-js = true; shell.bash.addBinToPath = true; audio.enable = true; + ssh.enable = true; music.enable = true; terminal.enable = true; devenv.enable = true; diff --git a/home/hosts/astyanax/default.nix b/home/hosts/astyanax/default.nix index 50a31673..b2acdc01 100644 --- a/home/hosts/astyanax/default.nix +++ b/home/hosts/astyanax/default.nix @@ -56,6 +56,7 @@ shell.bash.addBinToPath = true; my.yubikey.enable = true; audio.enable = true; + ssh.enable = true; music.enable = true; terminal.enable = true; devenv.enable = true; diff --git a/home/modules/ssh/default.nix b/home/modules/ssh/default.nix index e1d59f74..c468a0ea 100644 --- a/home/modules/ssh/default.nix +++ b/home/modules/ssh/default.nix @@ -1,10 +1,13 @@ { - myUtils, + config, lib, pkgs, + myUtils, ... }: + let + cfg = config.ssh; hostDir = ../../hosts; hostNames = myUtils.dirNames hostDir; hostsWithKeys = lib.filter ( @@ -12,31 +15,35 @@ let ) hostNames; in { - home.packages = with pkgs; [ sshfs ]; + options.ssh.enable = lib.mkEnableOption "ssh"; - programs.ssh = { - enable = true; - enableDefaultConfig = false; + config = lib.mkIf cfg.enable { + home.packages = with pkgs; [ sshfs ]; - matchBlocks = - lib.genAttrs hostsWithKeys ( - hostname: - let - meta = myUtils.hostMeta (hostDir + "/${hostname}"); - in - { - host = hostname; - user = meta.deployment.targetUser; - } - // lib.optionalAttrs (meta.deployment.targetHost != "") { - hostname = meta.deployment.targetHost; - } - ) - // { - "*" = { - addKeysToAgent = "yes"; - forwardAgent = false; + programs.ssh = { + enable = true; + enableDefaultConfig = false; + + matchBlocks = + lib.genAttrs hostsWithKeys ( + hostname: + let + meta = myUtils.hostMeta (hostDir + "/${hostname}"); + in + { + host = hostname; + user = meta.deployment.targetUser; + } + // lib.optionalAttrs (meta.deployment.targetHost != "") { + hostname = meta.deployment.targetHost; + } + ) + // { + "*" = { + addKeysToAgent = "yes"; + forwardAgent = false; + }; }; - }; + }; }; } diff --git a/modules/ssh/authorized-keys.nix b/modules/ssh/authorized-keys.nix index aea22fdd..3db84bb7 100644 --- a/modules/ssh/authorized-keys.nix +++ b/modules/ssh/authorized-keys.nix @@ -16,16 +16,17 @@ in }; }; - # auto generate authorized_keys from `authorizedHosts` - config.users.users.${username}.openssh.authorizedKeys.keys = - lib.flatten ( - map ( - hostname: - let - keyFile = ../../hosts/${hostname}/ssh_user.pub; - in - lib.optionals (builtins.pathExists keyFile) (lib.splitString "\n" (builtins.readFile keyFile)) - ) ((builtins.filter (h: h != config.host.name) adminHosts) ++ config.ssh.authorizedHosts) - ) - ++ lib.splitString "\n" (builtins.readFile ./ssh_bak.pub); + config = lib.mkIf config.ssh.enable { + users.users.${username}.openssh.authorizedKeys.keys = + lib.flatten ( + map ( + hostname: + let + keyFile = ../../hosts/${hostname}/ssh_user.pub; + in + lib.optionals (builtins.pathExists keyFile) (lib.splitString "\n" (builtins.readFile keyFile)) + ) ((builtins.filter (h: h != config.host.name) adminHosts) ++ config.ssh.authorizedHosts) + ) + ++ lib.splitString "\n" (builtins.readFile ./ssh_bak.pub); + }; } diff --git a/modules/ssh/default.nix b/modules/ssh/default.nix index b6e92e71..c733085b 100644 --- a/modules/ssh/default.nix +++ b/modules/ssh/default.nix @@ -1,10 +1,17 @@ -{ lib, ... }: +{ lib, config, ... }: +let + cfg = config.ssh; +in { imports = [ ./hardened-openssh.nix ]; - config.services.openssh = { - enable = lib.mkDefault true; - harden = lib.mkDefault true; + options.ssh.enable = lib.mkEnableOption "SSH server"; + + config = lib.mkIf cfg.enable { + services.openssh = { + enable = lib.mkDefault true; + harden = lib.mkDefault true; + }; }; } diff --git a/modules/ssh/extract-keys.nix b/modules/ssh/extract-keys.nix index 430b091c..bcb144ed 100644 --- a/modules/ssh/extract-keys.nix +++ b/modules/ssh/extract-keys.nix @@ -1,32 +1,34 @@ { lib, config, ... }: + let inherit (config.host) username; in { - # auto extract SSH keys - system.activationScripts.extractSshKeys = lib.stringAfter [ "etc" ] '' - HOST_KEY="/etc/ssh/ssh_host_ed25519_key.pub" - HOST_DIR="/home/${username}/nix/hosts/${config.networking.hostName}" + config = lib.mkIf config.ssh.enable { + system.activationScripts.extractSshKeys = lib.stringAfter [ "etc" ] '' + HOST_KEY="/etc/ssh/ssh_host_ed25519_key.pub" + HOST_DIR="/home/${username}/nix/hosts/${config.networking.hostName}" - if [ -f "$HOST_KEY" ] && [ -d "$HOST_DIR" ]; then - cp "$HOST_KEY" "$HOST_DIR/ssh_host.pub" - chown ${username}:users "$HOST_DIR/ssh_host.pub" - chmod 644 "$HOST_DIR/ssh_host.pub" - fi - - USER_KEY="" - for candidate in \ - "/home/${username}/.ssh/id_ed25519_sk.pub" \ - "/home/${username}/.ssh/id_ed25519.pub"; do - if [ -f "$candidate" ]; then - USER_KEY="$candidate" - break + if [ -f "$HOST_KEY" ] && [ -d "$HOST_DIR" ]; then + cp "$HOST_KEY" "$HOST_DIR/ssh_host.pub" + chown ${username}:users "$HOST_DIR/ssh_host.pub" + chmod 644 "$HOST_DIR/ssh_host.pub" fi - done - if [ -n "$USER_KEY" ] && [ -d "$HOST_DIR" ]; then - cp "$USER_KEY" "$HOST_DIR/ssh_user.pub" - chown ${username}:users "$HOST_DIR/ssh_user.pub" - chmod 644 "$HOST_DIR/ssh_user.pub" - fi - ''; + + USER_KEY="" + for candidate in \ + "/home/${username}/.ssh/id_ed25519_sk.pub" \ + "/home/${username}/.ssh/id_ed25519.pub"; do + if [ -f "$candidate" ]; then + USER_KEY="$candidate" + break + fi + done + if [ -n "$USER_KEY" ] && [ -d "$HOST_DIR" ]; then + cp "$USER_KEY" "$HOST_DIR/ssh_user.pub" + chown ${username}:users "$HOST_DIR/ssh_user.pub" + chmod 644 "$HOST_DIR/ssh_user.pub" + fi + ''; + }; } diff --git a/modules/ssh/hardened-openssh.nix b/modules/ssh/hardened-openssh.nix index b046f5ca..35df3a11 100644 --- a/modules/ssh/hardened-openssh.nix +++ b/modules/ssh/hardened-openssh.nix @@ -1,5 +1,7 @@ { lib, config, ... }: + with lib; + let cfg = config.services.openssh; in @@ -13,7 +15,7 @@ in options.services.openssh.harden = mkEnableOption "harden ssh server configuration"; config = { - networking.firewall.allowedTCPPorts = [ 22 ]; + networking.firewall.allowedTCPPorts = lib.mkIf config.ssh.enable [ 22 ]; services.openssh.settings = optionalAttrs cfg.harden { PermitRootLogin = "no"; diff --git a/modules/ssh/known-hosts.nix b/modules/ssh/known-hosts.nix index 2b81e42e..e0c3be8a 100644 --- a/modules/ssh/known-hosts.nix +++ b/modules/ssh/known-hosts.nix @@ -4,6 +4,7 @@ outputs, ... }: + let hosts = lib.attrNames outputs.nixosConfigurations; hostsWithKeys = lib.filter ( @@ -11,9 +12,10 @@ let ) hosts; in { - # auto generate known_hosts for all hosts in flake - programs.ssh.knownHosts = lib.genAttrs hostsWithKeys (hostname: { - publicKeyFile = ../../hosts/${hostname}/ssh_host.pub; - extraHostNames = lib.optional (hostname == config.networking.hostName) "localhost"; - }); + config = lib.mkIf config.ssh.enable { + programs.ssh.knownHosts = lib.genAttrs hostsWithKeys (hostname: { + publicKeyFile = ../../hosts/${hostname}/ssh_host.pub; + extraHostNames = lib.optional (hostname == config.networking.hostName) "localhost"; + }); + }; }