{ inputs }: let mkNode = name: hostname: { inherit hostname; sshUser = "deploy"; user = "root"; profiles.system = { path = inputs.deploy-rs.lib.x86_64-linux.activate.nixos inputs.self.nixosConfigurations.${name}; }; }; in { # Path-free ssh options only. The key path and known_hosts are runner-specific # and injected by the deploy.yml via deploy-rs `--ssh-opts` (which appends to # this list for both `nix copy` and the activation SSH). They must be absolute: # the gitea-runner is a systemd DynamicUser whose passwd home is `/`, so ssh # expands `~` to `/.ssh/...` (NOT $HOME) and a tilde here finds no key. The # workflow builds the absolute paths from $HOME, where bash expands correctly. # `-F none` ignores the runner's ~/.ssh/config; IdentitiesOnly pins the key. sshOpts = [ "-F" "none" "-o" "IdentitiesOnly=yes" "-o" "StrictHostKeyChecking=accept-new" ]; autoRollback = true; magicRollback = true; nodes = { # Order matters: the Gitea Actions workflow invokes them in this sequence. # SSH/deploy targets use public hostnames because the Gitea runner is not on # the private network. Host-to-host traffic still uses the 10.0.0.0/8 IPs. # See the host address table in README.md. db-host = mkNode "db-host" "db.gebos.online"; app-host = mkNode "app-host" "app.gebos.online"; mqtt-ingest = mkNode "mqtt-ingest" "ingest.gebos.online"; }; }