feat(extern): ssh home module

This commit is contained in:
arcnmx 2024-04-16 14:04:59 -07:00
parent 66d60c7977
commit b3ecadf461
7 changed files with 276 additions and 2 deletions

21
flake.lock generated
View file

@ -153,6 +153,26 @@
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1713166971,
"narHash": "sha256-t0P/rKlsE5l1O3O2LYtAelLzp7PeoPCSzsIietQ1hSM=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "1c43dcfac48a2d622797f7ab741670fdbcf8f609",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"nix-std": {
"locked": {
"lastModified": 1701658249,
@ -209,6 +229,7 @@
"flake-compat": "flake-compat",
"flake-utils": "flake-utils",
"flakelib": "flakelib",
"home-manager": "home-manager",
"nixpkgs": "nixpkgs",
"sops-nix": "sops-nix",
"std-fl": "std-fl",

View file

@ -39,6 +39,10 @@
utils.follows = "flake-utils";
};
};
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
systemd2mqtt = {
url = "github:arcnmx/systemd2mqtt";
inputs = {

View file

@ -1,7 +1,14 @@
{inputs, ...}: {...}: let
{inputs, ...}: {lib, osConfig, ...}: let
inherit (inputs.self.lib) meta;
inherit (lib.modules) mkIf;
in {
imports = [
meta.modules.extern.misc.args
];
config = {
lib.gensokyo-zone = mkIf (osConfig ? lib.gensokyo-zone) {
os = osConfig.lib.gensokyo-zone;
};
};
}

207
modules/extern/home/ssh.nix vendored Normal file
View file

@ -0,0 +1,207 @@
let
sshHostModule = {
lib,
gensokyo-zone,
osConfig,
homeConfig,
config,
name,
...
}: let
inherit (gensokyo-zone.lib) unmerged coalesce mkAlmostOptionDefault mapListToAttrs;
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf mkMerge mkOptionDefault mkDefault;
inherit (lib.lists) length head elem optional filter unique intersectLists;
inherit (lib.attrsets) filterAttrs mapAttrsToList nameValuePair;
inherit (lib.strings) optionalString;
inherit (osConfig.gensokyo-zone) access;
cfg = gensokyo-zone.ssh.cfg;
system = gensokyo-zone.systems.${config.systemName}.config;
in {
options = with lib.types; {
enable = mkEnableOption "ssh client configuration" // {
default = true;
};
name = mkOption {
type = str;
default = name;
};
systemName = mkOption {
type = str;
};
user = mkOption {
type = nullOr str;
default = cfg.user;
};
networks = mkOption {
type = listOf (nullOr str);
};
hostName = mkOption {
type = nullOr str;
};
extraOptions = mkOption {
type = unmerged.types.attrs;
};
set = {
matchBlocksSettings = mkOption {
type = unmerged.types.attrs;
default = {};
};
};
};
config = {
hostName = mkOptionDefault system.access.hostName;
extraOptions = mkOptionDefault (unmerged.mergeAttrs cfg.extraOptions);
user = mkIf (config.systemName == "u7pro") (mkAlmostOptionDefault "kittywitch");
networks = let
enabledNetworks = filterAttrs (_: net: net.enable) system.network.networks;
networkNames = mapAttrsToList (_: net: net.name) enabledNetworks;
networks' = filter (name: name == null || elem name networkNames) cfg.networks;
fallbackNetwork =
if system.network.networks.local.enable or false && access.local.enable then "local"
else if system.access.global.enable then null
else if system.network.networks.int.enable or false then "int"
else if system.network.networks.local.enable or false then "local"
else null;
networks = map (name: coalesce [ name fallbackNetwork ]) networks';
in mkOptionDefault (unique networks);
set = {
matchBlocksSettings = let
canonNetworkName' = intersectLists config.networks [ null "int" "local" ];
canonNetworkName = if canonNetworkName' != [ ] then head canonNetworkName' else null;
in mapListToAttrs (network: let
name = config.name + optionalString (network != canonNetworkName) "-${network}";
inherit (system.exports.services) sshd;
port = head (
optional (network == null && sshd.ports.global.enable or false) sshd.ports.global.port
++ optional (sshd.ports.public.enable or false) sshd.ports.public.port
++ [ sshd.ports.standard.port ]
);
needsProxy = network == "int" || (network == "local" && !access.local.enable);
in nameValuePair name {
hostname = mkDefault (
if network == null then system.access.fqdn
else system.network.networks.${network}.fqdn
);
user = mkIf (config.user != null) (mkDefault config.user);
port = mkIf (port != 22) (mkDefault port);
proxyJump = mkIf needsProxy (assert config.name != cfg.proxyJump;
mkAlmostOptionDefault cfg.proxyJump
);
identitiesOnly = mkIf (config.systemName == "u7pro") (mkAlmostOptionDefault true);
extraOptions = mkMerge [
(unmerged.mergeAttrs config.extraOptions)
{
HostKeyAlias = mkIf (config.hostName != null && network != null) (mkOptionDefault system.access.fqdn);
}
];
}) config.networks;
};
};
};
sshModule = {
lib,
gensokyo-zone,
osConfig,
homeConfig,
config,
pkgs,
...
}: let
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf mkMerge mkOptionDefault;
inherit (lib.attrsets) mapAttrs mapAttrsToList;
inherit (gensokyo-zone.lib) unmerged;
inherit (osConfig.gensokyo-zone) access;
in {
options = with lib.types; {
enable = mkEnableOption "ssh client configuration";
user = mkOption {
type = nullOr str;
default = null;
};
hosts = mkOption {
type = attrsOf (submoduleWith {
modules = [ sshHostModule ];
specialArgs = {
inherit gensokyo-zone osConfig homeConfig pkgs;
};
});
};
networks = mkOption {
type = listOf (nullOr str);
default = [ null ];
};
proxyJump = mkOption {
type = str;
};
extraOptions = mkOption {
type = unmerged.types.attrs;
default = {};
};
set = {
matchBlocksSettings = mkOption {
type = unmerged.types.attrs;
default = {};
};
};
};
config = {
proxyJump = mkOptionDefault (
if config.hosts.hakurei.enable then config.hosts.hakurei.name
else gensokyo-zone.systems.hakurei.config.access.fqdn
);
networks = mkOptionDefault [
(mkIf access.local.enable "local")
(mkIf access.tail.enabled "tail")
];
hosts = mapAttrs (name: system: let
enabled = system.config.access.online.enable && system.config.exports.services.sshd.enable;
in mkIf enabled {
systemName = mkOptionDefault name;
}) gensokyo-zone.systems;
set = {
matchBlocksSettings = let
mkMatchBlocksHost = host: mkIf host.enable (unmerged.mergeAttrs host.set.matchBlocksSettings);
in mkMerge (
mapAttrsToList (_: mkMatchBlocksHost) config.hosts
);
};
};
};
in {
config,
osConfig,
lib,
gensokyo-zone,
pkgs,
...
}: let
inherit (lib.options) mkOption;
inherit (lib.modules) mkIf;
inherit (gensokyo-zone.lib) unmerged;
cfg = config.gensokyo-zone.ssh;
in {
options.gensokyo-zone.ssh = mkOption {
type = lib.types.submoduleWith {
modules = [sshModule];
specialArgs = {
inherit gensokyo-zone pkgs;
inherit osConfig;
homeConfig = config;
};
};
default = { };
};
config = {
gensokyo-zone.ssh = {
};
programs.ssh = mkIf cfg.enable {
matchBlocks = unmerged.mergeAttrs cfg.set.matchBlocksSettings;
};
lib.gensokyo-zone.ssh = {
inherit cfg sshModule sshHostModule;
};
};
}

View file

@ -2,11 +2,12 @@
extern'test'inputs,
...
}: let
inherit (extern'test'inputs.self) nixosModules;
inherit (extern'test'inputs.self) nixosModules homeModules;
in {
imports = [
nixosModules.default
extern'test'inputs.sops-nix.nixosModules.sops
extern'test'inputs.home-manager.nixosModules.default
];
config = {
@ -42,5 +43,27 @@ in {
sops = {
age.sshKeyPaths = ["/etc/ssh/ssh_host_ed25519_key"];
};
users.users = {
me = {
isNormalUser = true;
};
};
home-manager = {
sharedModules = [
homeModules.default
];
users.me = { config, ... }: {
config = {
home.stateVersion = "23.11";
gensokyo-zone = {
ssh = {
enable = true;
};
};
programs.ssh.enable = true;
};
};
};
};
}

View file

@ -12,6 +12,10 @@ _: {
};
exports = {
services = {
sshd = {
enable = true;
ports.public.enable = false;
};
proxmox.enable = true;
};
};

View file

@ -7,4 +7,12 @@ _: {
address6 = null;
};
};
exports = {
services = {
sshd = {
enable = true;
ports.public.enable = false;
};
};
};
}