chore(scripts): move deploy+edit_secrets to scripts/, resolve repo root via git

- scripts now find the flake root regardless of cwd or where they live on PATH
- gitignore .env
This commit is contained in:
erik
2026-07-13 18:58:25 +02:00
parent ec309c8fe1
commit 2b170af346
3 changed files with 10 additions and 2 deletions
Executable
+99
View File
@@ -0,0 +1,99 @@
#!/usr/bin/env bash
# Deploy a NixOS host from this flake. ALL arguments are mandatory (no defaults).
#
# ./deploy kexec <host> headless kexec into a RAM installer, for a
# read-only-root box (ZimaOS) where
# nixos-anywhere can't ssh-copy-id. Ships our
# SSH login key. Then run `install`.
# ./deploy install <config> <host> first install (nixos-anywhere). Wipes the
# OS disk. Ships the host's sops key.
# ./deploy switch <config> <host> rebuild + activate on a running host.
# ./deploy boot <config> <host> stage for next boot, don't activate now.
# ./deploy test <config> <host> activate without adding a boot entry.
#
# <config> = a nixosConfigurations name (e.g. jupiter, vps). Its pre-generated
# SSH host key must be at ~/.config/homelab/<config>/ssh_host_ed25519_key.
#
# Runs from a non-NixOS host too (nixos-rebuild / nixos-anywhere via `nix run`).
set -euo pipefail
# Locate the repo root (flake dir) regardless of where this script lives on disk.
SCRIPT_DIR="$(cd "$(dirname "$(realpath "$0")")" && pwd)"
REPO="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || dirname "$SCRIPT_DIR")"
cd "$REPO"
export PATH="/nix/var/nix/profiles/default/bin:$PATH"
die() { echo "error: $*" >&2; exit 1; }
cmd="${1:-}"; [ -n "$cmd" ] || die "usage: ./deploy <kexec|install|switch|boot|test> ..."
case "$cmd" in
kexec)
host="${2:-}"; [ -n "$host" ] || die "usage: ./deploy kexec <host>"
echo ">> building kexec installer + static tools"
nix build .#nixosConfigurations.kexec.config.system.build.kexecInstallerTarball \
-o result-kexec
tb="$(ls result-kexec/*.tar.gz | head -1)"
# kexec/run rebuilds an initrd with `cpio` + `gzip` from PATH — ZimaOS lacks
# both. Ship static ones: GNU cpio (reliable -o -H newc), busybox as gzip.
cpio="$(nix build --no-link --print-out-paths nixpkgs#pkgsStatic.cpio)/bin/cpio"
bbox="$(nix build --no-link --print-out-paths nixpkgs#pkgsStatic.busybox)/bin/busybox"
# One password prompt: multiplex scp + ssh over a shared control connection.
cm="/tmp/homelab-cm-%r@%h:%p"
o=(-o ControlMaster=auto -o "ControlPath=$cm" -o ControlPersist=300 \
-o StrictHostKeyChecking=accept-new)
echo ">> connecting to root@$host (enter the root password once)"
ssh "${o[@]}" "root@$host" 'mkdir -p /tmp/bin'
scp "${o[@]}" "$cpio" "root@$host:/tmp/bin/cpio"
scp "${o[@]}" "$bbox" "root@$host:/tmp/bin/gzip" # busybox as gzip (argv0)
echo ">> streaming installer + kexec-ing. SSH drops as the box jumps into the"
echo " RAM installer. Disks are untouched."
ssh "${o[@]}" "root@$host" \
'chmod +x /tmp/bin/*; mkdir -p /tmp/k && tar -C /tmp/k -xzf - && PATH=/tmp/bin:$PATH /tmp/k/kexec/run' \
< "$tb" || true
ssh "${o[@]}" -O exit "root@$host" 2>/dev/null || true # close control socket
echo ">> box is kexec-ing. Wait ~1-2 min for the installer + network, then:"
echo " ./deploy install <config> $host"
;;
install)
config="${2:-}"; host="${3:-}"
{ [ -n "$config" ] && [ -n "$host" ]; } || die "usage: ./deploy install <config> <host>"
hostkey="$HOME/.config/homelab/$config/ssh_host_ed25519_key"
[ -f "$hostkey" ] || die "missing host key: $hostkey"
[ -d "./$config" ] || die "no ./$config directory in the repo"
# Stage the pre-generated SSH host key so sops can decrypt on boot #1.
stage="$(mktemp -d)"
trap 'rm -rf "$stage"' EXIT
install -Dm600 "$hostkey" "$stage/etc/ssh/ssh_host_ed25519_key"
install -Dm644 "$hostkey.pub" "$stage/etc/ssh/ssh_host_ed25519_key.pub"
echo ">> nixos-anywhere .#$config onto root@$host (OS disk WILL be wiped)"
nix run github:nix-community/nixos-anywhere -- \
--flake ".#$config" \
--extra-files "$stage" \
--generate-hardware-config nixos-generate-config "./$config/hardware-configuration.nix" \
--target-host "root@$host"
;;
switch|boot|test)
config="${2:-}"; host="${3:-}"
{ [ -n "$config" ] && [ -n "$host" ]; } || die "usage: ./deploy $cmd <config> <host>"
echo ">> nixos-rebuild $cmd .#$config on darman@$host"
nix run nixpkgs#nixos-rebuild -- "$cmd" \
--flake ".#$config" \
--target-host "darman@$host" \
--use-remote-sudo
;;
*)
die "unknown command '$cmd' (kexec|install|switch|boot|test)"
;;
esac
+53
View File
@@ -0,0 +1,53 @@
#!/usr/bin/env bash
# Edit (or view) a sops-encrypted secrets file with the admin age key.
#
# Usage:
# ./edit_secrets # edit secrets/jupiter.yaml
# ./edit_secrets secrets/other.yaml # edit another file
# ./edit_secrets --show # decrypt to stdout, no edit
#
# The admin age PRIVATE key must be at $SOPS_AGE_KEY_FILE
# (default ~/.config/sops/age/keys.txt). Never commit that key.
set -euo pipefail
# Locate the repo root (flake dir) regardless of where this script lives on disk.
SCRIPT_DIR="$(cd "$(dirname "$(realpath "$0")")" && pwd)"
REPO="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || dirname "$SCRIPT_DIR")"
cd "$REPO"
export PATH="/nix/var/nix/profiles/default/bin:$PATH"
export SOPS_AGE_KEY_FILE="${SOPS_AGE_KEY_FILE:-$HOME/.config/sops/age/keys.txt}"
if [ ! -f "$SOPS_AGE_KEY_FILE" ]; then
echo "error: admin age key not found at $SOPS_AGE_KEY_FILE" >&2
echo "set SOPS_AGE_KEY_FILE or generate one with age-keygen." >&2
exit 1
fi
show=0
file="secrets/jupiter.yaml"
for arg in "$@"; do
case "$arg" in
--show) show=1 ;;
*) file="$arg" ;;
esac
done
if [ "$show" -eq 1 ]; then
exec nix shell nixpkgs#sops -c sops --decrypt "$file"
fi
# sops opens $EDITOR on a temp file and re-encrypts only if it changed.
# Pitfalls that cause "File has not changed, exiting":
# - $EDITOR unset: no editor is on the `nix shell` PATH -> bundle one.
# - GUI editor (code/zed) forks and returns instantly -> force --wait.
editor="${VISUAL:-${EDITOR:-}}"
extra=()
case "$editor" in
"") editor="nano"; extra=(nixpkgs#nano) ;; # sane default, bundled
code|code\ *) editor="code --wait" ;; # VS Code must block
codium|codium\ *) editor="codium --wait" ;;
zeditor|zeditor\ *) editor="zeditor --wait" ;;
esac
export EDITOR="$editor"
exec nix shell nixpkgs#sops "${extra[@]}" -c sops "$file"