diff --git a/home/user.nix b/home/user.nix index 0d63cc3..977717e 100644 --- a/home/user.nix +++ b/home/user.nix @@ -1,7 +1,7 @@ { pkgs, ... }: { - home.stateVersion = "25.11"; + home.stateVersion = "26.05"; programs.home-manager.enable = true; diff --git a/hosts/desktop/default.nix b/hosts/desktop/default.nix index 6685a6a..04cbddc 100644 --- a/hosts/desktop/default.nix +++ b/hosts/desktop/default.nix @@ -8,6 +8,8 @@ networking.hostName = "desktop"; + users.users.root.hashedPassword = null; + users.users.user = { isNormalUser = true; home = "/home/user"; @@ -29,5 +31,5 @@ users.user = import ../../home/user.nix; }; - system.stateVersion = "25.11"; + system.stateVersion = "26.05"; } diff --git a/scripts/bootstrap-host.sh b/scripts/bootstrap-host.sh index a6c1260..8e4a082 100755 --- a/scripts/bootstrap-host.sh +++ b/scripts/bootstrap-host.sh @@ -1,168 +1,127 @@ #!/usr/bin/env bash - set -euo pipefail -REPO_DIR="/home/user/nixos-config" -PERSIST_DIR="/persist" -KEY_DIR="${PERSIST_DIR}/keys" -HOST_KEY="${KEY_DIR}/host-age.key" +umask 077 -SOPS_TEMPLATE="${REPO_DIR}/.sops.yaml.template" -LOCAL_SOPS="${REPO_DIR}/.sops.yaml" +# Repository containing this script. +REPO="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)" -echo "==> NixOS host bootstrap" +# Mounted target system. +TARGET="/mnt" +PERSIST="$TARGET/persist" -if [[ "${EUID}" -ne 0 ]]; then - echo "ERROR: Dieses Script muss als root ausgeführt werden." - exit 1 -fi +KEY_DIR="$PERSIST/keys" +HOST_KEY="$KEY_DIR/host-age.key" -if ! command -v age-keygen >/dev/null 2>&1; then - echo "ERROR: age-keygen wurde nicht gefunden." - exit 1 -fi +SOPS_TEMPLATE="$REPO/.sops.yaml.template" +SOPS_CONFIG="$REPO/.sops.yaml" -if ! command -v sops >/dev/null 2>&1; then - echo "ERROR: sops wurde nicht gefunden." +if [[ $EUID -ne 0 ]]; then + echo "ERROR: run this script as root." exit 1 fi if [[ -z "${SOPS_AGE_KEY_FILE:-}" ]]; then - echo "ERROR: SOPS_AGE_KEY_FILE ist nicht gesetzt." + echo "ERROR: SOPS_AGE_KEY_FILE is not set." echo - echo "Beispiel:" + echo "Example:" + echo " sudo env SOPS_AGE_KEY_FILE=age/yubikey-a.txt ./scripts/bootstrap-host.sh" + exit 1 +fi + +if [[ ! -f "$SOPS_AGE_KEY_FILE" ]]; then + echo "ERROR: YubiKey identity file not found:" + echo " $SOPS_AGE_KEY_FILE" + exit 1 +fi + +if [[ ! -d "$PERSIST" ]]; then + echo "ERROR: /mnt/persist is not mounted." + exit 1 +fi + +if [[ ! -f "$SOPS_TEMPLATE" ]]; then + echo "ERROR: missing SOPS template:" + echo " $SOPS_TEMPLATE" + exit 1 +fi + +if [[ -e "$HOST_KEY" ]]; then + echo "ERROR: host age key already exists:" + echo " $HOST_KEY" echo - echo " SOPS_AGE_KEY_FILE=${REPO_DIR}/age/yubikey-a.txt \\" - echo " sudo -E ${REPO_DIR}/scripts/bootstrap-host.sh" + echo "Refusing to overwrite it." exit 1 fi -if [[ ! -f "${SOPS_AGE_KEY_FILE}" ]]; then - echo "ERROR: SOPS_AGE_KEY_FILE existiert nicht:" - echo " ${SOPS_AGE_KEY_FILE}" - exit 1 -fi - -if ! mountpoint -q "${PERSIST_DIR}"; then - echo "ERROR: ${PERSIST_DIR} ist nicht gemountet." - exit 1 -fi - -if [[ ! -d "${REPO_DIR}" ]]; then - echo "ERROR: Repository fehlt:" - echo " ${REPO_DIR}" - exit 1 -fi - -if [[ ! -f "${SOPS_TEMPLATE}" ]]; then - echo "ERROR: SOPS template fehlt:" - echo " ${SOPS_TEMPLATE}" - exit 1 -fi - -if [[ -e "${HOST_KEY}" ]]; then - echo "ERROR: Host-Key existiert bereits:" - echo " ${HOST_KEY}" +if [[ -e "$SOPS_CONFIG" ]]; then + echo "ERROR: local .sops.yaml already exists:" + echo " $SOPS_CONFIG" echo - echo "Es wird nichts überschrieben." + echo "Refusing to overwrite it." exit 1 fi -if [[ -e "${LOCAL_SOPS}" ]]; then - echo "ERROR: Lokale .sops.yaml existiert bereits:" - echo " ${LOCAL_SOPS}" - echo - echo "Es wird nichts überschrieben." +echo "==> Checking SOPS access through YubiKey..." + +if ! sops --config "$SOPS_TEMPLATE" decrypt \ + "$REPO/secrets/user-password.yaml" >/dev/null; then + echo "ERROR: SOPS could not decrypt the test secret." + echo "Check the YubiKey and SOPS_AGE_KEY_FILE." exit 1 fi -echo -echo "==> SOPS identity:" -echo " ${SOPS_AGE_KEY_FILE}" +echo " YubiKey SOPS access: OK" -echo -echo "==> Erzeuge Host-age-Key" +echo "==> Creating host age key..." -install -d -m 0700 "${KEY_DIR}" +install -d -m 0700 "$KEY_DIR" -age-keygen -o "${HOST_KEY}" +age-keygen -o "$HOST_KEY" -chmod 0600 "${HOST_KEY}" -chown root:root "${HOST_KEY}" +chmod 0600 "$HOST_KEY" +chown root:root "$HOST_KEY" -HOST_RECIPIENT="$(age-keygen -y "${HOST_KEY}")" +HOST_RECIPIENT="$(age-keygen -y "$HOST_KEY")" -echo -echo "==> Host recipient:" -echo -echo " ${HOST_RECIPIENT}" +echo " Host recipient:" +echo " $HOST_RECIPIENT" -echo -echo "==> Erzeuge lokale .sops.yaml" +echo "==> Creating local .sops.yaml..." -sed "s/AGE_HOST_D/${HOST_RECIPIENT}/g" \ - "${SOPS_TEMPLATE}" > "${LOCAL_SOPS}" +sed \ + "s|AGE_HOST_D|$HOST_RECIPIENT|g" \ + "$SOPS_TEMPLATE" \ + > "$SOPS_CONFIG" -chmod 0600 "${LOCAL_SOPS}" +chmod 0600 "$SOPS_CONFIG" -echo -echo "============================================================" -echo "Der Host-Key wurde erzeugt." -echo -echo "Private Key:" -echo " ${HOST_KEY}" -echo -echo "Lokale SOPS-Konfiguration:" -echo " ${LOCAL_SOPS}" -echo -echo "Jetzt werden die vorhandenen Secrets auf" -echo "YubiKey A + YubiKey B + Recovery + Host" -echo "rekeyed." -echo "============================================================" -echo +echo "==> Rekeying secrets..." -read -r -p "Rekeying jetzt durchführen? [y/N] " answer - -if [[ "${answer}" != "y" && "${answer}" != "Y" ]]; then - echo - echo "Abgebrochen." - echo - echo "Der Host-Key und .sops.yaml wurden bereits erzeugt." - echo "Das Rekeying wurde NICHT durchgeführt." - exit 0 -fi +export SOPS_CONFIG shopt -s nullglob -secret_files=( "${REPO_DIR}"/secrets/*.yaml ) -shopt -u nullglob +secrets=( "$REPO"/secrets/*.yaml ) -if [[ "${#secret_files[@]}" -eq 0 ]]; then - echo - echo "Keine secrets/*.yaml gefunden." - echo "Host-Key wurde erfolgreich erzeugt." - exit 0 +if (( ${#secrets[@]} == 0 )); then + echo " No secrets found." +else + for secret in "${secrets[@]}"; do + echo " Updating $(basename "$secret")" + + sops updatekeys --yes "$secret" + done fi echo -echo "==> Rekeye Secrets" - -for secret in "${secret_files[@]}"; do - echo - echo "Updating:" - echo " ${secret}" - - SOPS_AGE_KEY_FILE="${SOPS_AGE_KEY_FILE}" \ - sops updatekeys --yes "${secret}" -done - -echo -echo "==> Bootstrap abgeschlossen." -echo -echo "Host recipient:" -echo " ${HOST_RECIPIENT}" +echo "==> Bootstrap complete." echo echo "Host key:" -echo " ${HOST_KEY}" +echo " $HOST_KEY" echo -echo "SOPS config:" -echo " ${LOCAL_SOPS}" +echo "SOPS configuration:" +echo " $SOPS_CONFIG" +echo +echo "You can now run:" +echo +echo " nixos-install --flake $REPO#desktop"