Infrastructure
Troubleshooting
Symptom-oriented infrastructure troubleshooting guide.
Symptom → likely cause → diagnosis → resolution. For recovery procedures, see Disaster recovery.
| |
|---|
| Symptom | dig returns correct IP; browser/curl shows TLS error |
| Likely cause | ACME failure, expired cert, or wrong resolver for host type |
| Diagnosis | openssl s_client -connect HOST:443 -servername HOST; check docker logs dokploy-traefik for ACME errors |
| Resolution | Explicit hosts: check HTTP-01 (acme.json). Wildcard: check DNS-01 token and acme-cloudflare.json. See TLS, Disaster recovery |
| |
|---|
| Symptom | Valid TLS on *.staging.getbytebite.co but Traefik 404 page |
| Likely cause | Container not on dokploy-network or Traefik labels missing |
| Diagnosis | docker inspect <storefront-container> --format '{{json .NetworkSettings.Networks}}' — check for dokploy-network |
| Resolution | Re-attach dokploy-network via Dokploy domain config or manual network connect. Verify labels in running container match compose.deploy.yml |
| |
|---|
| Symptom | Wildcard host serves dashboard or docs instead of storefront |
| Likely cause | Router priority conflict or missing wildcard labels |
| Diagnosis | Check Traefik router priorities; explicit Dokploy routers should have higher priority than wildcard (10/20) |
| Resolution | Verify Dokploy explicit domains still configured. Redeploy compose.deploy.yml to restore wildcard labels |
| |
|---|
| Symptom | curl https://HOST/api/health returns HTML or storefront response |
| Likely cause | Missing API wildcard router (priority 20) or StripPrefix middleware |
| Diagnosis | Check api container labels for bytebite-staging-wildcard-api router |
| Resolution | Redeploy from compose.deploy.yml. For explicit hosts, verify Dokploy /api path rule with StripPrefix |
| |
|---|
| Symptom | API logs show requests to /api/health instead of /health |
| Likely cause | StripPrefix middleware not applied |
| Diagnosis | Check Traefik middleware bytebite-staging-wildcard-strip-api on API router |
| Resolution | Verify compose.deploy.yml labels; redeploy |
| |
|---|
| Symptom | Storefront shows wrong branding for hostname |
| Likely cause | Database restaurant_domains mismatch or stale SSR cache |
| Diagnosis | curl -H "Host: EXPECTED_HOST" https://api.staging.getbytebite.co/storefront/restaurant |
| Resolution | Check restaurant_domains table. Re-run seed-staging.js if needed. This is an application/data issue, not routing |
| |
|---|
| Symptom | Random *.staging.getbytebite.co shows "Restaurant not found" |
| Expected | Storefront: HTTP 200 with not-found page. API tenant routes: HTTP 404. /api/health: HTTP 200 |
| Note | Storefront HTTP 200 for unknown tenants is a known application gap — not an infrastructure failure |
| |
|---|
| Symptom | /health/db returns degraded |
| Likely cause | PostgreSQL container down, wrong DATABASE_URL, network issue |
| Diagnosis | Check Dokploy PostgreSQL service status; verify DATABASE_URL in api container env (name only, not value) |
| Resolution | Restart PostgreSQL via Dokploy. See Disaster recovery |
| |
|---|
| Symptom | api.staging… works; random *.staging… fails |
| Likely cause | Wildcard labels missing, dokploy-network not attached, or DNS-01 cert issue |
| Diagnosis | Inspect storefront/api container labels and networks; test wildcard TLS separately |
| Resolution | Redeploy compose; verify Traefik DNS-01 wiring. See Traefik post-upgrade checklist |
| |
|---|
| Symptom | Reserved hosts serve storefront content |
| Likely cause | Wildcard priority higher than explicit Dokploy routers |
| Diagnosis | Compare router priorities in Traefik dashboard or logs |
| Resolution | Ensure Dokploy explicit Host() routers exist and have higher priority than wildcard (10/20). This was verified working post-rollout — regression indicates Dokploy config loss |
| |
|---|
| Symptom | Traefik logs: unknown cert resolver letsencrypt-cloudflare |
| Likely cause | Traefik recreated without custom traefik.yml |
| Diagnosis | Check /etc/dokploy/traefik/traefik.yml for letsencrypt-cloudflare block |
| Resolution | Restore from backup. See Disaster recovery |
| |
|---|
| Symptom | ACME DNS challenge fails; Cloudflare API errors in Traefik logs |
| Likely cause | Invalid/expired token, wrong permissions, or missing mount |
| Diagnosis | Verify token file exists at /etc/dokploy/traefik/secrets/cloudflare-dns-api-token (mode 600); check container mount |
| Resolution | Rotate token. See Operations |
| |
|---|
| Symptom | Wildcard cert not renewing or corrupt ACME state |
| Likely cause | File permissions, concurrent writes, or manual edit |
| Diagnosis | Check file exists and is valid JSON; compare with backup checksums |
| Resolution | Restore from /root/bytebite-traefik-post-wildcard-20260908-175333/ |
| |
|---|
| Symptom | All explicit TLS may work (HTTP-01) but wildcard TLS fails after Dokploy upgrade |
| Likely cause | Container env/mount customization lost on recreate |
| Diagnosis | docker inspect dokploy-traefik — check for CF_DNS_API_TOKEN_FILE and secrets mount |
| Resolution | Re-apply customization from backup inspect. See Disaster recovery |
| |
|---|
| Symptom | docker inspect fails with permission denied |
| Likely cause | User not in docker group or not root |
| Diagnosis | groups; try sudo docker inspect |
| Resolution | Use sudo or add user to docker group (requires re-login) |
| |
|---|
| Symptom | Local dev requests hang ~5s then succeed |
| Likely cause | Missing ::1 entries in /etc/hosts — macOS tries IPv6 AAAA first |
| Diagnosis | Check /etc/hosts for both 127.0.0.1 and ::1 lines per host |
| Resolution | Add IPv6 entries. See Local deployment |
| |
|---|
| Symptom | Preview Compose in Dokploy UI shows labels not in Git |
| Expected | Dokploy injects domain labels and dokploy-network — this is normal |
| Resolution | No action needed. Repository compose.deploy.yml + Dokploy injection combine at runtime. See Dokploy |
| |
|---|
| Symptom | curl https://dashboard.staging.getbytebite.co/.env returns HTTP 200 with HTML |
| Expected | nginx SPA fallback (try_files … /index.html) — not real file exposure |
| Resolution | Known gap. Fix requires nginx config change to reject dot-paths. See Security |