nixos-deploy wrapper steals sudo PATH and breaks 'just deploy' #138

Closed
opened 2026-08-03 23:29:19 +01:00 by nimmo · 0 comments
Owner

Goal

Restore the pre-PR-#125 behaviour of just deploy (uses nom, can run as a
non-root user via the system setuid sudo wrapper) while keeping the new
packages/nixos-deploy Nix module that replaced the inline Justfile bash.

Context

PR #125 moved the long inline bash recipe from justfiles/deploy.just into
scripts/nixos-deploy.sh and packaged it as packages/nixos-deploy/default.nix
(writeShellApplication with runtimeInputs = [ coreutils hostname nix nvd nix-output-monitor openssh sudo ]).

The script still does the right things when invoked directly. However, just deploy now shells out to nix run .#nixos-deploy -- ..., and the
writeShellApplication wrapper hard-codes a PATH that begins with the store
sudo (/nix/store/...-sudo-1.9.17p2/bin/sudo, mode 0555, not setuid) before
the user's PATH. The setuid sudo lives at /run/wrappers/bin/sudo (mode
4551), and is only first on PATH when the user opens a normal terminal — i.e.
after /etc/set-environment does export PATH="/run/wrappers/bin:$PATH".

Symptom: just deploy aborts at sudo -v with
sudo: /run/current-system/sw/bin/sudo must be owned by uid 0 and have the setuid bit set — i.e. it "complains about not being root". It also looks
like just deploy no longer uses nom, because the Justfile now only calls
nix run .#nixos-deploy; the nom build call is buried inside the packaged
script and never runs.

Scope

  • Keep packages/nixos-deploy/default.nix as the canonical "module" for the
    deploy command (per user direction: don't go back to inline Justfile bash).
  • Stop the wrapper from prepending the store sudo to PATH so the script
    resolves sudo via the caller's environment, which is the
    /run/wrappers/bin/sudo setuid wrapper on every NixOS host.
  • The script already honours NIXOS_DEPLOY_SUDO (and the other
    NIXOS_DEPLOY_* env vars) for explicit overrides; that mechanism stays.
  • Add a regression test that runs the script through a writeShellApplication
    wrapper (or via nix run) to exercise the real PATH assembly, so this
    cannot regress again.
  • Document why sudo is intentionally absent from runtimeInputs.

Acceptance criteria

  • just deploy (and nix run .#nixos-deploy -- ...) reaches the
    nom build --fallback ... step on a non-root invocation on a NixOS host.
  • NIXOS_DEPLOY_SUDO=/custom/path/sudo just deploy still overrides cleanly.
  • nix flake check and the new wrapped-PATH regression pass.
  • The packaged nixos-deploy command's --help and argument parsing remain
    unchanged.

Notes

  • Discovered while reviewing why just deploy started failing with the
    "must be owned by uid 0 and have the setuid bit set" sudo error after
    the PR #125 packaging landed.
  • Long-term, a more general fix would be a security.wrappers (setuid)
    wrapper for sudo at the system level, but that's already what
    /run/wrappers/bin/sudo is — we just need the deploy wrapper to stop
    shadowing it.
## Goal Restore the pre-PR-#125 behaviour of `just deploy` (uses `nom`, can run as a non-root user via the system setuid sudo wrapper) while keeping the new `packages/nixos-deploy` Nix module that replaced the inline Justfile bash. ## Context PR #125 moved the long inline bash recipe from `justfiles/deploy.just` into `scripts/nixos-deploy.sh` and packaged it as `packages/nixos-deploy/default.nix` (`writeShellApplication` with `runtimeInputs = [ coreutils hostname nix nvd nix-output-monitor openssh sudo ]`). The script still does the right things when invoked directly. However, `just deploy` now shells out to `nix run .#nixos-deploy -- ...`, and the `writeShellApplication` wrapper hard-codes a PATH that begins with the *store* sudo (`/nix/store/...-sudo-1.9.17p2/bin/sudo`, mode 0555, not setuid) before the user's PATH. The setuid sudo lives at `/run/wrappers/bin/sudo` (mode 4551), and is only first on PATH when the user opens a normal terminal — i.e. after `/etc/set-environment` does `export PATH="/run/wrappers/bin:$PATH"`. Symptom: `just deploy` aborts at `sudo -v` with `sudo: /run/current-system/sw/bin/sudo must be owned by uid 0 and have the setuid bit set` — i.e. it "complains about not being root". It also *looks* like `just deploy` no longer uses `nom`, because the Justfile now only calls `nix run .#nixos-deploy`; the `nom build` call is buried inside the packaged script and never runs. ## Scope - Keep `packages/nixos-deploy/default.nix` as the canonical "module" for the deploy command (per user direction: don't go back to inline Justfile bash). - Stop the wrapper from prepending the store sudo to PATH so the script resolves `sudo` via the caller's environment, which is the `/run/wrappers/bin/sudo` setuid wrapper on every NixOS host. - The script already honours `NIXOS_DEPLOY_SUDO` (and the other `NIXOS_DEPLOY_*` env vars) for explicit overrides; that mechanism stays. - Add a regression test that runs the script through a `writeShellApplication` wrapper (or via `nix run`) to exercise the real PATH assembly, so this cannot regress again. - Document why `sudo` is intentionally absent from `runtimeInputs`. ## Acceptance criteria - `just deploy` (and `nix run .#nixos-deploy -- ...`) reaches the `nom build --fallback ...` step on a non-root invocation on a NixOS host. - `NIXOS_DEPLOY_SUDO=/custom/path/sudo just deploy` still overrides cleanly. - `nix flake check` and the new wrapped-PATH regression pass. - The packaged `nixos-deploy` command's `--help` and argument parsing remain unchanged. ## Notes - Discovered while reviewing why `just deploy` started failing with the "must be owned by uid 0 and have the setuid bit set" sudo error after the PR #125 packaging landed. - Long-term, a more general fix would be a `security.wrappers` (setuid) wrapper for sudo at the system level, but that's already what `/run/wrappers/bin/sudo` is — we just need the deploy wrapper to stop shadowing it.
nimmo closed this issue 2026-08-04 06:26:12 +01:00
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
nimmo/nixos-config#138
No description provided.