Add navi deployment module and integrate SSH inventory for remote management

- Introduced a new `navi` module for managing deployments across multiple hosts.
- Enhanced SSH inventory management to support public key application for authorized hosts.
- Configured system deployment builder for seamless integration with Navi.
- Updated various host configurations to enable deployment capabilities and streamline SSH access.
This commit is contained in:
2026-06-04 16:51:30 -03:00
parent 403cf2fde5
commit 2a911b057b
11 changed files with 585 additions and 44 deletions
Generated
+306 -19
View File
@@ -16,6 +16,21 @@
"type": "github" "type": "github"
} }
}, },
"crane": {
"locked": {
"lastModified": 1770169865,
"narHash": "sha256-iPiy13xzDQ9GjpOez+NNIjh/qjl7i4RDf9dF2x5mF9I=",
"owner": "ipetkov",
"repo": "crane",
"rev": "8254ccf3b5b5131890ee073776f2e61c6d1e55d4",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"cursor": { "cursor": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -23,11 +38,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1779537840, "lastModified": 1780452866,
"narHash": "sha256-IS3aolEKgyL0VuMfd/QX2AHvur1YukCTa6eZdxQWe1A=", "narHash": "sha256-Fq5cR/qGYcGwOOZf6sShtM+kljwecgntgcKXnIBrQDE=",
"ref": "refs/heads/main", "ref": "refs/heads/main",
"rev": "8d9c19f98abf47aa4504efa8d2233730b4afed50", "rev": "344f4065e69455adbcdfb4db1cd8d07a73ae7140",
"revCount": 109, "revCount": 114,
"type": "git", "type": "git",
"url": "https://git.chiasson.cloud/Olivier/cursor-nixos-flake" "url": "https://git.chiasson.cloud/Olivier/cursor-nixos-flake"
}, },
@@ -52,6 +67,7 @@
"url": "https://git.chiasson.cloud/Olivier/DDRM" "url": "https://git.chiasson.cloud/Olivier/DDRM"
}, },
"original": { "original": {
"rev": "c3d014f96855e45b53f7391ce19729493887cb96",
"type": "git", "type": "git",
"url": "https://git.chiasson.cloud/Olivier/DDRM" "url": "https://git.chiasson.cloud/Olivier/DDRM"
} }
@@ -76,6 +92,29 @@
"type": "github" "type": "github"
} }
}, },
"disko": {
"inputs": {
"nixpkgs": [
"navi",
"nixos-anywhere",
"nixpkgs"
]
},
"locked": {
"lastModified": 1769524058,
"narHash": "sha256-zygdD6X1PcVNR2PsyK4ptzrVEiAdbMqLos7utrMDEWE=",
"owner": "nix-community",
"repo": "disko",
"rev": "71a3fc97d80881e91710fe721f1158d3b96ae14d",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "master",
"repo": "disko",
"type": "github"
}
},
"dms": { "dms": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -149,6 +188,46 @@
"inputs": { "inputs": {
"nixpkgs-lib": "nixpkgs-lib_2" "nixpkgs-lib": "nixpkgs-lib_2"
}, },
"locked": {
"lastModified": 1769996383,
"narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "57928607ea566b5db3ad13af0e57e921e6b12381",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-parts_3": {
"inputs": {
"nixpkgs-lib": [
"navi",
"nixos-anywhere",
"nixpkgs"
]
},
"locked": {
"lastModified": 1768135262,
"narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-parts_4": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib_3"
},
"locked": { "locked": {
"lastModified": 1778716662, "lastModified": 1778716662,
"narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=", "narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=",
@@ -163,7 +242,7 @@
"type": "github" "type": "github"
} }
}, },
"flake-parts_3": { "flake-parts_5": {
"inputs": { "inputs": {
"nixpkgs-lib": [ "nixpkgs-lib": [
"nur", "nur",
@@ -292,6 +371,50 @@
"type": "github" "type": "github"
} }
}, },
"navi": {
"inputs": {
"crane": "crane",
"flake-parts": "flake-parts_2",
"nix-github-actions": "nix-github-actions",
"nixos-anywhere": "nixos-anywhere",
"nixpkgs": "nixpkgs",
"stable": "stable"
},
"locked": {
"lastModified": 1777283737,
"narHash": "sha256-sVwTOYwxzUUqAEr5kjOZooJ/v8H2hcuZ42f17MgCqX8=",
"owner": "cafkafk",
"repo": "navi",
"rev": "b060683e4ca2bd37a1c3bcb4e04abd2296190e9d",
"type": "github"
},
"original": {
"owner": "cafkafk",
"repo": "navi",
"type": "github"
}
},
"nix-github-actions": {
"inputs": {
"nixpkgs": [
"navi",
"nixpkgs"
]
},
"locked": {
"lastModified": 1729742964,
"narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=",
"owner": "nix-community",
"repo": "nix-github-actions",
"rev": "e04df33f62cdcf93d73e9a04142464753a16db67",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-github-actions",
"type": "github"
}
},
"nix-monitor": { "nix-monitor": {
"locked": { "locked": {
"lastModified": 1771568669, "lastModified": 1771568669,
@@ -307,10 +430,33 @@
"type": "github" "type": "github"
} }
}, },
"nix-vm-test": {
"inputs": {
"nixpkgs": [
"navi",
"nixos-anywhere",
"nixpkgs"
]
},
"locked": {
"lastModified": 1769079217,
"narHash": "sha256-R6qzhu+YJolxE2vUsPQWWwUKMbAG5nXX3pBtg8BNX38=",
"owner": "Enzime",
"repo": "nix-vm-test",
"rev": "58c15f78947b431d6c206e0966500c7e9139bd2f",
"type": "github"
},
"original": {
"owner": "Enzime",
"ref": "pr-105-latest",
"repo": "nix-vm-test",
"type": "github"
}
},
"nixcord": { "nixcord": {
"inputs": { "inputs": {
"flake-compat": "flake-compat", "flake-compat": "flake-compat",
"flake-parts": "flake-parts_2", "flake-parts": "flake-parts_4",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ],
@@ -330,7 +476,62 @@
"type": "github" "type": "github"
} }
}, },
"nixos-anywhere": {
"inputs": {
"disko": "disko",
"flake-parts": "flake-parts_3",
"nix-vm-test": "nix-vm-test",
"nixos-images": "nixos-images",
"nixos-stable": "nixos-stable",
"nixpkgs": [
"navi",
"nixpkgs"
],
"treefmt-nix": "treefmt-nix"
},
"locked": {
"lastModified": 1772874867,
"narHash": "sha256-d79nCSys2aaV6E1tL/H4xEeKJvLFwEeP6yj5q0glbuQ=",
"owner": "cafkafk",
"repo": "nixos-anywhere",
"rev": "b88c2ee9734ce4ec5aa63cf74c2ea58f6f9970ec",
"type": "github"
},
"original": {
"owner": "cafkafk",
"ref": "kexec-ssh-args-bug",
"repo": "nixos-anywhere",
"type": "github"
}
},
"nixos-images": { "nixos-images": {
"inputs": {
"nixos-stable": [
"navi",
"nixos-anywhere",
"nixos-stable"
],
"nixos-unstable": [
"navi",
"nixos-anywhere",
"nixpkgs"
]
},
"locked": {
"lastModified": 1766770015,
"narHash": "sha256-kUmVBU+uBUPl/v3biPiWrk680b8N9rRMhtY97wsxiJc=",
"owner": "nix-community",
"repo": "nixos-images",
"rev": "e4dba54ddb6b2ad9c6550e5baaed2fa27938a5d2",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixos-images",
"type": "github"
}
},
"nixos-images_2": {
"inputs": { "inputs": {
"nixos-stable": [ "nixos-stable": [
"nixos-raspberrypi", "nixos-raspberrypi",
@@ -360,7 +561,7 @@
"inputs": { "inputs": {
"argononed": "argononed", "argononed": "argononed",
"flake-compat": "flake-compat_2", "flake-compat": "flake-compat_2",
"nixos-images": "nixos-images", "nixos-images": "nixos-images_2",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
] ]
@@ -380,17 +581,33 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs": { "nixos-stable": {
"locked": { "locked": {
"lastModified": 1779357205, "lastModified": 1769598131,
"narHash": "sha256-cCO8aTqss5x9Ky8GWkpY0Hy5fyTZEbtifSUV8QjSzic=", "narHash": "sha256-e7VO/kGLgRMbWtpBqdWl0uFg8Y2XWFMdz0uUJvlML8o=",
"owner": "nixos", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "f83fc3c307e74bc5fd5adb7eb6b8b13ffd2a36e1", "rev": "fa83fd837f3098e3e678e6cf017b2b36102c7211",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nixos", "owner": "NixOS",
"ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1750134718,
"narHash": "sha256-v263g4GbxXv87hMXMCpjkIxd/viIF7p3JpJrwgKdNiI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9e83b64f727c88a7711a2c463a7b16eedb69a84c",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable", "ref": "nixos-unstable",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
@@ -412,6 +629,21 @@
} }
}, },
"nixpkgs-lib_2": { "nixpkgs-lib_2": {
"locked": {
"lastModified": 1769909678,
"narHash": "sha256-cBEymOf4/o3FD5AZnzC3J9hLbiZ+QDT/KDuyHXVJOpM=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "72716169fe93074c333e8d0173151350670b824c",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixpkgs.lib",
"type": "github"
}
},
"nixpkgs-lib_3": {
"locked": { "locked": {
"lastModified": 1777168982, "lastModified": 1777168982,
"narHash": "sha256-GOkGPcboWE9BmGCRMLX3worL4EMnsnG8MyKmXNeYuhQ=", "narHash": "sha256-GOkGPcboWE9BmGCRMLX3worL4EMnsnG8MyKmXNeYuhQ=",
@@ -443,6 +675,22 @@
} }
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": {
"lastModified": 1779357205,
"narHash": "sha256-cCO8aTqss5x9Ky8GWkpY0Hy5fyTZEbtifSUV8QjSzic=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "f83fc3c307e74bc5fd5adb7eb6b8b13ffd2a36e1",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": { "locked": {
"lastModified": 1778869304, "lastModified": 1778869304,
"narHash": "sha256-30sZNZoA1cqF5JNO9fVX+wgiQYjB7HJqqJ4ztCDeBZE=", "narHash": "sha256-30sZNZoA1cqF5JNO9fVX+wgiQYjB7HJqqJ4ztCDeBZE=",
@@ -460,7 +708,7 @@
}, },
"nur": { "nur": {
"inputs": { "inputs": {
"flake-parts": "flake-parts_3", "flake-parts": "flake-parts_5",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
] ]
@@ -556,10 +804,11 @@
"home-manager": "home-manager", "home-manager": "home-manager",
"import-tree": "import-tree", "import-tree": "import-tree",
"mobile-nixos": "mobile-nixos", "mobile-nixos": "mobile-nixos",
"navi": "navi",
"nix-monitor": "nix-monitor", "nix-monitor": "nix-monitor",
"nixcord": "nixcord", "nixcord": "nixcord",
"nixos-raspberrypi": "nixos-raspberrypi", "nixos-raspberrypi": "nixos-raspberrypi",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs_2",
"nur": "nur", "nur": "nur",
"oom-hardware": "oom-hardware", "oom-hardware": "oom-hardware",
"personal-website": "personal-website", "personal-website": "personal-website",
@@ -614,6 +863,22 @@
"type": "github" "type": "github"
} }
}, },
"stable": {
"locked": {
"lastModified": 1750133334,
"narHash": "sha256-urV51uWH7fVnhIvsZIELIYalMYsyr2FCalvlRTzqWRw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "36ab78dab7da2e4e27911007033713bab534187b",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.05",
"repo": "nixpkgs",
"type": "github"
}
},
"swiftshare": { "swiftshare": {
"inputs": { "inputs": {
"flake-utils": "flake-utils_2", "flake-utils": "flake-utils_2",
@@ -703,11 +968,11 @@
"t2linux-patches": { "t2linux-patches": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1779369552, "lastModified": 1779914035,
"narHash": "sha256-vDcWjgjhYAQcXZH40QN17ZV9BS0zqZeme9APXBqjlHs=", "narHash": "sha256-VsHuI2CbQ8gFplW+51gUJvCqo1Ts10Ueks9aTtkAOiw=",
"owner": "t2linux", "owner": "t2linux",
"repo": "linux-t2-patches", "repo": "linux-t2-patches",
"rev": "716093d3244566cd708362661de269ab7e67ff0f", "rev": "7ee7d19c38e5df31a386b2a0c35ca8f064003960",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -716,6 +981,28 @@
"type": "github" "type": "github"
} }
}, },
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"navi",
"nixos-anywhere",
"nixpkgs"
]
},
"locked": {
"lastModified": 1769691507,
"narHash": "sha256-8aAYwyVzSSwIhP2glDhw/G0i5+wOrren3v6WmxkVonM=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "28b19c5844cc6e2257801d43f2772a4b4c050a1b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
},
"wallpapers": { "wallpapers": {
"flake": false, "flake": false,
"locked": { "locked": {
@@ -734,7 +1021,7 @@
}, },
"wrapper-modules": { "wrapper-modules": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs_2" "nixpkgs": "nixpkgs_3"
}, },
"locked": { "locked": {
"lastModified": 1779297405, "lastModified": 1779297405,
+2
View File
@@ -103,6 +103,8 @@
url = "git+https://git.chiasson.cloud/Olivier/DDRM?rev=c3d014f96855e45b53f7391ce19729493887cb96"; url = "git+https://git.chiasson.cloud/Olivier/DDRM?rev=c3d014f96855e45b53f7391ce19729493887cb96";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
navi.url = "github:cafkafk/navi";
}; };
outputs = inputs: outputs = inputs:
+149
View File
@@ -0,0 +1,149 @@
{
inputs,
self,
lib,
...
}:
let
ssh = self.lib.sshInventory;
# Remote deploy identity (see `nixosModules.systemDeployBuilder`).
defaultTargetUser = _: "builder";
hostSpecs = {
"14900k" = {
configuration = self.nixosModules."14900kConfiguration";
system = "x86_64-linux";
specialArgs = {
inherit self inputs;
host = "14900k";
system = "x86_64-linux";
};
};
ideapad = {
configuration = self.nixosModules.ideapadConfiguration;
system = "aarch64-linux";
specialArgs = {
inherit self inputs;
host = "ideapad";
system = "aarch64-linux";
};
};
t2mbp = {
configuration = self.nixosModules.t2mbpConfiguration;
system = "x86_64-linux";
specialArgs = {
inherit self inputs;
host = "t2mbp";
system = "x86_64-linux";
};
};
uConsole = {
modules = [
inputs.nixos-raspberrypi.nixosModules.raspberry-pi-5.base
inputs.oom-hardware.nixosModules.uc.kernel
inputs.oom-hardware.nixosModules.uc.configtxt
inputs.oom-hardware.nixosModules.uc.base-cm5
self.nixosModules.uConsoleConfiguration
];
system = "aarch64-linux";
specialArgs = inputs // {
inherit self;
inputs = inputs;
host = "uConsole";
system = "aarch64-linux";
};
};
nix-server = {
configuration = self.nixosModules.nix-serverConfiguration;
system = "x86_64-linux";
specialArgs = {
inherit self inputs;
host = "nix-server";
system = "x86_64-linux";
};
};
r5500 = {
configuration = self.nixosModules.r5500Configuration;
system = "x86_64-linux";
specialArgs = {
inherit self inputs;
host = "r5500";
system = "x86_64-linux";
};
};
};
deployments = lib.mapAttrs (
name: entry:
{
targetHost = entry.hostName;
targetUser = defaultTargetUser name;
tags =
[ name ]
++ lib.optionals (name == "nix-server") [ "server" ]
++ lib.optionals (lib.elem name [
"ideapad"
"uConsole"
]) [ "aarch64" ];
}
// lib.optionalAttrs (name == "14900k") {
allowLocalDeployment = true;
}
// lib.optionalAttrs (name == "nix-server") {
targetPort = 22;
}
) ssh.activeHosts;
metaNixpkgs = import inputs.nixpkgs {
system = "x86_64-linux";
};
in
{
flake.navi = self.lib.mkNaviHiveConfig {
inherit metaNixpkgs hostSpecs deployments;
};
flake.naviHive = inputs.navi.lib.makeHive self.outputs.navi;
perSystem =
{
pkgs,
system,
...
}:
lib.optionalAttrs (lib.elem system [
"x86_64-linux"
"aarch64-linux"
]) {
devShells.default = pkgs.mkShell {
packages = [ inputs.navi.packages.${system}.default ];
shellHook = ''
echo "Navi fleet deploy (from repo root):"
echo " navi apply --on <host> # build + switch one host"
echo " navi apply-local --node 14900k --sudo # switch this machine locally (needs root), --node if hostname differs"
echo " navi tui # interactive fleet dashboard"
'';
};
apps = {
navi = {
type = "app";
program = lib.getExe inputs.navi.packages.${system}.default;
};
navi-tui = {
type = "app";
program =
toString (
pkgs.writeShellApplication {
name = "navi-tui";
runtimeInputs = [ inputs.navi.packages.${system}.default ];
text = ''
exec navi tui "$@"
'';
}
);
};
};
};
}
+6 -1
View File
@@ -1,7 +1,12 @@
{ self, ... }: { { self, ... }: {
#TODO[epic=Moderate] Move this somewhere else, would prefer not relying on this module #TODO[epic=Moderate] Move this somewhere else, would prefer not relying on this module
flake.nixosModules."client-services" = { ... }: { flake.nixosModules."client-services" = { ... }: {
imports = [ self.nixosModules.systemBluetooth ]; imports = [
self.nixosModules.systemBluetooth
self.nixosModules.systemDeployBuilder
];
chiasson.system.deploy.builder.enable = true;
# Lab-ish SSH defaults on clients — tighten for anything exposed. # Lab-ish SSH defaults on clients — tighten for anything exposed.
services.openssh = { services.openssh = {
@@ -10,6 +10,7 @@
{ {
imports = [ imports = [
inputs.ddrm.nixosModules.default inputs.ddrm.nixosModules.default
self.nixosModules.systemDeployBuilder
self.nixosModules.nix-serverHardware self.nixosModules.nix-serverHardware
inputs.sops-nix.nixosModules.sops inputs.sops-nix.nixosModules.sops
self.nixosModules.system self.nixosModules.system
@@ -83,6 +84,8 @@
extraPackages = with pkgs; [ btop ]; extraPackages = with pkgs; [ btop ];
}; };
chiasson.system.deploy.builder.enable = true;
chiasson.users = { chiasson.users = {
enabled = [ "server" ]; enabled = [ "server" ];
hostOverrides.server = { hostOverrides.server = {
+3
View File
@@ -9,6 +9,7 @@
}: }:
{ {
imports = [ imports = [
self.nixosModules.systemDeployBuilder
self.nixosModules.r5500Hardware self.nixosModules.r5500Hardware
inputs.sops-nix.nixosModules.sops inputs.sops-nix.nixosModules.sops
self.nixosModules.system self.nixosModules.system
@@ -55,6 +56,8 @@
extraPackages = with pkgs; [ btop git ]; extraPackages = with pkgs; [ btop git ];
}; };
chiasson.system.deploy.builder.enable = true;
chiasson.users = { chiasson.users = {
enabled = [ "server" ]; enabled = [ "server" ];
hostOverrides.server = { hostOverrides.server = {
+33
View File
@@ -0,0 +1,33 @@
# Build a raw Navi hive attrset from host specs + deployment targets.
# Call `inputs.navi.lib.makeHive` on the result to produce `flake.naviHive`.
{ lib, inputs, ... }: {
flake.lib.mkNaviHiveConfig =
{
metaNixpkgs,
hostSpecs,
deployments,
}:
let
deployNodes = lib.filterAttrs (name: _: deployments ? ${name}) hostSpecs;
in
{
meta = {
nixpkgs = metaNixpkgs;
nodeNixpkgs = lib.mapAttrs (
name: spec:
import inputs.nixpkgs {
system = spec.system;
}
) deployNodes;
nodeSpecialArgs = lib.mapAttrs (_: spec: spec.specialArgs) deployNodes;
allowApplyAll = false;
};
}
// lib.mapAttrs (
name: spec:
{
imports = spec.modules or [ spec.configuration ];
deployment = deployments.${name};
}
) deployNodes;
}
+16 -4
View File
@@ -60,10 +60,17 @@
(builtins.attrNames selectedHosts) (builtins.attrNames selectedHosts)
); );
# Must come before inventory `Host` blocks and before `Host *`: LAN Gitea SSH is not a catalog PC, # Gitea git-over-SSH listens on port 222. System SSH (nix deploy, server@…) uses port 22
# and `Host *` sets `IdentityAgent none` — without this, git@nix-server never sees rbw keys. # via the catalog `nix-server` Host block — never list nix-server or 192.168.2.238 here.
giteaSshBlock = identityAgent: '' giteaSshBlock = identityAgent: ''
Host git.chiasson.cloud gitea nix-server 192.168.2.238 Host git.chiasson.cloud gitea
HostName 192.168.2.238
Port 222
User git
IdentityAgent ${identityAgent}
IdentitiesOnly no
Match host nix-server,192.168.2.238 user git
HostName 192.168.2.238 HostName 192.168.2.238
Port 222 Port 222
User git User git
@@ -84,11 +91,16 @@
entry = selectedHosts.${hostName}; entry = selectedHosts.${hostName};
hostPatterns = builtins.concatStringsSep " " (entry.aliases ++ [ entry.hostName ]); hostPatterns = builtins.concatStringsSep " " (entry.aliases ++ [ entry.hostName ]);
userLine = if user == null then "" else " User ${user}\n"; userLine = if user == null then "" else " User ${user}\n";
portLine =
if hostName == "nix-server" then
" Port 22\n"
else
"";
in in
'' ''
Host ${hostPatterns} Host ${hostPatterns}
HostName ${entry.hostName} HostName ${entry.hostName}
${userLine} IdentityFile ~/${mkIdentityFileName hostName} ${userLine}${portLine} IdentityFile ~/${mkIdentityFileName hostName}
IdentityAgent ${identityAgent} IdentityAgent ${identityAgent}
IdentitiesOnly yes IdentitiesOnly yes
'') '')
+4 -20
View File
@@ -7,26 +7,10 @@
let let
cfg = config.chiasson.ssh.inbound; cfg = config.chiasson.ssh.inbound;
inventory = self.lib.sshInventory; inventory = self.lib.sshInventory;
resolveSelection =
selection:
if selection == "all" then
inventory.authorizedKeys
else
let
missing = builtins.filter (name: !(builtins.hasAttr name inventory.hosts)) selection;
in
if missing != [ ] then
throw "ssh.inbound: unknown host keys: ${builtins.concatStringsSep ", " missing}"
else
lib.unique (
builtins.filter (key: key != null) (
builtins.map (hostName: inventory.hosts.${hostName}.publicKey) selection
)
);
in in
{ {
options.chiasson.ssh.inbound = { options.chiasson.ssh.inbound = {
enable = lib.mkEnableOption "Apply `authorizedKeys` from the SSH inventory."; enable = lib.mkEnableOption "Apply SSH inventory public keys to `authorized_keys`.";
userAuthorizedHosts = lib.mkOption { userAuthorizedHosts = lib.mkOption {
type = lib.types.attrsOf (lib.types.either (lib.types.enum [ "all" ]) (lib.types.listOf lib.types.str)); type = lib.types.attrsOf (lib.types.either (lib.types.enum [ "all" ]) (lib.types.listOf lib.types.str));
default = { }; default = { };
@@ -35,15 +19,15 @@
admin = [ "14900k" "t2mbp" ]; admin = [ "14900k" "t2mbp" ];
}; };
description = '' description = ''
Per user: `"all"` or a list of inventory host names whose keys land in `authorized_keys`. Catalog users that receive the SSH inventory public keys in `authorized_keys`.
''; '';
}; };
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
users.users = lib.mapAttrs users.users = lib.mapAttrs
(_user: selection: { (_user: _selection: {
openssh.authorizedKeys.keys = resolveSelection selection; openssh.authorizedKeys.keys = inventory.authorizedKeys;
}) })
cfg.userAuthorizedHosts; cfg.userAuthorizedHosts;
}; };
+49
View File
@@ -0,0 +1,49 @@
# Navi / remote-deploy identity: push closures + activate system profiles over SSH.
{ ... }: {
flake.nixosModules.systemDeployBuilder =
{ config, lib, pkgs, ... }:
let
cfg = config.chiasson.system.deploy.builder;
in
{
options.chiasson.system.deploy.builder = {
enable = lib.mkEnableOption ''
Fleet deploy user for Navi (and similar tools).
Creates the `builder` catalog user, trusts it with the Nix daemon for
`nix copy`, and grants passwordless sudo for non-interactive activation.
SSH inbound is limited to the deploy machine key (see catalog `builder.ssh`).
'';
};
config = lib.mkIf cfg.enable {
chiasson.users.enabled = lib.mkAfter [ "builder" ];
users.users.builder = {
password = "!";
# nix copy / navi push opens an SSH session; nologin breaks the store protocol.
shell = pkgs.bash;
};
nix.settings.trusted-users = lib.mkAfter [ "builder" ];
# Navi wraps remote steps in `sudo -H --` (nix-env, switch-to-configuration,
# provenance under /etc/navi, readlink, …). Scoped store-path rules are fragile;
# this account has no wheel; SSH/key-only in practice (password locked).
security.sudo.extraRules = [
{
users = [ "builder" ];
commands = [
{
command = "ALL";
options = [
"NOPASSWD"
"SETENV"
];
}
];
}
];
};
};
}
+14
View File
@@ -77,6 +77,20 @@
}; };
}; };
}; };
builder = {
isNormalUser = true;
description = "Navi fleet deploy (push + activate only)";
extraGroups = [ ];
createHome = false;
homeManager = {
enable = false;
module = null;
};
ssh.inbound.enable = true;
};
}; };
}; };
} }