Homelab
My own cloud on an old laptop, and the place I practice networking and cloud fundamentals.
An old laptop with a 2-core i3, 8 GB of RAM and a spinning disk runs Debian and replaces Google Drive and Photos for me. Every service has to earn its memory, which forces the same tradeoffs you make when paying for cloud resources.
What runs on it
| Service | Job |
|---|---|
| Immich | Photo library, tuned for a spinning disk |
| Gitea | Git hosting for most of my projects, with its own CI runner |
| Ollama | Small AI models on the CPU for my Switchboard tool |
| Caddy | Reverse proxy and static hosting |
| code-server | VS Code in the browser |
| Portainer | Container management |
| restic | Scheduled backups to a separate drive |
How it’s secured
- Private by default. Nothing is open to the internet or the home network. Every service is reached over Tailscale, an encrypted private network between my own devices.
- Host firewall. nftables drops any new connection that doesn’t arrive over Tailscale, including traffic that Docker would otherwise let through.
- SSH keys only. Password and root logins are off.
A security review found a browser-based editor running without a password on every network interface. It’s now limited to Tailscale, behind the firewall, and the lesson is in my mistake log.
A cloud lab I own
Each part of the homelab maps to something a cloud provider sells, so I can learn the concept hands-on without a bill.
| Cloud concept | Homelab version |
|---|---|
| Private network (VPC) | Tailscale network |
| Security groups | nftables firewall rules |
| Load balancer and ingress | Caddy reverse proxy |
| Container service | Docker Compose stacks |
| Infrastructure as code | Compose files in git |
| CI/CD | Gitea Actions runner |
| Managed database | Postgres behind Immich |
| Snapshots and backups | restic |
| Access management | SSH keys and Tailscale access rules |
Labs
Exercises I’m working through, each with a way to check the result:
- Firewall rules. Open a port, confirm it can’t be reached from a phone on Wi-Fi, then read the rule’s packet counter to see the drops.
- DNS. Give each service a name instead of an IP and port, and trace a lookup from the client to the answer.
- HTTPS. Put a service behind Caddy with a real certificate, then inspect the TLS handshake.
- Container networking. Connect two containers on their own network, capture the traffic between them, and explain every hop.
- Least privilege. Write Tailscale access rules so a device can reach one service and nothing else.
- Backup and restore. Restore a file from backup into a scratch folder and time it. That time is my recovery time objective.
- Monitoring. Add uptime and disk alerts, then break something on purpose to test them.
- Rebuild from scratch. Recreate a stack from git on a fresh virtual machine to prove the infrastructure is really written down.
- Same app, real cloud. Deploy a small service to a free cloud tier and compare cost, speed and effort with the homelab version.
Built with Debian, Docker, Tailscale, nftables, Caddy and restic.