diff --git a/load-balancing-my-homelab/content/index.md b/load-balancing-my-homelab/content/index.md index 78bd558..20b90cf 100644 --- a/load-balancing-my-homelab/content/index.md +++ b/load-balancing-my-homelab/content/index.md @@ -85,7 +85,7 @@ earlier state of the lab.

This diagram separates visitor traffic from deployment, control and monitoring. Application groups are illustrative; no real service catalogue, hostnames or private addresses are included. Solid arrows show the main flow within each section, while dashed arrows identify secondary paths, checks or control operations.

Detailed anonymized architecture: Cloudflare proxy and DNS-only access, two HAProxy and Anubis edges, private service failover, Tailscale origins, Semaphore deployment, Headscale policy, certificates and Prometheus monitoring -
Open the image at full size to follow the paths. Cloudflare checks the public entrance; each HAProxy checks its application paths. The shared origins remain a common dependency.
+
Open the image at full size to follow the paths. The separate red panel explains failure handling and redundancy limits; it is not an infrastructure component or a traffic path. Cloudflare checks the public entrance; each HAProxy checks its application paths.

The Mermaid source describes this generic architecture. It is maintained documentation, not a production configuration export.

diff --git a/load-balancing-my-homelab/diagrams/README.md b/load-balancing-my-homelab/diagrams/README.md index b234e22..b349dcf 100644 --- a/load-balancing-my-homelab/diagrams/README.md +++ b/load-balancing-my-homelab/diagrams/README.md @@ -96,8 +96,17 @@ flowchart TB PROM -. "HTTPS /_edge/metrics" .-> HA PROM -. "HTTPS /_edge/metrics" .-> HB - LIMITS["Failure boundaries
Cloudflare bypasses an unavailable public edge
HAProxy bypasses a failed per-service path when its peer is healthy
a failed shared origin is still unavailable
open video streams and WebSockets must reconnect"] - ORIGINS -.-> LIMITS + subgraph BOUNDARIES["Failure handling and limits - explanatory notes"] + direction LR + LIMIT_EDGE["Public edge unavailable
Cloudflare selects a healthy edge for new connections"] + LIMIT_PATH["One service path unavailable
HAProxy uses the peer when its path is healthy"] + LIMIT_ORIGIN["Shared origin unavailable
Both edges lose that application
edge redundancy does not replicate origins"] + LIMIT_STREAM["Open video streams and WebSockets
Existing connections do not migrate
clients must reconnect"] + LIMIT_EDGE ~~~ LIMIT_PATH ~~~ LIMIT_ORIGIN ~~~ LIMIT_STREAM + end + + %% Invisible positioning only: this is not a data-flow connection. + ORIGINS ~~~ BOUNDARIES classDef public fill:#233d58,stroke:#7ab5dc,color:#f2f6ff classDef edge fill:#284c44,stroke:#7bc8a7,color:#f2f6ff @@ -110,5 +119,6 @@ flowchart TB class VPS,ROUTER,FW,NPM,APPS origin class GIT,PLAN,DEPLOY,SECRETS,HS,CERT,CFAPI ops class PROM,GRAF,ALERT monitor - class LIMITS note + class LIMIT_EDGE,LIMIT_PATH,LIMIT_ORIGIN,LIMIT_STREAM note + style BOUNDARIES fill:#291f2a,stroke:#dd9ba7,color:#fff5f6 ``` diff --git a/load-balancing-my-homelab/diagrams/infrastructure.mmd b/load-balancing-my-homelab/diagrams/infrastructure.mmd index 295b21b..90d37b5 100644 --- a/load-balancing-my-homelab/diagrams/infrastructure.mmd +++ b/load-balancing-my-homelab/diagrams/infrastructure.mmd @@ -91,8 +91,17 @@ flowchart TB PROM -. "HTTPS /_edge/metrics" .-> HA PROM -. "HTTPS /_edge/metrics" .-> HB - LIMITS["Failure boundaries
Cloudflare bypasses an unavailable public edge
HAProxy bypasses a failed per-service path when its peer is healthy
a failed shared origin is still unavailable
open video streams and WebSockets must reconnect"] - ORIGINS -.-> LIMITS + subgraph BOUNDARIES["Failure handling and limits - explanatory notes"] + direction LR + LIMIT_EDGE["Public edge unavailable
Cloudflare selects a healthy edge for new connections"] + LIMIT_PATH["One service path unavailable
HAProxy uses the peer when its path is healthy"] + LIMIT_ORIGIN["Shared origin unavailable
Both edges lose that application
edge redundancy does not replicate origins"] + LIMIT_STREAM["Open video streams and WebSockets
Existing connections do not migrate
clients must reconnect"] + LIMIT_EDGE ~~~ LIMIT_PATH ~~~ LIMIT_ORIGIN ~~~ LIMIT_STREAM + end + + %% Invisible positioning only: this is not a data-flow connection. + ORIGINS ~~~ BOUNDARIES classDef public fill:#233d58,stroke:#7ab5dc,color:#f2f6ff classDef edge fill:#284c44,stroke:#7bc8a7,color:#f2f6ff @@ -105,4 +114,5 @@ flowchart TB class VPS,ROUTER,FW,NPM,APPS origin class GIT,PLAN,DEPLOY,SECRETS,HS,CERT,CFAPI ops class PROM,GRAF,ALERT monitor - class LIMITS note + class LIMIT_EDGE,LIMIT_PATH,LIMIT_ORIGIN,LIMIT_STREAM note + style BOUNDARIES fill:#291f2a,stroke:#dd9ba7,color:#fff5f6 diff --git a/load-balancing-my-homelab/files/infrastructure-mermaid.txt b/load-balancing-my-homelab/files/infrastructure-mermaid.txt index 295b21b..90d37b5 100644 --- a/load-balancing-my-homelab/files/infrastructure-mermaid.txt +++ b/load-balancing-my-homelab/files/infrastructure-mermaid.txt @@ -91,8 +91,17 @@ flowchart TB PROM -. "HTTPS /_edge/metrics" .-> HA PROM -. "HTTPS /_edge/metrics" .-> HB - LIMITS["Failure boundaries
Cloudflare bypasses an unavailable public edge
HAProxy bypasses a failed per-service path when its peer is healthy
a failed shared origin is still unavailable
open video streams and WebSockets must reconnect"] - ORIGINS -.-> LIMITS + subgraph BOUNDARIES["Failure handling and limits - explanatory notes"] + direction LR + LIMIT_EDGE["Public edge unavailable
Cloudflare selects a healthy edge for new connections"] + LIMIT_PATH["One service path unavailable
HAProxy uses the peer when its path is healthy"] + LIMIT_ORIGIN["Shared origin unavailable
Both edges lose that application
edge redundancy does not replicate origins"] + LIMIT_STREAM["Open video streams and WebSockets
Existing connections do not migrate
clients must reconnect"] + LIMIT_EDGE ~~~ LIMIT_PATH ~~~ LIMIT_ORIGIN ~~~ LIMIT_STREAM + end + + %% Invisible positioning only: this is not a data-flow connection. + ORIGINS ~~~ BOUNDARIES classDef public fill:#233d58,stroke:#7ab5dc,color:#f2f6ff classDef edge fill:#284c44,stroke:#7bc8a7,color:#f2f6ff @@ -105,4 +114,5 @@ flowchart TB class VPS,ROUTER,FW,NPM,APPS origin class GIT,PLAN,DEPLOY,SECRETS,HS,CERT,CFAPI ops class PROM,GRAF,ALERT monitor - class LIMITS note + class LIMIT_EDGE,LIMIT_PATH,LIMIT_ORIGIN,LIMIT_STREAM note + style BOUNDARIES fill:#291f2a,stroke:#dd9ba7,color:#fff5f6 diff --git a/load-balancing-my-homelab/img/infrastructure-overview.png b/load-balancing-my-homelab/img/infrastructure-overview.png index bad1958..250f311 100644 Binary files a/load-balancing-my-homelab/img/infrastructure-overview.png and b/load-balancing-my-homelab/img/infrastructure-overview.png differ diff --git a/load-balancing-my-homelab/img/infrastructure-overview.svg b/load-balancing-my-homelab/img/infrastructure-overview.svg index c94c614..c22307c 100644 --- a/load-balancing-my-homelab/img/infrastructure-overview.svg +++ b/load-balancing-my-homelab/img/infrastructure-overview.svg @@ -1 +1 @@ -Monitoring outside themeshDeployment and controlShared private originsDedicated entry layerPublic accessedge-bedge-aDNS lookupprimaryprimaryper-service backup overencrypted overlayper-service backup overencrypted overlayHTTPS to a healthyendpointHTTPS to a healthyendpointdirect HTTPS after DNSselectiondirect HTTPS after DNSselectionGET /_edge/entry-health:edge-readyGET /_edge/entry-health:edge-readydelegated policymanagementconfigure local renewalDNS-01deploy and verifydeploy and verifycontrol and access policyHTTPS /_edge/metricsHTTPS /_edge/metrics

Browser and API clients

Direct media clients

Cloudflare DNS-only LB
returns healthy edge addresses

Cloudflare proxied LB
shared pool, equal weights
session affinity

Cloudflare HTTPS monitor
ingress liveness only
source allowlist + monitor token

HAProxy HTTPS ingress
validate Host and source
rebuild trusted client headers
normalize paths and apply access rules

Service backend
prefer local path
peer as backup + routing cookie

Private service gateway
overlay listener, trusted edges only
local Anubis AND origin must be healthy

Per-service Anubis on loopback
browser challenge or client-compatible policy
application authentication still required

HAProxy HTTPS ingress
validate Host and source
rebuild trusted client headers
normalize paths and apply access rules

Service backend
prefer local path
peer as backup + routing cookie

Private service gateway
overlay listener, trusted edges only
local Anubis AND origin must be healthy

Per-service Anubis on loopback
browser challenge or client-compatible policy
application authentication still required

Encrypted Tailscale data plane
private routes and least-privilege access
Headscale is the control plane, not an HTTP transit hop

Private application hosts
applications bound to private listeners

Home subnet router
approved route to HTTPS gateway

Home firewall
allow HTTPS to gateway

Nginx Proxy Manager
private HTTPS with valid origin certificate

Home applications
native accounts, sessions and tokens

Git repository
service catalogue + generic templates
no credentials in source

Semaphore plan task
local inventory, no deployment secrets
validate catalogue + derived rules

Semaphore deployment task
SSH + sudo, serial rollout
validate candidate with selected HAProxy image
check local AND peer paths

Separate secret values
DNS API / Anubis signing
monitor / metrics

Headscale control host
validate and back up policy candidate
preserve unrelated rules, then reload

Certbot on each edge
DNS-01 certificate issuance and renewal
validate certificate/key and reload HAProxy

Cloudflare DNS API
certificate challenge + dedicated edge records
application LB publication managed separately

Prometheus
one DNS-only target per edge
verified TLS + authorized source + metrics token

Grafana
traffic, sessions, service paths
origin probes and backend errors

Optional alert rules and delivery
must be configured separately

Failure boundaries
Cloudflare bypasses an unavailable public edge
HAProxy bypasses a failed per-service path when its peer is healthy
a failed shared origin is still unavailable
open video streams and WebSockets must reconnect

\ No newline at end of file +Monitoring outside themeshDeployment and controlShared private originsDedicated entry layerPublic accessedge-bedge-aDNS lookupprimaryprimaryper-service backup overencrypted overlayper-service backup overencrypted overlayHTTPS to a healthyendpointHTTPS to a healthyendpointdirect HTTPS after DNSselectiondirect HTTPS after DNSselectionGET /_edge/entry-health:edge-readyGET /_edge/entry-health:edge-readydelegated policymanagementconfigure local renewalDNS-01deploy and verifydeploy and verifycontrol and access policyHTTPS /_edge/metricsHTTPS /_edge/metricsFailure handling and limits -explanatory notes

Public edge unavailable
Cloudflare selects a healthy edge for new connections

One service path unavailable
HAProxy uses the peer when its path is healthy

Shared origin unavailable
Both edges lose that application
edge redundancy does not replicate origins

Open video streams and WebSockets
Existing connections do not migrate
clients must reconnect

Browser and API clients

Direct media clients

Cloudflare DNS-only LB
returns healthy edge addresses

Cloudflare proxied LB
shared pool, equal weights
session affinity

Cloudflare HTTPS monitor
ingress liveness only
source allowlist + monitor token

HAProxy HTTPS ingress
validate Host and source
rebuild trusted client headers
normalize paths and apply access rules

Service backend
prefer local path
peer as backup + routing cookie

Private service gateway
overlay listener, trusted edges only
local Anubis AND origin must be healthy

Per-service Anubis on loopback
browser challenge or client-compatible policy
application authentication still required

HAProxy HTTPS ingress
validate Host and source
rebuild trusted client headers
normalize paths and apply access rules

Service backend
prefer local path
peer as backup + routing cookie

Private service gateway
overlay listener, trusted edges only
local Anubis AND origin must be healthy

Per-service Anubis on loopback
browser challenge or client-compatible policy
application authentication still required

Encrypted Tailscale data plane
private routes and least-privilege access
Headscale is the control plane, not an HTTP transit hop

Private application hosts
applications bound to private listeners

Home subnet router
approved route to HTTPS gateway

Home firewall
allow HTTPS to gateway

Nginx Proxy Manager
private HTTPS with valid origin certificate

Home applications
native accounts, sessions and tokens

Git repository
service catalogue + generic templates
no credentials in source

Semaphore plan task
local inventory, no deployment secrets
validate catalogue + derived rules

Semaphore deployment task
SSH + sudo, serial rollout
validate candidate with selected HAProxy image
check local AND peer paths

Separate secret values
DNS API / Anubis signing
monitor / metrics

Headscale control host
validate and back up policy candidate
preserve unrelated rules, then reload

Certbot on each edge
DNS-01 certificate issuance and renewal
validate certificate/key and reload HAProxy

Cloudflare DNS API
certificate challenge + dedicated edge records
application LB publication managed separately

Prometheus
one DNS-only target per edge
verified TLS + authorized source + metrics token

Grafana
traffic, sessions, service paths
origin probes and backend errors

Optional alert rules and delivery
must be configured separately

\ No newline at end of file