Archived
Compare commits
16
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6002c5c738 | ||
|
|
92c50df2f1 | ||
|
|
45e61844d5 | ||
|
|
e72df8fed5 | ||
|
|
5497a5b0ae | ||
|
|
e10e493ddd | ||
|
|
ae9acecbf3 | ||
|
|
a3be05538b | ||
|
|
289163c712 | ||
|
|
2123e4ad69 | ||
|
|
177950dd3d | ||
|
|
cbf1239be4 | ||
|
|
8a282ee32e | ||
|
|
25079a7f0a | ||
|
|
4952e5224d | ||
|
|
98409f4502 |
No files matched your search
@@ -20,6 +20,7 @@
|
||||
# vscode
|
||||
chromium
|
||||
claude-code
|
||||
fish
|
||||
];
|
||||
|
||||
# Optional: set environment vars
|
||||
|
||||
@@ -1,12 +1,74 @@
|
||||
{ vars, lib, ... }:
|
||||
{ vars, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
poolName = lib.removePrefix "/" vars.storageRoot;
|
||||
|
||||
# For each NFS share subpath, generate every ancestor path so ZFS datasets
|
||||
# are created parent-first. e.g. "docker/config" → ["docker" "docker/config"]
|
||||
ancestors = path:
|
||||
let parts = lib.splitString "/" path;
|
||||
in lib.imap1 (i: _: lib.concatStringsSep "/" (lib.take i parts)) parts;
|
||||
|
||||
poolDatasets = lib.unique (
|
||||
lib.concatMap (share: ancestors share.subpath) (lib.attrValues vars.nfsShares)
|
||||
);
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
../beszel/enable-agent.nix
|
||||
../services/zfs/enable-service.nix
|
||||
];
|
||||
|
||||
boot.zfs.extraPools = [ (lib.removePrefix "/" vars.storageRoot) ];
|
||||
boot.zfs.extraPools = [ poolName ];
|
||||
|
||||
# On a fresh image deploy the data disk (scsi1) starts blank — no pool
|
||||
# exists yet, so zfs-import-tank.service would spin for 60 s and fail.
|
||||
# This service runs first: if the pool is already present it exits instantly;
|
||||
# otherwise it creates it (with all required datasets) so the standard
|
||||
# import service finds it ready on the very first boot.
|
||||
systemd.services."zfs-init-${poolName}" = {
|
||||
description = "Initialize '${poolName}' ZFS pool on first boot if not present";
|
||||
wantedBy = [ "zfs-import-${poolName}.service" ];
|
||||
before = [ "zfs-import-${poolName}.service" ];
|
||||
after = [ "systemd-udev-settle.service" ];
|
||||
unitConfig.DefaultDependencies = false;
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
path = [ pkgs.zfs_unstable ];
|
||||
script = ''
|
||||
# Already imported — nothing to do.
|
||||
if zpool list "${poolName}" >/dev/null 2>&1; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Pool exists on a device but not yet imported — let the standard
|
||||
# zfs-import-${poolName}.service handle it normally.
|
||||
if zpool import -d /dev/disk/by-id -N "${poolName}" 2>/dev/null; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# No pool found at all. Create it on the Proxmox data disk (scsi1),
|
||||
# which appears as /dev/disk/by-id/scsi-*drive-scsi1 inside the VM.
|
||||
DATA_DISK=""
|
||||
for candidate in /dev/disk/by-id/scsi-*drive-scsi1; do
|
||||
[[ "$candidate" == *-part* ]] && continue
|
||||
[ -b "$candidate" ] && DATA_DISK="$candidate" && break
|
||||
done
|
||||
|
||||
if [ -z "$DATA_DISK" ]; then
|
||||
echo "zfs-init-${poolName}: no data disk found (expected /dev/disk/by-id/scsi-*drive-scsi1)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "zfs-init-${poolName}: creating pool on $DATA_DISK"
|
||||
zpool create -f "${poolName}" "$DATA_DISK"
|
||||
${lib.concatMapStrings (ds: ''
|
||||
zfs create "${poolName}/${ds}"
|
||||
'') poolDatasets}
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.nfs-server = {
|
||||
after = [ "zfs-mount.service" ];
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
openssh.authorizedKeys.keys = [
|
||||
vars.adminSshKey
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICMJhrfFayLBG+gWtO6oAvgambw5nWWgztiTFEaaaVRH debian@surface"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGygkCljN6uKpdJbHTOQtn8ZnH+wKXDLAwrDFbLrE/65 nixos@nixos"
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
Binary file not shown.
@@ -68,6 +68,7 @@ cat > "$HOME/.config/nix/nix.conf" <<'EOF'
|
||||
experimental-features = nix-command flakes
|
||||
accept-flake-config = false
|
||||
warn-dirty = false
|
||||
build-users-group =
|
||||
EOF
|
||||
|
||||
echo "Nix version:"
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@
|
||||
# (from this checkout's own `origin` remote) the first time it doesn't
|
||||
# find it, installing build tooling via scripts/codex-setup.sh, then
|
||||
# `git pull`s it before every subsequent build.
|
||||
: "${PROXMOX_REMOTE_REPO_DIR:=/root/nixos}"
|
||||
: "${PROXMOX_REMOTE_REPO_DIR:=/home/${PROXMOX_SSH_USER}/nixos}"
|
||||
|
||||
# Storage pool names -- Proxmox's own stock-install defaults, but this
|
||||
# varies a lot by setup (ZFS pool name, custom LVM-thin volume, etc.).
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -683,11 +683,11 @@ if [[ "$image_already_remote" -eq 0 && -z "$local_image" ]]; then
|
||||
# hands the result to the remote shell to re-split, which would
|
||||
# otherwise scatter NIX_EXTRA_OPTS (itself several space-separated,
|
||||
# %q-quoted tokens) across the wrong positional parameters below.
|
||||
printf -v remote_cmd 'bash -s -- %q %q %q %q %q' \
|
||||
"$remote_repo_dir" "$flake_target" "$remote_dir" "$remote_filename" "$NIX_EXTRA_OPTS"
|
||||
printf -v remote_cmd 'bash -s -- %q %q %q %q %q %q' \
|
||||
"$remote_repo_dir" "$flake_target" "$remote_dir" "$remote_filename" "$NIX_EXTRA_OPTS" "$sudo_prefix"
|
||||
ssh "$ssh_target" "$remote_cmd" <<'REMOTE_SCRIPT'
|
||||
set -euo pipefail
|
||||
repo_dir="$1"; target="$2"; dest_dir="$3"; dest_name="$4"; nix_extra_opts_str="$5"
|
||||
repo_dir="$1"; target="$2"; dest_dir="$3"; dest_name="$4"; nix_extra_opts_str="$5"; sudo_pfx="$6"
|
||||
declare -a NIX_OPTS=()
|
||||
[[ -n "$nix_extra_opts_str" ]] && eval "NIX_OPTS=(${nix_extra_opts_str})"
|
||||
cd "$repo_dir"
|
||||
@@ -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"
|
||||
@@ -730,7 +730,7 @@ REMOTE_SCRIPT
|
||||
"$remote_repo_dir" "$flake_target" "$remote_dir" "$remote_filename" "$NIX_EXTRA_OPTS" "$sudo_prefix"
|
||||
ssh "$ssh_target" "$remote_cmd" <<'REMOTE_SCRIPT'
|
||||
set -euo pipefail
|
||||
repo_dir="$1"; target="$2"; dest_dir="$3"; dest_name="$4"; nix_extra_opts_str="$5"; sudo_prefix="$6"
|
||||
repo_dir="$1"; target="$2"; dest_dir="$3"; dest_name="$4"; nix_extra_opts_str="$5"; sudo_pfx="$6"
|
||||
declare -a NIX_OPTS=()
|
||||
[[ -n "$nix_extra_opts_str" ]] && eval "NIX_OPTS=(${nix_extra_opts_str})"
|
||||
cd "$repo_dir"
|
||||
@@ -739,7 +739,7 @@ ensure_nix_profile
|
||||
nix build --no-use-registries --no-accept-flake-config "${NIX_OPTS[@]}" \
|
||||
".#nixosConfigurations.${target}.config.system.build.diskoImagesScript" \
|
||||
--out-link "result-${target}"
|
||||
$sudo_prefix "./result-${target}" \
|
||||
$sudo_pfx "./result-${target}" \
|
||||
--pre-format-files "host-keys/${target}_ssh_host_ed25519_key" /etc/ssh/ssh_host_ed25519_key \
|
||||
--pre-format-files "host-keys/${target}_ssh_host_ed25519_key.pub" /etc/ssh/ssh_host_ed25519_key.pub \
|
||||
--build-memory 2048
|
||||
@@ -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"
|
||||
|
||||
Reference in new issue
Block a user