DevBox supports opt-in HTTPS using Let's Encrypt wildcard certificates issued via the OVH DNS-01 ACME challenge. The TLS listener is bound to the Tailscale IP — there is no public 0.0.0.0:443 exposure. The certificate is publicly issued (anyone can fetch the cert chain), but the listener is reachable only through Tailscale.
This document covers the OVH-side setup. The integrated install flow is documented in docs/updating.md and the Quick start section of README.md.
When ENABLE_HTTPS=true:
setup.shreads~/.config/devbox/ovh.env(must exist, mode 0600) — refuses to proceed if absent.- Renders
services/traefik/traefik.https.yml.templateinto~/docker/traefik/traefik.yml, replacing the HTTP-only static config. - Creates
~/docker/traefik/letsencrypt/acme.json(mode 0600). - Renders
~/docker/traefik/.envfromservices/traefik/.env.templatewith the four OVH credentials. - Emits per-service
COMPOSE_FILE_<SVC>=docker-compose.yml:docker-compose.https.yml:docker-compose.lock.ymlinto~/.config/devbox/config.envso helpers chain the HTTPS overlay automatically. - The HTTPS overlay binds Traefik to
${TAILSCALE_IP}:443. No public bind.
- Open https://api.ovh.com/createToken/.
- Sign in.
- Fill in:
- Application name:
devbox-traefik-letsencrypt - Description:
Traefik DNS-01 challenge for Let's Encrypt - Validity:
Unlimited(or set per your security policy) - Rights:
GET /domain/zone/* POST /domain/zone/* DELETE /domain/zone/*
- Application name:
- Click Create keys.
- Save all three values — OVH only shows them once.
install -d -m 0700 ~/.config/devbox
cat > ~/.config/devbox/ovh.env <<EOF
OVH_ENDPOINT=ovh-eu
OVH_APPLICATION_KEY=your-application-key
OVH_APPLICATION_SECRET=your-application-secret
OVH_CONSUMER_KEY=your-consumer-key
EOF
chmod 600 ~/.config/devbox/ovh.envEndpoint values: ovh-eu (Europe), ovh-ca (Canada), ovh-us (United States).
export ENABLE_HTTPS=true
export DEVBOX_DOMAIN=yourdomain.com
export DEVBOX_EMAIL=you@yourdomain.com # for Let's Encrypt registration
# Optional preview without mutation:
./setup.sh --dry-run
# Apply:
sudo ./setup.shsetup.sh halts with a clear error if ENABLE_HTTPS=true and ~/.config/devbox/ovh.env is missing.
Add an A (or AAAA) record for the FQDNs Traefik will serve. The cert is wildcard-eligible via DNS-01, so a single record per published host is fine:
A ai.yourdomain.com → <Tailscale IP of devbox host>
A ollama.yourdomain.com → <Tailscale IP of devbox host>
Your own devices still resolve via /etc/hosts to the Tailscale IP for the .internal names; the public *.yourdomain.com records exist so Traefik's DNS-01 challenge can answer the wildcard request and so cosign-validating clients see the published name.
After start-all.sh:
docker logs traefik 2>&1 | grep -iE 'acme|letsencrypt|certificate'Expect:
Obtaining ACME certificate(s)
Certificate obtained successfully
First issuance typically takes 30–90 seconds (DNS propagation). Subsequent renewals (60-day cycle) are silent.
Certificate not issued after 5 minutes
dig TXT _acme-challenge.yourdomain.com— the TXT record must propagate.docker logs traefik 2>&1 | grep -i error— common errors:401 Unauthorized— OVH credentials wrong; recheck App Key + Consumer Key.NXDOMAIN— wrong endpoint region or zone not delegated to OVH.
Permission errors on acme.json
sudo chmod 600 ~/docker/traefik/letsencrypt/acme.json
docker compose -f ~/docker/traefik/docker-compose.yml -f ~/docker/traefik/docker-compose.https.yml restart traefikRouting the https URLs from your laptop
Add the FQDNs to /etc/hosts on the laptop, mapped to the Tailscale IP (not the public IP):
100.X.Y.Z ai.yourdomain.com ollama.yourdomain.com
Or use Tailscale MagicDNS + a Tailscale-side split-DNS rule.
If you want Traefik bound to 0.0.0.0:443 instead of the Tailscale IP, you must:
- Edit
services/traefik/docker-compose.https.ymlto change the bind from${TAILSCALE_IP}:443:443to0.0.0.0:443:443. - Open the port in UFW:
sudo ufw allow 443/tcp. - Disable Open WebUI signup, ensure ollama-auth credential is rotated, and run
~/docker/security-check.sh.
This breaks the Tailscale-only assumption documented elsewhere (README.md, ARCHITECTURE.md). Prefer Tailscale ACLs over public exposure.