NAS & Homelab
A self-hosted homelab, inventoried, hardened, and checked against Git rather than assumed to match it.
Underneath this site, and most of what I run at home, is a Synology NAS running a Docker and Portainer estate: currently 31 containers covering media, monitoring, home automation, and network services. Most of them are organised into thirteen Portainer stacks, defined as Compose files in Git with real secrets kept out of the repo in favor of environment placeholders and the macOS Keychain. Two things sit outside that arrangement - one stack is deployed straight from the Compose CLI because it builds its own image, and one service isn't containerised at all - which is precisely the sort of caveat that used to get rounded off to "everything is tracked".
The monitoring layer is where the estate has actually grown. A Prometheus and Grafana stack, cAdvisor, node-exporter, and half a dozen service-specific exporters replaced an older all-in-one tool, and now feed seven dashboards across eleven scrape jobs. The dashboards are defined as code in Git and compared against the live instance by a read-only script, so drift gets reported rather than discovered. Alerting went from nothing at all to eight rules in three groups, covering host memory pressure, swap, disk, target liveness, certificate expiry, and containers that restart more than they should. Every container runs a restart-always policy - a rule written into the estate after a Docker daemon crash took down everything that wasn't self-healing - and a full reboot test has since brought back all 31 with no intervention, which makes it a measured property rather than an intention.
The perimeter is hardened end to end: SSH is key-only, WAN access is closed, and the firewall runs a default-deny, LAN-only policy since a legacy hypervisor and virtual switch were retired. Exposed credentials get rotated on discovery, and internal traffic between services runs over HTTPS behind a reverse proxy, with wildcard certificates issued without opening an inbound port for the privilege. Remote access exists now where it previously didn't, and it too costs zero inbound ports. Internal names resolve internally.
The largest single addition is a publishing pipeline: thousands of stills and several hundred videos are pushed nightly from the NAS to object storage behind a Worker, with metadata stripped and capture dates preserved. Alongside it, a weekly automated snapshot writes the estate's configuration into version control, so the setup has a dated history instead of only a current state. Two services were also retired on purpose, one of them kept in restorable form - things leaving is as much a part of the picture as things arriving.
It's less a product than an ongoing exercise in operating infrastructure the way I'd want a team to: inventoried, monitored, and reconciled toward Git as the source of truth, one stack at a time. The newest habit is the one I'd defend hardest - a detector doesn't count as working until its signal has been shown to move during a real instance of the thing it's meant to catch.
- Synology DSM
- Docker + Portainer
- Prometheus + Grafana + cAdvisor
- Dashboards-as-code + drift detection
- Caddy (reverse proxy)
- Bash / scheduled-job automation
- Git-tracked Compose stacks