From 54c930d8dd2976b68686410f47fd889848c25363 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 23 Oct 2026 22:20:05 +0200 Subject: [PATCH] fix(install): keep operator SSH keys that mention coolify On a fresh install, install.sh removed every authorized_keys line that contained "coolify", including unrelated operator keys such as one commented "coolify-disposable". Remove only lines whose comment is exactly "coolify", the comment of the installer's own key. Closes #12278 Co-Authored-By: Claude Opus 5.5 --- other/nightly/install.sh | 3 +- scripts/install.sh | 3 +- scripts/restore-backup-vm.sh | 2 +- .../Unit/InstallScriptAuthorizedKeysTest.php | 36 +++++++++++++++++++ 4 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 tests/Unit/InstallScriptAuthorizedKeysTest.php diff --git a/other/nightly/install.sh b/other/nightly/install.sh index ebd309a021..f6975ef619 100755 --- a/other/nightly/install.sh +++ b/other/nightly/install.sh @@ -1006,7 +1006,8 @@ if [ "$IS_COOLIFY_VOLUME_EXISTS" -eq 0 ]; then test -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub && rm -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub ssh-keygen -t ed25519 -a 100 -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal -q -N "" -C coolify chown 9999 /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal - sed -i "/coolify/d" ~/.ssh/authorized_keys + # Remove only the key from a previous install (generated with the comment "coolify"), not other keys that contain "coolify" + sed -i -E "/[[:space:]]coolify[[:space:]]*$/d" ~/.ssh/authorized_keys cat /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub >>~/.ssh/authorized_keys rm -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub fi diff --git a/scripts/install.sh b/scripts/install.sh index 0c8c2ae6a8..93fef122e2 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -1006,7 +1006,8 @@ if [ "$IS_COOLIFY_VOLUME_EXISTS" -eq 0 ]; then test -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub && rm -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub ssh-keygen -t ed25519 -a 100 -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal -q -N "" -C coolify chown 9999 /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal - sed -i "/coolify/d" ~/.ssh/authorized_keys + # Remove only the key from a previous install (generated with the comment "coolify"), not other keys that contain "coolify" + sed -i -E "/[[:space:]]coolify[[:space:]]*$/d" ~/.ssh/authorized_keys cat /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub >>~/.ssh/authorized_keys rm -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub fi diff --git a/scripts/restore-backup-vm.sh b/scripts/restore-backup-vm.sh index 856e8fca1c..c60d6d6b8b 100755 --- a/scripts/restore-backup-vm.sh +++ b/scripts/restore-backup-vm.sh @@ -242,7 +242,7 @@ delete_vm "$VM_NAME" mkdir -p "$IMAGE_DIR" if [ ! -f "$SSH_KEY" ]; then - # The comment must not contain "coolify": install.sh removes such lines from authorized_keys. + # Do not use the comment "coolify": install.sh removes authorized_keys lines with exactly that comment. ssh-keygen -q -t ed25519 -N '' -C restore-test-vm -f "$SSH_KEY" fi diff --git a/tests/Unit/InstallScriptAuthorizedKeysTest.php b/tests/Unit/InstallScriptAuthorizedKeysTest.php new file mode 100644 index 0000000000..b2fd5136e4 --- /dev/null +++ b/tests/Unit/InstallScriptAuthorizedKeysTest.php @@ -0,0 +1,36 @@ +toHaveKey(1); + + $home = sys_get_temp_dir().'/coolify-install-keys-'.bin2hex(random_bytes(4)); + mkdir($home.'/.ssh', 0700, true); + file_put_contents($home.'/.ssh/authorized_keys', implode("\n", [ + 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOperatorKey coolify-disposable', + 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOperatorKey operator-lab', + 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHostKey root@coolify', + 'no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOptions deploy@coolify.example.com', + 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOldCoolifyKey coolify', + '', + ])); + + $process = new Process(['bash', '-c', $matches[1]], null, ['HOME' => $home]); + $process->mustRun(); + + expect(file_get_contents($home.'/.ssh/authorized_keys'))->toBe(implode("\n", [ + 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOperatorKey coolify-disposable', + 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOperatorKey operator-lab', + 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHostKey root@coolify', + 'no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOptions deploy@coolify.example.com', + '', + ])); + + exec('rm -rf '.escapeshellarg($home)); +})->with([ + 'stable install script' => ['scripts/install.sh'], + 'nightly install script' => ['other/nightly/install.sh'], +]);