Setup Guide
How ProxyOS fits into your homelab and how to expose services to the internet.
Internet ↓ Cloudflare edge ↓ Cloudflare Tunnel (cloudflared container) ↓ ProxyOS ← you are here ↓ your services (vaultwarden, gitea, sonarqube, etc.)
Every request from the internet hits ProxyOS. ProxyOS inspects the Host header and forwards to the right internal service. Never configure a Cloudflare Tunnel to point directly at a service — it always points at ProxyOS.
Mount the Docker socket in ProxyOS's compose so it can auto-discover and join networks:
services:
proxyos:
volumes:
- /var/run/docker.sock:/var/run/docker.sockOnce mounted, check the Networks page — all relevant networks should show "Joined". Then the Containers page shows everything ProxyOS can reach.
ProxyOS creates a homelab-edge network on startup. Cloudflared must join it so it can reach ProxyOS by container name.
services:
cloudflared:
networks:
- homelab-edge
networks:
homelab-edge:
external: trueOpen the Containers page, find the service, and click "Create Route" on the relevant port. Fill in:
- Domain: the public hostname (e.g.
vault.yourdomain.com) - Upstream: pre-filled from the Containers page (e.g.
http://vaultwarden:80) - TLS:
autoor leave default if Cloudflare terminates TLS at the edge - WebSocket: enable if the service uses WebSockets (vaultwarden, sonarqube, etc.)
Zero Trust → Networks → Tunnels → (your tunnel) → Public Hostname → Add:
proxyos:80 for every hostname. Never point it directly at a service — cloudflared isn't on that network, and you'd bypass all of ProxyOS's routing, SSO, and analytics.Verify each hop works:
# 1. DNS resolves to Cloudflare dig @1.1.1.1 vault.yourdomain.com +short # 2. Tunnel routes to ProxyOS and ProxyOS routes to the service curl -IL https://vault.yourdomain.com # Expected: HTTP/2 200 (or login redirect), not a 502/503 from Cloudflare
If you get a 502, check docker logs cloudflared — it'll say exactly what it couldn't reach.
Wrong: Service URL http://vaultwarden:80. Right: Service URL http://proxyos:80. Cloudflared probably can't resolve the container, and even if it could, you'd bypass all ProxyOS features.
Anything in Path restricts which URLs the tunnel routes. For a full-domain passthrough, leave Path empty.
IPs change when containers restart. Use container names — the Containers page shows you the correct name. They resolve via Docker DNS as long as ProxyOS is on the same network.
Compose projects like authentik or zammad create containers named authentik-server-1 or zammad-zammad-nginx-1. Use the exact name shown on the Containers page.
| Cloudflare Tunnel Service URL | http://proxyos:80 (every route) |
| Cloudflare Tunnel Path | (empty — don't enter anything) |
| ProxyOS Upstream | http://<container-name>:<port> |
| Cloudflared network | homelab-edge (same as ProxyOS) |
| Docker socket mount | /var/run/docker.sock:/var/run/docker.sock |