# Labels Traefik

Topologie **hybride** (cf. [`deploy.md`](./deploy.md)) :

- **WordPress** = ressource **Docker Compose** Coolify. Ses labels Traefik + l'alias
  réseau interne vivent **dans le repo** (`apps/wordpress/docker-compose.yml`,
  versionnés, relus en PR) — **rien à recopier dans l'UI**. Ils lisent `WP_HOST` /
  `APP_HOST` depuis l'onglet *Environment Variables* de la ressource.
- **Webapp** = **application Coolify** (image GHCR) → garde le *rolling update*
  zero-downtime natif. Une Application ne lit pas de compose : ses labels sont
  posés par `create-wp-reactor --provision`, ou collés à la main dans l'UI
  Coolify (onglet *Labels*) à défaut.

- `${APP_HOST}` = host du front (ex. `__PROJECT_NAME__.example.com`)
- `${WP_HOST}`  = host dédié WordPress (ex. `wp.__PROJECT_NAME__.example.com`)

## WordPress (`__PROJECT_NAME__-wordpress`)

Plus de copier-coller : les labels sont **inline dans `apps/wordpress/docker-compose.yml`**
(bloc `labels:` du service `wordpress`), tout comme l'alias réseau
`__PROJECT_NAME__-wordpress-internal` (bloc `networks:`). Pour les modifier, édite le
compose et redéploie — le diff passe en revue de code.

> Le `$` final de la regex sitemaps y est échappé `$$` (sinon Docker Compose
> l'interpolerait). En dehors d'un compose (paste UI), utilise un `$` simple.

## Webapp (`__PROJECT_NAME__-webapp`)

> **Source de vérité : `webappTraefikLabels()` dans `create-wp-reactor`**
> (`src/provision/coolify.ts`). Le bloc ci-dessous en est le miroir lisible —
> à mettre à jour avec lui.
>
> **Coolify pose ces labels en DEUX appels, et ce n'est pas un détail.** À la
> création d'une Application, il écrase `custom_labels` par ses propres labels
> auto-générés dès que `is_container_label_readonly_enabled` est vrai — c'est le
> défaut, et ce réglage n'est pas exposé par l'API. La même régénération sur
> `PATCH` n'a lieu que si la requête porte `domains`. D'où un `PATCH` séparé, ne
> contenant que `custom_labels`, après la création. Envoyer les labels dans le
> POST de création les perd **silencieusement**.

```
traefik.enable=true
traefik.docker.network=coolify
traefik.http.services.__PROJECT_NAME__-webapp.loadbalancer.server.port=3000

# Compression
traefik.http.middlewares.__PROJECT_NAME__-webapp-compress.compress=true
traefik.http.middlewares.__PROJECT_NAME__-webapp-compress.compress.encodings=br,gzip
traefik.http.middlewares.__PROJECT_NAME__-webapp-compress.compress.defaultEncoding=gzip

# Front (catch-all, priorité basse pour laisser passer les routes WP/SEO ci-dessus)
traefik.http.routers.__PROJECT_NAME__-webapp.rule=Host(`${APP_HOST}`)
traefik.http.routers.__PROJECT_NAME__-webapp.entrypoints=https
traefik.http.routers.__PROJECT_NAME__-webapp.priority=1
traefik.http.routers.__PROJECT_NAME__-webapp.middlewares=__PROJECT_NAME__-webapp-compress
traefik.http.routers.__PROJECT_NAME__-webapp.tls=true
traefik.http.routers.__PROJECT_NAME__-webapp.tls.certresolver=letsencrypt
```
