Why do this from the start?
As soon as a server (even an old recycled laptop) exposes services (website, API, Git, Nextcloud, dashboard, reverse proxy…), it becomes a target.
My Quick Setup
I already have Debian 12 Bookworm installed on an old recycled Toshiba laptop (dead battery, screen off, headless).
Hardware Old Toshiba Satellite → low power consumption, quiet once the fan calms down, ideal for getting started.

What I Want to Achieve
- Fixed IP → to always know where the server is
- Hardened SSH → only remote access method, ultra protected
- Firewall → blocks everything we haven’t explicitly allowed
- Fail2Ban → punishes bots trying thousands of passwords
- Auto updates → fixes vulnerabilities without me thinking about it
1. Fixed IP via DHCP Reservation
Why?
If the IP changes with every reboot (normal DHCP behavior), you have to check each time what IP your server got. It’s annoying and error-prone.
With a fixed IP (reserved by the router), you always connect to the same place: ssh lab.
How does it protect?
No direct protection, but avoids mistakenly connecting to the wrong IP and accidentally exposing another device.
How to do it
- On the server:
ip -brief link show→ note the MAC (e.g.,00:1f:29:ab:cd:ef) - On your router (web interface, DHCP / static leases section): associate MAC → fixed IP (e.g.,
192.168.1.200, outside dynamic range)
Verification:
ip a show | grep inet
Alternative if router doesn’t allow reservation
- Configure a static IP directly on the server (
/etc/network/interfacesornmcli/systemd-networkd) - → Less convenient if you change networks/routers
- → Risk of IP conflict if you forget to change the address
2. Simple Name + SSH Alias (~/.ssh/config)
Why?
Typing ssh level@192.168.1.200 50 times a day is long and prone to typos.
With an alias ssh lab, it’s instant + you can add options (key, keepalive…).
How does it protect?
Not directly, but reduces human errors (e.g., typing wrong IP).
Recommended method: ~/.ssh/config
Create/modify ~/.ssh/config on your client PC:
Host lab
HostName 192.168.1.200
User level
Port 22 # Recommended to change port
IdentityFile ~/.ssh/id_ed25519
ServerAliveInterval 60 # prevents connection from dropping
ServerAliveCountMax 3
Secure the file:
chmod 600 ~/.ssh/config
→ You just type ssh lab
Alternative
- Add to
/etc/hosts:192.168.x.x lab-home - → Simpler, but less powerful (no SSH options)
3. First SSH Access (before hardening)
Why?
It’s the entry point. We start with classic access (password) so we can then lock it down.
Command:
ssh lab
(accept the fingerprint the first time + current password)
4. SSH Hardening – The Most Critical Part
Why is it vital?
SSH is the only service exposed by default → 99% of attacks on a home server go through it (brute-force, exploits on old passwords, direct root login). We cut everything that’s weak.
Key modifications in /etc/ssh/sshd_config
PermitRootLogin no
Why? Attackers systematically try root with common passwords. Banning root via SSH forces going through a normal user (level) → double layer (need to crack two accounts).
PasswordAuthentication no
Why? Passwords are weak (even complex ones) and vulnerable to brute-force. Private keys (ed25519) are much stronger and impossible to brute-force.
PubkeyAuthentication yes
→ Enables keys (we enable it explicitly to be sure)
Personal bonuses
MaxAuthTries 3 # limits attempts per connection
LoginGraceTime 30 # prevents slow attacks
X11Forwarding no # disables X11
AllowTcpForwarding no # disables TCP forwarding
Apply changes
sudo systemctl restart ssh
Key installation
# Generate key pair
ssh-keygen -t ed25519 -C "level@lab-home"
# Copy public key to server
ssh-copy-id -i ~/.ssh/id_ed25519.pub lab
⚠️ Absolute rule
Always keep a parallel SSH session open when modifying sshd_config. If you mess up → lock-out = reboot + keyboard/screen required.
Alternatives if SSH keys fail
- Temporarily keep
PasswordAuthentication yes(but with very strong password) - Use Google Authenticator / Yubikey 2FA on SSH (more complex, add later)
5. UFW Firewall
Why?
By default, Debian doesn’t have an active firewall. If you install a service (e.g., Nginx on port 80), it’s directly exposed to the world. UFW = simple interface for iptables → we block everything except what we explicitly allow.
Basic rules
# Block ALL incoming except exceptions
sudo ufw default deny incoming
# Allow outgoing (updates, ping…)
sudo ufw default allow outgoing
# Keep SSH open
sudo ufw allow OpenSSH
# Enable firewall
sudo ufw enable
Verification
sudo ufw status verbose
Alternative
iptables/nftablesdirectly → more powerful but much more complexfirewalld→ heavier, not native on Debian
6. Fail2Ban (anti-bruteforce)
Why?
Even with SSH keys, some bots still try passwords (or if you forget to disable PasswordAuthentication). Fail2Ban reads SSH logs → after 3 failures → ban IP for 10 min.
Installation
sudo apt install -y fail2ban
Minimal config in /etc/fail2ban/jail.local
[sshd]
enabled = true
maxretry = 3
bantime = 10m
findtime = 10m
Restart service
sudo systemctl restart fail2ban
Alternative
- CrowdSec (more modern, community-based)
- Just disable PasswordAuthentication (already very effective)
7. Automatic Updates
Why?
Security vulnerabilities (e.g., OpenSSH, kernel) come out regularly. Without updates, your server becomes vulnerable even if well configured.
unattended-upgrades automatically installs security updates (not normal packages).
Installation and configuration
sudo apt install -y unattended-upgrades
# Configure automatic installation
sudo dpkg-reconfigure unattended-upgrades # → Yes
Alternative
- Custom cron or
apt-listchangesto be notified
8. Quick Checklist (copy-paste)
# Check IP
ip -brief a
# Check SSH config
sudo grep -E "PermitRootLogin|PasswordAuthentication" /etc/ssh/sshd_config
# Check UFW
sudo ufw status verbose
# Check Fail2Ban
sudo fail2ban-client status sshd
# Check open ports
sudo ss -tulpn
Conclusion
This baseline configuration is an excellent starting point for any Debian server. It covers the security fundamentals without being too complex.
Possible next steps:
- Add 2FA (Google Authenticator or Yubikey) on SSH
- Configure automatic backups
- Install a reverse proxy (Nginx/Caddy) with HTTPS
- Configure email alerts for connection attempts
Key takeaways:
- Security is done in layers: each measure adds an additional barrier
- SSH is the critical point: it’s your only entry door, protect it maximally
- Automate what can be: updates, bans, backups
- Always keep a backup access: don’t lock yourself out!
If you want me to develop any part further (e.g., why ed25519 > RSA, how to test a simulated brute-force, or add 2FA), let me know!
