Design considerations and trade-offs #
Key Architecture Decisions & Trade-offs
- Cost Efficiency:
- The Cloud cluster utilizes x2 2GB hosts for cost efficiency. Additional regions for redundancy were skipped in favor of a fast, and cost-effective GitOps recovery model.
- UpCloud was chosen over other public cloud providers (AWS/GCP/Azure) for simplicity and low operating costs.
- LXC over VMs:
- LXC containers were selected for homelab workloads due to minimal resource usage, fast startup times, and efficiency on local secondhand hardware (Lenovo Mini PC & Raspberry Pis).
- Runner Design:
- Split across environments: a self-hosted runner in the homelab cluster and a public runner for cloud workloads. A future iteration will see the public runner replaced with run-once scaling agents.
Global Topology #
flowchart LR
USERS(["Visitors & engineer"])
GITHUB["GitHub
Source · Actions · GHCR"]
CF["Cloudflare
Edge · Access · Tunnels"]
subgraph CLOUD["UpCloud K8s"]
ARGO["Argo CD"]
SITE["Public site"]
ARGO --> SITE
end
subgraph HOME["Homelab"]
K3S["K3s
Open WebUI · LiteLLM · MCP · observability"]
LXCS["Dedicated LXCs
n8n · self-hosted runner"]
end
USERS --> CF
CF --> SITE
CF --> K3S
GITHUB --> ARGO
GITHUB --> LXCS
classDef entry fill:#e0f2fe,stroke:#0284c7,color:#0f172a,stroke-width:1.5px;
classDef edge fill:#fef3c7,stroke:#d97706,color:#0f172a,stroke-width:1.5px;
classDef runtime fill:#ecfdf5,stroke:#059669,color:#0f172a,stroke-width:1.5px;
classDef delivery fill:#ede9fe,stroke:#7c3aed,color:#0f172a,stroke-width:1.5px;
class USERS,GITHUB entry;
class CF edge;
class K3S,LXCS,SITE runtime;
class ARGO delivery;
Figure 1: End-to-end hybrid topology and delivery flow.
Network VLANs
- VLAN 1: Default Management
- VLAN 3: Isolated Applications
- VLAN 4: Homelab & IoT
UniFi Hardware
- Cloud Gateway Max
- USW Ultra (1)
- USW Ultra (2)
- USW Ultra (3)
UniFi and Proxmox #
flowchart LR
GATEWAY["Cloud Gateway Max
VLAN routing & firewall policy"]
SWITCHES["USW Ultra switches
Access & PoE"]
subgraph NETWORKS["Networks"]
MGMT["VLAN 1
Management"]
APPS["VLAN 3
Isolated applications"]
LAB["VLAN 4
Homelab & IoT"]
end
subgraph PROXMOX["Proxmox"]
RUNNER["GitHub runner"]
PRIVATE["n8n LXC"]
CONTROL["K3s control plane"]
WORKER["K3s worker"]
end
GATEWAY --> SWITCHES
SWITCHES --> MGMT
SWITCHES --> APPS
SWITCHES --> LAB
APPS --> RUNNER
APPS --> PRIVATE
LAB --> CONTROL
LAB --> WORKER
CONTROL <--> WORKER
classDef network fill:#fef3c7,stroke:#d97706,color:#0f172a,stroke-width:1.5px;
classDef compute fill:#e0f2fe,stroke:#0284c7,color:#0f172a,stroke-width:1.5px;
classDef service fill:#ecfdf5,stroke:#059669,color:#0f172a,stroke-width:1.5px;
class GATEWAY,SWITCHES,MGMT,APPS,LAB network;
class CONTROL,WORKER,RUNNER compute;
class PRIVATE service;
Figure 2: Network segmentation and local compute boundaries.
IoT, SBC, and Proxmox compute hosts are isolated across separate VLANs.
Cloud K8s and GitOps #
flowchart TB
CHANGE["Reviewed change"] --> REPO["GitHub repository
Code & manifests"]
REPO --> CI["GitHub Actions
Build · test · publish"]
CI --> GHCR["GHCR
Versioned image"]
REPO -.-> ARGO["Argo CD
Reconcile"]
GHCR --> WORKLOAD["UpCloud Kubernetes
Public site workload"]
ARGO --> WORKLOAD
classDef source fill:#e0f2fe,stroke:#0284c7,color:#0f172a,stroke-width:1.5px;
classDef delivery fill:#ede9fe,stroke:#7c3aed,color:#0f172a,stroke-width:1.5px;
classDef runtime fill:#ecfdf5,stroke:#059669,color:#0f172a,stroke-width:1.5px;
class CHANGE,REPO source;
class CI,GHCR,ARGO delivery;
class WORKLOAD runtime;
Figure 3: Reviewed source through build, registry, and declarative deployment.
Build > Push > Deploy #
- Continuous Integration: GitHub Actions builds and pushes container images to GitHub Container Registry (GHCR).
- GitOps Reconciliation: Argo CD automatically detects new manifest updates and image tags in the repository and reconciles the desired state against the cluster.
Edge Security and Ingress #
flowchart TB
PUBLIC(["Public visitor"])
ENGINEER(["Engineer"])
EDGE["Cloudflare Edge
DNS · WAF · TLS"]
ACCESS["Cloudflare Access
Identity & service tokens"]
TUNNEL["Cloudflare Tunnel
Outbound-only"]
PUBLIC_APP["Public site"]
PRIVATE_APPS["Private services
Grafana · Open WebUI · LiteLLM"]
PUBLIC --> EDGE --> PUBLIC_APP
ENGINEER --> ACCESS --> TUNNEL --> PRIVATE_APPS
classDef entry fill:#e0f2fe,stroke:#0284c7,color:#0f172a,stroke-width:1.5px;
classDef security fill:#fef3c7,stroke:#d97706,color:#0f172a,stroke-width:1.5px;
classDef app fill:#ecfdf5,stroke:#059669,color:#0f172a,stroke-width:1.5px;
class PUBLIC,ENGINEER entry;
class EDGE,ACCESS,TUNNEL security;
class PUBLIC_APP,PRIVATE_APPS app;
Figure 4: Separate public and identity-aware private access paths.
Zero Trust Tunnel Architecture #
- Zero Inbound Ports: Cloudflare Zero Trust tunnels allow secure access to cluster services without exposing public IP addresses on nodes.
- RBAC & Isolation: Argo CD AppProjects enforce granular RBAC policies and resource whitelisting for each application.
- Identity-Aware Access: All traffic is authenticated and authorized via Cloudflare Zero Trust.
- Declarative Setup: Access and app configs are managed through code and git rather than manual dashboard clicking.
Network Topology #
[ Client / Admin ] ──► [ Cloudflare Edge (WAF & Access) ] ──► [ Cloudflare Tunnel ] ──► [ UpCloud K8s / Homelab ]
Cross-Cluster Telemetry #
flowchart LR
subgraph CLOUD["UpCloud K8s"]
SITE["Public site"]
CLOUD_PROM["Cloud Prometheus"]
SITE --> CLOUD_PROM
end
TOKEN["Cloudflare Access
Service-token protected path"]
subgraph LOCAL["Homelab"]
SERVICES["K3s services & LXCs"]
PROM["Prometheus"]
LOKI["Loki"]
GRAFANA["Grafana"]
SERVICES --> PROM
SERVICES --> LOKI
PROM --> GRAFANA
LOKI --> GRAFANA
end
CLOUD_PROM --> TOKEN --> GRAFANA
classDef telemetry fill:#e0f2fe,stroke:#0284c7,color:#0f172a,stroke-width:1.5px;
classDef edge fill:#fef3c7,stroke:#d97706,color:#0f172a,stroke-width:1.5px;
classDef workload fill:#ecfdf5,stroke:#059669,color:#0f172a,stroke-width:1.5px;
class SERVICES,SITE workload;
class PROM,LOKI,GRAFANA,CLOUD_PROM telemetry;
class TOKEN edge;
Figure 5: Local observability with protected cloud telemetry.
Skills & Tools #
A quick look at the tech and skills used throughout:
- IaC: OpenTofu / Terraform to manage UniFi network rules, Proxmox LXCs, and cloud infrastructure.
- Kubernetes & Containers: K3s inside LXC containers, managed UpCloud K8s, and Argo CD for GitOps deploys.
- Networking & Security: VLAN segmentation, Cloudflare Zero Trust tunnels (no port forwarding), and SSO.
- Observability: Prometheus, Loki, and Grafana for metrics and logs across clusters.
- Tooling: Nix shells for reproducible local CLI environments.
Summary #
| Layer / Host | Technology | IP / Subnet | Management / Access | Role |
|---|---|---|---|---|
| UniFi Network | Cloud Gateway Max + USW Ultra (x3) | VLAN 1, 3, 4 | OpenTofu infra/network | L2/L3 Routing & PoE switching |
| Omicron | Proxmox VE 9.x (Lenovo Mini-PC) | VLAN 4 | Proxmox Web GUI / SSH | Hypervisor host |
| k8s-node-01 / 02 | K3s in Debian 12 LXC | VLAN 4 | OpenTofu infra/proxmox | Homelab Kubernetes compute |
| showcase-cluster | UpCloud Managed K8s | Cloud VPC | OpenTofu infra/cloud | Production public cloud cluster |
| Edge Ingress | Cloudflare Tunnels & Access | *.conordot.com | Zero Trust SSO & Service Tokens | Ingress with 0 inbound open ports |
| Observability | Prometheus, Loki & Grafana | grafana.conordot.com | Cloudflare Access + Service Tokens | Hybrid cross-cluster monitoring |
| Private AI & automation | Open WebUI, LiteLLM, n8n | Private K3s / LXC boundaries | Scoped keys and application access | AI workspace, model routing, workflows |