67 lines
3.5 KiB
Markdown
67 lines
3.5 KiB
Markdown
# Label-managed edge cache
|
||
|
||
Services opt paths into the shared edge cache with Docker labels. The controller discovers the
|
||
labels, writes higher-priority Traefik routers, and maintains a single Cloudflare Cache Rule that
|
||
makes the declared host/path pairs eligible for edge caching.
|
||
|
||
```yaml
|
||
labels:
|
||
- "xiteng.site.cache.frontend.enabled=true"
|
||
- "xiteng.site.cache.frontend.routers=example,example-http"
|
||
- "xiteng.site.cache.frontend.paths=/static/,/assets/"
|
||
- "xiteng.site.cache.frontend.edge-ttl=604800"
|
||
- "xiteng.site.cache.frontend.browser-ttl=0"
|
||
- "xiteng.site.cache.frontend.stale-while-revalidate=86400"
|
||
```
|
||
|
||
The policy id (`frontend`) only needs to be unique inside one Compose service. `routers` refers to
|
||
Traefik Docker router names declared on the same service. When omitted, all explicit HTTP routers on
|
||
the service are used. Each router must declare its entrypoints and service so it can be referenced
|
||
from the file provider. Existing router middlewares are inherited, so request headers and origin-side
|
||
authentication are not silently removed.
|
||
|
||
| Field | Default | Behavior |
|
||
|---|---:|---|
|
||
| `enabled` | required | Only the exact value `true` enables a policy. |
|
||
| `routers` | auto | Comma-separated Traefik router names on the same container. |
|
||
| `paths` | required | Comma-separated directory prefixes. Each must start and end with `/`; `/`, traversal and encoded paths are rejected. |
|
||
| `hosts` | from `Host()` | Optional exact hostnames for complex router rules; hosts must be inside `xiteng.site`. |
|
||
| `edge-ttl` | `604800` | Cloudflare TTL in seconds, bounded to 60 seconds–365 days. |
|
||
| `browser-ttl` | `0` | When non-zero, also overrides the browser `Cache-Control` TTL. |
|
||
| `stale-while-revalidate` | `86400` | Stale revalidation window in seconds. |
|
||
|
||
The generated router only matches `GET` and `HEAD`, has priority 1000 above its base router, and adds
|
||
`Cloudflare-CDN-Cache-Control`. Cloudflare's managed rule makes extensionless files eligible for cache,
|
||
respects the TTL header for successful responses, and gives 3xx–5xx responses a zero edge TTL.
|
||
|
||
Declaring a path static is a security decision: every response below the prefix must be public and
|
||
independent of users, cookies, authorization headers, and request-specific data. Never label HTML,
|
||
API, callback, admin, download-token, or user-content paths. A Cloudflare cache hit is served before
|
||
Traefik/ForwardAuth, even though cache misses still inherit the base router's middlewares.
|
||
Removing a policy does not revoke copies already held by browsers or edge locations; choose bounded
|
||
TTLs and purge Cloudflare explicitly when previously public content must be withdrawn immediately.
|
||
|
||
## Cloudflare token
|
||
|
||
Place an untracked API token at `secrets/cloudflare_cache_api_token`. It needs access to the
|
||
`xiteng.site` zone and the permissions required to edit Cache Rules. The existing DNS-01 token is
|
||
intentionally not reused. The controller remains healthy without this file and reports
|
||
`waiting-for-token`; in that state Traefik headers and default-extension caching work, but arbitrary
|
||
extensionless URLs are not guaranteed to be cached by Cloudflare.
|
||
|
||
Create the token in Cloudflare, then install it without exposing it in shell history or chat:
|
||
|
||
```sh
|
||
./edge-cache/configure-token
|
||
```
|
||
|
||
Inspect the generated rule without contacting Cloudflare:
|
||
|
||
```sh
|
||
docker compose -f edge-cache/compose.yml exec controller \
|
||
node /app/cloudflare.mjs plan
|
||
```
|
||
|
||
The live controller automatically creates or updates only the rule whose description is
|
||
`Xiteng label-managed static paths`; it preserves all unrelated Cache Rules.
|