Securing Your Home Server: Essential Steps Every Self-Hoster Should Take
Running a home server gives you control over your data and services, but it also makes you responsible for security. Unlike managed cloud services, you are the sysadmin. One misconfiguration could expose your personal data, family photos, or entire network to attackers.
The good news? Securing a home server isn’t rocket science. Follow these essential steps and you’ll be miles ahead of most self-hosters.
1. Harden SSH Access
SSH is your primary gateway to manage the server remotely. It’s also the #1 target for automated attacks.
Change the Default Port
Attackers scan port 22 constantly. Moving SSH to a non-standard port dramatically reduces automated attacks.
sudo nano /etc/ssh/sshd_config
Change this line:
To something like:
Then restart SSH:
sudo systemctl restart sshd
Remember: Update your firewall rules and client configs to use the new port.
Disable Password Authentication
Passwords can be brute-forced. SSH keys cannot (within reasonable timeframes).
First, set up SSH keys on your client:
ssh-keygen -t ed25519 -C "[email protected]"
ssh-copy-id -p 2299 user@your-server
Then disable password auth:
sudo nano /etc/ssh/sshd_config
Set:
Restart SSH:
sudo systemctl restart sshd
Test Before Logging Out
Critical: Open a second terminal and test SSH before closing your current session. If something broke, you’ll still have access to fix it.
2. Configure a Firewall
Linux includes ufw (Uncomplicated Firewall), which makes firewall management simple.
Enable UFW
sudo apt install ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
Allow Only What You Need
# SSH (use your custom port)
sudo ufw allow 2299/tcp
# HTTP/HTTPS (if running web services)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Plex (example media server)
sudo ufw allow 32400/tcp
Enable the Firewall
sudo ufw enable
sudo ufw status
You should see:
Rate Limit SSH
Prevent brute-force attacks:
sudo ufw limit 2299/tcp
This blocks IPs that attempt 6+ connections in 30 seconds.
3. Keep Software Updated
Unpatched vulnerabilities are low-hanging fruit for attackers.
Enable Automatic Security Updates
On Ubuntu/Debian:
sudo apt install unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades
This installs security patches automatically while leaving major updates for manual review.
Update Regularly
Even with automatic updates, manually update weekly:
sudo apt update && sudo apt upgrade -y
For Docker containers (if you use them):
docker compose pull
docker compose up -d
4. Use Reverse Proxy with SSL
Exposing individual services directly is risky and messy. A reverse proxy centralizes access and encrypts traffic.
Install Nginx Proxy Manager
The easiest option for beginners:
mkdir -p ~/nginx-proxy-manager
cd ~/nginx-proxy-manager
wget https://github.com/NginxProxyManager/nginx-proxy-manager/raw/main/docker-compose.yml
docker compose up -d
Access at http://your-server:81 (default login: [email protected] / changeme).
Get Free SSL Certificates
Nginx Proxy Manager integrates Let’s Encrypt:
- Add a domain pointing to your server’s public IP
- Create a proxy host in NPM
- Enable “Force SSL” and “HTTP/2”
- NPM handles certificate renewal automatically
Result: Your services are accessible via https://service.yourdomain.com with valid certificates.
5. Implement Fail2Ban
Fail2Ban monitors logs and bans IPs after repeated failed login attempts.
Install Fail2Ban
sudo apt install fail2ban
Configure SSH Protection
sudo nano /etc/fail2ban/jail.local
Add:
[sshd]
enabled = true
port = 2299
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600
This bans IPs for 1 hour after 3 failed attempts in 10 minutes.
Start Fail2Ban:
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
Check status:
sudo fail2ban-client status sshd
6. Secure Docker Containers
If you use Docker, container security matters.
Don’t Run Containers as Root
Add this to your docker-compose.yml:
services:
app:
image: myapp
user: "1000:1000" # Your user/group ID
Find your UID/GID:
id
Use Read-Only Filesystems When Possible
services:
app:
image: myapp
read_only: true
tmpfs:
- /tmp
Keep Images Updated
docker image prune -a # Remove old images
docker compose pull # Update to latest
docker compose up -d # Restart with new images
7. Monitor Logs
You can’t fix what you don’t see.
Check Auth Logs Regularly
sudo tail -f /var/log/auth.log
Look for patterns like repeated failed logins from unfamiliar IPs.
Set Up Log Monitoring (Optional)
Tools like Grafana + Loki or Uptime Kuma can alert you to issues.
Simple option for uptime monitoring:
docker run -d \
-p 3001:3001 \
-v uptime-kuma:/app/data \
--name uptime-kuma \
louislam/uptime-kuma:1
Access at http://your-server:3001 and configure service checks.
8. Network Segmentation (Advanced)
Isolate your server from your home network using VLANs or a dedicated subnet.
Why It Matters
If your server gets compromised, segmentation prevents attackers from pivoting to other devices (laptops, phones, IoT devices).
How to Implement
- Configure VLANs on your router/switch (if supported)
- Place server in VLAN 10, trusted devices in VLAN 20
- Set firewall rules to allow only necessary traffic between VLANs
Alternative: Use a dedicated Raspberry Pi as a firewall running OPNsense or pfSense.
9. Backup and Test Restores
Security includes disaster recovery.
Automate Backups
Use tools like Restic or Duplicati:
# Install restic
sudo apt install restic
# Initialize backup repo
restic init --repo /mnt/backup
# Backup important directories
restic -r /mnt/backup backup /home /etc /var/www
# Set up cron job
echo "0 2 * * * restic -r /mnt/backup backup /home /etc /var/www" | sudo crontab -
Test Restores Monthly
A backup is worthless if you can’t restore it:
restic -r /mnt/backup restore latest --target /tmp/restore-test
10. Know When You’re Exposed
Use tools to check your attack surface.
Scan Your Ports
From an external network (phone LTE, friend’s house):
nmap -p 1-65535 your-public-ip
You should only see ports you explicitly opened.
Check for Vulnerabilities
sudo apt install lynis
sudo lynis audit system
Lynis audits your system and suggests hardening steps.
Security Checklist
- SSH on non-standard port, key-only auth, root disabled
- Firewall enabled with minimal open ports
- Automatic security updates enabled
- Reverse proxy with SSL (Let’s Encrypt)
- Fail2Ban monitoring SSH and web services
- Docker containers not running as root
- Regular log reviews
- Automated backups tested monthly
- Port scan confirms no unexpected open ports
- Lynis audit score >70
What About VPNs?
Many self-hosters avoid exposing services entirely by accessing them only via VPN (WireGuard or Tailscale).
Pros:
- No public attack surface
- Encrypted access from anywhere
- Simpler than reverse proxy setup
Cons:
- Must connect to VPN before accessing services
- Can’t share services with non-VPN users
Recommendation: Use VPN for admin access (SSH, Portainer) and reverse proxy for services you share (Jellyfin, Nextcloud).
Final Thoughts
Security is a process, not a one-time task. Threat landscapes change, software gets updated, and configurations drift.
Set a monthly reminder to:
- Review auth logs
- Run system updates
- Check Fail2Ban stats
- Scan your ports
- Test a backup restore
With these foundations in place, your home server will be significantly more secure than 90% of self-hosted setups.
Next Steps:
- How to Set Up Fail2ban (coming soon)
- SSL Certificates for Self-Hosted Services (coming soon)
- VPN Options for Remote Access (coming soon)
Got questions? Join our Discord community or drop a comment below.