Knowledge base

Add an SSH key and switch passwords off

Generate an ed25519 key, install it properly, test it before you break anything, and turn password authentication off for good.

Generate the key on the machine you sit at

Not on the server. The private half should never exist on a host you might lose access to, and copying it around defeats the point of having one.

ssh-keygen -t ed25519 -a 100 -C "laptop-2026"

-a 100 sets the number of KDF rounds protecting the passphrase, which is the only thing standing between a stolen laptop and your fleet. Use a passphrase. If you own a hardware token, use that instead:

ssh-keygen -t ed25519-sk -O resident -C "token-1"

Install the public half

ssh-copy-id -i ~/.ssh/id_ed25519.pub deploy@<ipv4>

By hand, from a root session, if the account has no password yet:

install -d -m 700 -o deploy -g deploy /home/deploy/.ssh
install -m 600 -o deploy -g deploy /dev/null /home/deploy/.ssh/authorized_keys
cat >> /home/deploy/.ssh/authorized_keys

Paste the single line, then Ctrl-D. Permissions matter more than people expect: sshd refuses a group-writable home or .ssh directory and explains itself only in the daemon log, never to the client.

Restrict the key while you are in there

Options in authorized_keys apply per key. restrict switches everything off, and then you add back what the key genuinely needs:

restrict,pty ssh-ed25519 AAAAC3Nza... deploy@laptop

A key that exists to run one job should be allowed to run one job:

restrict,command="/usr/local/bin/backup-receive" ssh-ed25519 AAAAC3Nza... backup

Test before you lock

Leave the first session connected. From a second terminal:

ssh -o PreferredAuthentications=publickey deploy@<ipv4> id

If that prints your uid, the key path works. If it does not, ssh -vvv on the client and journalctl -u ssh -n 50 on the server will between them say which side is unhappy. It is permissions roughly half the time and the wrong username most of the rest.

Switch passwords off

cat > /etc/ssh/sshd_config.d/20-keys-only.conf <<EOF
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitEmptyPasswords no
AuthenticationMethods publickey
EOF
sshd -t && systemctl reload ssh

AuthenticationMethods publickey is the belt under the braces. Even if a later drop-in quietly re-enables passwords, the daemon still refuses anything that is not a key.

Confirm from the client that the door is shut:

ssh -o PreferredAuthentications=password deploy@<ipv4>

The expected result is Permission denied (publickey).

Keys at deploy time

The panel keeps a key list per account. Tick the ones you want and cloud-init writes them during first boot, which means an instance can exist for the first time with password authentication already off. Attaching the key to the order turns the ten minutes above into one.

When you lose the key

There is no identity-based recovery here, because we hold no identity. The out-of-band console is the way back: it reaches the instance over a path that never touches sshd, and from a rescue shell you can append a new key and carry on.

Keep a second key on a second machine and you will never need to read that article.

Ready when you are

Pick a city. Pick a size. Pay in coin.

No forms about who you are, no wait for a human to approve you, no phone call to verify anything. The invoice clears and the credentials land in your inbox.