# 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

```caddy
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:
```bash
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):
```bash
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`
