Security measures for your homelab setup

Security measures for your homelab setup

I keep my homelab because it scratches a technical itch and gives me somewhere safe to test things. The sensible answer is not paranoia. It is basic security, repeatable automation, and a few checks that stop a small mistake turning into a proper headache.

These are the steps I use. Nothing clever. Just the sort of thing that keeps services contained, recoverable, and less likely to bite when I am not looking.

Lock the doors: basic security practices that actually work

Security is a stack of small choices. Pick a few and stick with them.

  1. Inventory and reduce your attack surface.
  • List exposed services with sudo ss -tulpen or sudo lsof -i -P -n. Remove anything you do not need.
  • Put lab gear on a separate VLAN or guest SSID. On OpenWrt or pfsense, tag ports so homelab traffic stays away from personal devices.
  1. Use SSH keys and limit access.
  • Disable password SSH for servers: in /etc/ssh/sshd_config set PasswordAuthentication no and PermitRootLogin no, then restart SSH:
systemctl restart sshd
  • Store private keys in a hardware token or an encrypted file with a strong passphrase. Add an SSH config entry per host to avoid typing mistakes.
  1. Use multi-factor where the service supports it.
  • Use a YubiKey or TOTP for services that support 2FA. For web UIs, I prefer hardware keys where they are available.
  • If a self-hosted app does not support MFA, put it behind an authenticated reverse proxy.
  1. Harden services and defaults.
  • Use unattended-upgrades on Debian or Ubuntu:
apt install unattended-upgrades && dpkg-reconfigure --priority=low unattended-upgrades
  • Check /var/log/unattended-upgrades for activity.
  • Keep admin panels on localhost or a VPN. Do not expose management ports like 8080 or 8000 directly to the internet.
  1. Tidy up privacy settings and logging.
  • Review app privacy settings before you add a new service. Turn off telemetry at install time where possible.
  • Keep logs for a reasonable window. Use logrotate and push critical logs to a separate machine so they are still there when something breaks.

Verify it from outside your LAN:

  • Run nmap -sT -p- <external-ip> to check only the ports you expect are open.
  • Test SSH key-only login from a clean client. Try a failed login too, then check that bans or rate limits trigger.

That cuts the chance of a silly break-in and keeps the lab less exposed than it needs to be.

Automate the boring and the dangerous

Automation cuts human error and means I spend less time babysitting services.

  1. Backups that run automatically and can be checked.
  • Run scheduled backups with restic or Borg. Example restic cron job:
0 3 * * * /usr/local/bin/restic-backup.sh
  • Include a verification step:
restic snapshots && restic check
  • I run a restore test monthly to a throwaway VM.
  1. Infrastructure as code for repeatability.
  • Use Ansible for configuration. Keep playbooks small and idempotent. Store secrets in an encrypted vault or secret manager.
  • A playbook that installs Docker, sets UFW rules, and deploys a reverse proxy means a dead server is more annoying than disastrous.
  1. Automated certificate renewals.
  • Use certbot with Nginx and a non-interactive renewal path:
certbot --nginx --non-interactive --agree-tos -m you@example.com
certbot renew --dry-run
  • Check /var/log/letsencrypt for failures. If you use Traefik, configure ACME there instead of running separate renewals.
  1. Service supervision and restarts.
  • Use systemd for services or a process manager like supervisord. Add Restart=on-failure and RestartSec=10 to unit files.
  1. Observability that tells you something useful.
  • Run Prometheus and Grafana for CPU, memory, disk I/O, certificate expiry, and backup success.
  • Alert only on things you can act on: failed backups, full disks, or certificates that expire within seven days.
  • Use a private push service, an encrypted message to your phone, or another low-noise channel. Alert fatigue is pointless.
  1. Small, safe automation wins.
  • Auto-update containers with something like watchtower only for non-critical apps. For important services, automate build and test pipelines rather than pushing straight to production.
  • Automate security scans with Lynis or OpenVAS, but run them at sensible times so the noise stays manageable.

Verify the automation before you trust it:

  • Break one component in a safe environment and watch the playbook or restore run.
  • Check alerts for false positives for two weeks, then tighten thresholds.

Practical privacy settings

  • For any self-hosted app, look for telemetry and disable it. If there is no switch, block the domains at Pi-hole or your DNS resolver.
  • For shared machines, create unprivileged accounts and limit sudo access with visudo rules.

Why it matters

  • Automation makes recovery predictable. Predictable recovery takes some of the fear out of running the lab.
  • When rebuilds and restores are documented and automated, a breakage is an operational task rather than a crisis.
  • That is the part that matters when you want to tinker without worrying about every small mistake.

Related posts

Monitoring radio, transport and core faults

Private 5G resilience does not come from a cheerful dashboard or a nice radio map. I want to see where the attach failed, which path dropped, and whether the core is quietly spoiling the whole thing;...

Immich | v3.2.2

Immich v3 2 2: small patch fixes cross user face reassign bug, skips faces owned by other accounts, recommended update for users relying on face reassign

Nextcloud | v35.0.0

Nextcloud v35: polished UI, Files and sharing upgrades, better client parity, security hardening, performance and admin gains, developer notes and upgrade tips