feat: automate SSH config ('known_hosts', 'authorized_keys' ...)
This commit is contained in:
@@ -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;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
25
home/modules/ssh.nix
Normal 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
1
home/ssh.pub
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIzP1PjIDb1tN9nhPOK88HYDtTNk9SN9ZpEem2id49Fa h@astyanax
|
||||||
@@ -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" ];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 = {
|
||||||
|
|||||||
1
hosts/astyanax/ssh_host.pub
Normal file
1
hosts/astyanax/ssh_host.pub
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO8+UOyZbvQeHfFfYox3SQi42KJ0S3RZj79iswSsZeFy root@nixos
|
||||||
1
hosts/astyanax/ssh_user.pub
Normal file
1
hosts/astyanax/ssh_user.pub
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIzP1PjIDb1tN9nhPOK88HYDtTNk9SN9ZpEem2id49Fa h@astyanax
|
||||||
@@ -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";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
24
modules/ssh/authorized-keys.nix
Normal file
24
modules/ssh/authorized-keys.nix
Normal 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
|
||||||
|
);
|
||||||
|
}
|
||||||
24
modules/ssh/extract-keys.nix
Normal file
24
modules/ssh/extract-keys.nix
Normal 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
|
||||||
|
'';
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
19
modules/ssh/known-hosts.nix
Normal file
19
modules/ssh/known-hosts.nix
Normal 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";
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user