Skip to the content
Documentation
Help Start
Reading in:
  • German: 9,075 of 9,075 pages
About the help in other languages
All help pages

Velocity beside Apache or nginx

The shapes in which Velocity and a traditional web server share a machine or an installation: a proxy in front of Velocity, both serving the same files during a migration, and A/B comparison, with the trust, ownership…

Download as PDF

Address: https://doc.exponential.earth/exphelp/viewer/help/hosting/servers/velocity-beside-apache-or-nginx.md

On this page

Velocity beside Apache or nginx

This page is for system administrators at hosting companies whose machines already run Apache or nginx and who add Velocity to them. It answers: which shapes work, what each needs (trusted proxies, one user for the files, shared sessions, one deploy), and how to check that a forwarded header cannot be forged. The sources are Chapter 8, sections 8.7 and 8.8 and Forwarded headers are trusted only from configured proxies.

Contents

  1. The three shapes
  2. Shape 1: a proxy in front of Velocity
  3. Who trusts the proxy
  4. Shape 2: both serving the same installation
  5. Shape 3: side by side for a comparison
  6. Certificates behind a proxy
  7. Checks
  8. Checklist

The three shapes

ShapeWhenWhat Velocity binds
1. Apache or nginx in front of Velocityone public address carries several services; several customers' Velocity instances behind one front server; Velocity must run as an ordinary user on a high portHost=127.0.0.1 (shipped), a high port
2. Velocity and Apache/nginx serving the same filesa migration from PHP-FPM to Velocity, with the old server left in place on the same filesits own ports
3. Both on their own ports for a testcomparing engines on the customer's own pagesits own ports

Velocity does not need a proxy for TLS; it serves HTTPS itself. A proxy is still the right shape for the cases above or when a load balancer or CDN already terminates TLS.

Shape 1: a proxy in front of Velocity

nginx in front of Velocity (derived example from chapter 8):

location / {
    proxy_pass http://127.0.0.1:8088;
    proxy_set_header Host              $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    # appending is safe: Exponential reads the list from the right
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_http_version 1.1;
}

Apache in front of Velocity (derived example; needs mod_proxy, mod_proxy_http and mod_headers):

ProxyPreserveHost On
ProxyPass        / http://127.0.0.1:8088/
ProxyPassReverse / http://127.0.0.1:8088/
RequestHeader set X-Forwarded-Proto "https"

For several customers on one machine, give each customer's Velocity its own port and its own worker user, and one front-server virtual host per customer pointing at that port. The proxy passes the original Host header; Velocity does not use X-Forwarded-Host.

Who trusts the proxy

Two lists, because Velocity decides before any PHP of the application runs:

ListWhereDefaultDecides
Q.webserver.proxy.trustedthe engine's configuration (a snippet in /etc/vc/conf-available/)127.0.0.1, ::1under Velocity: the visitor's address and whether the request is HTTPS
[HTTPHeaderSettings] TrustedProxies[]settings/override/site.ini.append.php127.0.0.1, ::1under Apache or nginx with PHP-FPM: which forwarded headers the kernel believes

A proxy on the same machine is covered by both defaults. A proxy on another address must be added. For Velocity:

cat > /etc/vc/conf-available/reverse-proxy.conf <<'EOF'
{ "Q": { "webserver": { "proxy": { "trusted": ["127.0.0.1", "::1", "192.0.2.10", "10.0.0.0/8"] } } } }
EOF
php bin/php/console exp:velocity conf enable --apply reverse-proxy --allow-root-user
php bin/php/console exp:velocity restart --allow-root-user

From a trusted proxy, Velocity takes the visitor's address from X-Forwarded-For (read from the right) and hands it to the kernel as REMOTE_ADDR, so ClientIpByCustomHTTPHeader is not needed under Velocity. It treats a plain connection as HTTPS when a trusted proxy sends X-Forwarded-Proto: https, CloudFront-Forwarded-Proto: https or CF-Visitor: {"scheme":"https"}.

Warning

Reading the forwarded protocol only from trusted proxies arrived in Exponential Velocity 0.0.4.44. Up to and including 0.0.4.43, a visitor on a plain listener could make a request look like HTTPS. Check with composer show se7enxweb/exponential-velocity; on an older engine keep Velocity's plain port unreachable from outside whenever a proxy is in front (Chapter 8, section 8.8).

Shape 2: both serving the same installation

When Apache (PHP-FPM) and Velocity serve the same installation, they share var/, the caches and the sessions (Chapter 8, One user, or one group):

  • One user. Give the PHP-FPM pool and Velocity's workers the same user ([ServerSettings] User and Group), or a common group with group-writable, setgid directories and the [FileSettings] permissions of chapter 8. Test with both running and look at the owner of new files in var/ after a few requests.
  • One deploy. exp:velocity deploy reloads the PHP-FPM that serves the site ([DeploySettings] PhpFpmService=auto finds it) and restarts Velocity, then clears the rendered-output caches. Do not set PhpFpmService=disabled in this shape.
  • Sessions. With the role-aware HTTP cache on, both servers must keep sessions in the same directory: the PHP-FPM pool's session.save_path and Velocity's [PHPSettings] IniOptions[]=session.save_path=0;0660;<dir> (HTTP cache).
  • Caches. Clearing a cache in Setup > Caches reaches both, because the files are shared. Two things do not: Velocity keeps settings in memory (restart it after clearing INI caches) and answers pages from its own response cache (exp:velocity cache clear) (Caches).
  • OPcache and APCu belong to each server's own processes.

Shape 3: side by side for a comparison

Each engine has its own port, pid file and logs, so Velocity can run next to the existing server for a test. Then measure both back to back:

php bin/php/console exp:benchmark --compare=https://www.example.com,https://www.example.com:8080 --allow-root-user
php bin/php/console exp:benchmark --compare=https://www.example.com,https://www.example.com:8080 --cold --runs=30 --allow-root-user

Compare only rows with the same cache answer: a cache hit against a render is not a comparison of engines (Benchmarking a hosted site).

Certificates behind a proxy

The proxy owns port 80, so Velocity's ACME HTTP-01 challenge cannot reach it directly. Either let the proxy obtain the certificate, or forward /.well-known/acme-challenge/ to Velocity, or set the engine's acme.webroot to a directory the proxy serves (Velocity HTTPS certificates).

Checks

A forwarded header sent by a visitor must change nothing. Against the site directly (no proxy):

curl -s -o /dev/null -w '%{redirect_url}\n' -H 'X-Forwarded-Proto: https' http://example.com/user/logout
# expected: http://example.com/   -- an https:// address here means the header was believed

Through the proxy, absolute links and redirects must carry https://, and the debug bar's "Is my address listed?" shows the address the kernel uses for the visitor.

SymptomCauseFix
redirects and absolute links go to http://the proxy is not trusted, or sends no X-Forwarded-Protolist it; set the header in the proxy
every visitor has the proxy's addressthe proxy is not trusted (or, under PHP-FPM, ClientIpByCustomHTTPHeader not set)list the proxy; set the header setting
a redirect loop after switching to HTTPSthe proxy speaks HTTPS to the visitor and plain HTTP to the server, and the server does not knowas the first row
root-owned files appear in var/a script or a server runs as rootrun everything as the site's user

Checklist

  • To do: Velocity bound to 127.0.0.1 when a proxy is in front; its plain port not reachable from outside.
  • To do: Engine 0.0.4.44 or later; the proxy listed in Q.webserver.proxy.trusted (and TrustedProxies[] for PHP-FPM).
  • To do: The proxy sets X-Forwarded-Proto and passes Host; the curl check passes.
  • To do: In shape 2: one user for both servers; deploy --dry-run shows the FPM reload and the Velocity restart.
  • To do: Certificate route decided (proxy, forwarded challenge or acme.webroot).

Become an Exponential Partner

Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.

Something wrong on this page? Report an error

Documentation license

This documentation is free documentation, licensed under the GNU Free Documentation License 1.3 or later.

Exponential Copyright © 1998-2026 Exponential Foundation and 7x