Networking
Why a tunnel
Section titled “Why a tunnel”Your controllers run on ctrlplane, but what they manage often lives in your network: a Proxmox host, a database, an internal API, network gear. From ctrlplane those addresses are unreachable, and they should stay unreachable from the internet.
A tunnel solves both: your side connects out to ctrlplane, and your controllers’ traffic travels back through that connection. Nothing in your network is opened inbound, no port forwarding, no public IP, and it works behind NAT and CGNAT.
Without a tunnel, controllers reach the public internet only.
controller ──HTTPS_PROXY──▶ tunnel (SOCKS5, on ctrlplane) ▲ ║ connector or Tailscale, ║ dialing out from your side your networkTwo ways to connect
Section titled “Two ways to connect”| Connector | Tailscale or Headscale | |
|---|---|---|
| You run | One Docker container on any machine that can reach your network | Nothing new, if you already use a tailnet |
| It reaches | Everything that machine can reach | What your subnet routers advertise |
| Auth | A command with a key, shown in the site | A reusable, ephemeral auth key you create |
| Good for | Quick setup, home labs, one network | Several sites, existing Tailscale setups, ACLs |
Turn one on under Network in the site.
Connector
Section titled “Connector”The site shows a command like this; run it on a machine in your network:
docker run -d --name ctrlplane-connector --restart=always jpillora/chisel:… client \ --auth <key> --fingerprint <fingerprint> https://<id>.tunnel.ctrlplane.run R:socksIt dials out to https://<id>.tunnel.ctrlplane.run over HTTPS and verifies ctrlplane’s side by
its fingerprint. The command contains your tunnel’s key: treat it like a password. Whatever that
machine can reach, your controllers can reach.
Tailscale or Headscale
Section titled “Tailscale or Headscale”- In your tailnet, create a reusable, ephemeral auth key.
- In Network, choose Tailscale or Headscale and paste the key (for Headscale, also its URL).
- The tunnel joins your tailnet as
ctrlplane-<control plane>. Whatever your subnet routers advertise is reachable through it; limit what it may reach with ACLs, like any other node.
The key is stored for this control plane and never shown again.
How controllers use it
Section titled “How controllers use it”With a tunnel on, every controller gets:
HTTPS_PROXY=socks5://tunnel.tenant-<control plane>.svc:1080HTTP_PROXY=socks5://tunnel.tenant-<control plane>.svc:1080NO_PROXY=tenant-<control plane>.svc,tenant-<control plane>.svc.cluster.local,<your forwards>Go programs (and most HTTP clients) honour these, and resolve names at the far end, so your
network’s own DNS names work, for example https://proxmox.home.lan:8006. Your control plane
itself stays direct.
Forwards, for clients that ignore proxies
Section titled “Forwards, for clients that ignore proxies”Some clients ignore HTTPS_PROXY (database drivers, SSH, some SDKs). For those, add a forward
as name=host:port, for example:
proxmox=192.168.0.200:8006postgres=db.home.lan:5432Your controllers then connect to proxmox:8006 or postgres:5432, and the tunnel carries the
connection to the real host, without any proxy settings.
Changing or turning it off
Section titled “Changing or turning it off”Change settings switches between connector and Tailscale or edits forwards; controllers restart to pick up the change. Turn off removes the tunnel, and controllers go back to public internet only. Your account’s limits decide whether you may connect a network at all.