Skip to content

DMZ Tier

Architecture

The DMZ tier (CX22) is the only VM with public-facing ports (80/tcp, 443/tcp). It serves as the ingress layer for all web-accessible services.

flowchart LR
    Internet((Internet)) -->|"443/tcp"| Caddy

    subgraph DMZ["CX22 DMZ Node"]
        Caddy["Caddy<br/>Reverse Proxy<br/>Auto-TLS"]
        Auth["Authelia<br/>TOTP Auth"]
        Ttyd["ttyd<br/>Web Terminal"]

        Caddy -->|"forward_auth"| Auth
        Caddy -->|"proxy"| Ttyd
    end

    Auth -.->|"authenticated"| Caddy

    subgraph Hub["CX32 Hub (via private net)"]
        Rancher["Rancher UI"]
        Grafana["Grafana"]
    end

    Caddy -->|"10.0.1.1"| Rancher
    Caddy -->|"10.0.1.1"| Grafana

    style DMZ fill:#7b241c,stroke:#c0392b,color:#fff
    style Hub fill:#1a5276,stroke:#2980b9,color:#fff

Caddy Reverse Proxy

Caddy handles all HTTPS ingress with automatic Let's Encrypt TLS certificates.

Caddyfile

{
    email dev@vdhome.be
    acme_dns hetzner {env.HETZNER_DNS_TOKEN}
}

ttyd.vdhome.be {
    forward_auth authelia:9091 {
        uri /api/verify?rd=https://auth.vdhome.be
        copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
    }
    reverse_proxy ttyd:7681
}

auth.vdhome.be {
    reverse_proxy authelia:9091
}

rancher.vdhome.be {
    forward_auth authelia:9091 {
        uri /api/verify?rd=https://auth.vdhome.be
        copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
    }
    reverse_proxy 10.0.1.1:443 {
        transport http {
            tls_insecure_skip_verify
        }
    }
}

grafana.vdhome.be {
    forward_auth authelia:9091 {
        uri /api/verify?rd=https://auth.vdhome.be
        copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
    }
    reverse_proxy 10.0.1.1:3000
}

TLS Configuration

Parameter Value
CA Let's Encrypt
Challenge type DNS-01 (via Hetzner DNS API)
Auto-renewal Yes (Caddy built-in)
Min TLS version 1.2
HSTS Enabled (Caddy default)
OCSP stapling Enabled (Caddy default)

DNS-01 challenge

DNS-01 is used instead of HTTP-01 because it works for all subdomains without opening additional ports and allows wildcard certificates if needed.

Authelia TOTP Configuration

Authelia provides single-factor (TOTP) authentication for all web services.

Parameter Value
Auth method TOTP (6-digit, 30s period)
Algorithm SHA1 (standard TOTP)
User storage Local YAML file (SOPS-encrypted in repo)
Session domain .vdhome.be
Session lifetime 8 hours
Inactivity timeout 1 hour
Remember me 30 days

Protection Levels

Domain Policy
auth.vdhome.be Bypass (Authelia portal itself)
ttyd.vdhome.be one_factor (TOTP required)
rancher.vdhome.be one_factor (TOTP required)
grafana.vdhome.be one_factor (TOTP required)

Why not two-factor?

Authelia supports two-factor (password + TOTP), but for a single-user lab, TOTP alone provides sufficient security. The TOTP seed is stored in an authenticator app and backed up in Bitwarden.

ttyd Web Terminal

ttyd provides a browser-based terminal, primarily for access from Defence workstations.

Parameter Value
Port 7681 (internal)
Shell /bin/bash
Forced command tmux attach -t main \|\| tmux new -s main
Write mode Enabled (authenticated users only)
Credential Authelia handles auth (no ttyd-level auth)

Forced Command

The ttyd session starts a tmux session, providing:

  • Session persistence (browser disconnect does not kill the shell)
  • Screen sharing (multiple browser tabs see the same session)
  • Scrollback buffer

Security constraint

ttyd runs as the deploy user with sudo access. This is acceptable for a single-user lab but would require RBAC in a multi-user setup.

Web App Security Context

All web-facing pods in the ingress namespace run with restricted security contexts:

securityContext:
  runAsNonRoot: true
  readOnlyRootFilesystem: true
  allowPrivilegeEscalation: false
  capabilities:
    drop:
      - ALL
    add:
      - NET_BIND_SERVICE  # Caddy only

DNS Records

Record Type Target Proxy
ttyd.vdhome.be A DMZ public IP No
auth.vdhome.be A DMZ public IP No
rancher.vdhome.be A DMZ public IP No
grafana.vdhome.be A DMZ public IP No
vdhome.be A DMZ public IP No

All DNS records are managed via OpenTofu using the Hetzner DNS provider.