From e2e87d56946c92f379693ca7e81a20fdc5b1204a Mon Sep 17 00:00:00 2001 From: steffen Date: Sat, 14 Mar 2026 14:33:06 +0100 Subject: [PATCH 1/5] switch CI deploy to local nixos-rebuild instead of deploy-rs over SSH Runner runs on the same server it deploys to, so SSH to itself was unnecessarily complex. Now builds locally and activates directly. - Replace deploy-rs SSH workflow with local build + switch - Add NOPASSWD sudo for gitea-runner to run nix-env and switch-to-configuration (required for local deployment) - Remove SSH key setup from deploy workflow --- .forgejo/workflows/deploy.yml | 15 ++++----------- modules/nixos/forgejo-runner/default.nix | 6 ++++++ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml index a08e312..ac98e74 100644 --- a/.forgejo/workflows/deploy.yml +++ b/.forgejo/workflows/deploy.yml @@ -22,18 +22,11 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Set up SSH - env: - DEPLOY_KEY: ${{ secrets.DEPLOY_SSH_KEY }} - run: | - mkdir -p ~/.ssh - echo "$DEPLOY_KEY" > ~/.ssh/id_ed25519 - chmod 600 ~/.ssh/id_ed25519 - ssh-keyscan -p 2299 -H cryodev.xyz >> ~/.ssh/known_hosts - chmod 644 ~/.ssh/known_hosts + - name: Build system configuration + run: nix build .#nixosConfigurations.cryodev-main.config.system.build.toplevel --out-link result - - name: Deploy with deploy-rs - run: NIX_SSHOPTS="-p 2299 -o StrictHostKeyChecking=accept-new" nix run github:serokell/deploy-rs -- -s .#cryodev-main + - name: Deploy locally + run: sudo nix-env -p /nix/var/nix/profiles/system --set $(readlink -f result) && sudo result/bin/switch-to-configuration switch build-pi-images: needs: flake-check diff --git a/modules/nixos/forgejo-runner/default.nix b/modules/nixos/forgejo-runner/default.nix index 2547f0e..d61e9a9 100644 --- a/modules/nixos/forgejo-runner/default.nix +++ b/modules/nixos/forgejo-runner/default.nix @@ -31,6 +31,12 @@ in config = mkIf cfg.enable { nix.settings.trusted-users = [ "gitea-runner" ]; + # Allow gitea-runner to deploy system configurations without password + security.sudo.extraConfig = '' + gitea-runner ALL=(root) NOPASSWD: /run/current-system/sw/bin/nix-env -p /nix/var/nix/profiles/system --set * + gitea-runner ALL=(root) NOPASSWD: /nix/store/*/bin/switch-to-configuration * + ''; + services.gitea-actions-runner = { package = pkgs.forgejo-runner; instances.default = { From ed806bf5fb1900e951238b90043f46864b86e96d Mon Sep 17 00:00:00 2001 From: steffen Date: Sat, 14 Mar 2026 14:35:56 +0100 Subject: [PATCH 2/5] fix CI deploy: use global SSH config for deploy-rs The nix-daemon runs as root and cannot access the gitea-runner user's ~/.ssh directory. Solution: write the deploy key and SSH config to /etc/deploy/ and /etc/ssh/ssh_config.d/ which are readable by all users including the nix-daemon. - Deploy key is written to /etc/deploy/key (cleaned up after deploy) - SSH config in /etc/ssh/ssh_config.d/deploy.conf (cleaned up after) - Minimal NOPASSWD sudo rules for gitea-runner to manage these files - Reverts local deploy approach, back to deploy-rs over SSH --- .forgejo/workflows/deploy.yml | 28 ++++++++++++++++++++---- modules/nixos/forgejo-runner/default.nix | 9 +++++--- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml index ac98e74..a78eb0c 100644 --- a/.forgejo/workflows/deploy.yml +++ b/.forgejo/workflows/deploy.yml @@ -22,11 +22,31 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Build system configuration - run: nix build .#nixosConfigurations.cryodev-main.config.system.build.toplevel --out-link result + - name: Set up SSH + env: + DEPLOY_KEY: ${{ secrets.DEPLOY_SSH_KEY }} + run: | + # Write key to a shared location readable by nix-daemon + sudo mkdir -p /etc/deploy + echo "$DEPLOY_KEY" | sudo tee /etc/deploy/key > /dev/null + sudo chmod 600 /etc/deploy/key - - name: Deploy locally - run: sudo nix-env -p /nix/var/nix/profiles/system --set $(readlink -f result) && sudo result/bin/switch-to-configuration switch + # Global SSH config so both the runner and nix-daemon can use it + sudo tee /etc/ssh/ssh_config.d/deploy.conf > /dev/null << 'EOF' + Host cryodev.xyz + Port 2299 + User root + IdentityFile /etc/deploy/key + StrictHostKeyChecking accept-new + EOF + + - name: Deploy with deploy-rs + run: nix run github:serokell/deploy-rs -- -s .#cryodev-main + + - name: Clean up SSH + if: always() + run: | + sudo rm -f /etc/deploy/key /etc/ssh/ssh_config.d/deploy.conf build-pi-images: needs: flake-check diff --git a/modules/nixos/forgejo-runner/default.nix b/modules/nixos/forgejo-runner/default.nix index d61e9a9..a4f77ba 100644 --- a/modules/nixos/forgejo-runner/default.nix +++ b/modules/nixos/forgejo-runner/default.nix @@ -31,10 +31,13 @@ in config = mkIf cfg.enable { nix.settings.trusted-users = [ "gitea-runner" ]; - # Allow gitea-runner to deploy system configurations without password + # Allow gitea-runner to manage deploy keys and SSH config for CI/CD security.sudo.extraConfig = '' - gitea-runner ALL=(root) NOPASSWD: /run/current-system/sw/bin/nix-env -p /nix/var/nix/profiles/system --set * - gitea-runner ALL=(root) NOPASSWD: /nix/store/*/bin/switch-to-configuration * + gitea-runner ALL=(root) NOPASSWD: /run/current-system/sw/bin/tee /etc/deploy/key + gitea-runner ALL=(root) NOPASSWD: /run/current-system/sw/bin/tee /etc/ssh/ssh_config.d/deploy.conf + gitea-runner ALL=(root) NOPASSWD: /run/current-system/sw/bin/mkdir -p /etc/deploy + gitea-runner ALL=(root) NOPASSWD: /run/current-system/sw/bin/chmod 600 /etc/deploy/key + gitea-runner ALL=(root) NOPASSWD: /run/current-system/sw/bin/rm -f /etc/deploy/key /etc/ssh/ssh_config.d/deploy.conf ''; services.gitea-actions-runner = { From c45a603d1c26e3d723b31e47205b8d8cba49e8ed Mon Sep 17 00:00:00 2001 From: steffen Date: Sat, 14 Mar 2026 14:43:15 +0100 Subject: [PATCH 3/5] replace deploy-rs CI with Comin pull-based deployment - Add Comin service for cryodev-main (polls git repo, auto-deploys) - Fix cryodev-pi Comin URL (cryodev-server.git -> cryodev.git) - Remove deploy-rs from CI pipeline (was insecure with shared runner) - Remove deploy SSH key, root SSH login, sudo rules for gitea-runner - Revert PermitRootLogin back to 'no' - CI now only runs flake-check + build (no deploy) - Deployment happens via Comin (both hosts poll and self-deploy) --- .forgejo/workflows/deploy.yml | 30 ++++-------------------- .gitignore | 1 + flake.nix | 2 -- hosts/cryodev-main/deploy-key.pub | 1 - hosts/cryodev-main/services/comin.nix | 24 +++++++++++++++++++ hosts/cryodev-main/services/default.nix | 10 ++++---- hosts/cryodev-main/services/openssh.nix | 5 ---- hosts/cryodev-pi/services/comin.nix | 2 +- modules/nixos/forgejo-runner/default.nix | 9 ------- modules/nixos/openssh/default.nix | 2 +- sid.ovh | 1 + 11 files changed, 37 insertions(+), 50 deletions(-) delete mode 100644 hosts/cryodev-main/deploy-key.pub create mode 100644 hosts/cryodev-main/services/comin.nix create mode 160000 sid.ovh diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml index a78eb0c..d69d66e 100644 --- a/.forgejo/workflows/deploy.yml +++ b/.forgejo/workflows/deploy.yml @@ -15,38 +15,18 @@ jobs: - name: Run flake check run: nix flake check --impure - deploy-cryodev-main: + build-hosts: needs: flake-check runs-on: host steps: - name: Checkout repository uses: actions/checkout@v4 - - name: Set up SSH - env: - DEPLOY_KEY: ${{ secrets.DEPLOY_SSH_KEY }} - run: | - # Write key to a shared location readable by nix-daemon - sudo mkdir -p /etc/deploy - echo "$DEPLOY_KEY" | sudo tee /etc/deploy/key > /dev/null - sudo chmod 600 /etc/deploy/key + - name: Build cryodev-main + run: nix build .#nixosConfigurations.cryodev-main.config.system.build.toplevel --impure - # Global SSH config so both the runner and nix-daemon can use it - sudo tee /etc/ssh/ssh_config.d/deploy.conf > /dev/null << 'EOF' - Host cryodev.xyz - Port 2299 - User root - IdentityFile /etc/deploy/key - StrictHostKeyChecking accept-new - EOF - - - name: Deploy with deploy-rs - run: nix run github:serokell/deploy-rs -- -s .#cryodev-main - - - name: Clean up SSH - if: always() - run: | - sudo rm -f /etc/deploy/key /etc/ssh/ssh_config.d/deploy.conf + - name: Build cryodev-pi + run: nix build .#nixosConfigurations.cryodev-pi.config.system.build.toplevel --impure build-pi-images: needs: flake-check diff --git a/.gitignore b/.gitignore index 750baeb..e6fb7da 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ result result-* +sid.ovh diff --git a/flake.nix b/flake.nix index 597bd18..d55310f 100644 --- a/flake.nix +++ b/flake.nix @@ -127,8 +127,6 @@ sshOpts = [ "-p" "2299" - "-o" - "StrictHostKeyChecking=accept-new" ]; profiles.system = { user = "root"; diff --git a/hosts/cryodev-main/deploy-key.pub b/hosts/cryodev-main/deploy-key.pub deleted file mode 100644 index b4e3f23..0000000 --- a/hosts/cryodev-main/deploy-key.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFIPGMqOV+YrGle8X7/hctW4Sha/bzeTsTP9AcDN9bA2 forgejo-deploy diff --git a/hosts/cryodev-main/services/comin.nix b/hosts/cryodev-main/services/comin.nix new file mode 100644 index 0000000..35ab81f --- /dev/null +++ b/hosts/cryodev-main/services/comin.nix @@ -0,0 +1,24 @@ +{ + config, + pkgs, + outputs, + constants, + ... +}: + +{ + imports = [ + outputs.nixosModules.comin + ]; + + services.comin = { + enable = true; + remotes = [ + { + name = "origin"; + url = "https://${constants.services.forgejo.fqdn}/steffen/cryodev.git"; + branches.main.name = "main"; + } + ]; + }; +} diff --git a/hosts/cryodev-main/services/default.nix b/hosts/cryodev-main/services/default.nix index 4b447cd..a7e03dc 100644 --- a/hosts/cryodev-main/services/default.nix +++ b/hosts/cryodev-main/services/default.nix @@ -1,17 +1,15 @@ { imports = [ - # Stufe 1: Services ohne externe Abhaengigkeiten + ./comin.nix ./forgejo.nix + ./forgejo-runner.nix + ./headplane.nix ./headscale.nix ./mailserver.nix ./netdata.nix ./nginx.nix ./openssh.nix ./sops.nix - - # Stufe 2: Erst aktivieren wenn Headscale/Forgejo laufen und echte Secrets existieren - ./forgejo-runner.nix # braucht: forgejo-runner/token (Forgejo) - ./headplane.nix # braucht: headplane/agent_pre_authkey (Headscale) - ./tailscale.nix # braucht: tailscale/auth-key (Headscale) + ./tailscale.nix ]; } diff --git a/hosts/cryodev-main/services/openssh.nix b/hosts/cryodev-main/services/openssh.nix index db9a56a..f71c084 100644 --- a/hosts/cryodev-main/services/openssh.nix +++ b/hosts/cryodev-main/services/openssh.nix @@ -9,9 +9,4 @@ ]; services.openssh.enable = true; - - # Root SSH key for deploy-rs (key-only, no password) - users.users.root.openssh.authorizedKeys.keyFiles = [ - ../deploy-key.pub - ]; } diff --git a/hosts/cryodev-pi/services/comin.nix b/hosts/cryodev-pi/services/comin.nix index 2317b06..35ab81f 100644 --- a/hosts/cryodev-pi/services/comin.nix +++ b/hosts/cryodev-pi/services/comin.nix @@ -16,7 +16,7 @@ remotes = [ { name = "origin"; - url = "https://${constants.services.forgejo.fqdn}/steffen/cryodev-server.git"; + url = "https://${constants.services.forgejo.fqdn}/steffen/cryodev.git"; branches.main.name = "main"; } ]; diff --git a/modules/nixos/forgejo-runner/default.nix b/modules/nixos/forgejo-runner/default.nix index a4f77ba..2547f0e 100644 --- a/modules/nixos/forgejo-runner/default.nix +++ b/modules/nixos/forgejo-runner/default.nix @@ -31,15 +31,6 @@ in config = mkIf cfg.enable { nix.settings.trusted-users = [ "gitea-runner" ]; - # Allow gitea-runner to manage deploy keys and SSH config for CI/CD - security.sudo.extraConfig = '' - gitea-runner ALL=(root) NOPASSWD: /run/current-system/sw/bin/tee /etc/deploy/key - gitea-runner ALL=(root) NOPASSWD: /run/current-system/sw/bin/tee /etc/ssh/ssh_config.d/deploy.conf - gitea-runner ALL=(root) NOPASSWD: /run/current-system/sw/bin/mkdir -p /etc/deploy - gitea-runner ALL=(root) NOPASSWD: /run/current-system/sw/bin/chmod 600 /etc/deploy/key - gitea-runner ALL=(root) NOPASSWD: /run/current-system/sw/bin/rm -f /etc/deploy/key /etc/ssh/ssh_config.d/deploy.conf - ''; - services.gitea-actions-runner = { package = pkgs.forgejo-runner; instances.default = { diff --git a/modules/nixos/openssh/default.nix b/modules/nixos/openssh/default.nix index 00f05c1..0958445 100644 --- a/modules/nixos/openssh/default.nix +++ b/modules/nixos/openssh/default.nix @@ -9,7 +9,7 @@ in ports = mkDefault [ 2299 ]; openFirewall = mkDefault true; settings = { - PermitRootLogin = mkDefault "prohibit-password"; + PermitRootLogin = mkDefault "no"; PasswordAuthentication = mkDefault false; }; }; diff --git a/sid.ovh b/sid.ovh new file mode 160000 index 0000000..197c824 --- /dev/null +++ b/sid.ovh @@ -0,0 +1 @@ +Subproject commit 197c8246234c1237b251d51d1bd54bcc9c1ba1d4 From e9a5af27e95c4ab80b3e8854e013c16561ac9b46 Mon Sep 17 00:00:00 2001 From: steffen Date: Sat, 14 Mar 2026 14:44:44 +0100 Subject: [PATCH 4/5] remove sid.ovh and clean up gitignore --- .gitignore | 1 - sid.ovh | 1 - 2 files changed, 2 deletions(-) delete mode 160000 sid.ovh diff --git a/.gitignore b/.gitignore index e6fb7da..750baeb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ result result-* -sid.ovh diff --git a/sid.ovh b/sid.ovh deleted file mode 160000 index 197c824..0000000 --- a/sid.ovh +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 197c8246234c1237b251d51d1bd54bcc9c1ba1d4 From a4dfbdcd5225429ed64689f281ca6a3601bfaa08 Mon Sep 17 00:00:00 2001 From: steffen Date: Sat, 14 Mar 2026 14:47:49 +0100 Subject: [PATCH 5/5] remove deploy-rs completely - Remove deploy-rs flake input - Remove deploy block from flake.nix - Remove deployChecks from flake checks - Remove deploy-rs from forgejo-runner hostPackages - Deployment is now handled by Comin (auto) and nix run .#deploy (manual) --- flake.lock | 84 ++---------------------- flake.nix | 22 ------- modules/nixos/forgejo-runner/default.nix | 1 - 3 files changed, 6 insertions(+), 101 deletions(-) diff --git a/flake.lock b/flake.lock index 5c8265f..3342164 100644 --- a/flake.lock +++ b/flake.lock @@ -38,28 +38,6 @@ "type": "github" } }, - "deploy-rs": { - "inputs": { - "flake-compat": "flake-compat_2", - "nixpkgs": [ - "nixpkgs" - ], - "utils": "utils" - }, - "locked": { - "lastModified": 1770019181, - "narHash": "sha256-hwsYgDnby50JNVpTRYlF3UR/Rrpt01OrxVuryF40CFY=", - "owner": "serokell", - "repo": "deploy-rs", - "rev": "77c906c0ba56aabdbc72041bf9111b565cdd6171", - "type": "github" - }, - "original": { - "owner": "serokell", - "repo": "deploy-rs", - "type": "github" - } - }, "devshell": { "inputs": { "nixpkgs": [ @@ -98,22 +76,6 @@ } }, "flake-compat_2": { - "flake": false, - "locked": { - "lastModified": 1733328505, - "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-compat_3": { "flake": false, "locked": { "lastModified": 1767039857, @@ -129,7 +91,7 @@ "type": "github" } }, - "flake-compat_4": { + "flake-compat_3": { "flake": false, "locked": { "lastModified": 1767039857, @@ -168,7 +130,7 @@ }, "flake-utils": { "inputs": { - "systems": "systems_2" + "systems": "systems" }, "locked": { "lastModified": 1731533236, @@ -186,7 +148,7 @@ }, "flake-utils_2": { "inputs": { - "systems": "systems_3" + "systems": "systems_2" }, "locked": { "lastModified": 1731533236, @@ -204,7 +166,7 @@ }, "git-hooks": { "inputs": { - "flake-compat": "flake-compat_3", + "flake-compat": "flake-compat_2", "gitignore": "gitignore", "nixpkgs": [ "nixpkgs" @@ -344,7 +306,7 @@ "nixos-mailserver": { "inputs": { "blobs": "blobs", - "flake-compat": "flake-compat_4", + "flake-compat": "flake-compat_3", "git-hooks": "git-hooks_2", "nixpkgs": [ "nixpkgs" @@ -451,7 +413,7 @@ "nixpkgs" ], "nuschtosSearch": "nuschtosSearch", - "systems": "systems_4" + "systems": "systems_3" }, "locked": { "lastModified": 1769049374, @@ -494,7 +456,6 @@ "root": { "inputs": { "comin": "comin", - "deploy-rs": "deploy-rs", "git-hooks": "git-hooks", "headplane": "headplane", "nixos-mailserver": "nixos-mailserver", @@ -570,21 +531,6 @@ "type": "github" } }, - "systems_4": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, "treefmt-nix": { "inputs": { "nixpkgs": "nixpkgs" @@ -602,24 +548,6 @@ "repo": "treefmt-nix", "type": "github" } - }, - "utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index d55310f..f157f22 100644 --- a/flake.nix +++ b/flake.nix @@ -15,9 +15,6 @@ comin.url = "github:nlewo/comin"; comin.inputs.nixpkgs.follows = "nixpkgs"; - deploy-rs.url = "github:serokell/deploy-rs"; - deploy-rs.inputs.nixpkgs.follows = "nixpkgs"; - nixvim.url = "github:nix-community/nixvim/nixos-25.11"; nixvim.inputs.nixpkgs.follows = "nixpkgs"; @@ -119,23 +116,6 @@ pkgs.writeShellScriptBin "pre-commit-run" script ); - deploy = { - nodes = { - cryodev-main = { - hostname = constants.domain; - sshUser = "root"; - sshOpts = [ - "-p" - "2299" - ]; - profiles.system = { - user = "root"; - path = inputs.deploy-rs.lib.x86_64-linux.activate.nixos self.nixosConfigurations.cryodev-main; - }; - }; - }; - }; - checks = forAllSystems ( system: let @@ -145,7 +125,6 @@ inherit system; overlays = [ self.overlays.modifications ]; }; - deployChecks = inputs.deploy-rs.lib.${system}.deployChecks self.deploy; in { pre-commit-check = inputs.git-hooks.lib.${system}.run { @@ -159,7 +138,6 @@ # package = overlaidPkgs.package; }; } - // deployChecks ); }; } diff --git a/modules/nixos/forgejo-runner/default.nix b/modules/nixos/forgejo-runner/default.nix index 2547f0e..7748483 100644 --- a/modules/nixos/forgejo-runner/default.nix +++ b/modules/nixos/forgejo-runner/default.nix @@ -49,7 +49,6 @@ in nix nodejs openssh - deploy-rs ]; settings = {