Why keys
A password can be guessed; a 256-bit Ed25519 key cannot. Every Ubuntu server on Joy is exposed to the internet from the first boot, and password guessing starts within minutes. Keys make brute force pointless and let scripts log in without secrets in plain text.
1. Generate a key pair (on your computer)
# Linux / macOS / Windows 10+ (PowerShell has ssh-keygen)
ssh-keygen -t ed25519 -C "you@example.com"
# accept the default path (~/.ssh/id_ed25519) and choose a passphrase
This creates a private key (id_ed25519 — never share it) and a public key (id_ed25519.pub — safe to paste anywhere).
2. Install the public key
At deploy time (recommended): paste the contents of id_ed25519.pub into the SSH key field on the deploy page; it is written to /root/.ssh/authorized_keys before first boot.
On an existing server:
ssh-copy-id root@YOUR_IP # enter the password from the server page once
# or manually:
cat ~/.ssh/id_ed25519.pub | ssh root@YOUR_IP 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'
Test in a new terminal: ssh root@YOUR_IP should log in without asking for the server password (it may ask for your key passphrase).
3. Create a non-root user (good practice)
adduser deploy
usermod -aG sudo deploy
mkdir -p /home/deploy/.ssh && cp /root/.ssh/authorized_keys /home/deploy/.ssh/
chown -R deploy:deploy /home/deploy/.ssh && chmod 700 /home/deploy/.ssh && chmod 600 /home/deploy/.ssh/authorized_keys
4. Disable password authentication
Only after step 2 works from a new terminal.
sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
# Ubuntu 24.04 ships a drop-in that may override the file:
printf 'PasswordAuthentication no\n' > /etc/ssh/sshd_config.d/50-joy.conf
sshd -t && systemctl restart ssh
5. Keep a way back in
- The noVNC console on the server page works regardless of SSH configuration and lets you log in with the root password.
- Reset password on the server page generates a new root password through the guest agent — useful if you lock yourself out.
- Keep a second key (for example on a phone or a hardware token) in
authorized_keys.
6. Using the key from scripts and CI
Store the private key as a secret in your CI system and write it to a file with mode 600 at job start. Use ssh -o StrictHostKeyChecking=accept-new for first contact with freshly deployed servers, and note that reinstalling a server regenerates its host key, so clear the old entry with ssh-keygen -R YOUR_IP after a reinstall.
7. Windows servers
Windows Server 2019+ can run OpenSSH Server (Settings → Optional features or Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0), but most people use RDP. Keys for administrators go in C:\ProgramData\ssh\administrators_authorized_keys. See the Windows RDP guide for securing RDP itself.
Common problems
"Permission denied (publickey)" — wrong permissions on ~/.ssh (700) or authorized_keys (600), or the key is for a different user. Still asked for a password — a drop-in file in /etc/ssh/sshd_config.d/ overrides your change; check with sshd -T | grep -i passwordauth. Host key changed warning — expected after a reinstall; remove the old entry with ssh-keygen -R.