HOME CLOUD / TECHNICAL OVERVIEW

A Proxmox lab with three nodes built around explicit failure domains.

Most services run in dedicated LXCs, persistent data lives on ZFS, redundant DNS spans physical hosts, and logs flow into a Graylog observability stack. This page explains the implementation and the July 2026 migration without publishing access details.

LOGICAL TOPOLOGY

Five layers, with failure boundaries between them.

The diagram intentionally omits addresses, but the components and relationships are real. Compute hosts do not double as DNS endpoints; DNS redundancy crosses physical nodes; the proxy is an access layer, not a substitute for service discovery; and monitoring is independent of application health.

CLIENT ACCESSFIREWALL · PRIVATE TLS
SERVICE ENTRYADGUARD HA · KEEPALIVED · NGINX
COMPUTE3× PROXMOX · LXC · VM
PERSISTENCEZFS RAIDZ1 · NVME · NFS · BACKUP
OPERATIONSGRAYLOG · WAZUH · UPTIME · GRAFANA

COMPONENT MATRIX

What runs where, and why.

Credentials, addresses, internal names, ports, and externally useful entry points are omitted.

LayerImplementationDesign decision

Compute

Proxmox cluster with three nodes using both LXC containers and virtual machines.

Most Linux applications get a dedicated LXC. VMs are reserved for workloads that need stronger isolation or a complete guest OS.

Storage

ZFS RAIDZ1 capacity pool, local NVMe, NFS storage, and separate backup targets.

Service root disks were consolidated on ZFS for capacity and operational consistency. Workloads sensitive to latency can remain on local NVMe.

Network

Bonded high speed uplink, Linux bridges, an nginx reverse proxy, and an internal certificate authority.

Browsers use private HTTPS names. Backend integrations use the most reliable path for that application rather than assuming every runtime resolves local DNS identically.

DNS

Two AdGuard Home instances with Keepalived providing a floating service address.

The pair runs on separate physical nodes. Either DNS guest can be stopped while the other continues answering requests.

Observability

Graylog 6.1, OpenSearch 2, MongoDB 6, Vector, Wazuh, Uptime Kuma, and Grafana.

Vector reads Docker logs or the systemd journal depending on the guest. Availability, centralized logs, and security monitoring remain separate signals.

Applications

Photo management, media automation, home automation, dashboards, developer tools, and production application services.

One service per guest is preferred where practical. It increases guest count but reduces dependency conflicts and makes maintenance boundaries obvious.

MIGRATION LOG / JULY 16 TO 19, 2026

Moving the services was the easy part. Moving their assumptions was harder.

PUBLIC TECHNICAL EDITION

Derived from the operating log. Security related identifiers and commands are removed; versions, architecture, failure modes, and engineering decisions remain.

The project consolidated services from an older Rocky Linux Docker host and a retired k3s environment into Proxmox guests. The target design uses dedicated LXCs for most applications, VMs where full guest isolation is useful, ZFS for the primary capacity tier, and separate systems for DNS, ingress, logs, availability, and security monitoring.

3physical Proxmox nodes
18LXC root disks moved sequentially
~1.6 TBmedia download data migrated
53,718photo assets verified after cutover

THE ACTUAL RUNBOOK

01

Map dependencies

Inventory each service, its data, upstream clients, downstream consumers, DNS name, proxy route, monitoring check, and rollback source. Protected production workloads and one member of the DNS pair were excluded from the bulk move.

02

Choose storage deliberately

Media downloads and libraries were placed on the same ZFS dataset boundary so Sonarr and Radarr could keep creating hardlinks. Splitting them would have converted moves into full copies and doubled storage use.

03

Move one guest at a time

Proxmox cannot move a running LXC root filesystem with the same online workflow available to VM disks. Each container followed stop → move volume → start → health check, so only one service was unavailable at a time.

04

Repair application topology

Several integrations still referenced the retired Kubernetes network or an obsolete endpoint. Download clients, indexer synchronization, DNS settings, and routes between services were checked independently of whether the process was merely running.

05

Cut over the access layer

After direct service validation, the reverse proxy route, private certificate path, DNS record, log forwarding, and uptime monitor were updated. Browser access was tested separately from backend API communication.

06

Retain rollback, then retire

Old instances were stopped before deletion. After the replacement survived a verification period, unused management and network boot guests were removed along with their proxy routes and monitors.

FAILURE ANALYSIS

Symptoms, root causes, fixes, and reusable lessons.

SymptomRoot causeFixGeneral lesson

Home automation opened with a blank default configuration.

The first migration used the wrong data copy. After the correct data replaced it, the running guest still held a bind mount to the previous directory inode.

Copy the authoritative application data, then restart the entire LXC so the mount namespace is rebuilt.

A successful file copy does not prove a running process has switched to the new filesystem object.

A newly assigned logging guest appeared reachable, but the traffic was not reaching it.

The selected static address was already in use; another device was answering ARP and ping.

Scan for conflicts before assignment, change the address, and validate the service instead of relying only on ICMP reachability.

A ping response can confirm the wrong machine just as easily as the right one.

A migrated security monitoring VM started on the destination host without network access.

Its virtual NIC referenced a bridge whose name existed on both hosts but represented a disconnected physical interface on the destination.

Rebind the virtual NIC to the destination’s active bridge while preserving the guest MAC address.

Matching bridge names do not guarantee matching physical topology across hypervisors.

Graylog’s network ports were open, but no events appeared in search.

Container port mappings existed, but Graylog inputs had not been created. Transport was available; the application pipeline was not.

Create the GELF and syslog inputs, send a tagged test event, and confirm it through search.

A listening socket is not a complete observability test.

Indexer changes stopped propagating to one media manager even though every application reported healthy.

The integration still referenced a service name from the retired Kubernetes cluster.

Update the application synchronization endpoint and test propagation by changing data at the source and verifying it at the destination.

Platform migrations fail at dependency edges long after the processes themselves turn green.

KNOWN GAPS

What is not finished yet.

A useful architecture document includes incomplete work, not only the successful cutover.

01

Hypervisor telemetry

Container logs are centralized; Proxmox host logs still need a defined retention and forwarding policy.

02

Remaining VM migration

One mail workload remains on its original node after two storage path failures. The next attempt needs an independently verified destination path and rollback window.

03

Storage placement review

Most service disks favor ZFS capacity and consistency. Workloads with measurable latency sensitivity should be benchmarked before moving away from local NVMe.