From a3be05538b7449a8043d25cb2e1d72866fec72c8 Mon Sep 17 00:00:00 2001 From: beatzaplenty Date: Thu, 23 Jul 2026 10:37:57 +1000 Subject: [PATCH 1/2] fix: support single-user (non-root) nix in configure-nix-cache-client.sh The script was root-only and hard-coded /etc/nix/nix.conf and /etc/ssh/ssh_known_hosts, making it always fail (non-fatally) when called as a non-root SSH user from create-proxmox-resource.sh. Add dual-mode detection based on EUID: - root (multi-user/daemon): existing behavior unchanged -- writes /etc/nix/nix.conf, /etc/ssh/ssh_known_hosts, restarts nix-daemon - non-root (single-user): writes ~/.config/nix/nix.conf and ~/.ssh/known_hosts, creates the config file if missing, skips the daemon restart (single-user has no daemon), defaults REMOTE_BUILDER_KEY to ~/.ssh/id_ed25519 instead of /root/.ssh/id_ed25519 create-proxmox-resource.sh already calls the script without sudo (as the SSH user), so no change is needed there -- the script now handles both cases on its own. Co-Authored-By: Claude Sonnet 4.6 --- scripts/proxmox/configure-nix-cache-client.sh | 69 ++++++++++++------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/scripts/proxmox/configure-nix-cache-client.sh b/scripts/proxmox/configure-nix-cache-client.sh index b191c11..3e53340 100755 --- a/scripts/proxmox/configure-nix-cache-client.sh +++ b/scripts/proxmox/configure-nix-cache-client.sh @@ -6,27 +6,31 @@ # # This is the non-NixOS equivalent of modules/nix-cache/client.nix + # modules/nix-cache/remote-builder-client.nix -- those two only apply to -# hosts built from this flake. A plain Debian box with Nix installed -# (single- or multi-user install, nix-daemon running) has no NixOS module -# system to pick that config up, so this edits /etc/nix/nix.conf by hand -# instead. Run this ON the target Debian machine, as root. +# hosts built from this flake. A plain Debian box with Nix installed has no +# NixOS module system to pick that config up, so this edits nix.conf by hand. +# +# Two modes depending on who runs it: +# +# root (multi-user / daemon install): +# Writes /etc/nix/nix.conf, /etc/ssh/ssh_known_hosts, restarts nix-daemon. +# Requires /etc/nix/nix.conf to already exist (i.e. nix-daemon is set up). +# Run as: sudo ./configure-nix-cache-client.sh [options] +# +# non-root (single-user install): +# Writes ~/.config/nix/nix.conf, ~/.ssh/known_hosts. No daemon to restart. +# Run as: ./configure-nix-cache-client.sh [options] # # The values below mirror variables.nix / modules/nix-cache/client.nix in # this repo -- update both if nix-cache is ever rebuilt with a new host # key or the cache signing key is rotated (see docs/nix-cache.md). # -# REMOTE_BUILDER_KEY defaults to this machine's own default root SSH -# identity (matches modules/nix-cache/remote-builder-client.nix's -# convention for real NixOS clients: authenticate as nixremote with the -# host's own default key, added individually to -# vars.remoteBuilderAuthorizedKeys, rather than a separately-named or -# shared keypair) -- generate one with -# `ssh-keygen -t ed25519 -N '' -f /root/.ssh/id_ed25519` if this machine -# doesn't have one yet, then add its .pub to vars.remoteBuilderAuthorizedKeys -# and rebuild nix-cache. +# REMOTE_BUILDER_KEY defaults to the running user's default SSH identity +# (root: /root/.ssh/id_ed25519, other user: ~/.ssh/id_ed25519). That key +# must be listed in vars.remoteBuilderAuthorizedKeys in this repo and +# nix-cache rebuilt before remote building works. # # Usage: -# sudo ./configure-nix-cache-client.sh [--dry-run] [--no-remote-builder] [--no-restart] +# ./configure-nix-cache-client.sh [--dry-run] [--no-remote-builder] [--no-restart] # # Env overrides (defaults match variables.nix): # NIX_CACHE_HOST, NIX_CACHE_HOST_KEY, REMOTE_BUILDER_USER, REMOTE_BUILDER_KEY @@ -36,17 +40,28 @@ set -euo pipefail : "${NIX_CACHE_HOST:=nix-cache}" : "${NIX_CACHE_HOST_KEY:=ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPeWgMsdaiz4axT/deFc1+0B5bN+GX/NOeW9bbQ0c/IT lxc-nix-cache}" : "${REMOTE_BUILDER_USER:=nixremote}" -: "${REMOTE_BUILDER_KEY:=/root/.ssh/id_ed25519}" CACHE_PUB_KEY="cache.local-1:usoWYanY3Kpq2+kDIS2nhWoLZiRxanmdysdzqCFBHW4=" FALLBACK_URL="https://cache.nixos.org/" FALLBACK_PUB_KEY="cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" -NIX_CONF="/etc/nix/nix.conf" -KNOWN_HOSTS="/etc/ssh/ssh_known_hosts" MARKER_BEGIN="# BEGIN nix-cache client config (configure-nix-cache-client.sh)" MARKER_END="# END nix-cache client config" +# Mode: root uses system-wide paths and restarts the daemon; non-root uses +# user-level paths and has no daemon to restart. +if [[ "$EUID" -eq 0 ]]; then + install_mode="multi" + NIX_CONF="/etc/nix/nix.conf" + KNOWN_HOSTS="/etc/ssh/ssh_known_hosts" + : "${REMOTE_BUILDER_KEY:=/root/.ssh/id_ed25519}" +else + install_mode="single" + NIX_CONF="${XDG_CONFIG_HOME:-$HOME/.config}/nix/nix.conf" + KNOWN_HOSTS="$HOME/.ssh/known_hosts" + : "${REMOTE_BUILDER_KEY:=$HOME/.ssh/id_ed25519}" +fi + dry_run=0 with_remote_builder=1 restart_daemon=1 @@ -57,7 +72,7 @@ for arg in "$@"; do --no-remote-builder) with_remote_builder=0 ;; --no-restart) restart_daemon=0 ;; -h|--help) - sed -n '2,20p' "$0" + sed -n '2,37p' "$0" exit 0 ;; *) @@ -67,21 +82,22 @@ for arg in "$@"; do esac done -if [[ "$dry_run" -eq 0 && "$EUID" -ne 0 ]]; then - echo "ERROR: must run as root (writes $NIX_CONF and, unless --no-remote-builder, $KNOWN_HOSTS)." >&2 - exit 1 -fi - if ! command -v nix >/dev/null 2>&1; then echo "ERROR: no 'nix' binary on PATH -- install the Nix package manager first." >&2 exit 1 fi -if [[ ! -f "$NIX_CONF" ]]; then +if [[ "$install_mode" == "multi" && ! -f "$NIX_CONF" ]]; then echo "ERROR: $NIX_CONF not found -- expected an existing multi-user Nix install." >&2 exit 1 fi +# Single-user: create the config file if it doesn't exist yet. +if [[ "$install_mode" == "single" && "$dry_run" -eq 0 ]]; then + mkdir -p "$(dirname "$NIX_CONF")" + [[ -f "$NIX_CONF" ]] || touch "$NIX_CONF" +fi + builder_line="" if [[ "$with_remote_builder" -eq 1 ]]; then if [[ -f "$REMOTE_BUILDER_KEY" ]]; then @@ -117,7 +133,7 @@ fi block="${block} $MARKER_END" -echo "== nix.conf block to install ==" +echo "== nix.conf block to install ($NIX_CONF) ==" echo "$block" echo "================================" @@ -159,7 +175,8 @@ if [[ "$with_remote_builder" -eq 1 ]]; then fi fi -if [[ "$dry_run" -eq 0 && "$restart_daemon" -eq 1 ]]; then +# Only restart the daemon for multi-user installs -- single-user has no daemon. +if [[ "$dry_run" -eq 0 && "$restart_daemon" -eq 1 && "$install_mode" == "multi" ]]; then if command -v systemctl >/dev/null 2>&1 && systemctl is-active --quiet nix-daemon 2>/dev/null; then systemctl restart nix-daemon echo "Restarted nix-daemon to pick up the new config." From ae9acecbf3cc01f3668fcae561879c0d18b20a76 Mon Sep 17 00:00:00 2001 From: beatzaplenty Date: Thu, 23 Jul 2026 10:39:09 +1000 Subject: [PATCH 2/2] fix: sudo the tarball/image staging into /var/lib/vz The post-build cp/mv into /var/lib/vz/template/cache (LXC) and /var/lib/vz/import (VM) are Proxmox-owned root directories -- they need sudo_pfx just like pct/qm/pvesh do. nix build writes to the nix store as the SSH user, but staging into /var/lib/vz/ requires root. Co-Authored-By: Claude Sonnet 4.6 --- scripts/proxmox/create-proxmox-resource.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/proxmox/create-proxmox-resource.sh b/scripts/proxmox/create-proxmox-resource.sh index 7d43d7e..fd4f3a0 100755 --- a/scripts/proxmox/create-proxmox-resource.sh +++ b/scripts/proxmox/create-proxmox-resource.sh @@ -705,8 +705,8 @@ if [[ -z "$built" ]]; then echo "ERROR: no tarball found under result-${target}/tarball after build." >&2 exit 1 fi -mkdir -p "$dest_dir" -cp "$built" "${dest_dir}/${dest_name}" +$sudo_pfx mkdir -p "$dest_dir" +$sudo_pfx cp "$built" "${dest_dir}/${dest_name}" echo "Built and staged: ${dest_dir}/${dest_name}" REMOTE_SCRIPT local_image="$remote_path" @@ -748,8 +748,8 @@ if [[ -z "$built" ]]; then echo "ERROR: no .raw image found in ${repo_dir} after build." >&2 exit 1 fi -mkdir -p "$dest_dir" -mv "$built" "${dest_dir}/${dest_name}" +$sudo_pfx mkdir -p "$dest_dir" +$sudo_pfx mv "$built" "${dest_dir}/${dest_name}" echo "Built and staged: ${dest_dir}/${dest_name}" REMOTE_SCRIPT local_image="$remote_path"