diff --git a/docs/content/docs/1.getting-started/4.these-images-vs-others.md b/docs/content/docs/1.getting-started/4.these-images-vs-others.md
index 0d6f7941b..f0c70f0ce 100644
--- a/docs/content/docs/1.getting-started/4.these-images-vs-others.md
+++ b/docs/content/docs/1.getting-started/4.these-images-vs-others.md
@@ -72,7 +72,7 @@ Our images run as the `www-data` user by default, following the principle of lea
We also include additional security hardening:
- Disabled dangerous PHP functions by default (but you control them)
- Proper file permissions out of the box
-- CloudFlare trusted proxy support for accurate IP logging
+- Customizable trusted proxy configuration (Cloudflare, Sucuri, local, or off) for accurate IP logging
- Regular security updates from official PHP base images
### Performance Optimized
diff --git a/docs/content/docs/5.guide/4.configuring-trusted-proxies.md b/docs/content/docs/5.guide/4.configuring-trusted-proxies.md
new file mode 100644
index 000000000..e076b321c
--- /dev/null
+++ b/docs/content/docs/5.guide/4.configuring-trusted-proxies.md
@@ -0,0 +1,350 @@
+---
+head.title: 'Configuring Trusted Proxies - Docker PHP - Server Side Up'
+description: 'Learn how to configure trusted proxies to get accurate client IP addresses when running behind load balancers, CDNs, or reverse proxies.'
+layout: docs
+---
+
+::lead-p
+When your application runs behind a load balancer, CDN, or reverse proxy, the web server sees the proxy's IP address instead of the actual visitor's IP. Trusted proxy configuration tells your web server which proxies to trust for forwarding the real client IP.
+::
+
+## Why Trusted Proxies Matter
+
+Without proper trusted proxy configuration, your application will:
+- Log the proxy's IP address instead of the visitor's real IP
+- Have incorrect geolocation data
+- Potentially break rate limiting or IP-based security rules
+- Show incorrect information in Laravel's `request()->ip()` or similar methods
+
+::warning
+Never trust all IP addresses as proxies. Only trust specific proxy IPs that you control or know are legitimate (like your CDN provider).
+::
+
+## Available Options
+
+Set the `TRUSTED_PROXY` environment variable to one of the following values:
+
+| Value | Description |
+|-------|-------------|
+| `cloudflare` (default) | Trusts [Cloudflare's IP ranges](https://www.cloudflare.com/ips/){target="_blank"} **+ local Docker networks** using the `CF-Connecting-IP` header |
+| `sucuri` | Trusts [Sucuri's IP ranges](https://docs.sucuri.net/website-firewall/sucuri-firewall-troubleshooting-guide/){target="_blank"} **+ local Docker networks** using the `X-Forwarded-For` header |
+| `local` | Trusts only private/local network ranges (Docker networks, localhost) using the `X-Forwarded-For` header |
+| `off` | Disables trusted proxy configuration entirely |
+
+::tip
+**You don't need to choose between your CDN and local proxies.** All options (except `off`) automatically include Docker's internal network ranges (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`). This means if you're behind Cloudflare *and* running a reverse proxy like Traefik or Caddy in Docker, just use `cloudflare` — it already trusts both.
+::
+
+## Quick Start
+
+### Using Cloudflare (Default)
+
+If you're using Cloudflare as your CDN/proxy, you don't need to change anything. The default configuration already trusts Cloudflare's IP ranges:
+
+```yml [compose.yml]
+services:
+ php:
+ image: serversideup/php:8.5-fpm-nginx
+ ports:
+ - "80:8080"
+ volumes:
+ - .:/var/www/html
+ # TRUSTED_PROXY defaults to "cloudflare"
+```
+
+### Using Sucuri
+
+If you're using Sucuri as your web application firewall:
+
+```yml [compose.yml]{8}
+services:
+ php:
+ image: serversideup/php:8.5-fpm-nginx
+ ports:
+ - "80:8080"
+ volumes:
+ - .:/var/www/html
+ environment:
+ TRUSTED_PROXY: "sucuri"
+```
+
+### Local/Docker Networks Only
+
+If you're running behind your own reverse proxy (like Traefik or Caddy) on the same Docker network:
+
+```yml [compose.yml]{8}
+services:
+ php:
+ image: serversideup/php:8.5-fpm-nginx
+ ports:
+ - "80:8080"
+ volumes:
+ - .:/var/www/html
+ environment:
+ TRUSTED_PROXY: "local"
+```
+
+### Disabling Trusted Proxies
+
+If you want to handle proxy configuration yourself or your application is directly exposed to the internet:
+
+```yml [compose.yml]{8}
+services:
+ php:
+ image: serversideup/php:8.5-fpm-nginx
+ ports:
+ - "80:8080"
+ volumes:
+ - .:/var/www/html
+ environment:
+ TRUSTED_PROXY: "off"
+```
+
+## Laravel Configuration
+
+While the Docker images handle the web server's trusted proxy configuration, Laravel also needs to know about trusted proxies at the application level.
+
+Laravel includes a `TrustProxies` middleware that you should configure in your application. For most setups using our images, you can trust all proxies since the web server has already validated them:
+
+```php [bootstrap/app.php]
+->withMiddleware(function (Middleware $middleware) {
+ $middleware->trustProxies(at: '*');
+})
+```
+
+Or if you prefer more control, configure specific headers:
+
+```php [bootstrap/app.php]
+->withMiddleware(function (Middleware $middleware) {
+ $middleware->trustProxies(
+ at: '*',
+ headers: Request::HEADER_X_FORWARDED_FOR |
+ Request::HEADER_X_FORWARDED_HOST |
+ Request::HEADER_X_FORWARDED_PORT |
+ Request::HEADER_X_FORWARDED_PROTO
+ );
+})
+```
+
+::tip
+For Cloudflare specifically, Laravel can use the `CF-Connecting-IP` header. The `HEADER_X_FORWARDED_FOR` setting works because Cloudflare also sets this header.
+::
+
+:u-button{to="https://laravel.com/docs/requests#trusting-proxies" target="_blank" label="Learn more about Laravel's TrustProxies middleware" aria-label="Learn more about Laravel's TrustProxies middleware" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold ring ring-inset ring-blue-600 text-blue-600 hover:ring-blue-500 hover:text-blue-500"}
+
+## How It Works
+
+### Cloudflare
+When `TRUSTED_PROXY=cloudflare`:
+- Trusts Cloudflare's published IPv4 and IPv6 ranges
+- Uses the `CF-Connecting-IP` header to get the real client IP
+- Includes Docker network ranges for container-to-container communication
+
+### Sucuri
+When `TRUSTED_PROXY=sucuri`:
+- Trusts Sucuri's WAF IP ranges
+- Uses the `X-Forwarded-For` header to get the real client IP
+- Includes Docker network ranges for container-to-container communication
+
+### Local
+When `TRUSTED_PROXY=local`:
+- Trusts only private network ranges (RFC 1918)
+- Trusts localhost and IPv6 loopback addresses
+- Uses the `X-Forwarded-For` header
+- Perfect for setups with your own reverse proxy on the same network
+
+## Security Considerations
+
+::caution
+Incorrectly configuring trusted proxies can allow attackers to spoof their IP address by sending fake headers. Only trust IP ranges that you know are legitimate proxies.
+::
+
+- **Don't trust all IPs**: Never set your web server to trust `X-Forwarded-For` from any IP address
+- **Keep configurations updated**: CDN IP ranges can change over time. Our images are updated regularly, but if security is critical, verify the ranges match your provider's published list
+- **Use the right option**: If you're not using Cloudflare or Sucuri, don't use those options. Use `local` if you have your own reverse proxy, or `off` if you don't need proxy trust
+
+## Troubleshooting
+
+### Still seeing proxy IP instead of real IP
+
+1. **Check your CDN/proxy is in the trusted list**: Verify your proxy's IP is within the trusted ranges for your chosen option
+2. **Check the header being used**: Different proxies use different headers. Cloudflare uses `CF-Connecting-IP`, while most others use `X-Forwarded-For`
+3. **Check Laravel configuration**: Remember to also configure Laravel's `TrustProxies` middleware
+
+### Application works but logs show wrong IP
+
+Your web server might be configured correctly, but your application framework might need separate configuration. See the [Laravel Configuration](#laravel-configuration) section above.
+
+### Need to trust a different proxy provider
+
+If your proxy provider isn't listed, you can create a custom configuration. See [Custom Trusted Proxy Configuration](#custom-trusted-proxy-configuration) below.
+
+## Custom Trusted Proxy Configuration
+
+If you're using a proxy provider that isn't included (like AWS ALB, Fastly, or a custom load balancer), you can create your own trusted proxy configuration.
+
+### Two Ways to Add Custom Configs
+
+| Method | Best For | How It Works |
+|--------|----------|--------------|
+| **Dockerfile (recommended)** | Production deployments | Bakes the config into your image |
+| **Volume mount** | Local development | Mount the file at runtime |
+
+The examples below use the Dockerfile approach. To use a volume mount instead, simply replace the `COPY` instruction with a volume mount in your `compose.yml`:
+
+```yml [compose.yml]
+volumes:
+ # Mount syntax: ./local/path:/container/path:ro
+ - ./docker/trusted-proxy/aws-alb.conf:/etc/nginx/trusted-proxy/aws-alb.conf:ro
+```
+
+| Variation | Config Path |
+|-----------|-------------|
+| `fpm-nginx` | `/etc/nginx/trusted-proxy/{name}.conf` |
+| `fpm-apache` | `/etc/apache2/trusted-proxy/{name}.conf` |
+| `frankenphp` | `/etc/frankenphp/trusted-proxy/{name}.caddyfile` |
+
+::tip
+Always include Docker's internal network ranges (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`) so container-to-container communication works correctly.
+::
+
+::warning
+Keep your custom IP ranges up to date. Cloud providers periodically update their IP ranges.
+::
+
+### FPM-NGINX Custom Configuration
+
+::code-tree{defaultValue="Dockerfile"}
+
+```dockerfile [Dockerfile]
+FROM serversideup/php:8.5-fpm-nginx
+
+# Copy our custom trusted proxy configuration
+COPY --chmod=644 docker/trusted-proxy/aws-alb.conf /etc/nginx/trusted-proxy/aws-alb.conf
+```
+
+```yml [compose.yml]
+services:
+ php:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ ports:
+ - "80:8080"
+ volumes:
+ - .:/var/www/html
+ environment:
+ TRUSTED_PROXY: "aws-alb"
+```
+
+```conf [docker/trusted-proxy/aws-alb.conf]
+##
+# AWS ALB - Trusted Proxy (example)
+##
+
+# Configure docker networks and loopback addresses
+set_real_ip_from 10.0.0.0/8;
+set_real_ip_from 172.16.0.0/12;
+set_real_ip_from 192.168.0.0/16;
+set_real_ip_from 127.0.0.1/8;
+set_real_ip_from ::1;
+set_real_ip_from fd00::/8;
+
+# Add your proxy provider's IP ranges
+# Example: AWS us-east-1 ranges (check AWS docs for current IPs)
+set_real_ip_from 3.0.0.0/8;
+
+# Set the header your proxy uses
+real_ip_header X-Forwarded-For;
+```
+::
+
+### FPM-Apache Custom Configuration
+
+::code-tree{defaultValue="Dockerfile"}
+
+```dockerfile [Dockerfile]
+FROM serversideup/php:8.5-fpm-apache
+
+# Copy our custom trusted proxy configuration
+COPY --chmod=644 docker/trusted-proxy/aws-alb.conf /etc/apache2/trusted-proxy/aws-alb.conf
+```
+
+```yml [compose.yml]
+services:
+ php:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ ports:
+ - "80:8080"
+ volumes:
+ - .:/var/www/html
+ environment:
+ TRUSTED_PROXY: "aws-alb"
+```
+
+```conf [docker/trusted-proxy/aws-alb.conf]
+##
+# AWS ALB - Trusted Proxy (example)
+##
+
+# Set the header your proxy uses
+RemoteIPHeader X-Forwarded-For
+
+# Configure docker networks
+RemoteIPTrustedProxy 10.0.0.0/8
+RemoteIPTrustedProxy 172.16.0.0/12
+RemoteIPTrustedProxy 192.168.0.0/16
+RemoteIPTrustedProxy 127.0.0.1/8
+RemoteIPTrustedProxy ::1
+RemoteIPTrustedProxy fd00::/8
+
+# Add your proxy provider's IP ranges
+# Example: AWS us-east-1 ranges (check AWS docs for current IPs)
+RemoteIPTrustedProxy 3.0.0.0/8
+```
+::
+
+### FrankenPHP Custom Configuration
+
+::code-tree{defaultValue="Dockerfile"}
+
+```dockerfile [Dockerfile]
+FROM serversideup/php:8.5-frankenphp
+
+# Copy our custom trusted proxy configuration
+COPY --chmod=644 docker/trusted-proxy/aws-alb.caddyfile /etc/frankenphp/trusted-proxy/aws-alb.caddyfile
+```
+
+```yml [compose.yml]
+services:
+ php:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ ports:
+ - "80:8080"
+ volumes:
+ - .:/var/www/html
+ environment:
+ TRUSTED_PROXY: "aws-alb"
+```
+
+```caddyfile [docker/trusted-proxy/aws-alb.caddyfile]
+servers {
+ # Trust Docker/private networks + loopback
+ trusted_proxies static \
+10.0.0.0/8 \
+172.16.0.0/12 \
+192.168.0.0/16 \
+127.0.0.1/8 \
+::1 \
+fd00::/8 \
+3.0.0.0/8
+
+ # Set the header your proxy uses
+ client_ip_headers X-Forwarded-For
+}
+```
+::
diff --git a/docs/content/docs/8.reference/1.environment-variable-specification.md b/docs/content/docs/8.reference/1.environment-variable-specification.md
index 0b6d28f4d..e839b3ec7 100644
--- a/docs/content/docs/8.reference/1.environment-variable-specification.md
+++ b/docs/content/docs/8.reference/1.environment-variable-specification.md
@@ -119,3 +119,4 @@ Setting environment variables all depends on what method you're using to run you
`SSL_CERTIFICATE_FILE`
*Default: "/etc/ssl/private/self-signed-web.crt"*|Path to public certificate file for HTTPS. You must provide this file otherwise a self-signed key pair will be generated for you.|fpm-nginx,
fpm-apache
`SSL_MODE`
*Default: "off"*|Configure how you would like to handle SSL. This can be "off" (HTTP only), "mixed" (HTTP + HTTPS), or "full" (HTTPS only). If you use HTTP, you may need to also change `PHP_SESSION_COOKIE_SECURE`.|fpm-nginx,
fpm-apache,
frankenphp
`SSL_PRIVATE_KEY_FILE`
*Default: "/etc/ssl/private/self-signed-web.key"*|Path to private key file for HTTPS. You must provide this file otherwise a self-signed key pair will be generated for you.|fpm-nginx,
fpm-apache,
frankenphp
+`TRUSTED_PROXY`
*Default: "cloudflare"*|Configure which proxy IPs are trusted to pass the real client IP address. Valid options: `cloudflare`, `sucuri`, `local`, or `off`. See [Configuring Trusted Proxies](/docs/guide/configuring-trusted-proxies) for details.|fpm-nginx,
fpm-apache,
frankenphp
diff --git a/docs/content/index.md b/docs/content/index.md
index a6cbf94d9..a9e76dda7 100644
--- a/docs/content/index.md
+++ b/docs/content/index.md
@@ -105,10 +105,10 @@ These images [give a lot more]{.text-pink-500} than other PHP Docker Images.
orientation: vertical
---
#title
- Native CloudFlare Support
+ Trusted Proxy Support
#description
- Get real IP addresses from visitors from trusted proxies.
+ Get real IP addresses from Cloudflare, Sucuri, or local proxies.
:::
:::u-page-card
diff --git a/src/s6/etc/entrypoint.d/10-init-webserver-config.sh b/src/s6/etc/entrypoint.d/10-init-webserver-config.sh
index a34608d75..4a06a093b 100644
--- a/src/s6/etc/entrypoint.d/10-init-webserver-config.sh
+++ b/src/s6/etc/entrypoint.d/10-init-webserver-config.sh
@@ -42,8 +42,8 @@ process_template() {
return 1
fi
- # Get all environment variables starting with 'NGINX_', 'SSL_', `LOG_`, 'APACHE_', and 'HEALTHCHECK_PATH'
- subst_vars=$(env | grep -E '^(PHP_|NGINX_|SSL_|LOG_|APACHE_|HEALTHCHECK_PATH)' | cut -d= -f1 | awk '{printf "${%s},",$1}' | sed 's/,$//')
+ # Get all environment variables starting with certain prefixes
+ subst_vars=$(env | grep -E '^(PHP_|NGINX_|SSL_|LOG_|APACHE_|HEALTHCHECK_PATH|TRUSTED_PROXY)' | cut -d= -f1 | awk '{printf "${%s},",$1}' | sed 's/,$//')
# Validate that all required variables are set
for var_name in $(echo "$subst_vars" | tr ',' ' '); do
diff --git a/src/variations/fpm-apache/Dockerfile b/src/variations/fpm-apache/Dockerfile
index 3d4e52f55..0fa0d3fc1 100644
--- a/src/variations/fpm-apache/Dockerfile
+++ b/src/variations/fpm-apache/Dockerfile
@@ -99,7 +99,8 @@ ENV APACHE_DOCUMENT_ROOT=/var/www/html/public \
SHOW_WELCOME_MESSAGE=true \
SSL_MODE=off \
SSL_CERTIFICATE_FILE=/etc/ssl/private/self-signed-web.crt \
- SSL_PRIVATE_KEY_FILE=/etc/ssl/private/self-signed-web.key
+ SSL_PRIVATE_KEY_FILE=/etc/ssl/private/self-signed-web.key \
+ TRUSTED_PROXY=cloudflare
# copy our scripts
COPY --chmod=755 src/common/ /
diff --git a/src/variations/fpm-apache/etc/apache2/conf-available/remoteip.conf b/src/variations/fpm-apache/etc/apache2/conf-available/remoteip.conf
index 59724b0aa..b6e3a544e 100644
--- a/src/variations/fpm-apache/etc/apache2/conf-available/remoteip.conf
+++ b/src/variations/fpm-apache/etc/apache2/conf-available/remoteip.conf
@@ -1,26 +1,5 @@
-RemoteIPHeader CF-Connecting-IP
-RemoteIPTrustedProxy 173.245.48.0/20
-RemoteIPTrustedProxy 103.21.244.0/22
-RemoteIPTrustedProxy 103.22.200.0/22
-RemoteIPTrustedProxy 103.31.4.0/22
-RemoteIPTrustedProxy 141.101.64.0/18
-RemoteIPTrustedProxy 108.162.192.0/18
-RemoteIPTrustedProxy 190.93.240.0/20
-RemoteIPTrustedProxy 188.114.96.0/20
-RemoteIPTrustedProxy 197.234.240.0/22
-RemoteIPTrustedProxy 198.41.128.0/17
-RemoteIPTrustedProxy 162.158.0.0/15
-RemoteIPTrustedProxy 172.64.0.0/13
-RemoteIPTrustedProxy 131.0.72.0/22
-RemoteIPTrustedProxy 104.16.0.0/13
-RemoteIPTrustedProxy 104.24.0.0/14
-RemoteIPTrustedProxy 2400:cb00::/32
-RemoteIPTrustedProxy 2606:4700::/32
-RemoteIPTrustedProxy 2803:f800::/32
-RemoteIPTrustedProxy 2405:b500::/32
-RemoteIPTrustedProxy 2405:8100::/32
-RemoteIPTrustedProxy 2a06:98c0::/29
-RemoteIPTrustedProxy 2c0f:f248::/32
-RemoteIPTrustedProxy 10.0.0.0/8
-RemoteIPTrustedProxy 172.16.0.0/12
-RemoteIPTrustedProxy 192.168.0.0/16
\ No newline at end of file
+#
+# Trusted Proxy Configuration
+# Available options: cloudflare, sucuri, local, off
+#
+Include /etc/apache2/trusted-proxy/${TRUSTED_PROXY}.conf
\ No newline at end of file
diff --git a/src/variations/fpm-apache/etc/apache2/sites-available/ssl-full.conf b/src/variations/fpm-apache/etc/apache2/sites-available/ssl-full.conf
index 056ddde91..c6b8406ac 100644
--- a/src/variations/fpm-apache/etc/apache2/sites-available/ssl-full.conf
+++ b/src/variations/fpm-apache/etc/apache2/sites-available/ssl-full.conf
@@ -3,9 +3,6 @@
ServerName localhost
ServerAdmin webmaster@localhost
- # Set CloudFlare Real IP
- RemoteIPHeader CF-Connecting-IP
-
# Turn on rewrite engine
RewriteEngine On
diff --git a/src/variations/fpm-apache/etc/apache2/trusted-proxy/cloudflare.conf b/src/variations/fpm-apache/etc/apache2/trusted-proxy/cloudflare.conf
new file mode 100644
index 000000000..9d58bc45b
--- /dev/null
+++ b/src/variations/fpm-apache/etc/apache2/trusted-proxy/cloudflare.conf
@@ -0,0 +1,37 @@
+##
+## Cloudflare - Trusted Proxy
+##
+
+# Set RealIP header
+RemoteIPHeader CF-Connecting-IP
+
+# Allow Cloudflare's IP addresses
+# IP source: https://www.cloudflare.com/ips/
+
+RemoteIPTrustedProxy 173.245.48.0/20
+RemoteIPTrustedProxy 103.21.244.0/22
+RemoteIPTrustedProxy 103.22.200.0/22
+RemoteIPTrustedProxy 103.31.4.0/22
+RemoteIPTrustedProxy 141.101.64.0/18
+RemoteIPTrustedProxy 108.162.192.0/18
+RemoteIPTrustedProxy 190.93.240.0/20
+RemoteIPTrustedProxy 188.114.96.0/20
+RemoteIPTrustedProxy 197.234.240.0/22
+RemoteIPTrustedProxy 198.41.128.0/17
+RemoteIPTrustedProxy 162.158.0.0/15
+RemoteIPTrustedProxy 172.64.0.0/13
+RemoteIPTrustedProxy 131.0.72.0/22
+RemoteIPTrustedProxy 104.16.0.0/13
+RemoteIPTrustedProxy 104.24.0.0/14
+RemoteIPTrustedProxy 2400:cb00::/32
+RemoteIPTrustedProxy 2606:4700::/32
+RemoteIPTrustedProxy 2803:f800::/32
+RemoteIPTrustedProxy 2405:b500::/32
+RemoteIPTrustedProxy 2405:8100::/32
+RemoteIPTrustedProxy 2a06:98c0::/29
+RemoteIPTrustedProxy 2c0f:f248::/32
+
+# Configure docker networks
+RemoteIPTrustedProxy 10.0.0.0/8
+RemoteIPTrustedProxy 172.16.0.0/12
+RemoteIPTrustedProxy 192.168.0.0/16
\ No newline at end of file
diff --git a/src/variations/fpm-apache/etc/apache2/trusted-proxy/local.conf b/src/variations/fpm-apache/etc/apache2/trusted-proxy/local.conf
new file mode 100644
index 000000000..417f20553
--- /dev/null
+++ b/src/variations/fpm-apache/etc/apache2/trusted-proxy/local.conf
@@ -0,0 +1,14 @@
+##
+## Local - Trusted Proxy
+##
+
+# Set RealIP header
+RemoteIPHeader X-Forwarded-For
+
+# Configure docker networks
+RemoteIPTrustedProxy 10.0.0.0/8
+RemoteIPTrustedProxy 172.16.0.0/12
+RemoteIPTrustedProxy 192.168.0.0/16
+RemoteIPTrustedProxy 127.0.0.1/8
+RemoteIPTrustedProxy ::1
+RemoteIPTrustedProxy fd00::/8
\ No newline at end of file
diff --git a/src/variations/fpm-apache/etc/apache2/trusted-proxy/off.conf b/src/variations/fpm-apache/etc/apache2/trusted-proxy/off.conf
new file mode 100644
index 000000000..8dc31e72c
--- /dev/null
+++ b/src/variations/fpm-apache/etc/apache2/trusted-proxy/off.conf
@@ -0,0 +1 @@
+# Include nothing when TRUSTED_PROXY is set to off
\ No newline at end of file
diff --git a/src/variations/fpm-apache/etc/apache2/trusted-proxy/sucuri.conf b/src/variations/fpm-apache/etc/apache2/trusted-proxy/sucuri.conf
new file mode 100644
index 000000000..24917082a
--- /dev/null
+++ b/src/variations/fpm-apache/etc/apache2/trusted-proxy/sucuri.conf
@@ -0,0 +1,21 @@
+##
+## Sucuri - Trusted Proxy
+##
+
+# Set RealIP header
+RemoteIPHeader X-Forwarded-For
+
+# Allow Sucuri's IP addresses
+# IP source: https://docs.sucuri.net/website-firewall/sucuri-firewall-troubleshooting-guide/
+
+# Configure docker networks
+RemoteIPTrustedProxy 10.0.0.0/8
+RemoteIPTrustedProxy 172.16.0.0/12
+RemoteIPTrustedProxy 192.168.0.0/16
+
+# Allow Sucuri's IP addresses
+RemoteIPTrustedProxy 192.88.134.0/23
+RemoteIPTrustedProxy 185.93.228.0/22
+RemoteIPTrustedProxy 66.248.200.0/22
+RemoteIPTrustedProxy 2a02:fe80::/29
+RemoteIPTrustedProxy 208.109.0.0/22
\ No newline at end of file
diff --git a/src/variations/fpm-apache/etc/apache2/vhost-templates/http.conf b/src/variations/fpm-apache/etc/apache2/vhost-templates/http.conf
index 5684f34da..8284272f7 100644
--- a/src/variations/fpm-apache/etc/apache2/vhost-templates/http.conf
+++ b/src/variations/fpm-apache/etc/apache2/vhost-templates/http.conf
@@ -2,9 +2,6 @@
ServerName localhost
ServerAdmin webmaster@localhost
-# Set CloudFlare Real IP
-RemoteIPHeader CF-Connecting-IP
-
# Configure main document root
DocumentRoot ${APACHE_DOCUMENT_ROOT}
diff --git a/src/variations/fpm-apache/etc/apache2/vhost-templates/https.conf b/src/variations/fpm-apache/etc/apache2/vhost-templates/https.conf
index f2831f45f..c721ece56 100644
--- a/src/variations/fpm-apache/etc/apache2/vhost-templates/https.conf
+++ b/src/variations/fpm-apache/etc/apache2/vhost-templates/https.conf
@@ -7,9 +7,6 @@ Protocols h2 http/1.1
SSLProtocol -all +TLSv1.2 +TLSv1.3
-# Set CloudFlare Real IP
-RemoteIPHeader CF-Connecting-IP
-
# Configure main document root
DocumentRoot ${APACHE_DOCUMENT_ROOT}
diff --git a/src/variations/fpm-nginx/Dockerfile b/src/variations/fpm-nginx/Dockerfile
index 83518d33d..e945a3d57 100644
--- a/src/variations/fpm-nginx/Dockerfile
+++ b/src/variations/fpm-nginx/Dockerfile
@@ -173,7 +173,8 @@ ENV APP_BASE_DIR=/var/www/html \
SHOW_WELCOME_MESSAGE=true \
SSL_MODE=off \
SSL_CERTIFICATE_FILE=/etc/ssl/private/self-signed-web.crt \
- SSL_PRIVATE_KEY_FILE=/etc/ssl/private/self-signed-web.key
+ SSL_PRIVATE_KEY_FILE=/etc/ssl/private/self-signed-web.key \
+ TRUSTED_PROXY=cloudflare
# copy our scripts
COPY --chmod=755 src/common/ /
diff --git a/src/variations/fpm-nginx/etc/nginx/site-opts.d/http.conf.template b/src/variations/fpm-nginx/etc/nginx/site-opts.d/http.conf.template
index 08a90ff96..3b2cd4b7b 100644
--- a/src/variations/fpm-nginx/etc/nginx/site-opts.d/http.conf.template
+++ b/src/variations/fpm-nginx/etc/nginx/site-opts.d/http.conf.template
@@ -47,5 +47,8 @@ location ~ \.php$ {
fastcgi_read_timeout $PHP_MAX_EXECUTION_TIME;
}
+# trusted proxy configuration
+include /etc/nginx/trusted-proxy/${TRUSTED_PROXY}.conf;
+
# additional config
include /etc/nginx/server-opts.d/*.conf;
\ No newline at end of file
diff --git a/src/variations/fpm-nginx/etc/nginx/site-opts.d/https.conf.template b/src/variations/fpm-nginx/etc/nginx/site-opts.d/https.conf.template
index 810ff0747..a796f5d7f 100644
--- a/src/variations/fpm-nginx/etc/nginx/site-opts.d/https.conf.template
+++ b/src/variations/fpm-nginx/etc/nginx/site-opts.d/https.conf.template
@@ -53,5 +53,8 @@ location ~ \.php$ {
fastcgi_read_timeout $PHP_MAX_EXECUTION_TIME;
}
+# trusted proxy configuration
+include /etc/nginx/trusted-proxy/${TRUSTED_PROXY}.conf;
+
# additional config
include /etc/nginx/server-opts.d/*.conf;
\ No newline at end of file
diff --git a/src/variations/fpm-nginx/etc/nginx/server-opts.d/remoteip.conf b/src/variations/fpm-nginx/etc/nginx/trusted-proxy/cloudflare.conf
similarity index 79%
rename from src/variations/fpm-nginx/etc/nginx/server-opts.d/remoteip.conf
rename to src/variations/fpm-nginx/etc/nginx/trusted-proxy/cloudflare.conf
index 22c36bf65..c99d3aea1 100644
--- a/src/variations/fpm-nginx/etc/nginx/server-opts.d/remoteip.conf
+++ b/src/variations/fpm-nginx/etc/nginx/trusted-proxy/cloudflare.conf
@@ -1,13 +1,17 @@
##
-# Real IP Addresses
+# Cloudflare - Trusted Proxy
##
-# Configure docker networks
+# Configure docker networks and loopback addresses
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
+set_real_ip_from 127.0.0.1/8;
+set_real_ip_from ::1;
+set_real_ip_from fd00::/8;
-# CloudFlare
+# Allow Cloudflare's IP addresses
+# IP source: https://www.cloudflare.com/ips/
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
diff --git a/src/variations/fpm-nginx/etc/nginx/trusted-proxy/local.conf b/src/variations/fpm-nginx/etc/nginx/trusted-proxy/local.conf
new file mode 100644
index 000000000..86563705e
--- /dev/null
+++ b/src/variations/fpm-nginx/etc/nginx/trusted-proxy/local.conf
@@ -0,0 +1,14 @@
+##
+# Local - Trusted Proxy
+##
+
+# Configure docker networks and loopback addresses
+set_real_ip_from 10.0.0.0/8;
+set_real_ip_from 172.16.0.0/12;
+set_real_ip_from 192.168.0.0/16;
+set_real_ip_from 127.0.0.1/8;
+set_real_ip_from ::1;
+set_real_ip_from fd00::/8;
+
+# Set RealIP header
+real_ip_header X-Forwarded-For;
\ No newline at end of file
diff --git a/src/variations/fpm-nginx/etc/nginx/trusted-proxy/off.conf b/src/variations/fpm-nginx/etc/nginx/trusted-proxy/off.conf
new file mode 100644
index 000000000..8dc31e72c
--- /dev/null
+++ b/src/variations/fpm-nginx/etc/nginx/trusted-proxy/off.conf
@@ -0,0 +1 @@
+# Include nothing when TRUSTED_PROXY is set to off
\ No newline at end of file
diff --git a/src/variations/fpm-nginx/etc/nginx/trusted-proxy/sucuri.conf b/src/variations/fpm-nginx/etc/nginx/trusted-proxy/sucuri.conf
new file mode 100644
index 000000000..11aedd1c0
--- /dev/null
+++ b/src/variations/fpm-nginx/etc/nginx/trusted-proxy/sucuri.conf
@@ -0,0 +1,22 @@
+##
+# Sucuri - Trusted Proxy
+##
+
+# Configure docker networks and loopback addresses
+set_real_ip_from 10.0.0.0/8;
+set_real_ip_from 172.16.0.0/12;
+set_real_ip_from 192.168.0.0/16;
+set_real_ip_from 127.0.0.1/8;
+set_real_ip_from ::1;
+set_real_ip_from fd00::/8;
+
+# Allow Sucuri's IP addresses
+# IP source: https://docs.sucuri.net/website-firewall/sucuri-firewall-troubleshooting-guide/
+set_real_ip_from 192.88.134.0/23;
+set_real_ip_from 185.93.228.0/22;
+set_real_ip_from 66.248.200.0/22;
+set_real_ip_from 2a02:fe80::/29;
+set_real_ip_from 208.109.0.0/22;
+
+# Set RealIP header
+real_ip_header X-Forwarded-For;
\ No newline at end of file
diff --git a/src/variations/frankenphp/Dockerfile b/src/variations/frankenphp/Dockerfile
index f9c1ed677..2034e6f6d 100644
--- a/src/variations/frankenphp/Dockerfile
+++ b/src/variations/frankenphp/Dockerfile
@@ -27,7 +27,8 @@ RUN set -eux; \
/etc/frankenphp/ssl-mode \
/etc/frankenphp/log-level \
/etc/frankenphp/auto-https \
- /etc/frankenphp/caddyfile.d; \
+ /etc/frankenphp/caddyfile.d \
+ /etc/frankenphp/caddyfile-global.d; \
# Create default index.php
echo ' /var/www/html/public/index.php; \
# Create symbolic links
@@ -176,6 +177,7 @@ LABEL org.opencontainers.image.title="serversideup/php (frankenphp)" \
SSL_MODE=off \
SSL_CERTIFICATE_FILE="/etc/ssl/private/self-signed-web.crt" \
SSL_PRIVATE_KEY_FILE="/etc/ssl/private/self-signed-web.key" \
+ TRUSTED_PROXY=cloudflare \
XDG_CONFIG_HOME=/config \
XDG_DATA_HOME=/data
diff --git a/src/variations/frankenphp/etc/frankenphp/Caddyfile b/src/variations/frankenphp/etc/frankenphp/Caddyfile
index 50b2158be..756479417 100644
--- a/src/variations/frankenphp/etc/frankenphp/Caddyfile
+++ b/src/variations/frankenphp/etc/frankenphp/Caddyfile
@@ -11,48 +11,16 @@
skip_install_trust
- # Match serversideup/php log levels to Caddy global log levels
import log-level/global/{$LOG_OUTPUT_LEVEL:info}.caddyfile
frankenphp {
{$FRANKENPHP_CONFIG}
}
- servers {
- # Trust Docker/private networks + loopback + Cloudflare ranges
- trusted_proxies static \
-10.0.0.0/8 \
-172.16.0.0/12 \
-192.168.0.0/16 \
-127.0.0.1/8 \
-::1 \
-fd00::/8 \
-173.245.48.0/20 \
-103.21.244.0/22 \
-103.22.200.0/22 \
-103.31.4.0/22 \
-141.101.64.0/18 \
-108.162.192.0/18 \
-190.93.240.0/20 \
-188.114.96.0/20 \
-197.234.240.0/22 \
-198.41.128.0/17 \
-162.158.0.0/15 \
-104.16.0.0/13 \
-104.24.0.0/14 \
-172.64.0.0/13 \
-131.0.72.0/22 \
-2400:cb00::/32 \
-2606:4700::/32 \
-2803:f800::/32 \
-2405:b500::/32 \
-2405:8100::/32 \
-2a06:98c0::/29 \
-2c0f:f248::/32
-
- # Prefer Cloudflare's header; keep XFF as fallback
- client_ip_headers CF-Connecting-IP X-Forwarded-For
- }
+ import trusted-proxy/{$TRUSTED_PROXY:cloudflare}.caddyfile
+
+ # Add additional Caddy configuration files from the caddyfile-global.d directory
+ import caddyfile-global.d/*.caddyfile
{$CADDY_GLOBAL_OPTIONS}
}
diff --git a/src/variations/frankenphp/etc/frankenphp/trusted-proxy/cloudflare.caddyfile b/src/variations/frankenphp/etc/frankenphp/trusted-proxy/cloudflare.caddyfile
new file mode 100644
index 000000000..55d6bcdda
--- /dev/null
+++ b/src/variations/frankenphp/etc/frankenphp/trusted-proxy/cloudflare.caddyfile
@@ -0,0 +1,36 @@
+servers {
+ # Trust Docker/private networks + loopback + Cloudflare ranges
+ # IP source: https://www.cloudflare.com/ips/
+ trusted_proxies static \
+10.0.0.0/8 \
+172.16.0.0/12 \
+192.168.0.0/16 \
+127.0.0.1/8 \
+::1 \
+fd00::/8 \
+173.245.48.0/20 \
+103.21.244.0/22 \
+103.22.200.0/22 \
+103.31.4.0/22 \
+141.101.64.0/18 \
+108.162.192.0/18 \
+190.93.240.0/20 \
+188.114.96.0/20 \
+197.234.240.0/22 \
+198.41.128.0/17 \
+162.158.0.0/15 \
+104.16.0.0/13 \
+104.24.0.0/14 \
+172.64.0.0/13 \
+131.0.72.0/22 \
+2400:cb00::/32 \
+2606:4700::/32 \
+2803:f800::/32 \
+2405:b500::/32 \
+2405:8100::/32 \
+2a06:98c0::/29 \
+2c0f:f248::/32
+
+ # Prefer Cloudflare's header; keep XFF as fallback
+ client_ip_headers CF-Connecting-IP X-Forwarded-For
+}
diff --git a/src/variations/frankenphp/etc/frankenphp/trusted-proxy/local.caddyfile b/src/variations/frankenphp/etc/frankenphp/trusted-proxy/local.caddyfile
new file mode 100644
index 000000000..13a870c12
--- /dev/null
+++ b/src/variations/frankenphp/etc/frankenphp/trusted-proxy/local.caddyfile
@@ -0,0 +1,12 @@
+servers {
+ # Trust Docker/private networks + loopback
+ trusted_proxies static \
+10.0.0.0/8 \
+172.16.0.0/12 \
+192.168.0.0/16 \
+127.0.0.1/8 \
+::1 \
+fd00::/8
+
+ client_ip_headers X-Forwarded-For
+}
diff --git a/src/variations/frankenphp/etc/frankenphp/trusted-proxy/off.caddyfile b/src/variations/frankenphp/etc/frankenphp/trusted-proxy/off.caddyfile
new file mode 100644
index 000000000..e41cd9acc
--- /dev/null
+++ b/src/variations/frankenphp/etc/frankenphp/trusted-proxy/off.caddyfile
@@ -0,0 +1 @@
+# Include nothing when TRUSTED_PROXY is set to off
diff --git a/src/variations/frankenphp/etc/frankenphp/trusted-proxy/sucuri.caddyfile b/src/variations/frankenphp/etc/frankenphp/trusted-proxy/sucuri.caddyfile
new file mode 100644
index 000000000..5de970404
--- /dev/null
+++ b/src/variations/frankenphp/etc/frankenphp/trusted-proxy/sucuri.caddyfile
@@ -0,0 +1,18 @@
+servers {
+ # Trust Docker/private networks + loopback + Sucuri ranges
+ # IP source: https://docs.sucuri.net/website-firewall/sucuri-firewall-troubleshooting-guide/
+ trusted_proxies static \
+10.0.0.0/8 \
+172.16.0.0/12 \
+192.168.0.0/16 \
+127.0.0.1/8 \
+::1 \
+fd00::/8 \
+192.88.134.0/23 \
+185.93.228.0/22 \
+66.248.200.0/22 \
+2a02:fe80::/29 \
+208.109.0.0/22
+
+ client_ip_headers X-Forwarded-For
+}