Cheap home servers are great.
You take an old Dell, Lenovo, ThinkCentre, NUC, laptop, Raspberry Pi or whatever was cheap enough not to hurt the wallet, throw Linux on it, add Docker, maybe some file sharing, maybe a media server, maybe a few scripts, and suddenly it becomes “production”.
Production in quotes, of course.
Because at home, production usually means:
- if it dies, someone complains;
- if the disk fills, something stops working;
- if SSH gets exposed by mistake, the internet starts knocking;
- if updates are forgotten for six months, the box becomes a tiny museum of old packages.
So this is my practical Linux home server security checklist. Not enterprise paranoia. Not “install 47 tools and build a SOC in the kitchen”. Just sensible hardening for a cheap homelab machine that is always on and probably doing more than it should.
The goal is simple: make the server boring.
Boring is good. Boring means patched, firewalled, backed up, logged, and not silently accepting nonsense from the network.
1. First rule: know what the server is actually doing
Before hardening anything, write down what the machine is for.
Hostname: homeserver01
Purpose: Docker, file backups, Jellyfin, test VMs
Access: SSH from LAN only
Exposed to internet: No
Important data: /home, /srv/docker, /mnt/storage
Backup target: external USB disk + another machine
This sounds boring, but it matters. You cannot secure “random stuff running somewhere”. You can secure a machine with a known purpose.
Start with basic discovery:
hostnamectl
ip a
ss -tulpn
systemctl --type=service --state=running
The most interesting command here is:
ss -tulpn
That shows which ports are listening. If you see services you forgot existed, congratulations, you found your first security improvement.
If the server only needs SSH and a couple of internal Docker services, then why is there an old test web server listening on all interfaces? Kill it. Purge it. Document it.
Less stuff running = less stuff to patch, misconfigure and explain later.
2. Update first, tweak later
Before changing SSH, firewall rules or services, update the box.
For Ubuntu, Debian, Linux Mint and similar systems:
sudo apt update
sudo apt upgrade
sudo apt autoremove
Then check if the server needs a reboot:
[ -f /var/run/reboot-required ] && cat /var/run/reboot-required
If the server has been running for months, do not be surprised if half the internet fits inside the update list.
For a home server, automatic security updates are usually a good idea. Ubuntu documents unattended-upgrades as the mechanism used to apply security updates automatically, and it can also be configured for other update behavior.
Install or verify it:
sudo apt install unattended-upgrades
sudo dpkg-reconfigure unattended-upgrades
Check the basic configuration:
cat /etc/apt/apt.conf.d/20auto-upgrades
You want something like this:
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
Logs live here:
ls /var/log/unattended-upgrades/
Do I enable automatic reboots? Usually no for my home boxes. I prefer to get the update, see that a reboot is needed, and reboot when nobody is streaming, copying files or using the thing.
3. SSH hardening: do not lock yourself out
SSH is usually the front door of a Linux home server.
Ubuntu’s OpenSSH documentation notes that OpenSSH supports multiple authentication methods, including password authentication and public key cryptography. For a home server, SSH keys are normally the better option.
On your laptop or desktop:
ssh-keygen -t ed25519 -C "yourname@homelab"
ssh-copy-id youruser@server-ip
Test it:
ssh youruser@server-ip
Now keep that working SSH session open. Open another terminal and test again. Only after you confirm key login works should you disable password login.
Create a separate SSH hardening file:
sudo nano /etc/ssh/sshd_config.d/99-homelab-hardening.conf
Add this:
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
X11Forwarding no
AllowUsers youruser
Replace youruser with your actual username.
Test the SSH config before reloading:
sudo sshd -t
If there is no output, good.
Reload SSH:
sudo systemctl reload ssh
Now test from a new terminal:
ssh youruser@server-ip
Do not close the old working session until you confirm the new one works.
Should you change the SSH port?
Maybe, but do not treat it as magic.
Changing SSH from port 22 to another port mostly reduces log noise from dumb bots. Real security is SSH keys, no root login, no password login, firewall restrictions and sane users.
If the server is LAN-only, I usually keep port 22 and restrict access with the firewall. If it is internet-facing, I would rather use a VPN than expose SSH directly.
4. Firewall: allow what you need, block the rest
Ubuntu’s default firewall frontend is ufw. It is designed to make host-based firewall rules easier to manage, and Ubuntu’s documentation notes that it is initially disabled by default.
Install it if needed:
sudo apt install ufw
Before enabling it, allow SSH:
sudo ufw allow OpenSSH
Then set sane defaults:
sudo ufw default deny incoming
sudo ufw default allow outgoing
Enable it:
sudo ufw enable
Check the result:
sudo ufw status verbose
Example for a LAN-only web service:
sudo ufw allow from 192.168.1.0/24 to any port 8080 proto tcp
That is better than:
sudo ufw allow 8080
Why? Because the first rule says “only my local network can access this”. The second says “anyone who can reach the machine can try”.
For a home server, that difference matters.
5. Remove services you do not use
Run:
ss -tulpn
Then ask: do I need all of this?
Also check enabled services:
systemctl list-unit-files --type=service --state=enabled
If you installed something for a test six months ago, remove it.
sudo apt purge package-name
sudo apt autoremove
This is not glamorous, but it is one of the best hardening steps. Every service is another patching responsibility.
- Old FTP server? Gone.
- Forgotten database? Gone.
- Test dashboard bound to
0.0.0.0? Gone or firewalled. - Random container from a tutorial? Gone with fire.
6. Run Lynis and actually read the output
I already wrote about using Lynis to harden Linux, and I still like it because it gives you a checklist instead of vague security feelings.
Lynis is a security auditing and hardening tool for Linux, Unix and macOS systems. It scans the machine and gives recommendations for improving security.
Install it:
sudo apt install lynis
Run an audit:
sudo lynis audit system
Do not try to fix everything in one go. That is how you break things and then pretend it was “a learning experience”.
My method:
- Run Lynis.
- Save or read the report.
- Fix the obvious stuff first.
- Reboot if needed.
- Run Lynis again.
- Repeat later.
Useful files:
sudo less /var/log/lynis.log
sudo less /var/log/lynis-report.dat
The score is fun, but do not worship it. The real value is the list of findings. A server with a slightly lower score but a clean, understood configuration is better than a high score created by blindly pasting commands from the internet.
7. Users, sudo and passwords
Home servers often collect users over time.
Check local users:
cut -d: -f1 /etc/passwd
Check sudo/admin group membership:
getent group sudo
Remove users that should not exist anymore:
sudo deluser olduser
If you need to keep the user but disable login:
sudo usermod -L olduser
For your real admin account:
- use a strong password;
- use SSH keys;
- do not reuse passwords;
- use a password manager;
- do not share the admin login with “just one quick test”.
Also, root SSH login should stay disabled. Use your normal user, then sudo.
For password habits, see the older post on creating strong unique passwords.
8. Docker and containers: convenient does not mean safe
Docker is amazing for homelabs. It is also a fantastic way to forget what is running.
List containers:
docker ps
docker ps -a
List exposed ports:
docker ps --format "table {{.Names}}\t{{.Ports}}"
Things I try to avoid unless there is a real reason:
network_mode: host
privileged: true
Sometimes they are needed. Most times they are copied from a random compose file and never questioned.
For each container, ask:
- Does it need to be reachable from the whole LAN?
- Does it need write access to that folder?
- Does it really need privileged mode?
- Is the image maintained?
- Where is the configuration stored?
- How do I restore it?
Update containers intentionally:
docker compose pull
docker compose up -d
docker image prune
Do not auto-update everything blindly unless you have backups and you accept the risk. A broken container is annoying. A broken container with no backup is character building.
9. Backups: security includes “oops”
Backups are security.
Ransomware, disk failure, bad commands, power loss, bad updates, tired human at 1 AM — all of these are security problems when they destroy data.
At minimum, back up:
/home/etc/srv- Docker compose files
- application data volumes
- important scripts
- SSH keys, if appropriate and stored safely
Example with rsync:
sudo rsync -aAX --info=progress2 /home/ /mnt/backup/home/
sudo rsync -aAX --info=progress2 /etc/ /mnt/backup/etc/
sudo rsync -aAX --info=progress2 /srv/ /mnt/backup/srv/
Be very careful with --delete. It is useful, but it will delete files from the backup if they are gone from the source.
Use it only when you understand the direction:
sudo rsync -aAX --delete /srv/ /mnt/backup/srv/
A backup you never tested is not a backup. It is a nice feeling.
Test restoring at least one file:
mkdir /tmp/restore-test
cp /mnt/backup/etc/hostname /tmp/restore-test/
cat /tmp/restore-test/hostname
10. Logs: look before something explodes
You do not need a full SIEM at home. You do need to look at logs sometimes.
Useful commands:
journalctl -p warning -b
journalctl -u ssh -b
last -a | head
df -h
free -h
uptime
Failed SSH attempts:
sudo journalctl -u ssh | grep "Failed password"
Disk usage:
df -h
sudo du -h --max-depth=1 /var | sort -h
If /var is huge, logs or containers may be eating the disk.
For Docker logs:
docker logs container-name --tail=100
For containers using too much space:
docker system df
Again: boring is good. If you check logs only after something breaks, logs become archaeology.
11. Add Fail2ban if SSH is noisy
If SSH is exposed to more than your LAN, Fail2ban is worth considering.
Install:
sudo apt install fail2ban
Create a local jail config:
sudo nano /etc/fail2ban/jail.local
Simple SSH example:
[sshd]
enabled = true
port = ssh
filter = sshd
backend = systemd
maxretry = 5
findtime = 10m
bantime = 1h
Restart:
sudo systemctl restart fail2ban
Check:
sudo fail2ban-client status
sudo fail2ban-client status sshd
Fail2ban is not a replacement for SSH keys and firewall rules. It is another layer. Layers are good when they are understood.
12. Optional: add a honeypot, but do it properly
A small honeypot can be fun and useful in a homelab, especially if you want to see what touches your network.
I previously wrote about OpenCanary honeypot deployment on Linux. OpenCanary can emulate services and log connection attempts, which makes it useful as a small early-warning system.
But do not randomly expose a honeypot to the internet from your home connection without thinking. You are inviting noise, logs and possibly trouble.
Good places for a home honeypot:
- isolated VLAN;
- lab network;
- behind a firewall;
- no access to important machines;
- logs forwarded somewhere else.
Bad place:
- same flat network as everything important;
- running as root;
- forgotten forever;
- exposed to the whole internet “for science”.
Honeypots are useful when they answer a question. For example:
Is something scanning my internal network?
That is a good question.
Can I attract every bot on the internet to my living room?
That is less good.
13. Physical security counts too
Home servers are physical machines. Physical reality is rude.
Do this:
- plug it into a decent power strip or UPS;
- clean dust from fans;
- check temperatures;
- avoid stacking disks in weird places;
- label cables;
- keep it away from pets, drinks and “temporary” floor setups.
Check temperatures:
sudo apt install lm-sensors
sudo sensors-detect
sensors
Check disks:
lsblk
sudo apt install smartmontools
sudo smartctl -a /dev/sda
A secure server with a dying disk is just a future sadness generator.
This is especially relevant if you are running a cheap always-on machine like the old Dell T1600 home server style setup: old hardware can be great, but it deserves cleaning, monitoring and backups.
14. My minimum monthly Linux home server security checklist
Once a month, I like to run:
sudo apt update
sudo apt upgrade
sudo lynis audit system
sudo ufw status verbose
df -h
docker ps
docker system df
journalctl -p warning --since "30 days ago"
Then I ask:
- Any unexpected open ports?
- Any failed services?
- Any disk almost full?
- Any containers I forgot?
- Any updates pending?
- Any users that should not exist?
- Any backups tested recently?
That is enough for most home servers.
Not perfect. Not enterprise. But much better than “installed Ubuntu in 2021 and hoped for the best”.
Final thoughts
Linux home server security is not one magic tool.
It is small boring things done consistently:
- update the system;
- use SSH keys;
- disable root login;
- firewall everything;
- remove unused services;
- run Lynis;
- back up important data;
- read logs sometimes;
- keep Docker under control;
- document what the box is supposed to do.
A cheap homelab server does not need to be fragile. Even an old workstation can be a very decent little server if it is patched, quiet, backed up and not exposing random ports to the world.
And if nothing exciting happens after you harden it?
Perfect.
That means it is working.
FAQ
Do I need a firewall if my Linux server is behind a router?
Yes. Your router helps, but a local firewall still protects the server from mistakes, other devices on the LAN and accidental exposure. UFW is simple enough that there is little reason not to use it.
Is changing the SSH port enough to secure SSH?
No. Changing the port mainly reduces automated noise. Use SSH keys, disable password login, disable root login and restrict access with a firewall.
Should I enable automatic updates on a home server?
For security updates, usually yes. For automatic reboots or full non-security upgrades, it depends on what the server runs and how painful downtime would be.
Is Lynis only for enterprise servers?
No. Lynis is useful on home servers because it gives a practical list of things to check. You do not need to fix every warning immediately; use it as a guide.
What is the biggest homelab security mistake?
Exposing services to the internet without understanding what is listening, how it is authenticated and how it is updated. The second biggest mistake is not having backups.
No comments:
Post a Comment