TLS & ACME
HTTP-01 explicit certificates, DNS-01 wildcard certificates, and Cloudflare token model.
TLS & ACME
ByteBite staging uses two Let's Encrypt ACME resolvers in Traefik: HTTP-01 for explicit hosts and DNS-01 (via Cloudflare) for the staging wildcard.
Wildcard certificate verified: 2026-09-08
Why two resolvers
| Use case | Challenge | Reason |
|---|---|---|
Explicit hosts (api.staging…, docs.staging…, etc.) | HTTP-01 | Dokploy-managed domains; Traefik proves control via port 80 |
Wildcard *.staging.getbytebite.co | DNS-01 | HTTP-01 cannot issue wildcard certificates |
HTTP-01 resolver: letsencrypt
| Setting | Value |
|---|---|
info@berkearas.de | |
| Storage | /etc/dokploy/traefik/dynamic/acme.json |
| Challenge | httpChallenge |
| Entry point | web (port 80) |
Used by Dokploy-injected routers for explicit staging domains. Certificates renew automatically through Traefik's ACME integration.
DNS-01 resolver: letsencrypt-cloudflare
| Setting | Value |
|---|---|
info@berkearas.de | |
| Storage | /etc/dokploy/traefik/dynamic/acme-cloudflare.json |
| Challenge | dnsChallenge |
| Provider | Cloudflare |
Cloudflare API token
| Attribute | Value |
|---|---|
| Host file | /etc/dokploy/traefik/secrets/cloudflare-dns-api-token |
| Owner / mode | root:root, 600 |
| Container path | /run/secrets/cloudflare-dns-api-token |
| Env var | CF_DNS_API_TOKEN_FILE=/run/secrets/cloudflare-dns-api-token |
Never document the token value.
Required Cloudflare token permissions:
| Permission | Scope |
|---|---|
| Zone → Zone → Read | getbytebite.co only |
| Zone → DNS → Edit | getbytebite.co only |
Optional hardening: restrict token source IP to 88.99.0.118/32. Whether this restriction is configured is unknown — document as optional only.
Token was verified active and successfully queried getbytebite.co zone (2026-09-08).
Issued wildcard certificate
| Attribute | Value |
|---|---|
| Domain | *.staging.getbytebite.co |
| SAN | DNS:*.staging.getbytebite.co |
| Issuer | Let's Encrypt |
| Issuer CN (observed) | YR2 — do not depend on this remaining stable |
| Storage | acme-cloudflare.json (separate from acme.json) |
Wildcard and explicit certificates are stored in separate ACME state files.
Automatic renewal
Traefik handles ACME renewal for both resolvers. Renewal failures typically appear in Traefik logs and manifest as TLS errors on affected hostnames.
Validation commands
Replace TENANT_HOST with any valid one-label staging hostname (e.g. test-tenant.staging.getbytebite.co).
Check certificate on explicit host
echo | openssl s_client -connect api.staging.getbytebite.co:443 -servername api.staging.getbytebite.co 2>/dev/null | openssl x509 -noout -subject -issuer -datesCheck wildcard certificate
TENANT_HOST="smoke-$(date +%s).staging.getbytebite.co"
echo | openssl s_client -connect "${TENANT_HOST}:443" -servername "${TENANT_HOST}" 2>/dev/null | openssl x509 -noout -subject -issuer -dates -ext subjectAltNameVerify HTTP → HTTPS redirect
curl -sI "http://staging.getbytebite.co/" | head -5Expected: 301 or 308 to https://.
Troubleshooting pointers
| Symptom | Likely cause | See |
|---|---|---|
| TLS error on wildcard host only | DNS-01 resolver or token issue | Troubleshooting |
| TLS error on explicit host only | HTTP-01 challenge failure | Troubleshooting |
| All TLS broken after Dokploy upgrade | Traefik container recreated without secret mount | Disaster recovery |
acme-cloudflare.json permission errors | File ownership or mode | Backups |
Production TLS (planned)
Production will require TLS for apex and custom restaurant domains. Custom-domain TLS strategy is not implemented. See Known gaps.
Related
- Traefik — resolver and router configuration
- DNS — Cloudflare records
- Secrets — token storage policy
- Validation — full smoke test suite