new build script
This commit is contained in:
1 parent
685be88e44
commit
dcfd574f59
4 files changed
+150
-26
No files matched your search
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
server-info.txt
|
server-info.txt
|
||||||
nixos/out
|
nixos/out
|
||||||
nixos/error
|
nixos/error
|
||||||
virtual-machines/*/result/
|
virtual-machines/*/result
|
||||||
@@ -206,6 +206,11 @@
|
|||||||
# Init with `incus admin init --minimal`
|
# Init with `incus admin init --minimal`
|
||||||
virtualisation.incus.enable = true;
|
virtualisation.incus.enable = true;
|
||||||
|
|
||||||
|
# allow sandboxes to see my temp keys
|
||||||
|
nix.settings.extra-sandbox-paths = [
|
||||||
|
"/run/sops-virtual-key.txt=/run/sops-virtual/virtual-key.txt"
|
||||||
|
];
|
||||||
|
|
||||||
networking = {
|
networking = {
|
||||||
hostName = meta.hostname;
|
hostName = meta.hostname;
|
||||||
hostId = meta.hostId;
|
hostId = meta.hostId;
|
||||||
|
|||||||
@@ -1,54 +1,176 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -Eeuo pipefail
|
||||||
|
|
||||||
# Usage:
|
# Usage:
|
||||||
# ./build-image.sh <alias> [vmname]
|
# ./build-image.sh <vm-folder> <alias> [vmname]
|
||||||
#
|
#
|
||||||
# Examples:
|
# Example:
|
||||||
# ./build-image.sh nixos/custom/vm
|
# ./build-image.sh vm-test nixos/custom/jellybean
|
||||||
# ./build-image.sh nixos/custom/my-vm my-vm
|
#
|
||||||
|
# Run from anywhere; all project operations use virtual-machines/.
|
||||||
|
|
||||||
if [[ $# -lt 1 || $# -gt 2 ]]; then
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
echo "Usage: $0 <alias> [vmname]"
|
cd "$SCRIPT_DIR"
|
||||||
echo
|
|
||||||
echo " alias Required Incus image alias"
|
if [[ $# -lt 2 || $# -gt 3 ]]; then
|
||||||
echo " vmname NixOS configuration name (default: vm)"
|
echo "Usage: $0 <vm-folder> <alias> [vmname]"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ALIAS="$1"
|
VM_FOLDER="$1"
|
||||||
VMNAME="${2:-vm}"
|
ALIAS="$2"
|
||||||
|
VMNAME="${3:-vm}"
|
||||||
|
|
||||||
|
VM_DIR="$SCRIPT_DIR/$VM_FOLDER"
|
||||||
|
SOPS_CONFIG="$SCRIPT_DIR/.sops.yaml"
|
||||||
|
AGE_DIR="/run/sops-virtual"
|
||||||
|
AGE_KEY="$AGE_DIR/virtual-key.txt"
|
||||||
|
SANDBOX_KEY="/run/sops-virtual-key.txt"
|
||||||
|
|
||||||
|
for cmd in age-keygen sops yq nix incus sudo; do
|
||||||
|
command -v "$cmd" >/dev/null 2>&1 || {
|
||||||
|
echo "Missing required command: $cmd" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ -d "$VM_DIR" ]] || {
|
||||||
|
echo "VM directory not found: $VM_DIR" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
[[ -f "$VM_DIR/flake.nix" ]] || {
|
||||||
|
echo "No flake.nix found in $VM_DIR" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
[[ -f "$SOPS_CONFIG" ]] || {
|
||||||
|
echo "SOPS config not found: $SOPS_CONFIG" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
[[ -d "$VM_DIR/secrets" ]] || {
|
||||||
|
echo "Secrets directory not found: $VM_DIR/secrets" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Refuse to overwrite a key that may belong to another running build.
|
||||||
|
if sudo test -e "$AGE_KEY"; then
|
||||||
|
echo "Temporary key already exists: $AGE_KEY" >&2
|
||||||
|
echo "Remove it or investigate the previous build before continuing." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SOPS_BACKUP="$(mktemp)"
|
||||||
|
AGE_TEMP="$(mktemp)"
|
||||||
|
cp -p "$SOPS_CONFIG" "$SOPS_BACKUP"
|
||||||
|
|
||||||
|
CLEANED_UP=0
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
local status=$?
|
||||||
|
|
||||||
|
if [[ "$CLEANED_UP" -eq 1 ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
CLEANED_UP=1
|
||||||
|
|
||||||
|
# Restore the repository's original SOPS configuration.
|
||||||
|
cp "$SOPS_BACKUP" "$SOPS_CONFIG"
|
||||||
|
rm -f "$SOPS_BACKUP" "$AGE_TEMP"
|
||||||
|
|
||||||
|
# Remove the temporary private key, even if the build failed.
|
||||||
|
sudo rm -f "$AGE_KEY"
|
||||||
|
sudo rmdir "$AGE_DIR" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "Temporary age key removed."
|
||||||
|
|
||||||
|
return "$status"
|
||||||
|
}
|
||||||
|
|
||||||
|
trap cleanup EXIT
|
||||||
|
trap 'exit 130' INT
|
||||||
|
trap 'exit 143' TERM
|
||||||
|
|
||||||
|
echo "Generating temporary age identity..."
|
||||||
|
|
||||||
|
age-keygen -o "$AGE_TEMP"
|
||||||
|
AGE_PUBLIC_KEY="$(age-keygen -y "$AGE_TEMP")"
|
||||||
|
|
||||||
|
# Make the key readable by Nix build users, but not ordinary users.
|
||||||
|
sudo install -d -o root -g nixbld -m 0750 "$AGE_DIR"
|
||||||
|
sudo install -o root -g nixbld -m 0440 \
|
||||||
|
"$AGE_TEMP" "$AGE_KEY"
|
||||||
|
|
||||||
|
# Update age recipients in the SOPS creation rules temporarily.
|
||||||
|
# Requires mikefarah/yq v4 and simple comma-separated age fields.
|
||||||
|
export AGE_PUBLIC_KEY
|
||||||
|
|
||||||
|
if ! yq -e \
|
||||||
|
'.creation_rules | any(.[]; has("age"))' \
|
||||||
|
"$SOPS_CONFIG" >/dev/null; then
|
||||||
|
echo "No creation_rules with an age field found in .sops.yaml" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
yq -i '
|
||||||
|
(.creation_rules[] | select(has("age")) | .age) |= (
|
||||||
|
split(",")
|
||||||
|
| map(trim)
|
||||||
|
| map(select(. != ""))
|
||||||
|
| . + [strenv(AGE_PUBLIC_KEY)]
|
||||||
|
| unique
|
||||||
|
| join(",")
|
||||||
|
)
|
||||||
|
' "$SOPS_CONFIG"
|
||||||
|
|
||||||
|
echo "Updating SOPS recipients for secrets in $VM_FOLDER..."
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
SECRET_FILES=("$VM_DIR"/secrets/*)
|
||||||
|
shopt -u nullglob
|
||||||
|
|
||||||
|
if [[ ${#SECRET_FILES[@]} -eq 0 ]]; then
|
||||||
|
echo "No secret files found in $VM_DIR/secrets" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
for secret in "${SECRET_FILES[@]}"; do
|
||||||
|
[[ -f "$secret" ]] || continue
|
||||||
|
echo "Updating recipients: ${secret#"$SCRIPT_DIR"/}"
|
||||||
|
sops updatekeys --yes "$secret"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Building VM metadata..."
|
||||||
|
|
||||||
# Build the NixOS LXC metadata tarball
|
|
||||||
TARBALL_DIR="$(nix build \
|
TARBALL_DIR="$(nix build \
|
||||||
".#nixosConfigurations.${VMNAME}.config.system.build.metadata" \
|
"./$VM_FOLDER#nixosConfigurations.${VMNAME}.config.system.build.metadata" \
|
||||||
--print-out-paths)"
|
--print-out-paths)"
|
||||||
|
|
||||||
# Find the tarball
|
|
||||||
TARBALL="$(find "$TARBALL_DIR" -type f -name '*.tar.xz' -print -quit)"
|
TARBALL="$(find "$TARBALL_DIR" -type f -name '*.tar.xz' -print -quit)"
|
||||||
|
|
||||||
if [[ -z "$TARBALL" ]]; then
|
if [[ -z "$TARBALL" ]]; then
|
||||||
echo "Could not find a .tar.xz tarball in: $TARBALL_DIR"
|
echo "Could not find a .tar.xz tarball in: $TARBALL_DIR" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Metadata tarball: $TARBALL"
|
echo "Metadata tarball: $TARBALL"
|
||||||
|
|
||||||
# Build the QEMU disk image
|
echo "Building QEMU disk image..."
|
||||||
|
|
||||||
QCOW2_DIR="$(nix build \
|
QCOW2_DIR="$(nix build \
|
||||||
".#nixosConfigurations.${VMNAME}.config.system.build.qemuImage" \
|
"./$VM_FOLDER#nixosConfigurations.${VMNAME}.config.system.build.qemuImage" \
|
||||||
--print-out-paths)"
|
--print-out-paths)"
|
||||||
|
|
||||||
QCOW2="$QCOW2_DIR/nixos.qcow2"
|
QCOW2="$QCOW2_DIR/nixos.qcow2"
|
||||||
|
|
||||||
if [[ ! -f "$QCOW2" ]]; then
|
if [[ ! -f "$QCOW2" ]]; then
|
||||||
echo "QEMU image not found: $QCOW2"
|
echo "QEMU image not found: $QCOW2" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Found QEMU image: $QCOW2"
|
echo "QEMU image: $QCOW2"
|
||||||
|
|
||||||
echo
|
|
||||||
echo "Importing image into Incus..."
|
echo "Importing image into Incus..."
|
||||||
|
|
||||||
incus image import \
|
incus image import \
|
||||||
@@ -56,6 +178,5 @@ incus image import \
|
|||||||
"$TARBALL" \
|
"$TARBALL" \
|
||||||
"$QCOW2"
|
"$QCOW2"
|
||||||
|
|
||||||
echo
|
|
||||||
echo "Successfully imported image: $ALIAS"
|
echo "Successfully imported image: $ALIAS"
|
||||||
|
|
||||||
@@ -27,9 +27,7 @@
|
|||||||
pkgs.runCommand "sops-decrypt-${filename}"
|
pkgs.runCommand "sops-decrypt-${filename}"
|
||||||
{
|
{
|
||||||
# Use special separate injectable key that can only decrypt these dummy secrets
|
# Use special separate injectable key that can only decrypt these dummy secrets
|
||||||
SOPS_AGE_KEY_FILE = "/home/roy/.config/sops/age/virtual-key.txt";
|
SOPS_AGE_KEY_FILE = "/run/sops-virtual-key.txt";
|
||||||
|
|
||||||
__noChroot = true;
|
|
||||||
}
|
}
|
||||||
''
|
''
|
||||||
${pkgs.sops}/bin/sops -d ${./secrets}/${filename} > $out
|
${pkgs.sops}/bin/sops -d ${./secrets}/${filename} > $out
|
||||||
|
|||||||
Reference in new issue
Block a user