Three scripts, two workflows. Pick what you need.
| Script | What it's for |
|---|---|
generate.sh |
Generate a passphrase-protected Ed25519 key pair on your local machine |
deploy.sh |
Push your key to remote servers — optionally replace old keys, optionally harden |
harden.sh |
Full lockdown — sshd, firewall, auto-updates, fail2ban, sysctl, shared memory |
chmod +x harden.sh deploy.sh generate.shAlready have a hardened server (or any server) and just want to swap out the SSH certificates? No sshd changes, no firewall changes — just key management.
Step 1: Generate a new key locally
bash generate.sh # creates ~/.ssh/hardened
bash generate.sh mykey # creates ~/.ssh/mykey (custom name)Step 2: Push it to your server
# Append your new key (keeps existing keys)
bash deploy.sh user@server-ip
# Or wipe all old keys and replace with yours only
bash deploy.sh user@server-ip 2223 --replaceThat's it. Old certs gone, new key in place, nothing else touched.
ssh -p 2223 -i ~/.ssh/hardened user@server-ipGot a fresh VPS or a box that still has password auth wide open? This locks down everything in one shot: SSH config, firewall, key generation, the works.
sudo bash harden.sh # hardens for the current sudo user
sudo bash harden.sh someuser # hardens for a specific userThe script will:
- Install
openssh-serverif missing - Generate a passphrase-protected Ed25519 key pair
- Add the public key to
authorized_keys - Write a hardened
sshd_config(pubkey-only, port 2223, root disabled, modern ciphers) - Install UFW and lock the firewall down to port 2223 only
- Enable automatic security updates (unattended-upgrades / dnf-automatic / yum-cron)
- Install and configure fail2ban (bans IPs after 3 failed SSH attempts for 24h)
- Apply kernel/network hardening via sysctl (SYN cookies, anti-spoofing, no redirects)
- Harden shared memory (
/run/shmmounted withnoexec,nosuid,nodev) - Install rkhunter rootkit scanner with daily cron job and baseline snapshot
- Install AIDE file integrity monitor with daily cron job and baseline snapshot
- Set up a dynamic MOTD security dashboard (shown on every SSH login)
- Print a one-liner to copy your private key to your local machine
⚠️ Do NOT close your SSH session until you verify access from a second terminal.
If you already have ~/.ssh/hardened on your local machine (from generate.sh or a previous run), you can harden a remote server without logging into it manually:
# Push your key + full hardening
bash deploy.sh user@server-ip 22 --harden
# Replace old keys + full hardening
bash deploy.sh user@server-ip 22 --replace --hardenAfter either option:
ssh -p 2223 -i ~/.ssh/hardened user@server-ip| Flag | What it does |
|---|---|
| (none) | Appends your key to authorized_keys — existing keys stay |
--replace |
Wipes authorized_keys and adds only your key |
--harden |
Copies harden.sh to the server and runs it (full lockdown) |
Flags combine: --replace --harden wipes old keys and hardens the server.
bash deploy.sh user@server-ip [port] [--replace] [--harden]| Setting | Value |
|---|---|
| SSH Port | 2223 |
| Authentication | Pubkey only (password login disabled) |
| Key type | Ed25519 + passphrase |
| Root login | Disabled |
| Max auth tries | 3 |
| X11 / TCP / Agent forwarding | Disabled |
| Key exchange | curve25519-sha256 only |
| Ciphers | chacha20-poly1305, aes256-gcm, aes128-gcm |
| MACs | hmac-sha2-512-etm, hmac-sha2-256-etm |
| Firewall (UFW) | Deny all in/out, allow 2223/tcp + DNS/HTTP/HTTPS/NTP outbound |
| Auto-updates | Security-only (unattended-upgrades / dnf-automatic / yum-cron) |
| fail2ban | SSH jail — 3 failed attempts = 24h ban |
| Sysctl | SYN cookies, anti-spoofing, no ICMP redirects, no source routing |
| Shared memory | /run/shm mounted noexec,nosuid,nodev |
| rkhunter | Rootkit scanner with daily cron, baseline snapshot |
| AIDE | File integrity monitor with daily cron, baseline snapshot |
| Login MOTD | Dynamic security dashboard (services, bans, logins, scan results) |
- Debian/Ubuntu, Fedora/RHEL, or Arch-based Linux
- Root (sudo) access for hardening
openssh-server(auto-installed by harden.sh if missing)
harden.sh saves a timestamped backup of your original sshd_config:
/etc/ssh/sshd_config.bak.YYYYMMDDHHMMSS
To revert SSH config:
sudo cp /etc/ssh/sshd_config.bak.* /etc/ssh/sshd_config
sudo systemctl restart sshdTo revert firewall:
sudo ufw reset
sudo ufw default allow incoming
sudo ufw enableTo revert sysctl hardening:
sudo rm /etc/sysctl.d/99-hardening.conf
sudo sysctl --systemTo revert shared memory:
# Remove the tmpfs line added by harden.sh from /etc/fstab
sudo nano /etc/fstab