feat: automate SSH config ('known_hosts', 'authorized_keys' ...)

This commit is contained in:
2026-01-17 17:37:37 +01:00
parent 33b022c659
commit 8464884fdb
15 changed files with 143 additions and 9 deletions

View File

@@ -50,6 +50,7 @@
nvim, nvim,
}@inputs: }@inputs:
let let
inherit (self) outputs;
lib = inputs.nixpkgs.lib; lib = inputs.nixpkgs.lib;
utils = import ./utils { inherit lib; }; utils = import ./utils { inherit lib; };
hostDirNames = utils.dirNames ./hosts; hostDirNames = utils.dirNames ./hosts;
@@ -67,14 +68,18 @@
host: host:
nixpkgs.lib.nixosSystem { nixpkgs.lib.nixosSystem {
modules = [ ./hosts/${host} ]; modules = [ ./hosts/${host} ];
specialArgs = { inherit inputs; }; specialArgs = {
inherit inputs outputs;
};
} }
); );
homeConfigurations = { homeConfigurations = {
work = home-manager.lib.homeManagerConfiguration { work = home-manager.lib.homeManagerConfiguration {
inherit pkgs; inherit pkgs;
modules = [ ./home/hosts/work ]; modules = [ ./home/hosts/work ];
extraSpecialArgs = { inherit inputs; }; extraSpecialArgs = {
inherit inputs outputs;
};
}; };
}; };
}; };

View File

@@ -14,6 +14,7 @@ in
../../modules/desktop/niri ../../modules/desktop/niri
../../modules/git.nix ../../modules/git.nix
../../modules/k9s.nix ../../modules/k9s.nix
../../modules/ssh.nix
../../modules/taskwarrior.nix ../../modules/taskwarrior.nix
../../modules/keepassxc.nix ../../modules/keepassxc.nix
../../modules/anki.nix ../../modules/anki.nix

View File

@@ -14,6 +14,7 @@ in
../../modules/desktop/niri ../../modules/desktop/niri
../../modules/git.nix ../../modules/git.nix
../../modules/k9s.nix ../../modules/k9s.nix
../../modules/ssh.nix
../../modules/taskwarrior.nix ../../modules/taskwarrior.nix
../../modules/keepassxc.nix ../../modules/keepassxc.nix
../../modules/browser ../../modules/browser

25
home/modules/ssh.nix Normal file
View File

@@ -0,0 +1,25 @@
{
outputs,
lib,
...
}:
let
nixosConfigs = builtins.attrNames outputs.nixosConfigurations;
homeConfigs = map (n: lib.last (lib.splitString "@" n)) (
builtins.attrNames outputs.homeConfigurations
);
allHosts = lib.unique (homeConfigs ++ nixosConfigs);
hostsWithKeys = lib.filter (
hostname: builtins.pathExists ../../hosts/${hostname}/ssh_host.pub
) allHosts;
in
{
programs.ssh = {
enable = true;
enableDefaultConfig = false;
matchBlocks = lib.genAttrs hostsWithKeys (hostname: {
host = hostname;
});
};
}

1
home/ssh.pub Normal file
View File

@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIzP1PjIDb1tN9nhPOK88HYDtTNk9SN9ZpEem2id49Fa h@astyanax

View File

@@ -1,6 +1,7 @@
{ {
lib, lib,
inputs, inputs,
outputs,
config, config,
pkgs, pkgs,
... ...
@@ -81,7 +82,9 @@ in
home-manager = { home-manager = {
useGlobalPkgs = true; useGlobalPkgs = true;
useUserPackages = true; useUserPackages = true;
extraSpecialArgs = { inherit inputs; }; extraSpecialArgs = {
inherit inputs outputs;
};
users.${username} = import ../../home/hosts/andromache { users.${username} = import ../../home/hosts/andromache {
inherit lib; inherit lib;
inherit inputs; inherit inputs;
@@ -90,6 +93,8 @@ in
}; };
}; };
ssh.authorizedHosts = [ "astyanax" ];
services.xserver = { services.xserver = {
videoDrivers = [ "nvidia" ]; videoDrivers = [ "nvidia" ];
}; };

View File

@@ -1,6 +1,7 @@
{ {
lib, lib,
inputs, inputs,
outputs,
config, config,
pkgs, pkgs,
... ...
@@ -75,7 +76,9 @@ in
home-manager = { home-manager = {
useGlobalPkgs = true; useGlobalPkgs = true;
useUserPackages = true; useUserPackages = true;
extraSpecialArgs = { inherit inputs; }; extraSpecialArgs = {
inherit inputs outputs;
};
users.${username} = import ../../home/hosts/astyanax { users.${username} = import ../../home/hosts/astyanax {
inherit inputs; inherit inputs;
inherit config; inherit config;
@@ -88,6 +91,8 @@ in
hostId = "80eef97e"; hostId = "80eef97e";
}; };
ssh.authorizedHosts = [ "andromache" ];
services = { services = {
fwupd.enable = true; fwupd.enable = true;
openssh = { openssh = {

View File

@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO8+UOyZbvQeHfFfYox3SQi42KJ0S3RZj79iswSsZeFy root@nixos

View File

@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIzP1PjIDb1tN9nhPOK88HYDtTNk9SN9ZpEem2id49Fa h@astyanax

View File

@@ -1,4 +1,11 @@
{ pkgs, ... }: {
lib,
inputs,
outputs,
config,
pkgs,
...
}:
# Also see <https://wiki.nixos.org/wiki/Install_NixOS_on_Hetzner_Cloud> # Also see <https://wiki.nixos.org/wiki/Install_NixOS_on_Hetzner_Cloud>
@@ -31,12 +38,14 @@
username = { username = {
isNormalUser = true; isNormalUser = true;
extraGroups = [ "wheel" ]; extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOOXPEhdKOVnb6mkeLLUcFGt+mnUR5pMie17JtjrxwgO h@andromache"
];
}; };
}; };
ssh = {
username = "username";
authorizedHosts = [ "andromache" ];
};
security.sudo.wheelNeedsPassword = false; security.sudo.wheelNeedsPassword = false;
networking = { networking = {
@@ -57,4 +66,6 @@
enable = true; enable = true;
harden = true; harden = true;
}; };
networking.hostName = "hecuba";
} }

View File

@@ -1,6 +1,7 @@
{ {
lib, lib,
inputs, inputs,
outputs,
config, config,
pkgs, pkgs,
... ...
@@ -58,7 +59,9 @@ in
home-manager = { home-manager = {
useGlobalPkgs = true; useGlobalPkgs = true;
useUserPackages = true; useUserPackages = true;
extraSpecialArgs = { inherit inputs; }; extraSpecialArgs = {
inherit inputs outputs;
};
users.${username} = import ../../home/hosts/vm { users.${username} = import ../../home/hosts/vm {
inherit inputs; inherit inputs;
inherit config; inherit config;

View File

@@ -0,0 +1,24 @@
{ lib, config, ... }:
{
options.ssh = {
authorizedHosts = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
username = lib.mkOption {
type = lib.types.str;
default = "h";
};
};
# auto generate authorized_keys from `authorizedHosts`
config.users.users.${config.ssh.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))
) config.ssh.authorizedHosts
);
}

View File

@@ -0,0 +1,24 @@
{ lib, config, ... }:
let
username = config.ssh.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}"
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="/home/${username}/.ssh/id_ed25519.pub"
if [ -f "$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
'';
}

View File

@@ -4,9 +4,17 @@ let
cfg = config.services.openssh; cfg = config.services.openssh;
in in
{ {
imports = [
./known-hosts.nix
./authorized-keys.nix
./extract-keys.nix
];
options.services.openssh.harden = mkEnableOption "harden ssh server configuration"; options.services.openssh.harden = mkEnableOption "harden ssh server configuration";
config = { config = {
networking.firewall.allowedTCPPorts = [ 22 ]; networking.firewall.allowedTCPPorts = [ 22 ];
services.openssh.settings = optionalAttrs cfg.harden { services.openssh.settings = optionalAttrs cfg.harden {
PermitRootLogin = "no"; PermitRootLogin = "no";
PasswordAuthentication = false; PasswordAuthentication = false;

View File

@@ -0,0 +1,19 @@
{
lib,
config,
outputs,
...
}:
let
hosts = lib.attrNames outputs.nixosConfigurations;
hostsWithKeys = lib.filter (
hostname: builtins.pathExists ../../hosts/${hostname}/ssh_host.pub
) 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";
});
}