Appearance
SSH Keys
Managed uses SSH keys to connect to your servers for running commands, installing services, and uploading files.
Automatic setup
When you run managed init, the wizard will:
- Scan
~/.ssh/for existing key pairs (id_ed25519,id_rsa,id_ecdsa) - Let you pick an existing key or generate a new one
- Save the choice in
managed.yamlunderdefaults
If you run managed apply without a configured SSH key, the same wizard runs automatically.
Generated keys
When you choose "Generate a new key", managed creates an Ed25519 key pair at:
.managed/ssh_keys/managed_ed25519
.managed/ssh_keys/managed_ed25519.pubThese are stored in your project directory (not ~/.ssh/), so each project can have its own key. The .managed/ directory should be added to .gitignore.
Manual setup
You can also generate a key manually:
bash
managed ssh generate-key
managed ssh generate-key --name my-key --dir ~/.sshConfiguration
SSH key settings live in the defaults section of managed.yaml:
yaml
defaults:
provider: digitalocean
ssh_key_name: managed_ed25519| Field | Description |
|---|---|
ssh_key_name | Base name of the key file (looked up in .managed/ssh_keys/ or ~/.ssh/) |
ssh_private_key_path | Full path to a private key (overrides directory lookup) |
ssh_key_directory | Directory to search for keys (default: .managed/ssh_keys) |
Using an existing key from ~/.ssh
yaml
defaults:
ssh_key_name: id_rsa
ssh_private_key_path: ~/.ssh/id_rsaUsing SSH agent
If you use an SSH agent (e.g. 1Password), set the key name to agent:
yaml
defaults:
ssh_key_name: agentThis skips file-based key lookup and uses the agent for authentication.
How it works
When managed apply creates a server:
- Resolves the SSH key from config defaults
- Reads the
.pubfile - Uploads the public key to the cloud provider
- Creates the server with that key
- Uses the private key for all subsequent SSH connections
The public key is uploaded once per provider, if it already exists with the same content, the upload is skipped.
Server identity (host keys)
The keys above prove who you are to the server. Servers also prove who they are: each one has an SSH identity (its host keys), and managed pins it.
The first time managed connects to a server — the moment it's provisioned or imported, which is a moment you control — the identity the server presents is recorded in the project (ssh_host_keys on the server's saved state). Every later connection requires the server to present that same identity, and is refused before any passwords or commands are sent if it doesn't. This is what stops someone on the network from impersonating your server and capturing credentials.
When a connection is refused you'll see:
✗ Stopped connecting to 'database-1' — it is not the server managed remembers.
Either it was rebuilt, or something between you and the server is
intercepting the connectionIf you didn't change the server, treat this seriously — don't connect until you understand why its identity changed.
If you did rebuild, restore, or reinstall the server on purpose, accept its new identity and retry:
bash
managed server trust database-1
managed applyServers set up before this feature simply have their identity recorded on the next connection — no action needed.