State of the homelab

  • Posted: August 15, 2026
  • Updated: August 18, 2026

Currently, my homelab runs on one machine: a Beelink Mini PC with an AMD Ryzen 7 6800U (8C/16T), 19 GiB of RAM, and a 512 GB NVMe disk running Fedora 44. Everything is a systemd service on the host, except the Homepage dashboard, which runs in a rootless Podman container. The design goal was one: simplicity and reliability. I’ve had Kubernetes homelabs and fancy stuff in the past with Talos Linux, but never actualy depended on it.

                 ┌────────────────────────────────────────────┐
                 │                  CLIENTS                   │
                 │            (laptop or cellphone)           │
                 └──────────────────────┬─────────────────────┘
                                        │  *.yyvf.xyz → 100.72.197.102
                                        ▼  Tailscale VPN (encrypted, MagicDNS)
┌───────────────────────────────────────┴──────────────────────────────┐
│                        HOST: beelink1 (Fedora 44)                    │
│                                                                      │
│  ┌──────────────────────┐                                            │
│  │   Caddy v2.11.4      │  wildcard *.yyvf.xyz (Cloudflare DNS-01)   │
│  │                      │  :80/:443                                  │
│  └──────────┬───────────┘                                            │
│             │ reverse_proxy (by hostname)                            │
│             ├──────────────▶ Forgejo      :3000   git.yyvf.xyz       │
│             ├──────────────▶ Homepage     :3001   homepage.yyvf.xyz  │
│             ├──────────────▶ Grafana      :3002   grafana.yyvf.xyz   │
│             └──────────────▶ gonic        :4747   gonic.yyvf.xyz     │
│                              (127.0.0.1)                             │
│                                                                      │
│   Prometheus :9090 ──▶ node-exporter :9100                           │
│   Tailscale  :41641/UDP ──▶ 100.72.197.102                           │
│                                                                      │
│   Container Podman rootless (user homepage):                         │
│   └── Homepage :3001 ▶ dashboard ghcr.io/gethomepage/homepage        │
└──────────────────────────────────────────────────────────────────────┘

Tailnet as the network, DNS as the gate

There is no public exposure. All *.yyvf.xyz domains point at the host’s Tailscale IP (100.72.197.102), so they only resolve for devices inside the tailnet. Tailscale handles the encrypted tunnel, MagicDNS, and the client IPs — no firewall rules open to the world, no reverse DNS leaks.

Services run the same domain names you’d use in production (git.yyvf.xyz, gonic.yyvf.xyz, …), which means client configs and app URLs work identically from anywhere on the tailnet.

Caddy is the only door

Caddy is the only process bound to the public interfaces, and the only one doing TLS. Backends stay on localhost or on ports the firewall doesn’t expose outside the tailnet.

The whole routing config is one site block:

*.yyvf.xyz {
    tls { dns cloudflare "<token>"; resolvers 1.1.1.1 }
    handle gonic.yyvf.xyz     { reverse_proxy localhost:4747 }
    handle git.yyvf.xyz       { reverse_proxy localhost:3000 }
    handle homepage.yyvf.xyz  { reverse_proxy localhost:3001 }
    handle grafana.yyvf.xyz   { reverse_proxy localhost:3002 }
    handle                    { respond "Not Found" 404 }
}

The wildcard certificate is issued with the Cloudflare DNS-01 solver, so browsers trust it with no local CA to install. Adding a service is: bind it to a localhost port, add one handle line, done.

The services

ServicePortURLHow it runs
Caddy80, 443, 2019systemd
Forgejo3000https://git.yyvf.xyzsystemd, sqlite, SSH on 22
gonic4747https://gonic.yyvf.xyzsystemd, Subsonic API
Homepage3001https://homepage.yyvf.xyzrootless Podman container
Grafana3002https://grafana.yyvf.xyzsystemd (Fedora package)
Prometheus9090http://localhost:9090systemd
node-exporter9100http://localhost:9100systemd
Tailscale41641/UDPsystemd

Forgejo (a Gitea fork) stores git repos in sqlite under /var/lib/forgejo and serves SSH on port 22 with SSH_DOMAIN = git.yyvf.xyz. gonic streams music over the Subsonic protocol, so DSub/Subtracks work against gonic.yyvf.xyz from any tailnet device. Grafana consumes the local Prometheus; Prometheus scrapes node-exporter every 5s for host metrics.

Homepage runs as a rootless Podman container under a dedicated homepage user with linger enabled, publishing port 3001. It has HOMEPAGE_ALLOWED_HOSTS pointing at its hostname, so direct access via localhost:3001 is rejected on purpose.

What’s maybe next