Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@
# cookbook entry "How do I override env config locally?".
*.local

# 1.x → 3.x migration intermediates, all secret-bearing: env.3x is the
# converter export from `task upgrade_prep` on the 1.x stack; the others are
# produced by `task env:migrate`.
env.3x
.env.symfony.migrated
.env.symfony.infra-advisory

# Operator-generated by `task host:resources` — host-specific resource limits.
compose.resource-limits.yml
.playwright-mcp/
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ See the [v2.x.x — Skipped](#v2xx---skipped) entry below for why this major ski
templates.
- `task env:diff` compares your `.env.symfony` against the example shipped in the
currently-pinned API image.
- `task env:migrate` rewrites a 1.x `.env.docker.local` into the v3 layout.
- `task env:migrate` stages a v3 `.env.symfony` from `env.3x` (the export the 1.x
`task upgrade_prep` produces via the 2.8 API's `app:utils:convert-env-to-3x`) when present —
splitting off the infrastructure advisory — and falls back to the sed rewrite of a 1.x
`.env.docker.local` otherwise.
- Per-service `.env.<svc>.local` override layer for site-specific tuning; gitignored.
- Compose profiles (`COMPOSE_PROFILES=mariadb,traefik`) gate built-in services — drop
`mariadb` for an external DB, drop `traefik` for an external proxy.
Expand All @@ -38,6 +41,16 @@ See the [v2.x.x — Skipped](#v2xx---skipped) entry below for why this major ski
— return only when the stack is genuinely ready (no more `sleep 20` race).
- New `task db:backup` (online `mariadb-dump` to `./backup/<ts>.sql.gz`) and `task db:upgrade`
(idempotent `mariadb-upgrade`).
- The mariadb service sets `MARIADB_AUTO_UPGRADE=1`, so `mariadb-upgrade` runs automatically on
the first 11.4 boot against a carried-over 10.x data dir (the 1.x → 3.x case) — no manual
step required for the system-table upgrade. It also refreshes the healthcheck user, rescuing
data dirs old enough to predate it.
- The mariadb service sets `stop_grace_period: 1m`, so the engine gets room for a clean shutdown
instead of being SIGKILLed mid-flush by the 10s default — important right before a major bump.
- `UPGRADE.md` restructured around the 2.8 converter: a pre-upgrade checklist that exports the
running 1.x configuration (`task upgrade_prep`) *before* the stack is stopped, converter-first
env migration with the sed rename demoted to a fallback, MariaDB auto-upgrade and data-volume
continuity notes, and the `rm docker-compose.yml` step needed before `git checkout`.
- New MariaDB diagnostics: `task db:metrics`, `db:processes`, `db:errors`.
- New `task php:opcache` — operator report on the FPM pool's OPcache (memory, interned
strings, cached-key headroom, hit rate, restarts, preload) with warnings mapped to the
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,10 @@ reasoning.
#### How do I upgrade the bundled MariaDB across a major version?

See [UPGRADE.md](UPGRADE.md). The 1.x → 3.x section has the recipe (it covers the 10.x → 11.4
jump that came with the 3.0 release); the same `task db:backup` → `task db:upgrade` →
update `DATABASE_URL` `serverVersion=` flow applies to any future major bump.
jump that came with the 3.0 release). The mariadb service sets `MARIADB_AUTO_UPGRADE=1`, so
`mariadb-upgrade` runs automatically the first time a newer image starts against the existing
data dir; the manual flow for any future major bump is `task db:backup` → bump the image tag →
`task db:upgrade` (explicit, idempotent re-run) → update `DATABASE_URL` `serverVersion=`.

#### How do I switch from Let's Encrypt to a custom certificate?

Expand Down Expand Up @@ -1248,7 +1250,7 @@ Lifecycle
Bootstrap and env-file tooling
env:init Bootstrap .env.symfony from the API image
env:diff Compare .env.symfony against the image's shipped example
env:migrate Convert a 1.x .env.docker.local to .env.symfony.migrated
env:migrate Stage .env.symfony.migrated from env.3x (preferred) or a 1.x .env.docker.local
env:traefik Interactive .env.traefik setup (alias: traefik_env)

Operations
Expand Down
54 changes: 51 additions & 3 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -284,18 +284,66 @@ tasks:
rm -f "$tmp"

env:migrate:
desc: Convert a 1.x .env.docker.local into a 3.x-shaped .env.symfony.migrated
desc: Stage a 3.x-shaped .env.symfony.migrated — from env.3x (preferred) or a 1.x .env.docker.local
cmds:
- |
OUT=.env.symfony.migrated

# Preferred path: env.3x produced by `task upgrade_prep` on the 1.x
# stack (the API's app:utils:convert-env-to-3x command). It already
# carries the loaded values under their 3.x names AND the admin/client
# config.json conversion the sed path below can't see — so when it's
# present we just split off the trailing infrastructure-advisory
# comment block (COMPOSE_*/PHP_*/NGINX_*/MARIADB_* notes) into a
# reminder, and the rest becomes .env.symfony directly.
if [ -f env.3x ]; then
echo "Found env.3x from the 1.x upgrade prep — using it as the source."
# env.3x ends with a trailing advisory block the converter
# introduces with a fixed marker line; everything above it is the
# application env. Split at the marker: app env to .env.symfony,
# the advisory to its own file (surfaced below, not buried in the
# app env).
ADVISORY=.env.symfony.infra-advisory
rm -f "$ADVISORY"
awk -v adv="$ADVISORY" '
/^# The following loaded variables are NOT read/ { infra = 1 }
infra { print > adv; next }
{ print }
' env.3x > "$OUT"
echo "Wrote $OUT (from env.3x)."
if [ -s "$ADVISORY" ]; then
echo ""
echo "Infrastructure variables were split into $ADVISORY."
echo "They do NOT belong in .env.symfony — distribute them across the"
echo "per-service files of the 3.x layout:"
echo " COMPOSE_* -> .env PHP_* -> .env.php"
echo " NGINX_* -> .env.nginx MARIADB_* -> .env.mariadb"
fi
echo ""
echo "Review with: diff -u env.3x $OUT"
echo "Apply with: mv $OUT .env.symfony"
echo ""
echo "Still set by hand: DATABASE_URL serverVersion=11.4.10-MariaDB"
echo "(after the MariaDB upgrade — see UPGRADE.md step 6)."
exit 0
fi

# Fallback path: no env.3x (older 1.x without the converter command, or
# the stack is already down). Convert a 1.x .env.docker.local by sed —
# an APP_ strip plus the per-site renames the converter would do.
if [ -f .env.docker.local ]; then
SRC=.env.docker.local
elif [ -f .env.local ]; then
SRC=.env.local
else
echo "Error: neither .env.docker.local nor .env.local exists."
echo "Error: no env.3x, .env.docker.local or .env.local found."
echo "On the 1.x stack, prefer 'task upgrade_prep' to produce env.3x."
exit 1
fi
OUT=.env.symfony.migrated
echo "No env.3x found — falling back to the sed conversion of $SRC."
echo "(The env.3x path from 'task upgrade_prep' on 1.x is preferred:"
echo " it also converts the admin/client config.json, which sed can't.)"
echo ""
# Strip APP_ prefix from every key EXCEPT the framework-defined trio
# (APP_ENV, APP_SECRET, APP_DEBUG) — Symfony recognises those by name,
# and renaming them silently breaks env-driven debug/secret/env config.
Expand Down
Loading
Loading