Calabi client — public reverse tunnels + a private WireGuard mesh, via Calabi Cloud.
2.7K
calabinet/calabiCalabi client — public reverse tunnels + a private WireGuard mesh, via Calabi Cloud.
calabi is the client for Calabi Cloud — a reverse-tunneling service that gives
a local service (on your laptop, a container, a Raspberry Pi, or a private LAN) a
public HTTPS/TCP/UDP address, over a single outbound connection with no inbound
ports to open.
This image is configured for Calabi Cloud: it authenticates with your API key and serves tunnels through the managed edge nodes.
The same client also joins your mesh: your devices, containers and LANs connected to each other over WireGuard — directly when they can, through a relay when they cannot — each at a private IP, with nothing exposed to the internet. Tunnels and the mesh run side by side in one client.
Without an account: run your own server — edge, coordinator and client are open source (Apache-2.0): https://github.com/calabinet/calabi
docker run --rm -it \
-e CALABI_API_KEY=tk_xxxxxxxx \
--network host \
calabinet/calabi:latest http 8080
--network host lets the client reach services on 127.0.0.1 (Linux). Swap
http 8080 for tcp 5432, udp 51820, and so on.
The image's default command is daemon, which stays online as an agent: give it
your API key and manage its tunnels from the console. Mount a volume so the agent
keeps its device identity across restarts (otherwise it re-registers every time).
docker run -d --restart unless-stopped \
-e CALABI_API_KEY=tk_xxxxxxxx \
--network host \
-v calabi-data:/home/calabi \
calabinet/calabi:latest
Enable Mesh for your organization in the console, and this agent joins it with the same API key; there is no extra command. The container needs a few grants from the host to create the mesh interface:
docker run -d --restart unless-stopped \
--user 0:0 \
--cap-add=NET_ADMIN \
--device=/dev/net/tun \
--sysctl net.ipv4.ip_forward=1 \
-e CALABI_API_KEY=tk_xxxxxxxx \
-v calabi-data:/home/calabi \
calabinet/calabi:latest
--cap-add=NET_ADMIN + --device=/dev/net/tun — to create and configure the
mesh interface.--user 0:0 — the mesh interface can only be configured as root
(why). The data stays in the same
/home/calabi/.config/calabi as the plain agent above.--sysctl net.ipv4.ip_forward=1 — only if this device shares subnet routes or
is an exit device. It has to be set when the container starts.-v calabi-data:/home/calabi — the same volume and path as the plain agent
above, so it stays the same device when you turn the mesh on.If your container panel has no fields for these options (they do not go in the
"command" field), use this Compose file — on the command line
(docker compose up -d) or in any panel that imports Compose:
services:
calabi:
image: calabinet/calabi:latest
restart: unless-stopped
user: "0:0" # --user 0:0
cap_add: [NET_ADMIN] # --cap-add=NET_ADMIN
devices: ["/dev/net/tun:/dev/net/tun"] # --device=/dev/net/tun
sysctls: ["net.ipv4.ip_forward=1"] # --sysctl net.ipv4.ip_forward=1
environment:
CALABI_API_KEY: "tk_xxxxxxxx"
volumes:
- calabi-data:/home/calabi
# optional — to reach the client's own local console, add to environment:
# CALABI_STATUS_ADDR: "0.0.0.0:7400"
# then publish it to loopback: ports: ["127.0.0.1:7400:7400"]
# it will ask for an unlock secret; `docker compose logs calabi` prints it
volumes:
calabi-data:
Other devices then reach this one at its private mesh IP. In the console's Mesh page you add and remove devices, edit access rules (ACLs), and set up subnet routes and exit devices.
Bridge networking works. With --network host, more connections go direct; set
net.ipv4.ip_forward on the host then, instead of with --sysctl.
| Variable | Purpose |
|---|---|
CALABI_API_KEY | Your platform API key (tk_…), from the console. Required. |
CALABI_STATUS_ADDR | Bind address of the local web console (default 127.0.0.1:7400). Read the note below before changing it. |
CALABI_STATUS_SECRET | Unlock secret the console asks of anyone reaching it from another machine. Unset = one is generated on first start and printed in the container log. See the note below. |
CALABI_DEBUG | 1 = verbose logging for troubleshooting. |
The daemon stores its device identity, credentials, and state under $HOME
(/home/calabi). Mount a volume there (as in the agent example above) so a
restarted container stays the same device instead of re-registering.
:7400 console from outside the containerSet CALABI_STATUS_ADDR=0.0.0.0:7400 and publish the port to loopback
(-p 127.0.0.1:7400:7400). Opening it from the host asks for an unlock secret
(why):
docker logs <container> 2>&1 | grep "unlock secret"
console-secret in /home/calabi/.config/calabi; mount
the volume, or it changes whenever the container is recreated.
CALABI_STATUS_SECRET sets your own.0.0.0.0 exposes it on public
interfaces too, and Docker's -p can bypass a host firewall.Day to day, manage the agent from the cloud console.
--user 0:0?The image runs as a non-root user, and Docker gives added capabilities no ambient
rights to a non-root process, so bringing the interface up fails with EPERM. The
image sets HOME=/home/calabi for every user, so root uses the same data
directory.
The console answers freely only to a caller on the same machine. A request
published with -p arrives from the Docker bridge, not from loopback, so the host
counts as another machine.
latest — most recent releasex.y.z — pinned versionContent type
Image
Digest
sha256:6626d4020…
Size
13.9 MB
Last updated
2 days ago
docker pull calabinet/calabi