Security
How I secure my homelab. Everything listed here really runs like this.
Network & access
Separate networks
My own network, smart home devices, cameras and guests each sit in their own zone. The cameras have no internet at all. What may pass from one zone to another is allowed one rule at a time.
Why: A hacked lamp or camera can't reach my machines that way.
A firewall on every system
Every container and every VM has its own firewall on top, and by default everything is closed. Services are only reachable through the reverse proxy, not directly.
Why: A new service starts closed and I only open what it needs. After every change I test both directions. It has to block from the wrong machine and let the right one through.
Reverse proxy with HTTPS
All web interfaces go through a reverse proxy with automatic certificates. Only what I explicitly allowed is reachable from the internet.
Second factor
Important pages have a central login with a second factor in front. Server administration is protected with a one-time code too. Personally my second factor is a YubiKey, kept separate from the password manager.
Why: A password alone isn't enough, and a stolen one even less.
Locking out attackers
The reverse proxy asks CrowdSec whether an address is known to be bad or acts weird. On the servers, fail2ban bans addresses for an hour after three failed SSH logins.
Hardening
Only as many rights as needed
Every service runs in its own container. My dashboard can only display things, for switching there's a separate token. And the watchdog may only run a few fixed queries on the servers.
Why: Whoever takes over one piece shouldn't automatically hold everything.
Hardened SSH
I log in with keys everywhere. Few attempts, short time to log in, plus kernel settings against the usual network tricks.
No secrets in code
Passwords and tokens never sit in code or compose files, only in .env files that just the service itself may read. After the audit in April I rotated the database passwords. The same rule applies to this website.
Detecting & monitoring
Logging changes
auditd runs on the servers. It records when SSH keys, sudo rights, users or cron jobs get touched. For SSH keys and sudo I get a message on my phone within a few minutes, the rest arrives as a daily summary.
Why: If someone gets in, I want to notice before they settle in.
Weekly scans
Every Sunday a script checks all servers and containers with trivy for known vulnerabilities and with lynis for hardening gaps. An nmap run compares the whole network with the last state and reports new devices and open ports. The result is a summary with a comparison to the week before.
Watchdog
A container of its own runs 24 checks around the clock and tells me via Telegram when something's off.
Why: An alert only counts as done for me when the message really arrives on my phone. And I watch the false alarms, otherwise I'd end up swiping them away.
Deliberately light
I looked at a full SIEM like Wazuh and dropped it. It would be too heavy for my cluster. Small scripts do exactly what I need.
Updates & recovery
Updates run on their own
The containers pull security updates at night by themselves. Home Assistant makes a backup before an update, and I get a message if something stops working afterwards. Critical programs like the reverse proxy are locked and get updated by hand.
Why: Automatic is great, unless it wrecks my proxy.
Backups I actually test
Backups go to the NAS at night and encrypted to the cloud. Whether a restore works, I try out. Restore a backup into a test VM, compare checksums, throw it away.
Everything documented
Every audit gets a log of what I found and changed. In April that was over 30 fixes.
How the pieces fit together is in the diagram on the setup page.