As discussed in earlier post, the hardware choice was ultimately simple given the requirements. Even top-level software choice (Linux running Debian) did not seem particularly hard, but then started the hard part: coming up with reasonable design for what to run there.

The requirements (2023 November)

  • As I had 2,5GB ethernet ports (finally), my main Mac and NAS had to be directly connected to the box
    • I used to have separate 2,5GB point-to-point between the two, but using simply one port in each instead of two made management slightly simpler and less error prone
  • ’Internet-facing’ part would need to be relatively static and not touching Debian directly at all (instead, something bit more hardened would be the first ingress point)
  • Both rootful and rootless containers would be nice to have
  • The more containers the merrier - at this point I foresaw about half dozen useful containers
    • something firewall/router-y facing internet
    • DNS ad blocker (e.g. adguard, or pi-hole)
    • reverse proxy to handle HTTPS (from both inside home, as well as from the internet) using proper certificates (e.g. caddy, traefik)
    • home assistant (for home visibility and automation)
    • jellyfin (for media)
  • Infrastructure as Code (IaC from now on)

What I did not choose to use

Proxmox ( https://www.proxmox.com/en/ ) seems like the toy of the hour in the enthusiast circles. I am not quite sure why; perhaps it is the GUI. But the combination of GUI driven material (mostly), as well as not particularly good IaC (no first-party Terraform support - at the time there is third-party one in Proxmox Provider - Terraform Registry) did not make it particularly tempting for me. And besides, I was mostly planning to use pyinfra anyway.

Docker isn’t great at dealing with low-level virtualisation, and after the Moby debacle I did not feel it to be particularly open source anyway. The default one baked into Debian is not apparently ‘official’, and Install Docker Engine on Debian is bit elaborate, and from my point somewhat sketchy as I am not fan of adding external sources from commercial companies without that inspiring open source track record.

Kubernetes I didn’t even consider, as single node Kubernetes setup adds lots of complexity while again keeping bit too far away from the hardware.

The stack

The initial choice was what to run facing internet. As my old setup was based on Turris Omnia (which uses OpenWrt branch of their own), I chose to go with OpenWrt. The realistic virtualization options were either something with hypervisor with its own kernel (e.g. KVM based), or shared kernel based containers.

After some consideration, I figured that this stack will go with containers all the way, so I went with Linux Containers - LXC as the low-level containers ( to run https://openwrt.org/ and Adguard Home )

For the rest, I chose to use vanilla Podman (that came with Debian 12, which is admittedly bit dated but works well enough) with both rootful as well as rootless containers. Jellyfin hardware acceleration support requires root, and without changing restricted port ranges caddy (chosen reverse proxy) does as well.

I wondered also about how to specify and update the containers; ultimately I wound up writing relatively simple two types of pyinfra configurations, with

  • lxc containers handled ‘by hand’
    • I did not see foresee getting more of them, and that is still the case - I am still running just two of them as of May, 2024
  • podman containers handled using one utility Python function, which supports
    • rootful/rootless container
    • custom Containerfile, or pre-existing image
    • (optional) configuration data dir to be synced to the node being managed
    • systemd-unit based persistence
    • (manually) triggered autoupdate support
      • if I run normal deploy, existing things are not upgraded, but if I run the deployment in upgrade mode, podman auto-update is run (if using existing images) or images are recreated (if custom Containerfile is used)

Pretty picture!

This is the (slightly anonymised) architecture diagram of the home infrastructure at the time: It has been relatively good so far (half year in, at the time of writing). The overall architecture has stayed the same, and so far the uptime has been 100% (- two times the box has to have been moved, which caused about two minutes downtime each time).

The box is addressable via 3 IPv4 addresses (and also IPv6, but at the time I do not see much of a point using):

  • .2 : the main Debian (all podman containers)
  • .4: OpenWrt
  • .8: adguard

Not colocating the ‘core’ services (IP routing/bridging, DNS) seems to have been reasonably good choice, as there have been no issues with conflicts thanks to e.g. shared port 53 use (for DNS), and the hosts can actually have reasonable fallback IP list for DNS resolver to use.

In practise adguard has been configured to use OpenWrt as its backend, but if adguard is down, DNS in the network still works to some extent.

What’s next?

The above diagram describes how the infrastructure looked sometime in December 2023. It was just start of the journey for that box, though, as the number of containers has grown up quite a bit after that. More about this later..