This page is not relevant if the ServicePulse static files have been extracted, and is being hosted in anything other than the Container or Windows Service hosting options provided. Forward header configuration is only required if using a reverse proxy.
When ServicePulse is deployed behind a reverse proxy that terminates SSL/TLS (like nginx, Traefik, or a cloud load balancer), you need to configure forwarded headers so ServicePulse correctly understands the original client request.
Configuration
There are two hosting options for ServiceControl, Container and Windows Service. The container is configured via environment variables, while the Windows Service is configured using command-line arguments. See the Hosting Guide for example usage of these configuration settings, along with Authentication and TLS, in a scenario-based format.
Container
Windows Service
| Command-Line Argument | Default | Description |
|---|---|---|
--forwardedheadersenabled= | true | Enable forwarded headers processing |
--forwardedheaderstrustallproxies= | true | Trust all proxies (auto-disabled if known proxies/networks set) |
--forwardedheadersknownproxies= | (none) | Comma-separated IP addresses of trusted proxies |
--forwardedheadersknownnetworks= | (none) | Comma-separated CIDR networks (e.g., 10.) |
Example:
"C:\Program Files (x86)\Particular Software\ServicePulse\ServicePulse.Host.exe" --forwardedheadersenabled=true --forwardedheaderstrustallproxies=true
What Headers Are Processed
When enabled, ServicePulse processes:
X-Forwarded-For- Original client IP addressX-Forwarded-Proto- Original protocol (http/https)X-Forwarded-Host- Original host header
When the proxy is trusted:
Request.will be set fromScheme X-Forwarded-Proto(e.g.,https)Request.will be set fromHost X-Forwarded-Host(e.g.,servicepulse.)example. com - Client IP will be available from
X-Forwarded-For
When the proxy is not trusted (incorrect KnownProxies):
X-Forwarded-*headers are ignored (not applied to the request)Request.remainsScheme httpRequest.remains the internal hostnameHost - The request is still processed (not blocked)
Interaction with the Container Built-in Reverse Proxy
ServicePulse includes a built-in YARP reverse proxy with the Container that forwards requests to ServiceControl Primary and Monitoring instances. The forwarded headers configuration does not affect this proxy.
- UseForwardedHeaders processes incoming headers from an upstream proxy so ServicePulse understands the original client request (scheme, host, client IP)
- YARP independently handles outgoing requests to ServiceControl/Monitoring backends
These operate at different points in the request flow and do not conflict.
HTTP to HTTPS Redirect
When using a reverse proxy that terminates SSL, you can configure ServicePulse to redirect HTTP requests to HTTPS. This works in combination with forwarded headers:
- The reverse proxy forwards both HTTP and HTTPS requests to ServicePulse
- The proxy sets
X-Forwarded-Prototo indicate the original protocol - ServicePulse reads this header (via forwarded headers processing)
- If the original request was HTTP and redirect is enabled, ServicePulse returns a redirect to HTTPS
To enable HTTP to HTTPS redirect, see TLS Configuration for details on how to do this.
Proxy Chain Behavior (ForwardLimit)
When processing X-Forwarded-For headers with multiple IPs (proxy chains), the behavior depends on trust configuration:
| Configuration | ForwardLimit | Behavior |
|---|---|---|
TrustAllProxies = true | null (no limit) | Processes all IPs, returns original client IP |
TrustAllProxies = false | 1 (default) | Processes only the last proxy IP |
For example, with X-Forwarded-For: 203.:
- TrustAllProxies = true: Returns
203.(original client)0. 113. 50 - TrustAllProxies = false: Returns
192.(last proxy)168. 1. 1
Configuration examples
The following examples show common forward header configurations for different deployment scenarios.
Single reverse proxy (known IP)
When running behind a single reverse proxy with a known IP address:
Container:
docker run -e SERVICEPULSE_FORWARDEDHEADERS_ENABLED=true \
-e SERVICEPULSE_FORWARDEDHEADERS_TRUSTALLPROXIES=false \
-e SERVICEPULSE_FORWARDEDHEADERS_KNOWNPROXIES=10.0.0.5 \
...
particular/servicepulse:latest
Windows Service:
ServicePulse.Host.exe --forwardedheadersenabled=true --forwardedheaderstrustallproxies=false --forwardedheadersknownproxies=10.0.0.5
Multiple reverse proxies
When running behind multiple proxies (e.g., load balancer and application gateway):
Container:
docker run -e SERVICEPULSE_FORWARDEDHEADERS_ENABLED=true \
-e SERVICEPULSE_FORWARDEDHEADERS_TRUSTALLPROXIES=false \
-e SERVICEPULSE_FORWARDEDHEADERS_KNOWNPROXIES=10.0.0.5,10.0.0.6 \
...
particular/servicepulse:latest
Windows Service:
ServicePulse.Host.exe --forwardedheadersenabled=true --forwardedheaderstrustallproxies=false --forwardedheadersknownproxies=10.0.0.5,10.0.0.6
Container/Kubernetes environment
When running in a container environment where proxy IPs are dynamic, trust a network range:
docker run -e SERVICEPULSE_FORWARDEDHEADERS_ENABLED=true \
-e SERVICEPULSE_FORWARDEDHEADERS_TRUSTALLPROXIES=false \
-e SERVICEPULSE_FORWARDEDHEADERS_KNOWNNETWORKS=10.0.0.0/8 \
...
particular/servicepulse:latest
Development/trusted environment
For development or fully trusted environments (not recommended for production):
Container:
docker run -e SERVICEPULSE_FORWARDEDHEADERS_ENABLED=true \
-e SERVICEPULSE_FORWARDEDHEADERS_TRUSTALLPROXIES=true \
...
particular/servicepulse:latest
Windows Service:
ServicePulse.Host.exe --forwardedheadersenabled=true --forwardedheaderstrustallproxies=true
Troubleshooting
HTTPS redirect loops
Symptom: Browser shows "too many redirects" or redirect loop errors when accessing the application through a reverse proxy with SSL termination.
Cause: The X-Forwarded-Proto header is not being processed, so the application thinks the request is HTTP and keeps redirecting to HTTPS.
Solutions:
- Verify forwarded headers are enabled
- Check that the proxy IP is in
KnownProxiesorKnownNetworks, or enableTrustAllProxies - Confirm the reverse proxy is sending the
X-Forwarded-Protoheader
Wrong host in generated URLs
Symptom: Links or redirects use the internal hostname (e.g., localhost or container name) instead of the public hostname.
Cause: The X-Forwarded-Host header is not being trusted or processed.
Solutions:
- Verify the proxy IP is trusted (check
KnownProxies/KnownNetworksconfiguration) - Confirm the reverse proxy is sending the
X-Forwarded-Hostheader - In Kubernetes, ensure the correct pod/node network is in
KnownNetworks
Client IP shows proxy IP instead of real client
Symptom: Logs or audit trails show the proxy's IP address instead of the actual client IP.
Cause: The X-Forwarded-For header is not being processed, or the wrong IP is being extracted from a proxy chain.
Solutions:
- Verify forwarded headers are enabled and the proxy is trusted
- For proxy chains, check the
ForwardLimitbehavior — withTrustAllProxies=false, only the last proxy IP is used - If using multiple proxies, ensure all proxy IPs are listed in
KnownProxies
Headers not processed in Kubernetes
Symptom: Forward headers work locally but not in Kubernetes, even with headers enabled.
Cause: In Kubernetes, the ingress controller or load balancer IP may differ from what's configured in KnownProxies.
Solutions:
- Use
KnownNetworkswith the pod/service CIDR range instead of specific IPs (e.g.,10.)0. 0. 0/ 8 - Check what IP the request is actually coming from (ingress controller pod IP, node IP, or load balancer IP)
- For development/testing, temporarily enable
TrustAllProxies=trueto confirm headers are the issue
Verifying header processing
To confirm whether forwarded headers are being processed correctly:
- Enable verbose logging to see incoming request details
- Check that
Request.showsScheme https(nothttp) when accessing via HTTPS-terminating proxy - Verify the
Hostheader in logs matches the expected public hostname - Compare client IP in logs against the expected client IP