Caddy and Tailscale With Docker Compose
Caddy 2 is a powerful web server that can be used to serve static files, reverse proxy to other services, and more.
Tailscale is a VPN service that makes it easy to connect to your home network from anywhere.
In this post, I’ll show you how to set up Caddy and Tailscale, serve with an HTTPS certificate your ts.net domain with Docker compose.
problem
Caddy has the support to automatically get a certificate from tailscale ts.net. To achieve this, Caddy needs to communicate with the Tailscale socket.
Example of a simple docker-compose file:
services:
tailscale-caddy:
image: tailscale/tailscale:latest
hostname: caddy # hostname is important and used for you DNS
environment:
- TS_AUTHKEY=tskey-XXXXXXXXXXXXXXX
- TS_EXTRA_ARGS=--advertise-tags=tag:container
- TS_STATE_DIR=/var/lib/tailscale
- TS_USERSPACE=false
volumes:
- ${PWD}/tailscale/state:/var/lib/tailscale
- ${PWD}/tailscale/config/ts/:/serve/
- /dev/net/tun:/dev/net/tun
cap_add:
- net_admin
- sys_module
restart: unless-stopped
caddy:
image: caddy:2-alpine
restart: unless-stopped
cap_add:
- NET_ADMIN
volumes:
- $PWD/Caddyfile:/etc/caddy/Caddyfile
- $PWD/site:/srv
- caddy_data:/data
- caddy_config:/config
depends_on:
- tailscale-caddy
network_mode: service:tailscale-caddy
volumes:
caddy_data:
external: true
caddy_config:
If you try to access the server using your Tailscale domain ts.net, you will get an error like this:
caddy-1 | {"level":"warn","ts":1730215067.0461261,"logger":"http","msg":"could not get status; will try to get certificate anyway","error":"Get \"http://local-tailscaled.sock/localapi/v0/status\": dial unix /var/run/tailscale/tailscaled.sock: connect: no such file or directory"}
As you can see, Caddy can’t find the Tailscale socket.
Solution
The solution is to force Tailscale to share its socket. The socket is stored in /tmp/tailscaled.sock.
To accomplish this, we update the docker-compose file:
services:
tailscale-caddy:
image: tailscale/tailscale:latest
hostname: caddy # hostname is important and used for you DNS
environment:
...
volumes:
...
- ${PWD}/tailscale/tmp:/tmp # Share the tmp folder with the tailscale socket
cap_add:
- net_admin
- sys_module
restart: unless-stopped
caddy:
image: caddy:2-alpine
restart: unless-stopped
cap_add:
- NET_ADMIN
volumes:
...
- $PWD/tailscale/tmp/tailscaled.sock:/var/run/tailscale/tailscaled.sock # mount the socket at the right place
depends_on:
- tailscale-caddy
network_mode: service:tailscale-caddy
volumes:
caddy_data:
external: true
caddy_config:
Once this is done, you can access your server using your Tailscale domain ts.net and get a valid certificate with HTTPS.