Appearance
Varnish configuration for staging and dev
This runbook owns the Varnish VCL deployed to Menzzo Magento staging and developer environments. The repository contains one ready-to-install file per environment because the backend health probe must send that environment's storefront host.
Do not copy a staging or dev file to production. Production keeps its existing backend, probe, purge sources and Varnish version. The separate production bfcache procedure changes only the response cache policy and includes its own backup and rollback.
Managed files
| Environment | VCL | Runtime path | Compose file |
|---|---|---|---|
staging-02 | download | /srv/devbox/runtime/staging-02/default.vcl | /srv/devbox/runtime/staging-02/docker-compose.yml |
ax-dev-01 | download | /srv/devbox/runtime/ax-dev-01/default.vcl | /srv/devbox/workspaces/ax-dev-01/docker-compose.yml |
ax-dev-02 | download | /srv/devbox/runtime/ax-dev-02/default.vcl | /srv/devbox/workspaces/ax-dev-02/docker-compose.yml |
ax-dev-03 | download | /srv/devbox/runtime/ax-dev-03/default.vcl | /srv/devbox/workspaces/ax-dev-03/docker-compose.yml |
ax-dev-04 | download | /srv/devbox/runtime/ax-dev-04/default.vcl | /srv/devbox/runtime/ax-dev-04/docker-compose.yml |
All five files use nginx:80 as the Docker backend. Their probe requests GET /health_check.php with the matching menzzo-<environment>.trydev.ovh host. The deployed image reported Varnish 4.1.1, so the files declare vcl 4.0.
The VCL permits PURGE requests from localhost, nginx, php85-fpm and shell. These are Docker-network service aliases, not public addresses.
Browser cache behavior
For non-static responses, Varnish applies one of two policies:
- A backend response marked
publicbecomesno-cache, must-revalidate, max-age=0. Omittingno-storeallows a browser to keep the page in its back/forward cache while still requiring normal revalidation. - Every other response keeps
no-store, no-cache, must-revalidate, max-age=0.
This VCL change only makes public pages eligible for bfcache. Magento must still mark cacheable pages public; Varnish must also produce a HIT before storefront cache behavior is considered complete. Do not remove no-store from private responses.
Compile before activation
Copy the candidate into the running Varnish container and compile it with the same binary that will load it:
bash
ENV=staging-02
CONTAINER="env-${ENV}-varnish"
docker cp "/tmp/menzzo-default-${ENV}.vcl" "${CONTAINER}:/tmp/menzzo-default.vcl"
docker exec "${CONTAINER}" sh -lc \
'varnishd -C -f /tmp/menzzo-default.vcl >/dev/null 2>&1'A zero exit status is the activation gate. A local syntax check with another Varnish version is insufficient.
Install and persist
Create a timestamped backup, install the environment-specific file, and make sure the Varnish Compose service mounts it read-only:
bash
ENV=staging-02
TARGET="/srv/devbox/runtime/${ENV}/default.vcl"
STAMP="$(date -u +%Y%m%dT%H%M%SZ)"
sudo cp "${TARGET}" "${TARGET}.bak-${STAMP}"
sudo install -m 0644 "/tmp/menzzo-default-${ENV}.vcl" "${TARGET}"The varnish service must contain this mount:
yaml
volumes:
- /srv/devbox/runtime/<environment>/default.vcl:/etc/varnish/default.vcl:roValidate Compose before recreating only Varnish:
bash
docker compose -f <compose-file> config --quiet
docker compose -f <compose-file> up -d --no-deps --force-recreate varnishax-dev-04 requires the devbox environment file for both commands:
bash
docker compose \
--env-file /home/debian/apps/devbox/.env \
-f /srv/devbox/runtime/ax-dev-04/docker-compose.yml \
config --quietRuntime validation
Confirm the backend becomes healthy and the health route succeeds through Varnish:
bash
ENV=staging-02
HOST="menzzo-${ENV}.trydev.ovh"
docker exec "env-${ENV}-varnish" varnishadm backend.list
docker exec "env-${ENV}-shell" curl -sS -o /dev/null -w '%{http_code}\n' \
-H "Host: ${HOST}" \
-H 'X-Forwarded-Proto: https' \
http://varnish/health_check.phpExpected results are a Healthy backend and HTTP 200. Compare the homepage through Varnish and directly through Nginx. A matching application error on both paths is not a Varnish regression, but it remains an environment issue.
For a cacheable anonymous page, send two requests and inspect Age, X-Magento-Cache-Debug and Cache-Control. Completion requires a Varnish HIT and a public response without no-store. Check a private route such as the cart separately and confirm it still includes no-store.
Deployment record: 2026-10-19
The environment-specific files above were compiled inside every target Varnish 4.1.1 container before activation. After activation:
| Environment | Backend probe | Health through Varnish | Homepage through Varnish / Nginx |
|---|---|---|---|
staging-02 | Healthy | 200 | 200 / 200 |
ax-dev-01 | Healthy | 200 | 500 / 500 |
ax-dev-02 | Healthy | 200 | 200 / 200 |
ax-dev-03 | Healthy | 200 | 200 / 200 |
ax-dev-04 | Healthy | 200 | 200 / 200 |
The ax-dev-01 homepage failure is reproduced directly against Nginx. The other storefront homepages were reachable. All tested homepages still returned MISS with no-store, which means the Magento full-page-cache settings or response classification must be corrected before bfcache and Varnish HIT acceptance can pass.
Rollback
Restore the newest known-good backup, validate the Compose file, then recreate only Varnish:
bash
sudo cp <default.vcl.backup> /srv/devbox/runtime/<environment>/default.vcl
sudo cp <docker-compose.yml.backup> <compose-file> # only if the mount must be reverted
docker compose -f <compose-file> config --quiet
docker compose -f <compose-file> up -d --no-deps --force-recreate varnishRun the backend-health and HTTP checks again after rollback. Use the --env-file argument shown above for ax-dev-04.