My VPS Stack & Zero Trust Architecture
/ 10 min read
Table des matières
Self-hosting modern infrastructure often turns into an uncomfortable compromise between autonomy, convenience, and security. In conventional setups, scaling up services means punching dozens of ports through public firewalls, running exposed reverse proxies subject to vulnerability scans, and hand-crafting security rules across heterogeneous services.
My production infrastructure takes a radically different route: a unified stack running over 20 Docker containers (development toolchains, project management, AI agents, game servers, databases) governed by a strict Zero Trust architecture.
The core principle? Zero application sockets listen on any public interface. Inbound requests travel over outbound QUIC tunnels, edge access requires federated multi-IdP authentication, and direct administrative access to internal resources (databases, MCP servers) runs over a private mesh network via the MASQUE protocol.
Here is the comprehensive technical breakdown of this VPS stack and its multi-layer security posture.
Infrastructure Architecture Overview
The entire stack is deployed on a dedicated Linux machine (Debian 12) hosted at OVH.
flowchart TB
subgraph Clients["Clients & Administration Workstations"]
Browser["Web Browser / Client App"]
AdminDev["Admin Workstation (WARP Client)"]
DiscordClient["Discord (Bots & Autonomous Agents)"]
end
subgraph Edge["Cloudflare Edge & Zero Trust"]
Access["Cloudflare Access (IAP / IdP)"]
Gateway["Cloudflare Gateway (L4/L7/DNS Inspection)"]
VNet["Virtual Network (Teamnet Mesh)"]
CFMail["smtp.mx.cloudflare.net:465"]
end
subgraph Host["Dedicated Server (Debian 12)"]
subgraph Daemons["Host System Daemons"]
CFTunnel["cloudflared (QUIC Ingress Tunnel)"]
WARPConn["WARP Connector (MASQUE Mesh Tunnel)"]
end
subgraph DockerEngine["Docker Engine (vps monorepo)"]
subgraph NetApp["Bridge: applications"]
AppWeb["Public Web Frontends<br>Dockhand, Pocket ID, Gitea<br>Kaneo, AI Agents, Beszel Hub"]
end
subgraph NetRes["Bridge: resources"]
DBs["Internal Databases<br>PostgreSQL, Redis, MariaDB, MongoDB"]
InternalServ["Internal Daemons<br>Postfix SMTP Relay, MCP Servers"]
end
subgraph NetWings["Bridge: wings"]
WingsDaemon["Pelican Wings Daemon"]
GameContainers["Isolated Game Servers"]
end
end
end
Browser -->|HTTPS and HTTP3| Access
Access -->|Outbound QUIC Tunnel UDP 7844| CFTunnel
CFTunnel -->|Loopback 127.0.0.1| NetApp
AdminDev -->|MASQUE Tunnel| Gateway
Gateway --> VNet
VNet -->|Private Route| WARPConn
WARPConn -->|Netfilter conntrack| NetRes
WARPConn -->|Netfilter conntrack| NetApp
InternalServ -->|TLS Wrappermode port 465| CFMail
1. Stack Orchestration & Management: Dockhand
Managing two dozen containers alongside independent volumes, bind mounts, and encrypted environment files quickly turns unwieldy through raw shell commands.
To centralize management without ever exposing the Docker daemon socket (/var/run/docker.sock) to the internet, the stack is orchestrated using Dockhand, a fast and modern Docker management platform.
flowchart LR
subgraph HostEnv["Server Host"]
Socket["/var/run/docker.sock"]
Compose["docker-compose.yml (vps monorepo)"]
EnvFiles[".env (Encrypted variables)"]
end
subgraph DockhandUI["Dockhand Engine"]
UI["Web Management UI"]
Metrics["Telemetry & Event Log"]
AutoPrune["Image Pruning & Updates"]
end
UI --> Socket
UI --> Compose
UI --> EnvFiles
Core Orchestration Highlights:
- Unified Declarative Stack (
vps): Every service, virtual network, and storage volume is declared within a structured, version-controlled Docker Compose file. - Systematic Healthchecks: Every critical dependency (PostgreSQL, MariaDB, MongoDB, Redis, Gitea, Kaneo, Pelican, etc.) implements explicit probes (
CMD-SHELL,pg_isready,mongosh ping), ensuring deterministic boot sequences usingdepends_on: service_healthy. - Automated Lifecycle & Hygiene: Automated image digest polling (
latest,lts) paired with periodic automated orphan image pruning. - Isolated Control Plane: Dockhand itself runs in an isolated container backed by a dedicated volume.
2. Application Catalog: Service Overview
The stack serves everyday needs across multiple domains: development toolchains, identity management, productivity, AI workflows, gaming, and analytics.
A. Identity, Authentication & Security
- Pocket ID: Modern, lightweight OIDC identity provider written in Go and Svelte. Natively supports Passkeys (FIDO2 / WebAuthn) for passwordless, hardware-backed biometric sign-ins.
- phpMyAdmin: Web-based administration interface for internal MariaDB databases.
B. Development, GitOps & CI/CD
- Gitea: Self-hosted Git forge backed by PostgreSQL for state storage and Postfix for transactional mail notifications.
- Gitea Mirror: Automated service continuously mirroring remote GitHub repositories onto the local Gitea instance to maintain sovereign, offline backups.
- act-runner: Native CI/CD runner executing GitHub Actions workflows directly on the server without external dependencies.
C. Productivity & Project Management
- Kaneo: Modern project and issue tracker (a fluid alternative to Linear or Jira), integrated with Pocket ID via OAuth/OIDC using PKCE flows.
- Pingvin Share: Privacy-first file sharing platform offering client-side encryption and time-limited download links.
- BentoPDF: Full-featured web utility suite for processing and editing PDF documents.
D. AI Ecosystem, Agents & MCP
- Executor: Secure sandboxed code runtime and Model Context Protocol (MCP) server, offering controlled execution primitives for AI agents.
- Hermes Agent: Autonomous AI agent (powered by NousResearch Hermes) acting as a Discord administration bot, connected through the CLI Proxy API gateway.
- Pi Bridge: Communication and remote execution gateway for the Pi Coding Agent, synchronized in real time with Discord.
- CLI Proxy API: Gateway proxy standardizing LLM requests with Service Token authorization.
- GTFS MCP: Private MCP server offering transit query and spatial data analysis tools.
E. Gaming & Game Server Virtualization
- Pelican Panel: Next-generation game server management interface (the modern successor to Pterodactyl), connected to PostgreSQL and Postfix.
- Pelican Wings: Host daemon governing the lifecycle of game server containers (Minecraft Bedrock, SteamCMD dedicated servers) on an isolated bridge network.
F. Media & Utilities
- Cobalt: Private, privacy-preserving media download and extraction instance.
- VERT: High-performance CPU-accelerated video conversion engine.
- Your Spotify: Personal analytics dashboard tracking Spotify listening history and habits over a MongoDB datastore.
G. Observability & Monitoring
- Beszel: Central monitoring hub providing real-time telemetry on CPU, RAM, disk I/O, and container health.
- Beszel Agent: Lightweight monitoring agent deployed with a read-only Docker socket mount (
/var/run/docker.sock:ro) feeding system telemetry continuously.
3. Layer 7 Ingress: Cloudflare Tunnel & QUIC
To make these applications reachable from the web without opening a single incoming HTTP or HTTPS port on the server’s firewall, Ingress relies on Cloudflare Tunnel (cloudflared).
sequenceDiagram
participant Edge as Cloudflare Edge (PoPs)
participant Cloudflared as cloudflared Daemon (Host)
participant LocalApp as Docker Container (127.0.0.1:local_port)
Note over Cloudflared,Edge: Boot: 4 outbound QUIC tunnels to the Edge
Cloudflared->>Edge: Outbound persistent connection (UDP/7844)
Edge-->>Cloudflared: Tunnels established & active
Note over Edge: Inbound user request for a service
Edge->>Cloudflared: Request multiplexed inside QUIC stream
Cloudflared->>LocalApp: Local HTTP reverse proxy to 127.0.0.1
LocalApp-->>Cloudflared: HTTP 200 OK Response
Cloudflared-->>Edge: Packet returned via QUIC stream
Secured Ingress Mechanics
Every web application container binds strictly to loopback 127.0.0.1 on an unexposed port:
# cloudflared Ingress rules exampleingress: - hostname: auth.example.com service: http://127.0.0.1:8001 - hostname: git.example.com service: http://127.0.0.1:8007 - hostname: tasks.example.com service: http://127.0.0.1:8012 - service: http_status:404With this architecture:
- Zero Public Listening Ports: Running
netstatorssreveals no listeners on0.0.0.0:80or0.0.0.0:443. - Edge-Level DDoS Protection: All inbound traffic is scrubbed across Cloudflare’s Anycast network before tunneling over outbound UDP.
4. Authentication & IAP: Multi-IdP Identity Broker
Application endpoints are guarded behind Cloudflare Access (Identity Aware Proxy).
sequenceDiagram
participant Client as Web Browser
participant Access as Cloudflare Access (IAP)
participant OIDCProvider as OIDC Provider
participant Service as Web Application
Client->>Access: Navigates to application URL
Access->>Client: Redirect to Identity Broker
Client->>OIDCProvider: Authenticates (Passkeys / WebAuthn)
OIDCProvider-->>Access: Signed OIDC assertion
Note over Access: Evaluates policies + signs JWT RS256
Access->>Client: Encrypted session cookie
Access->>Service: Injects Cf-Access-Jwt-Assertion header
Service-->>Client: Renders application
Multi-Provider Federation (IdPs):
- Pocket ID: Primary self-hosted IdP enforcing FIDO2 / WebAuthn Passkeys.
- Discord OIDC: Identity broker for community bots and companion agent apps.
- GitHub & Google OAuth: Fallback identities for emergencies and recovery.
Granular Policies & Service Tokens:
- Admin Policy (
allow): Unrestricted access for the verified administrator. - WARP Device Posture (
non_identity): Transparent single-click pass-through for trusted machines enrolled with a verified client certificate. - Machine-to-Machine Service Tokens: Automated script access via
CF-Access-Client-IdandCF-Access-Client-Secretheaders. - Targeted Bypass Rules: Selective public access for external endpoints (e.g. MCP OAuth metadata discovery).
- Zero-Port SSH Access: SSH access is encapsulated over HTTPS using
cloudflared access ssh --hostname ssh.example.com, completely removing port 22 from the public internet.
5. Layer 4 Mesh Network: WARP Connector & the MASQUE Protocol
To interact directly with backend datastores (PostgreSQL, MariaDB, Redis, MongoDB) or private MCP servers using local desktop tools (DBeaver, TablePlus, VS Code), the host runs a WARP Connector joined to a Cloudflare Virtual Network (Teamnet).
flowchart LR
subgraph DevMachine["Developer Workstation (WARP Client)"]
DBeaver["DBeaver / TablePlus (SQL)"]
MongoCompass["MongoDB Compass"]
MCPClient["MCP Client / VS Code"]
end
subgraph CFMesh["Cloudflare Virtual Network"]
VNet["Private Virtual Network"]
CGNAT["CGNAT Range: 100.64.0.0/10"]
end
subgraph VPS["Host Server (WARP Connector)"]
WARPInt["CloudflareWARP Interface (MASQUE)"]
Netfilter["Netfilter / conntrack"]
subgraph Subnets["Announced Docker Subnets"]
SubRes["resources network (Databases)"]
SubApp["applications network (Tools & MCP)"]
SubWings["wings network (Game servers)"]
end
end
DBeaver -->|TCP SQL| WARPInt
MongoCompass -->|TCP NoSQL| WARPInt
MCPClient -->|HTTP MCP| WARPInt
WARPInt --> Netfilter
Netfilter --> SubRes
Netfilter --> SubApp
The MASQUE Protocol (RFC 9298 / RFC 9484)
The mesh tunnel operates via MASQUE (Multiplexed Application Substrate over QUIC Encryption), tunneling raw IP packets (TCP and UDP) inside HTTP/3 over QUIC streams.
Compared to legacy VPN protocols (like standard WireGuard):
- Traffic seamlessly negotiates corporate firewalls and restrictive proxies, masquerading as regular outbound HTTPS on port 443.
- QUIC multiplexing prevents head-of-line blocking across concurrent database queries and admin sessions.
Client-Side Split Tunneling (Include Mode):
Only targeted destination IP blocks enter the tunnel:
- Private Docker subnets on the host
- Cloudflare WARP CGNAT range:
100.64.0.0/10(RFC 6598) - Specified internal domain zones
6. Docker Micro-Segmentation: 3 Isolated Bridge Networks
To strictly limit the blast radius if any single application container is compromised, the environment is segmented into three independent bridge networks:
flowchart TD
subgraph NetApp["Bridge: applications"]
A1["Dockhand"]
A2["Pocket ID"]
A3["Gitea"]
A4["Kaneo"]
A5["Executor MCP"]
end
subgraph NetRes["Bridge: resources"]
R1[("PostgreSQL")]
R2[("Redis")]
R3[("MariaDB")]
R4[("MongoDB")]
R5["Postfix SMTP Relay"]
end
subgraph NetWings["Bridge: wings"]
W1["Pelican Wings Daemon"]
W2["Dedicated Game Servers"]
end
A3 -->|SQL Queries| R1
A4 -->|SQL Queries| R1
A2 -->|SQL Queries| R1
A3 -->|Outbound SMTP| R5
A2 -->|Outbound SMTP| R5
W1 -->|SQL Queries| R3
applications: Hosts public web services. Containers on this bridge cannot communicate with theresourcesnetwork unless explicitly multi-homed.resources: Houses internal databases and backend tools. No ports are mapped to the host; connections originate exclusively from authorized application containers or through the WARP mesh tunnel.wings: Dedicated entirely to gaming containers created by Pelican Wings, completely walled off from production databases and developer tooling.
7. Secure SMTP Egress via Cloudflare Email Routing
Transactional emails (account verification, Git notifications, system health alerts) bypass unencrypted or risky direct SMTP relays:
sequenceDiagram
participant App as App Container (Gitea / Pocket ID)
participant Postfix as Postfix Relay Container (Internal)
participant CFMail as Cloudflare Email (smtp.mx.cloudflare.net:465)
participant Recipient as Final Recipient
App->>Postfix: Internal plaintext SMTP (port 25)
Note over Postfix: TLS Wrappermode + SASL Auth (API Token)
Postfix->>CFMail: TLS Connection to port 465
CFMail-->>Recipient: Delivered with SPF / DKIM / DMARC signatures
The internal postfix container operates inside the resources bridge and securely forwards all outbound traffic to [smtp.mx.cloudflare.net]:465 using TLS wrappermode and a scoped Cloudflare API Token.
# Postfix service definition in docker-compose.ymlpostfix: container_name: postfix image: mwader/postfix-relay:latest networks: - resources environment: - POSTFIX_mynetworks=10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8, 100.64.0.0/10 - POSTFIX_relayhost=[smtp.mx.cloudflare.net]:465 - POSTFIX_smtp_tls_security_level=encrypt - POSTFIX_smtp_tls_wrappermode=yes - POSTFIX_smtp_sasl_auth_enable=yes - POSTFIX_smtp_sasl_password_maps=hash:/etc/postfix/sasl_passwd - POSTMAP_sasl_passwd=[smtp.mx.cloudflare.net]:465 api_token:${CF_SMTP_API_TOKEN}8. Linux Kernel Tuning: Netfilter, Conntrack & Routing
Bridging the WARP Connector virtual interface (CloudflareWARP) with internal Docker bridges requires the Linux kernel’s connection tracking subsystem (nf_conntrack) combined with IPv4 packet forwarding:
# Enable kernel-level packet forwardingsysctl -w net.ipv4.ip_forward=1
# Permit ingress forwarding from WARP to internal Docker bridgesiptables -I FORWARD 1 -i CloudflareWARP -d 172.18.0.0/16 -j ACCEPT
# Allow return traffic via stateful conntrack inspectioniptables -I FORWARD 2 -o CloudflareWARP -s 172.18.0.0/16 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPTWhen an administrator connects to an internal database via DBeaver across the WARP tunnel:
- The TCP SYN enters through
CloudflareWARP. - The
nf_conntrackengine registers the new flow in its state table. - The packet is routed directly to the appropriate Docker bridge.
- The service’s TCP SYN-ACK reply matches the
RELATED,ESTABLISHEDstate rule and is returned automatically without public port exposure.
9. Gateway Filtering: DNS, HTTP & L4 Network Security
Upstream of the server, every connection is continuously screened by Cloudflare Gateway policies:
| Layer | Policy Rule | Action | Result |
|---|---|---|---|
| DNS | Anti-Malware | Block |
Prevents resolution of known malicious domains |
| DNS | Anti-Phishing | Block |
Mitigates credential harvesting attempts |
| DNS | Trusted Allowlist | Allow |
Prioritizes DNSSEC-validated trusted endpoints |
| HTTP | Threat Inspection | Block |
Detects and intercepts malicious payload URLs |
| L4 / Network | Malware & Phishing Drop | Block |
Immediate packet drop on flagged FQDN destinations |
Conclusion
This infrastructure demonstrates that self-hosting a comprehensive, highly productive suite of services does not require sacrificing security:
- Uncompromised Productivity: Over 20 containers handling dev, AI, gaming, and project workflows, orchestrated cleanly through Dockhand.
- Zero Public Attack Surface: No web or SSH ports open to the public internet. Port scans encounter an impenetrable wall.
- Continuous Identity Verification: Every request is verified through Pocket ID (Passkeys) and Cloudflare Access with cryptographic JWT assertions.
- Transparent Remote Engineering: Administrative access to databases and backend tools relies on MASQUE mesh tunnels with zero friction and zero bastion servers.
A robust, modern setup built to last.