From aa148fe435bfed76d0073b22396761d56f585050 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Jun 2026 22:12:39 +0000 Subject: [PATCH 1/6] Initial plan From db1a88ab2eb877726b723113ff956610f9ec545f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Jun 2026 22:14:06 +0000 Subject: [PATCH 2/6] fix: repair legacy factory ssh key passphrases --- modules/core/ssh-bootstrap.nix | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/modules/core/ssh-bootstrap.nix b/modules/core/ssh-bootstrap.nix index e88dcd8..91c6160 100644 --- a/modules/core/ssh-bootstrap.nix +++ b/modules/core/ssh-bootstrap.nix @@ -31,7 +31,7 @@ lib.mkIf userExists { }; systemd.services.factory-ssh-keygen = { - description = "Generate factory SSH key for ${userName} if missing"; + description = "Generate or repair factory SSH key for ${userName}"; wantedBy = [ "multi-user.target" ]; after = [ "ssh-passphrase-setup.service" ]; requires = [ "ssh-passphrase-setup.service" ]; @@ -41,12 +41,34 @@ lib.mkIf userExists { }; path = [ pkgs.openssh pkgs.coreutils ]; script = '' - if [ ! -f "${keyPath}" ]; then - PASSPHRASE=$(cat /var/lib/secrets/ssh-passphrase) + PASSPHRASE=$(cat /var/lib/secrets/ssh-passphrase) + + generate_factory_key() { ssh-keygen -q -N "$PASSPHRASE" -t ed25519 -f "${keyPath}" chown ${userName}:users "${keyPath}" "${keyPath}.pub" chmod 600 "${keyPath}" chmod 644 "${keyPath}.pub" + } + + if [ ! -f "${keyPath}" ]; then + generate_factory_key + elif ! ssh-keygen -y -P "$PASSPHRASE" -f "${keyPath}" >/dev/null 2>&1; then + backup_suffix=$(date -u +%Y%m%d%H%M%S) + backup_path="${keyPath}.bak-$backup_suffix" + backup_index=0 + + while [ -e "$backup_path" ] || [ -e "$backup_path.pub" ]; do + backup_index=$((backup_index + 1)) + backup_path="${keyPath}.bak-$backup_suffix-$backup_index" + done + + mv "${keyPath}" "$backup_path" + + if [ -f "${keyPath}.pub" ]; then + mv "${keyPath}.pub" "$backup_path.pub" + fi + + generate_factory_key fi ''; }; From 181465c3762092e27d4e342df076d101268383af Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Jun 2026 22:14:42 +0000 Subject: [PATCH 3/6] chore: log legacy ssh key regeneration --- modules/core/ssh-bootstrap.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/core/ssh-bootstrap.nix b/modules/core/ssh-bootstrap.nix index 91c6160..d200510 100644 --- a/modules/core/ssh-bootstrap.nix +++ b/modules/core/ssh-bootstrap.nix @@ -53,6 +53,7 @@ lib.mkIf userExists { if [ ! -f "${keyPath}" ]; then generate_factory_key elif ! ssh-keygen -y -P "$PASSPHRASE" -f "${keyPath}" >/dev/null 2>&1; then + echo "Existing factory SSH key does not match current passphrase; backing it up and generating a replacement." backup_suffix=$(date -u +%Y%m%d%H%M%S) backup_path="${keyPath}.bak-$backup_suffix" backup_index=0 From 439021f798bf08451a027a3218fc44b26bc756f3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Jun 2026 22:15:24 +0000 Subject: [PATCH 4/6] chore: harden ssh bootstrap script --- modules/core/ssh-bootstrap.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/core/ssh-bootstrap.nix b/modules/core/ssh-bootstrap.nix index d200510..dedf934 100644 --- a/modules/core/ssh-bootstrap.nix +++ b/modules/core/ssh-bootstrap.nix @@ -41,6 +41,8 @@ lib.mkIf userExists { }; path = [ pkgs.openssh pkgs.coreutils ]; script = '' + set -eu + PASSPHRASE=$(cat /var/lib/secrets/ssh-passphrase) generate_factory_key() { @@ -54,7 +56,7 @@ lib.mkIf userExists { generate_factory_key elif ! ssh-keygen -y -P "$PASSPHRASE" -f "${keyPath}" >/dev/null 2>&1; then echo "Existing factory SSH key does not match current passphrase; backing it up and generating a replacement." - backup_suffix=$(date -u +%Y%m%d%H%M%S) + backup_suffix=$(date -u +%Y%m%d_%H%M%S) backup_path="${keyPath}.bak-$backup_suffix" backup_index=0 From 31abf40722baf6e23fedad393691fe557f7d6556 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Jun 2026 22:16:05 +0000 Subject: [PATCH 5/6] chore: serialize ssh bootstrap key repairs --- modules/core/ssh-bootstrap.nix | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/core/ssh-bootstrap.nix b/modules/core/ssh-bootstrap.nix index dedf934..facbf1b 100644 --- a/modules/core/ssh-bootstrap.nix +++ b/modules/core/ssh-bootstrap.nix @@ -44,6 +44,14 @@ lib.mkIf userExists { set -eu PASSPHRASE=$(cat /var/lib/secrets/ssh-passphrase) + lock_dir="${keyPath}.lock" + + if ! mkdir "$lock_dir"; then + echo "Factory SSH key setup is already running." >&2 + exit 1 + fi + + trap 'rmdir "$lock_dir"' EXIT generate_factory_key() { ssh-keygen -q -N "$PASSPHRASE" -t ed25519 -f "${keyPath}" From 7f975bc4f1a93f9acac16b01cf7c102f09af0bf7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Jun 2026 22:16:44 +0000 Subject: [PATCH 6/6] chore: use flock for ssh bootstrap repair --- modules/core/ssh-bootstrap.nix | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/core/ssh-bootstrap.nix b/modules/core/ssh-bootstrap.nix index facbf1b..9a0c7ba 100644 --- a/modules/core/ssh-bootstrap.nix +++ b/modules/core/ssh-bootstrap.nix @@ -39,20 +39,20 @@ lib.mkIf userExists { Type = "oneshot"; RemainAfterExit = true; }; - path = [ pkgs.openssh pkgs.coreutils ]; + path = [ pkgs.openssh pkgs.coreutils pkgs.util-linux ]; script = '' set -eu PASSPHRASE=$(cat /var/lib/secrets/ssh-passphrase) - lock_dir="${keyPath}.lock" + lock_file="${keyPath}.lock" - if ! mkdir "$lock_dir"; then + exec 9>"$lock_file" + + if ! flock -n 9; then echo "Factory SSH key setup is already running." >&2 exit 1 fi - trap 'rmdir "$lock_dir"' EXIT - generate_factory_key() { ssh-keygen -q -N "$PASSPHRASE" -t ed25519 -f "${keyPath}" chown ${userName}:users "${keyPath}" "${keyPath}.pub" @@ -63,8 +63,7 @@ lib.mkIf userExists { if [ ! -f "${keyPath}" ]; then generate_factory_key elif ! ssh-keygen -y -P "$PASSPHRASE" -f "${keyPath}" >/dev/null 2>&1; then - echo "Existing factory SSH key does not match current passphrase; backing it up and generating a replacement." - backup_suffix=$(date -u +%Y%m%d_%H%M%S) + backup_suffix="$(date -u +%Y%m%d_%H%M%S)-$$" backup_path="${keyPath}.bak-$backup_suffix" backup_index=0 @@ -73,6 +72,7 @@ lib.mkIf userExists { backup_path="${keyPath}.bak-$backup_suffix-$backup_index" done + echo "Existing factory SSH key does not match current passphrase; backing it up to $backup_path and generating a replacement." mv "${keyPath}" "$backup_path" if [ -f "${keyPath}.pub" ]; then