1. The problem I’m having:
I’m trying to get Caddy to use TLS certificates from Tailscale to enable HTTPS for my Docker containers. Originally, I wanted to reverse proxy services into their own subdomains, but upon realizing this wasn’t possible with Tailscale MagicDNS, I switched to subfolders and ran into “the subfolder problem.” However, Jellyfin worked and I successfully created a WebDAV server backend, so I decided to keep the working parts of the configuration. Since none of the other containers worked (although HTTPS was enabled, they delivered blank pages), I decided to stick with port numbers for containers that actually need HTTPS (such as Actual, which breaks without it.) For some reason, I can’t get it to work despite attempting multiple different configurations. From what I understand, this is supposed to be automatic, but I’m not sure how to get it working. I have Tailscale installed globally on the machine and I’m using a pre-built Docker image of Caddy bundled with mholt’s WebDAV plugin.
I’m very new to self-hosting and server management, so any guidance would be much appreciated.
2. Error messages and/or full log output:
$ wget https://orangepi.pancake-enigmatic.ts.net:5006
--2025-01-08 03:55:10-- https://orangepi.pancake-enigmatic.ts.net:5006/
Resolving orangepi.pancake-enigmatic.ts.net (orangepi.pancake-enigmatic.ts.net)... 100.109.35.122
Connecting to orangepi.pancake-enigmatic.ts.net (orangepi.pancake-enigmatic.ts.net)|100.109.35.122|:5006... connected.
GnuTLS: An unexpected TLS packet was received.
Unable to establish SSL connection.
$ docker logs caddy
{"level":"info","ts":1736310310.1800172,"msg":"using config from file","file":"/etc/caddy/Caddyfile"}
{"level":"info","ts":1736310310.1872396,"msg":"adapted config to JSON","adapter":"caddyfile"}
{"level":"info","ts":1736310310.1952615,"logger":"admin","msg":"admin endpoint started","address":"localhost:2019","enforce_origin":false,"origins":["//[::1]:2019","//127.0.0.1:2019","//localhost:2019"]}
{"level":"info","ts":1736310310.1959658,"logger":"http.auto_https","msg":"server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS","server_name":"srv0","https_port":443}
{"level":"info","ts":1736310310.1959867,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0x4000218e80"}
{"level":"info","ts":1736310310.1960385,"logger":"http.auto_https","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
{"level":"info","ts":1736310310.2001424,"logger":"http","msg":"enabling HTTP/3 listener","addr":":443"}
{"level":"info","ts":1736310310.2008374,"msg":"failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 7168 kiB, got: 416 kiB). See https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes for details."}
{"level":"info","ts":1736310310.201608,"logger":"http.log","msg":"server running","name":"srv0","protocols":["h1","h2","h3"]}
{"level":"warn","ts":1736310310.201685,"logger":"http","msg":"HTTP/3 skipped because it requires TLS","network":"tcp","addr":":5006"}
{"level":"warn","ts":1736310310.2017977,"logger":"http","msg":"HTTP/2 skipped because it requires TLS","network":"tcp","addr":":5006"}
{"level":"info","ts":1736310310.2018197,"logger":"http.log","msg":"server running","name":"srv1","protocols":["h1","h2","h3"]}
{"level":"warn","ts":1736310310.2018487,"logger":"http","msg":"HTTP/3 skipped because it requires TLS","network":"tcp","addr":":80"}
{"level":"warn","ts":1736310310.20194,"logger":"http","msg":"HTTP/2 skipped because it requires TLS","network":"tcp","addr":":80"}
{"level":"info","ts":1736310310.2019649,"logger":"http.log","msg":"server running","name":"remaining_auto_https_redirects","protocols":["h1","h2","h3"]}
{"level":"info","ts":1736310310.2026048,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"}
{"level":"info","ts":1736310310.2026432,"msg":"serving initial configuration"}
{"level":"info","ts":1736310310.213812,"logger":"tls","msg":"storage cleaning happened too recently; skipping for now","storage":"FileStorage:/data/caddy","instance":"3dd2ea30-3c7f-4e39-857d-0e118c5c7dda","try_again":1736396710.213804,"try_again_in":86399.999996918}
{"level":"info","ts":1736310310.2142305,"logger":"tls","msg":"finished cleaning storage units"}
3. Caddy version:
v2.9.0
4. How I installed and ran Caddy:
Docker compose. I also use Portainer for management.
a. System environment:
Caddy is installed as a Docker container on my Orange Pi Zero 3 running DietPi. It has its own Docker network that all containers share.
b. Command:
$ docker compose up -d
c. Compose file:
services:
caddy:
image: juvenn/caddy-dav:2.9.0
container_name: caddy
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- /mnt/external/siyuan-data:/mnt/external/siyuan-data # Siyuan notes
- /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock:ro # Tailscale
- caddy_data:/data
- caddy_config:/config
restart: unless-stopped
networks:
- caddy_network
networks:
caddy_network:
driver: bridge
volumes:
caddy_data:
caddy_config:
d. My complete Caddy config:
{
order webdav before file_server
}
orangepi.pancake-enigmatic.ts.net {
handle_path /jellyfin/* {
reverse_proxy jellyfin:8096
}
handle_path /webdav/* {
root * /mnt/external/siyuan-data
basicauth {
admin HASHED_PASSWORD
}
file_server browse
webdav
}
}
:5006 {
reverse_proxy actual:5006
}