Files

2.7 KiB

Caddy Subdomain Routing Pattern

When to Use Subdomains vs Path-Based Routing

Subdomains (n8n.itpropartner.com) are preferred when:

  • The backend app uses absolute asset paths (/assets/foo.js, /static/bar.css)
  • The app has its own SPA router that doesn't support base-path rewriting
  • You need WebSocket support for real-time features
  • The app redirects internally (signin flows, OAuth callbacks)

Path-based (app1.itpropartner.com/n8n/) only works when:

  • The app supports BASE_PATH or equivalent configuration
  • All internal asset references are relative or use the base path
  • You've verified the SPA router handles the sub-path correctly

Subdomain Caddyfile Pattern

n8n.itpropartner.com {
    reverse_proxy 127.0.0.1:5678 {
        flush_interval -1
    }
}

flush_interval -1 enables WebSocket support — required for n8n's real-time editor.

Let's Encrypt Pitfalls

Rate Limit: Too Many Failed Authorizations

If DNS isn't pointing to the server when cert issuance is attempted, failed validations count against a 5-per-hour-per-domain rate limit. After 5 failures, Let's Encrypt blocks further attempts for 1 hour.

Fix: Ensure DNS A record resolves to the correct IP BEFORE adding the domain to Caddyfile. Caddy auto-requests certs on config load.

Staging vs Production Certs

Caddy tries staging first, then production. A staging cert issuance success does NOT mean the production cert will work — they have separate rate limits.

Retry After Rate Limit

Caddy auto-retries when the limit resets. Check with:

journalctl -u caddy --no-pager -n 20 | grep -E "cert|rateLimit|will retry"

n8n-Specific Configuration

Docker Volume Permissions

When migrating n8n Docker volumes between servers, the n8n_data volume must be owned by UID 1000 (the node user inside the container):

chown -R 1000:1000 /var/lib/docker/volumes/n8n_n8n_data/_data

Failure to do this causes EACCES: permission denied, open '/home/node/.n8n/crash.journal'.

N8N_PROTOCOL Behind Reverse Proxy

Set N8N_PROTOCOL=http when behind Caddy — Caddy handles SSL termination. Setting it to https inside forces n8n to do its own SSL redirects, creating redirect loops.

N8N_HOST

Must match the public domain — n8n.itpropartner.com. n8n uses this for OAuth callbacks and webhook URLs.

Migration Steps

  1. Stop old containers: docker compose down
  2. Tar volumes: tar czf n8n-data.tar.gz -C /var/lib/docker/volumes n8n_postgres_data n8n_n8n_data
  3. SCP to new server
  4. Extract, create volumes, restore data
  5. Fix permissions on n8n_data volume
  6. Update .env with new N8N_HOST and N8N_PROTOCOL=http
  7. docker compose up -d