Trusted Proxies
Safe forwarded-header handling for reverse-proxy and load-balanced deployments.
If VelvetCMS runs behind a reverse proxy, the direct TCP peer is not the real client. In that setup, Core can read X-Forwarded-* headers, but only when the request came from a trusted proxy address.
Why this matters #
Without trusted proxy handling, the request layer sees:
- the proxy IP instead of the client IP
- the proxy host instead of the public host in some setups
httpinstead ofhttpswhen TLS terminates upstream
With trusted proxies configured correctly, Request::ip(), Request::host(), Request::isSecure(), and Request::url() all reflect the public-facing request.
Configuration #
'trusted_proxies' => [
'enabled' => true,
'proxies' => [
'127.0.0.1',
'10.0.0.0/8',
],
'headers' => [
'for' => 'X-Forwarded-For',
'proto' => 'X-Forwarded-Proto',
'host' => 'X-Forwarded-Host',
],
],
Safe defaults #
Keep these rules in mind:
- leave trusted proxies disabled unless you actually need them
- list only proxy IPs or ranges you control
- keep the standard header names unless your infrastructure rewrites them
Do not trust all clients by default. If any direct client can send spoofed forwarded headers, request URL and IP resolution become unreliable.
Common scenarios #
Local reverse proxy #
If Nginx proxies to PHP-FPM or the built-in server on the same machine:
'proxies' => ['127.0.0.1', '::1'],
Private load balancer #
If a private network load balancer sits in front of the app:
'proxies' => ['10.0.0.0/8'],
Custom forwarded headers #
If your infrastructure emits different header names, override them explicitly:
'headers' => [
'for' => 'X-Real-IP',
'proto' => 'X-Forwarded-Proto',
'host' => 'X-Forwarded-Host',
],
What Core reads #
Once a request is confirmed to come from a trusted proxy, Core consults these headers:
forfor the client IPprotofor HTTP vs HTTPShostfor host resolution
If the remote address is not trusted, those headers are ignored completely.