LFCS 113 ๐ง SSH Keys โ Generating and Deploying
The previous chapters configured the SSH server to accept key-based authentication and reject passwords. This chapter covers the client side: generating a key pair, deploying the public key to the server’s authorized_keys file, and fixing the permission errors that cause key authentication to fail silently. The LFCS exam tests the workflow and the specific permission requirements. The most common failure is not a wrong keyโit is a wrong permission on the .ssh directory or the authorized_keys file. OpenSSH refuses to use a key if the permissions are too permissive, and the error message (Permission denied (publickey)) does not indicate that the cause is a permission issue.
Key point: The private key stays on the client, with permissions 600. The public key goes to the server’s ~/.ssh/authorized_keys, which must also be 600. The .ssh directory on both sides must be 700. A home directory that is group-writable will also cause key authentication to fail.
Why key deployment requires precise permissions
The silent failure problem. OpenSSH checks the permissions of the .ssh directory, the private key, and the authorized_keys file before attempting authentication. If any of these are accessible to group or other users, the key is ignored. The server does not report “your authorized_keys is too permissive.” It reports “Permission denied (publickey),” which sends the administrator looking for a key mismatch that does not exist .
The private key protection problem. The private key is the credential. If it is readable by another user on the client machine, that user can authenticate as the key’s owner. The 600 permission on the private key ensures that only the owner can read it. The public key (644) is safe to share because it cannot be used to derive the private key .
The deployment problem. The public key must be appended to the server’s ~/.ssh/authorized_keys. The file can contain multiple keys, one per line. If the file does not exist, it must be created with the correct permissions before the key is added. If the file exists but has the wrong permissions, the key is ignored even if it is present .
The algorithm problem. The default key algorithm in modern OpenSSH is ed25519. It is faster and more secure than RSA at equivalent key sizes. RSA is still supported for compatibility with older systems, but the key size should be at least 4096 bits. The exam may ask for the command to generate an ed25519 key or an RSA key .
The trade-off. Keys without a passphrase are convenientโthey authenticate without any prompt. Keys with a passphrase are more secureโa stolen private key is useless without the passphrase. The ssh-agent caches the passphrase for a session, so the user types it once and the agent handles the rest. The exam tests the generation and deployment, not the agent configuration, but the passphrase is the security layer that makes the private key worth protecting.
a. Generating the key pair
The ssh-keygen command generates the key pair. The -t flag specifies the algorithm. The -b flag specifies the bit size for RSA. The -C flag adds a comment (typically the email address) for identification.
# Generate an ED25519 key (preferred)
ssh-keygen -t ed25519 -C "user@example.com"
# Generate an RSA key (for compatibility)
ssh-keygen -t rsa -b 4096 -C "user@example.com"
The command prompts for three things: the file path (default ~/.ssh/id_ed25519 or ~/.ssh/id_rsa), the passphrase (empty for no passphrase), and the confirmation of the passphrase. The private key is written to the specified path. The public key is written to the same path with a .pub extension .
# Default output paths for ED25519
~/.ssh/id_ed25519 # Private key
~/.ssh/id_ed25519.pub # Public key
The private key must not be shared. The public key is the file that will be deployed to the server.
b. Deploying the public key with ssh-copy-id
The ssh-copy-id command automates the deployment. It logs into the remote server (using password authentication, which must still be enabled), creates the ~/.ssh directory if it does not exist, and appends the public key to ~/.ssh/authorized_keys .
# Deploy the default key
ssh-copy-id user@server
# Deploy a specific key
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server
The -i flag specifies the public key file. If omitted, ssh-copy-id uses the default identity file or the keys loaded in the agent. The command prompts for the remote user’s password, then installs the key .
After deployment, the authorized_keys file on the server contains the public key. The file permissions are set by ssh-copy-id, but they should be verified.
# Verify the key is present
ssh user@server "cat ~/.ssh/authorized_keys"
# Verify permissions
ssh user@server "ls -la ~/.ssh/authorized_keys"
# Expected: -rw------- (600)
c. Manual deployment and permission correction
If ssh-copy-id is unavailable, the public key can be appended manually. The cat command reads the local public key, pipes it over SSH, and appends it to the remote authorized_keys.
# Manual deployment
cat ~/.ssh/id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
This works, but it does not set the permissions. The .ssh directory and the authorized_keys file must be corrected manually.
# Fix permissions on the server
ssh user@server "chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"
The correct permissions are mandatory. The .ssh directory must be 700 (read, write, execute for the owner only). The authorized_keys file must be 600 (read and write for the owner only). The private key on the client must be 600. The public key can be 644 .
The home directory permissions are also checked. If the home directory is group-writable (e.g., 775), OpenSSH refuses key authentication. The home directory should be 700 or 750 .
Complete Example Session
# ============================================
# PART 1: GENERATE THE KEY PAIR
# ============================================
ssh-keygen -t ed25519 -C "admin@example.com"
# Enter file in which to save the key: (Enter)
# Enter passphrase: (Enter for no passphrase)
# Enter same passphrase again: (Enter)
# Your identification has been saved in ~/.ssh/id_ed25519
# Your public key has been saved in ~/.ssh/id_ed25519.pub
# ============================================
# PART 2: VERIFY THE KEY FILES
# ============================================
ls -la ~/.ssh/id_ed25519*
# -rw------- id_ed25519
# -rw-r--r-- id_ed25519.pub
# ============================================
# PART 3: DEPLOY THE PUBLIC KEY
# ============================================
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server
# Password prompt: enter the remote user's password
# Number of key(s) added: 1
# ============================================
# PART 4: TEST KEY AUTHENTICATION
# ============================================
ssh user@server
# Login succeeds without a password prompt.
# ============================================
# PART 5: VERIFY SERVER-SIDE PERMISSIONS
# ============================================
ssh user@server "ls -la ~/.ssh/"
# drwx------ .ssh
# -rw------- authorized_keys
# ============================================
# PART 6: FIX PERMISSIONS IF NEEDED
# ============================================
ssh user@server "chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"
# ============================================
# PART 7: MANUAL DEPLOYMENT (ALTERNATIVE)
# ============================================
cat ~/.ssh/id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
ssh user@server "chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"
# ============================================
# PART 8: VERIFY THE PUBLIC KEY ON SERVER
# ============================================
ssh user@server "cat ~/.ssh/authorized_keys"
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5... admin@example.com
# ============================================
# PART 9: TROUBLESHOOT FAILURE
# ============================================
ssh -v user@server
# Look for "Offering public key: ~/.ssh/id_ed25519"
# If the server rejects it, check permissions on both sides.
The nine parts trace the key lifecycle: generation, file verification, deployment with ssh-copy-id, authentication test, server-side permission check, permission correction, manual deployment, key verification, and verbose troubleshooting.
Quick Reference
Key Generation
| Command | Algorithm | Default Path |
|---|---|---|
ssh-keygen -t ed25519 | ED25519 | ~/.ssh/id_ed25519 |
ssh-keygen -t rsa -b 4096 | RSA 4096 | ~/.ssh/id_rsa |
Deployment Commands
| Command | Purpose |
|---|---|
ssh-copy-id user@server | Deploy default key |
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server | Deploy specific key |
cat ~/.ssh/id_ed25519.pub | ssh user@server "cat >> ~/.ssh/authorized_keys" | Manual deployment |
Permission Requirements
| Path | Permission | Purpose |
|---|---|---|
~/.ssh | 700 | Directory, both sides |
~/.ssh/id_ed25519 | 600 | Private key, client only |
~/.ssh/id_ed25519.pub | 644 | Public key, both sides |
~/.ssh/authorized_keys | 600 | Server only |
| Home directory | 700 or 750 | Both sides, not group-writable |
Best Practices
โ Do This:
ssh-keygen -t ed25519 -C "user@example.com"
<!-- Use ED25519 for new keys --> # โ
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server
<!-- Deploy the public key --> # โ
chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys
<!-- Fix permissions on the server --> # โ
โ Don’t Do This:
# Share or copy the private key
<!-- Private key stays on the client --> # โ
# Leave authorized_keys at 644 or 664
<!-- OpenSSH ignores the key --> # โ
# Use RSA 2048 for new keys
<!-- Use ED25519 or RSA 4096 --> # โ
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Permission denied (publickey) | Wrong permissions on .ssh or authorized_keys | chmod 700 ~/.ssh, chmod 600 ~/.ssh/authorized_keys |
| Key ignored | Home directory group-writable | chmod 700 ~ or chmod 750 ~ |
ssh-copy-id fails | Password auth disabled on server | Temporarily enable password auth |
| Key not found | Wrong path or filename | Use -i with the correct path |
| Multiple keys conflict | Old key in authorized_keys | Remove the old key |
Real-World Examples
1. Generate ED25519 Key
ssh-keygen -t ed25519 -C "user@example.com"
2. Generate RSA Key
ssh-keygen -t rsa -b 4096 -C "user@example.com"
3. Deploy with ssh-copy-id
ssh-copy-id user@server
4. Manual Deploy
cat ~/.ssh/id_ed25519.pub | ssh user@server "cat >> ~/.ssh/authorized_keys"
5. Fix Server Permissions
ssh user@server "chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"
6. Verify Key on Server
ssh user@server "cat ~/.ssh/authorized_keys"
7. Test Authentication
ssh user@server
8. Verbose Troubleshooting
ssh -v user@server
9. Check Private Key Permission
chmod 600 ~/.ssh/id_ed25519
10. Check Home Directory Permission
chmod 750 ~
Visual
Key Deployment Flow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ CLIENT โ
โ ~/.ssh/id_ed25519 (private, 600) โ
โ ~/.ssh/id_ed25519.pub (public, 644) โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ ssh-copy-id
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SERVER โ
โ ~/.ssh/ (700) โ
โ ~/.ssh/authorized_keys (600) โ
โ Contains the public key โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ ssh user@server
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Server verifies signature with public key โ
โ Client proves possession of private key โ
โ Access granted, no password โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Permission Failure Path
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ authorized_keys is 644 (readable by others) โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ OpenSSH refuses to use the key โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Server returns: Permission denied (publickey)โ
โ The key is present but ignored. โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ chmod 600
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Key is accepted. โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Item | Value |
|---|---|
| Key generation | ssh-keygen -t ed25519 |
| RSA alternative | ssh-keygen -t rsa -b 4096 |
| Deployment | ssh-copy-id user@server |
| Manual deployment | cat key.pub | ssh user@server "cat >> ~/.ssh/authorized_keys" |
| Private key permission | 600 |
| Public key permission | 644 |
.ssh directory | 700 |
authorized_keys | 600 |
| Home directory | 700 or 750 |
Key takeaways:
- The private key never leaves the client. The public key is deployed to the server’s
authorized_keys. The private key is the credential and must be protected with600permissions . ssh-copy-idautomates deployment. It creates the.sshdirectory andauthorized_keysif needed, and appends the public key. Manual deployment requires setting the permissions afterward .- Permissions are mandatory. The
.sshdirectory must be700, theauthorized_keysfile must be600, and the home directory must not be group-writable. OpenSSH refuses to use keys with permissive permissions, and the error message does not indicate the cause . ssh -vis the diagnostic tool. The verbose output shows which keys are offered and whether the server accepts them. If the key is offered but rejected, the problem is permissions or a key mismatch .- ED25519 is the preferred algorithm. It is faster and more secure than RSA at equivalent key sizes. RSA is supported for compatibility but should be at least 4096 bits .
Remember: The key deployment is a two-sided operation. The client generates the pair. The server stores the public key. The permissions on both sides determine whether the key is used. The private key is 600. The public key is 644. The .ssh directory is 700. The authorized_keys file is 600. If any of these is wrong, the key is ignored and the error message is the same as a wrong key.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!