No daemon to restart, and no systemctl to try it with
The workflow's first run failed in five seconds at `systemctl restart nix-daemon`, exit 127. Two wrong assumptions in one line: the runner's image has no systemctl, and there is no daemon to restart anyway — the installer says "installing Nix as root is not supported by this script" and falls back to a single-user install. Which install it is decides whether appended nix.conf settings need a restart to take effect — a daemon reads that file once at start, a single-user client reads it per invocation. So the restart is now conditional on there being something to restart, and the single-user case says so rather than failing. The key stays in /root/.ssh. That was reasoned from the daemon running as root, which turns out not to be the case here, but the conclusion holds for the better reason: single-user nix as root IS the process opening the connection. `nix config show builders` afterwards, because the failure this guards against is not an error. A builder that did not get configured means every derivation is built on the runner, and the first symptom of that is three hours of compiling libcosmic. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
459c9cd parent: 65c27be modified
.rickub/workflows/build.yml +23 -12 | @@ -71,13 +71,9 @@ jobs: | ||
| 71 | 71 | NIXBUILD_SSH_KEY: ${{ secrets.NIXBUILD_SSH_KEY }} |
| 72 | 72 | run: | |
| 73 | 73 | set -eu |
| 74 | - # ROOT's ~/.ssh, and this is the one thing that differs from the | |
| 75 | - # GitLab job. There the whole job runs as root in a nixos/nix image; | |
| 76 | - # here install-nix-action leaves a multi-user install, so the process | |
| 77 | - # that opens the SSH connection to the builder is nix-daemon running | |
| 78 | - # as root. A key under the runner user's home is a key it never | |
| 79 | - # reads, and the failure is a build that silently stays local — | |
| 80 | - # which on this graph means a runner trying to compile libcosmic. | |
| 74 | + # ROOT's ~/.ssh. The GitLab job runs as root in a nixos/nix image and | |
| 75 | + # needs no such care; here the step below decides which install this | |
| 76 | + # is, and root is the answer either way — see the note there. | |
| 81 | 77 | sudo mkdir -p /root/.ssh |
| 82 | 78 | # base64 because a CI variable can only carry a single line. |
| 83 | 79 | printf '%s' "$NIXBUILD_SSH_KEY" | base64 -d | sudo tee /root/.ssh/nixbuild >/dev/null |
| @@ -96,11 +92,26 @@ jobs: | ||
| 96 | 92 | require-sigs = false |
| 97 | 93 | max-jobs = $(nproc) |
| 98 | 94 | EOF |
| 99 | - # The daemon reads nix.conf at start, so settings appended after | |
| 100 | - # install-nix-action has already started it do nothing until it is | |
| 101 | - # restarted. Without this the job runs with none of the above and | |
| 102 | - # the first symptom is an hour of local compilation. | |
| 103 | - sudo systemctl restart nix-daemon | |
| 95 | + # Only if there IS a daemon. The runner's installer says | |
| 96 | + # "installing Nix as root is not supported by this script" and falls | |
| 97 | + # back to a SINGLE-USER install, so there is no nix-daemon to | |
| 98 | + # restart and no systemctl in the image to try — an unconditional | |
| 99 | + # restart here exited 127 and took the job with it. | |
| 100 | + # | |
| 101 | + # Which install it is decides two things, and they happen to agree. | |
| 102 | + # A daemon reads nix.conf once at start, so appended settings need | |
| 103 | + # the restart; a single-user client reads it per invocation, so they | |
| 104 | + # are live immediately. And the process opening the SSH connection | |
| 105 | + # is root either way — the daemon in one case, this job in the | |
| 106 | + # other — so the key belongs in /root/.ssh regardless. | |
| 107 | + if command -v systemctl >/dev/null 2>&1 && systemctl is-active --quiet nix-daemon; then | |
| 108 | + sudo systemctl restart nix-daemon | |
| 109 | + else | |
| 110 | + echo "single-user nix: nix.conf is read per invocation, nothing to restart" | |
| 111 | + fi | |
| 112 | + # Printed rather than assumed. If the builder is not set here, every | |
| 113 | + # derivation below is built on this runner, and the first symptom of | |
| 114 | + # that is not an error — it is three hours of compiling libcosmic. | |
| 104 | 115 | nix config show builders |
| 105 | 116 | nix config show max-jobs |
| 106 | 117 | |
| @@ -71,13 +71,9 @@ jobs: | |||
| 71 | NIXBUILD_SSH_KEY: ${{ secrets.NIXBUILD_SSH_KEY }} | 71 | NIXBUILD_SSH_KEY: ${{ secrets.NIXBUILD_SSH_KEY }} |
| 72 | run: | | 72 | run: | |
| 73 | set -eu | 73 | set -eu |
| 74 | - # ROOT's ~/.ssh, and this is the one thing that differs from the | 74 | + # ROOT's ~/.ssh. The GitLab job runs as root in a nixos/nix image and |
| 75 | - # GitLab job. There the whole job runs as root in a nixos/nix image; | 75 | + # needs no such care; here the step below decides which install this |
| 76 | - # here install-nix-action leaves a multi-user install, so the process | 76 | + # is, and root is the answer either way — see the note there. |
| 77 | - # that opens the SSH connection to the builder is nix-daemon running | ||
| 78 | - # as root. A key under the runner user's home is a key it never | ||
| 79 | - # reads, and the failure is a build that silently stays local — | ||
| 80 | - # which on this graph means a runner trying to compile libcosmic. | ||
| 81 | sudo mkdir -p /root/.ssh | 77 | sudo mkdir -p /root/.ssh |
| 82 | # base64 because a CI variable can only carry a single line. | 78 | # base64 because a CI variable can only carry a single line. |
| 83 | printf '%s' "$NIXBUILD_SSH_KEY" | base64 -d | sudo tee /root/.ssh/nixbuild >/dev/null | 79 | printf '%s' "$NIXBUILD_SSH_KEY" | base64 -d | sudo tee /root/.ssh/nixbuild >/dev/null |
| @@ -96,11 +92,26 @@ jobs: | |||
| 96 | require-sigs = false | 92 | require-sigs = false |
| 97 | max-jobs = $(nproc) | 93 | max-jobs = $(nproc) |
| 98 | EOF | 94 | EOF |
| 99 | - # The daemon reads nix.conf at start, so settings appended after | 95 | + # Only if there IS a daemon. The runner's installer says |
| 100 | - # install-nix-action has already started it do nothing until it is | 96 | + # "installing Nix as root is not supported by this script" and falls |
| 101 | - # restarted. Without this the job runs with none of the above and | 97 | + # back to a SINGLE-USER install, so there is no nix-daemon to |
| 102 | - # the first symptom is an hour of local compilation. | 98 | + # restart and no systemctl in the image to try — an unconditional |
| 103 | - sudo systemctl restart nix-daemon | 99 | + # restart here exited 127 and took the job with it. |
| 100 | + # | ||
| 101 | + # Which install it is decides two things, and they happen to agree. | ||
| 102 | + # A daemon reads nix.conf once at start, so appended settings need | ||
| 103 | + # the restart; a single-user client reads it per invocation, so they | ||
| 104 | + # are live immediately. And the process opening the SSH connection | ||
| 105 | + # is root either way — the daemon in one case, this job in the | ||
| 106 | + # other — so the key belongs in /root/.ssh regardless. | ||
| 107 | + if command -v systemctl >/dev/null 2>&1 && systemctl is-active --quiet nix-daemon; then | ||
| 108 | + sudo systemctl restart nix-daemon | ||
| 109 | + else | ||
| 110 | + echo "single-user nix: nix.conf is read per invocation, nothing to restart" | ||
| 111 | + fi | ||
| 112 | + # Printed rather than assumed. If the builder is not set here, every | ||
| 113 | + # derivation below is built on this runner, and the first symptom of | ||
| 114 | + # that is not an error — it is three hours of compiling libcosmic. | ||
| 104 | nix config show builders | 115 | nix config show builders |
| 105 | nix config show max-jobs | 116 | nix config show max-jobs |
| 106 | 117 | ||