Skip to content

Bug: Passphrase-Protected SSH Key Silently Fails During Automated Deployment #411

@josecelano

Description

@josecelano

Overview

When a user configures a passphrase-protected SSH private key in ssh_credentials, the deployer fails silently during provision with a misleading Permission denied (publickey,password) error. The root cause — that the key is encrypted and cannot be decrypted without a passphrase in an unattended environment — is never surfaced to the user.

This was triggered during the Hetzner demo deployment (#405) where a fresh deployment key was created with a passphrase. In an interactive terminal session the OS SSH agent transparently decrypts the key, so the error only appears when running the deployer in an automated context (Docker container, CI/CD pipeline) where no agent is available.

There is no blocking code fix required — passphrase-protected keys are valid in some workflows (e.g. with SSH agent forwarding). The two actions needed are:

  1. Early warning in create environment — detect passphrase-protected keys and notify the user before they reach provision
  2. Documentation — add a user guide section on SSH key handling and the supported workflows

Specification

See detailed specification: docs/issues/411-bug-ssh-key-passphrase-breaks-automated-deployment.md

Implementation Plan

Phase 1: Detection and warning (code change)

  • Implement is_passphrase_protected(path: &Path) -> bool in src/adapters/ssh/ssh/credentials.rs (or a new key_inspector.rs module)
    • Check for ENCRYPTED in PEM header (legacy format)
    • Check for bcrypt near the start of the decoded OpenSSH body
    • Return false on any I/O or parse error
  • In the create environment handler (handler.rs): after LoadConfiguration, call the detection function and emit a warning via user_output if the key appears to be passphrase-protected
  • Add unit test it_detects_passphrase_protected_key

Phase 2: Documentation

  • Create docs/user-guide/ssh-keys.md covering all workflows and security notes
  • Update docs/user-guide/providers/hetzner.md with an SSH key requirements note
  • Update docs/user-guide/commands/create.md to mention the passphrase warning
  • Update docs/user-guide/README.md to link to the new ssh-keys.md page

Phase 3: Linting and pre-commit

  • Run linters: cargo run --bin linter all
  • Run pre-commit: ./scripts/pre-commit.sh

Acceptance Criteria

Note for Contributors: These criteria define what the PR reviewer will check. Use this as your pre-review checklist before submitting the PR to minimize back-and-forth iterations.

Quality Checks:

  • Pre-commit checks pass: ./scripts/pre-commit.sh

Task-Specific Criteria:

  • create environment emits a visible warning (not an error) when the configured private key file is passphrase-protected
  • create environment still succeeds (environment is created) even when the warning is emitted — the user is not blocked
  • create environment emits no warning when the key is unencrypted
  • The warning message names all three resolution options (remove passphrase, agent forwarding, separate key)
  • docs/user-guide/ssh-keys.md exists and covers key requirements, workflows, and security notes
  • docs/user-guide/providers/hetzner.md references the SSH key requirements

Related

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdocsrust

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions