Linux and Bash for Developers · Environment, Networking and Remote Access
SSH Keys, Permissions and Config
Create SSH keys, fix 'unprotected private key' errors, and simplify connections with ~/.ssh/config and jump hosts.
Scenario
A new developer can't log in to the bastion host: SSH ignores their key with UNPROTECTED PRIVATE KEY FILE!. Another team shares one private key in a chat channel, and everyone types long ssh -i ... -p ... user@host commands from a wiki page.
What you see in production
Permissions 0644 for 'id_ed25519' are too openandPermission denied (publickey).- Shared keys that can't be revoked for one person.
- Long, error-prone SSH commands, and agent forwarding used to hop between hosts.
The naive code
cp shared_key ~/.ssh/id_rsa # one key for the whole team
chmod 644 ~/.ssh/id_rsa # "so it can be read"
ssh -i ~/.ssh/id_rsa -p 2222 -A [email protected]
Reproduce it
mkdir -p "$HOME/.ssh" && chmod 700 "$HOME/.ssh"
ssh-keygen -q -t ed25519 -N '' -C 'ana@laptop' -f "$HOME/.ssh/id_ed25519"
chmod 644 "$HOME/.ssh/id_ed25519"
ssh-keygen -y -f "$HOME/.ssh/id_ed25519" 2>&1 | grep -E 'UNPROTECTED|too open' | head -n 2 | sed "s|$HOME|~|"
Output
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @ Permissions 0644 for '~/.ssh/id_ed25519' are too open.
Run this on your computer — see “Get Started” for setup.
Root cause
SSH refuses private keys that other users could read, because anyone who can read the key can log in as you. Shared keys make it impossible to know who did what or to remove one person's access.
The fix
One key per person (and per machine), correct permissions, and a config file instead of long commands:
mkdir -p "$HOME/.ssh" && chmod 700 "$HOME/.ssh"
ssh-keygen -q -t ed25519 -N '' -C 'ana@laptop' -f "$HOME/.ssh/id_ed25519"
chmod 600 "$HOME/.ssh/id_ed25519"
stat -c '%a %n' "$HOME/.ssh" "$HOME/.ssh/id_ed25519" "$HOME/.ssh/id_ed25519.pub" | sed "s|$HOME|~|"
cat > "$HOME/.ssh/config" <<'EOF'
Host bastion
HostName bastion.example.com
User ana
IdentityFile ~/.ssh/id_ed25519
Host app-*
User deploy
ProxyJump bastion
IdentityFile ~/.ssh/id_ed25519
EOF
chmod 600 "$HOME/.ssh/config"
ssh -F "$HOME/.ssh/config" -G app-1 | grep -E '^(user|proxyjump|hostname) ' | sort
Output
700 ~/.ssh 600 ~/.ssh/id_ed25519 644 ~/.ssh/id_ed25519.pub hostname app-1 proxyjump bastion user deploy
Run this on your computer — see “Get Started” for setup.
ssh-keygen -t ed25519creates a modern key; protect it with a passphrase and usessh-agent.- Permissions:
~/.ssh700, private keys600,authorized_keys600. - Add public keys to servers (
ssh-copy-idor configuration management); remove them when people leave. - Use
ProxyJump(or-J) to reach private hosts through a bastion instead of agent forwarding (-A), which lets the bastion use your agent. ssh -G hostprints the effective configuration without connecting, which is handy for debugging (-F filetests a specific config file).
Trade-offs
- Passphrases add safety but need an agent for convenience.
- For larger teams, SSH certificates (signed by a CA, short-lived) or cloud session managers scale better than managing
authorized_keysfiles. - Hardware-backed keys (
ed25519-sk) protect against key theft but need a security key present.
Detect it in production
- Audit
authorized_keyson servers against your team list. - Log and alert on SSH logins to production; prefer short-lived access.
ssh -vshows which keys are offered and why authentication fails.
Key points
- Private keys must be readable only by you (600); ~/.ssh must be 700.
- One key per person; never share private keys.
- Use ~/.ssh/config and ProxyJump instead of long commands and agent forwarding.
Further reading: ssh_config(5) · ssh-keygen(1)
Practice questions
Why does SSH reject a private key with mode 644?
Answer
Other users could read the key and impersonate you, so ssh refuses keys that aren't private (600).
What's the advantage of ProxyJump over agent forwarding?
Answer
Your keys stay on your machine; with agent forwarding, anyone with root on the jump host can use your agent while you're connected.
How do you see the effective SSH settings for a host?
Answer
ssh -G host prints the configuration after applying ~/.ssh/config and defaults, without connecting.
Open in the app to mark lessons complete, take notes and track your progress.