Skip to content

Architecture

These views map the homelab's machines, workloads, control paths, monitoring, and storage. Versions, ports, mounts, addresses, hostnames, and the live tunnel map remain in configuration or private site data.

Network and access

OPNsense is the network edge. The Debian server runs the live workloads, while the separate Proxmox host provides disposable test machines.

flowchart TB
    internet[Internet] --> router[OPNsense router<br/>Firewall · dnsmasq · AdGuard Home · CrowdSec]
    router --> network[Home network]
    network --> server[Debian 13 server]
    network --> proxmox[Proxmox test host]
    proxmox --> vms[Disposable VMs]
    server --> compose[Docker Compose<br/>Media · Monitoring · Actual]
    server --> host[Host services<br/>Storage · systemd jobs]

Remote and trusted clients use different access paths. Exact public tunnel routes are intentionally omitted; see Security boundaries.

Client Access path Destination
Internet Caddy Plex
Internet Encrypted remote ingress through cloudflared Selected remote-user services
LAN or VPN Caddy Plex
LAN or VPN Direct private listeners Operator services

Applications

The main media path stays linear from request to playback.

flowchart TB
    seerr[Seerr] --> managers[Radarr · Radarr Remux<br/>Sonarr · Anime Sonarr]
    managers --> search[Prowlarr searches sources]
    search --> download[SABnzbd<br/>qBittorrent via VPN]
    download --> library[Shared media library]
    library --> playback[Plex · Kavita · Audiobookshelf]

Supporting workloads connect to that path without sitting directly in it.

Service Role
Clonarr Keeps release profiles aligned across the media managers
cross-seed Finds reusable torrent matches for qBittorrent
Kometa Manages Plex metadata and collections
Plex Auto Languages Keeps Plex language choices consistent
AniBridge Connects anime activity with Plex
Audiobookshelf Streams the audiobook library to LAN and VPN clients
Tautulli Records Plex viewing activity
Wizarr Manages Plex invitations
Actual Budget Runs as a separate personal-service Compose project
Authelia Single sign-on login and TOTP MFA (OpenID Connect provider)
lldap The user directory that Authelia authenticates against

The media, Actual, monitoring, and identity projects have separate default networks. The external proxy network is their only shared network and is joined only where ingress needs to reach a service.

Authelia is the single sign-on login for Audiobookshelf, Kavita, and Actual Budget; lldap is the shared user directory behind it, and each of those apps keeps a local login as a fallback. Only Authelia is reachable from the internet; lldap and its Redis session cache stay internal. Plex and the request apps keep their own Plex-based sign-in. The identity page explains the trust boundaries in full.

Audiobookshelf is available only on its private LAN/VPN listener. On first run, create its root account and add /audiobooks as the library. That media mount is read-only and stays in the replaceable mergerfs/SnapRAID media boundary; its configuration and metadata stay in appdata and receive the existing local and offsite restic backups.

Operations and observability

Repository changes are checked in GitHub Actions. Ansible converges the Debian host and deploys the four Compose projects.

flowchart TB
    repo[Repository] --> checks[GitHub Actions checks]
    repo --> ansible[Ansible]
    ansible --> server[Debian host<br/>Configuration · Compose projects · systemd timers]

systemd runs SnapRAID sync and scrub, appdata backup, btrfs scrub, restic checks, the watchdog, and monitoring collectors.

Metrics take one collection path into dashboards and alerts.

flowchart TB
    sources[Router · host · disks and GPU<br/>applications · probes · scheduled jobs]
    sources --> collectors[Exporters and textfile collectors]
    collectors --> prometheus[Prometheus]
    prometheus --> outputs[Grafana dashboards<br/>Alertmanager notifications]

The exporters cover Node, SMART, Intel GPU, OPNsense, Radarr, Sonarr, Prowlarr, SABnzbd, qBittorrent, Tautulli, speed tests, and black-box probes. Host collectors report maintenance-job results without waking the parity disk.

Logs take a separate path into Grafana.

flowchart TB
    logs[Docker logs through a read-only socket proxy<br/>systemd journal]
    logs --> alloy[Alloy]
    alloy --> loki[Loki]
    loki --> grafana[Grafana]

Storage and backups

Five independent XFS data drives form the mergerfs media pool. SnapRAID parity protects that pool, while incomplete usenet downloads use the NVMe cache.

flowchart TB
    drives[5 x XFS data drives] --> pool[mergerfs media pool]
    incomplete[NVMe incomplete downloads] --> pool
    parity[SnapRAID parity<br/>Normally spun down] -. protects .-> pool

Application data follows a separate backup path.

flowchart TB
    appdata[NVMe btrfs appdata] --> snapshot[Read-only btrfs snapshot]
    snapshot --> restic[restic]
    restic --> copies[Local array backup<br/>Offsite backup]

Media protection and appdata backups solve different failure cases. The full disk layout, staging behavior, and recovery model are documented in Storage and backups.