The scenario
You are sitting at your desk, typing ssh user@remote-fedora-server every time you need to push a file or run a quick command. The password prompt interrupts your workflow. You type it wrong once, get locked out for a minute, and lose your train of thought. You want to connect instantly. You want to automate backups without hardcoding passwords in scripts. You are ready to switch to SSH key-based authentication.
What SSH keys actually do
Password authentication works like a shared secret. You type a string, the server hashes it, and compares it to the stored hash. If they match, you get in. The problem is that passwords travel over the network, even if encrypted, and they are vulnerable to brute-force attacks. Key-based authentication replaces the shared secret with a cryptographic handshake. You generate two files on your local machine. One stays private. The other travels to the server. When you connect, the server sends a random challenge. Your private key signs that challenge mathematically. The server verifies the signature using your public key. If the math checks out, you are logged in. No password is transmitted. No guessing is possible.
Think of it like a physical lock and key. The public key is the lock you install on the server door. The private key is the only metal key that fits it. You never send the metal key over the network. You just prove you have it by turning the lock.
Run ssh-keygen first. Generate the pair before you touch the server configuration.
Generate and deploy the key pair
Fedora ships with openssh-clients preinstalled. You do not need to install anything extra on the local machine. Open your terminal and generate a new Ed25519 key pair. Ed25519 is the modern standard. It is faster, more secure, and shorter than RSA. Older guides recommend RSA with 4096 bits. That is unnecessary overhead. Ed25519 provides equivalent security with a smaller footprint and faster signature generation.
Here is how to generate the pair with a descriptive comment.
ssh-keygen -t ed25519 -C "fedora-workstation-2024" # -t selects the algorithm. ed25519 is the current best practice.
# The prompt asks for a file path. Press Enter to accept ~/.ssh/id_ed25519.
# The prompt asks for a passphrase. Set one. A passphrase encrypts the private key on disk.
# Without a passphrase, anyone who steals your laptop can use the key immediately.
The command creates two files in ~/.ssh/. The file without the .pub extension is your private key. The .pub file is your public key. Never share the private key. Treat it like a root password. Store it in a secure backup if you manage multiple machines.
Next, copy the public key to your Fedora server. The ssh-copy-id command handles permissions automatically. It appends your key to ~/.ssh/authorized_keys and sets the correct ownership and mode. This avoids the most common permission errors.
Here is how to push the public key to the remote host.
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@fedora-server-ip # -i points to the specific public key file.
# The command will prompt for your current password one last time.
# After successful upload, it prints a confirmation and the number of keys added.
# The remote ~/.ssh directory is created if it does not exist.
If ssh-copy-id is not available on your local system, you can pipe the key manually. This is rare on Fedora but happens on minimal containers or stripped-down rescue environments.
Here is the manual fallback for copying the key.
cat ~/.ssh/id_ed25519.pub | ssh user@fedora-server-ip "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys" # Pipes the public key over SSH and appends it to the target file.
# You must manually set permissions on the server after using this method.
# Run chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys on the remote host.
# Incorrect permissions will cause sshd to silently ignore the file.
Keep the private key readable only by you. Run chmod 600 ~/.ssh/id_ed25519 locally if the prompt warns about insecure permissions.
Harden the SSH daemon
Uploading the key does not disable password logins. The server will still accept passwords until you tell it otherwise. Fedora stores the SSH daemon configuration in /etc/ssh/sshd_config. The file ships with sensible defaults, but you need to verify two settings. Fedora uses a drop-in directory for SSH configuration. You should never edit /etc/ssh/sshd_config directly. Create a new file in /etc/ssh/sshd_config.d/ instead. The daemon reads everything in that directory alphabetically. This keeps your customizations separate from package updates.
Here is how to inspect the active configuration before editing.
sudo sshd -T | grep -E "^(passwordauthentication|pubkeyauthentication)" # Dumps the resolved config after all includes are processed.
# sshd -T shows the effective settings, not just the raw file.
# This prevents surprises from dropped-in config snippets in /etc/ssh/sshd_config.d/.
# Always check the effective config before making changes.
Create a drop-in file to disable password authentication permanently. The filename should start with a number or letter that places it late in the alphabetical sort, ensuring it overrides base defaults.
Here is how to disable password authentication permanently.
# /etc/ssh/sshd_config.d/99-disable-passwords.conf
PasswordAuthentication no # Tells sshd to reject password logins entirely.
PubkeyAuthentication yes # Ensures key-based auth remains active.
ChallengeResponseAuthentication no # Disables PAM-based password fallbacks.
UsePAM yes # Keeps PAM active for session limits and account policies.
Save the file. Restart the SSH service to apply the changes. Do not close your current terminal session until you verify the new configuration works. A misconfigured sshd can lock you out of the machine. Keep a second terminal window open with an active session as a safety net.
Here is how to reload the daemon safely.
sudo systemctl restart sshd # Applies the new configuration immediately.
# systemctl restart is safe here because sshd forks a new process.
# The listening socket stays open during the transition.
# Verify the service state with systemctl status sshd immediately after.
Test the configuration syntax before restarting if you want extra safety. Run sudo sshd -t to check for syntax errors. The command returns nothing on success. It prints the exact line number on failure.
Verify the connection
Open a new terminal window. Keep your old session alive as a safety net. Attempt to connect to the server. The client will automatically look for id_ed25519 in ~/.ssh/ and offer it to the server.
Here is how to test the key-based login.
ssh user@fedora-server-ip # Attempts connection using the default key in ~/.ssh/.
# If the private key is encrypted, you will be prompted for the passphrase.
# If it succeeds, you will drop straight into the remote shell.
# The connection should establish without asking for a password.
If you see a password prompt, the key was not accepted. Check the remote ~/.ssh/authorized_keys file. Ensure it contains exactly one line. Line breaks in the middle of a key break the parser. Run ssh -v user@fedora-server-ip to see exactly which key the client tried to send and why the server rejected it. The verbose output shows the exact authentication methods offered and the server's response.
Add your key to the SSH agent if you do not want to type the passphrase every time. The agent caches the decrypted key in memory for the duration of your session.
Here is how to load the key into the agent.
eval "$(ssh-agent -s)" # Starts the agent in the current shell and exports environment variables.
ssh-add ~/.ssh/id_ed25519 # Prompts for the passphrase once and caches the decrypted key.
# The agent will sign requests automatically for the rest of the session.
# Run ssh-add -l to list currently loaded keys.
Close your old safety session only after the new one is stable. Verify file transfers and command execution work as expected.
Common pitfalls and exact error messages
SSH key setup fails in predictable ways. Recognizing the exact output saves hours of guessing. Search for the exact string in your terminal. Match it to the cause below.
Permission denied (publickey).
The server did not find a matching public key. Check the remote ~/.ssh/ directory permissions. The home directory must not be writable by group or others. The .ssh directory must be 700. The authorized_keys file must be 600. Run chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys on the server. SELinux also enforces strict context labels on /home/. If you symlink .ssh from another partition, you will get silent authentication failures. Keep .ssh inside your home directory.
Agent admitted failure to sign using the key.
Your SSH agent does not have the private key loaded. This happens when you set a passphrase but never added the key to the agent. Run ssh-add ~/.ssh/id_ed25519 on your local machine. The agent will cache the decrypted key in memory for the duration of your session. If you are using a desktop environment, Fedora starts ssh-agent automatically via D-Bus. You may only need to run ssh-add once per boot.
Host key verification failed.
You are connecting to an IP or hostname that changed its identity. This usually means the server was reinstalled or you are hitting a different machine. Edit ~/.ssh/known_hosts on your local machine and remove the stale entry. You can also run ssh-keygen -R fedora-server-ip to automate the cleanup. The client refuses to connect until the host key matches the stored fingerprint.
Load key "/home/user/.ssh/id_ed25519": permissions 0644 are too open.
The private key is readable by other users on your local machine. SSH refuses to use it to prevent credential theft. Run chmod 600 ~/.ssh/id_ed25519 locally. The client enforces strict permissions on private keys. Fix the permissions before attempting to connect again.
Check the remote journal if the server rejects the key without a clear client-side error. Run journalctl -xeu sshd on the server. Look for Authentication refused: bad ownership or modes for directory or Authentication refused: bad ownership or modes for file. The daemon logs the exact reason it skipped a key.
When to use keys versus passwords
Use SSH keys when you manage servers, run automated scripts, or connect to the same machine multiple times a day. Use passwords when you are logging into a shared workstation that multiple people access. Use hardware security keys like YubiKey when you require FIDO2 compliance or want to eliminate passphrase management entirely. Stay on password authentication only if you are running a temporary test environment that will be destroyed in a few hours.