SSH Key and Config File Permissions in CI
OpenSSH ignores private keys and config files that are readable or writable by others, so CI must set strict modes.
Most "publickey" failures in CI are really permission failures: a key written from a secret lands at the default umask and ssh refuses it. The fix is a few chmod calls.
What it does
OpenSSH checks ownership and mode on the private key, the config file, and the ~/.ssh directory. A private key must not be group- or world-accessible; ssh skips it otherwise. The config file must not be group- or world-writable. ~/.ssh should be 700.
Common usage
mkdir -p ~/.ssh && chmod 700 ~/.ssh
# write the key with safe perms from the start
install -m 600 /dev/null ~/.ssh/deploy_key
printf '%s\n' "$DEPLOY_KEY" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key ~/.ssh/config ~/.ssh/known_hostsOptions
| Path | Required mode |
|---|---|
| ~/.ssh (directory) | 700 (drwx------) |
| private key | 600 (-rw-------) |
| ~/.ssh/config | 600 (not group/world-writable) |
| known_hosts | 600 (writable for accept-new) |
| *.pub / authorized_keys | 644 is acceptable |
In CI
Set permissions right when you write the file: install -m 600 /dev/null key creates it locked before you fill it. Restoring a key from a cache can reset its mode, so chmod again after restore. The directory matters too: a world-writable ~/.ssh triggers errors even with a correct key mode.
Common errors in CI
"Permissions 0644 for 'deploy_key' are too open. ... This private key will be ignored." then "Permission denied (publickey)" is the canonical sequence; chmod 600 the key. "Bad owner or permissions on /root/.ssh/config" means the config is too permissive or wrongly owned. "Load key 'deploy_key': bad permissions" is the same root cause.