Enkiel Hub Newsletter

Archives
December 3, 2025

Server Hardening Quickstart (SSH, Passkeys, Fail2ban)

Practical hardening steps for an internet-facing Linux box (tested on Debian/Ubuntu). Adjust paths and package managers as needed.

Before you start

  • Replace adminuser with your actual sudo-capable account name.
  • Use your server IP/hostname anywhere SERVER_IP appears.
  • In the Fail2ban config, update destemail/sender or switch to action = %(action_)s if you do not want email.
  • In UFW, only allow the ports you truly need (e.g., drop 80/443 if not serving web traffic; add others if required).
  • Then run the steps below in order on the target server.

a) Patch and add a sudo user

sudo apt update && sudo apt upgrade -y sudo apt install unattended-upgrades -y sudo dpkg-reconfigure --priority=low unattended-upgrades sudo adduser adminuser sudo usermod -aG sudo adminuser 
  • Enable automatic security updates; use the new user for SSH, not root.

b) Set up SSH key authentication

Option A: Use your existing SSH key

If you already have an SSH key, you can use it instead of generating a new one.

For existing OpenSSH keys (Linux/Mac/Windows OpenSSH):

Check if you have an existing key:

ls -la ~/.ssh/id_*.pub 

If you see a public key file (e.g., id_rsa.pub, id_ed25519.pub), copy it to the server:

ssh-copy-id adminuser@SERVER_IP 

For .ppk files (PuTTY format):

Option 1: Extract public key and keep using .ppk (recommended if you want to keep using PuTTY):

First, install puttygen if needed:

# On Linux (Debian/Ubuntu): sudo apt install putty-tools -y # On macOS: brew install putty # On Windows: Download PuTTY installer from putty.org 

Extract the public key from your .ppk:

# Using command-line puttygen (Linux/Mac/Windows): puttygen yourkey.ppk -O public-openssh -o yourkey.pub # Or using PuTTYgen GUI (Windows/Linux with GUI): # 1. Open PuTTYgen # 2. Click "Load" and select your .ppk file # 3. Copy the text from "Public key for pasting into OpenSSH authorized_keys file" box # 4. Save it to a file named yourkey.pub 

Copy the public key to the server:

# Using ssh-copy-id (Linux/Mac): ssh-copy-id -i yourkey.pub adminuser@SERVER_IP # Or manually: # 1. Copy the contents of yourkey.pub # 2. SSH to server and run: echo "paste-public-key-here" >> ~/.ssh/authorized_keys 

Now you can connect using PuTTY with your .ppk file:

  • In PuTTY: Connection → SSH → Auth → Private key file for authentication → Browse to your .ppk
  • Or load the .ppk into Pageant (system tray) for automatic authentication

Option 2: Convert .ppk to OpenSSH format (if you want to use standard SSH clients):

# Using command-line puttygen (Linux/Mac/Windows): puttygen yourkey.ppk -O private-openssh -o ~/.ssh/id_rsa puttygen yourkey.ppk -O public-openssh -o ~/.ssh/id_rsa.pub # Then copy to server: ssh-copy-id -i ~/.ssh/id_rsa.pub adminuser@SERVER_IP 

Option B: Generate a new FIDO2 passkey (enhanced security)

Generate a FIDO2-backed key on your laptop (requires a hardware key with resident credential support):

ssh-keygen -t ed25519-sk -O resident -O verify-required -C "adminuser@server-fido2" 
  • If your token lacks resident storage, drop -O resident.
  • Copy the public key to the server:
    ssh-copy-id adminuser@SERVER_IP 

Harden SSH configuration (applies to both options)

Harden /etc/ssh/sshd_config (append or edit):

PermitRootLogin no PasswordAuthentication no KbdInteractiveAuthentication no ChallengeResponseAuthentication no PubkeyAuthentication yes AllowUsers adminuser MaxAuthTries 3 MaxStartups 10:30:60 ClientAliveInterval 300 ClientAliveCountMax 2 LogLevel VERBOSE 

Then reload:

sudo systemctl reload sshd 

c) Firewall: allow only what you use

sudo apt install ufw -y sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow OpenSSH # or: sudo ufw allow 22/tcp sudo ufw allow 80/tcp 443/tcp # if serving web traffic sudo ufw enable sudo ufw status 

d) Fail2ban for SSH

sudo apt install fail2ban -y cat <<'EOF' | sudo tee /etc/fail2ban/jail.local [DEFAULT] bantime = 1h findtime = 10m maxretry = 4 backend = systemd destemail = you@example.com sender = fail2ban@server mta = sendmail [sshd] enabled = true filter = sshd port = ssh logpath = %(sshd_log)s maxretry = 4 action = %(action_mwl)s EOF sudo systemctl enable --now fail2ban sudo fail2ban-client status sshd 
  • Uses systemd journal, emails ban reports (action_mwl); adjust email settings or switch to action = %(action_)s if no mailer.

e) Additional hardening knobs

  • sudo apt install auditd lynis for baseline auditing checks.
  • sudo sysctl -w net.ipv4.conf.all.rp_filter=1 net.ipv4.tcp_syncookies=1 net.ipv4.conf.all.accept_source_route=0 and persist via /etc/sysctl.d/99-hardening.conf.
  • Disable unused services: systemctl list-unit-files --type=service --state=enabled then sudo systemctl disable --now name.

f) Quick verification

  • New session uses SSH key: ssh -v adminuser@SERVER_IP should show debug1: Offering public key: with your key name (passkeys show ...sk suffix).
  • Root login refused: ssh root@SERVER_IP should fail.
  • Firewall: sudo ufw status shows only required ports.
  • Fail2ban jails: sudo fail2ban-client status lists sshd with active bans.

Troubleshooting

  • If passkey prompts fail, ensure your FIDO2 token is inserted/unlocked and libfido2 is installed on the client.
  • If using .ppk with PuTTY and authentication fails, verify the key is loaded in Pageant and the public key exists in ~/.ssh/authorized_keys on the server.
  • If OpenSSH key conversion fails, ensure puttygen is installed (sudo apt install putty-tools on Linux).
  • Locked out by firewall? Use console/serial access and run ufw disable temporarily.
Don't miss what's next. Subscribe to Enkiel Hub Newsletter:
Powered by Buttondown, the easiest way to start and grow your newsletter.