Proxies & Password Pusher
Settings for configuring Password Pusher with a Proxy.
When hosting Password Pusher behind a reverse proxy (such as Nginx, Apache, Caddy, Traefik, or Cloudflare), you can leverage your proxy for SSL/TLS termination, load balancing, rate limiting, and enhanced security.
This guide covers how to configure Password Pusher to work correctly behind a proxy, including URL generation, trusted proxies, and special configurations for Cloudflare.
Quick Start
Choose your configuration approach based on your setup:
| Scenario | Recommended Approach |
|---|---|
| Single proxy on same server | Configure proxy headers |
| Remote proxy or load balancer | Configure proxy headers + trusted proxies |
| Cloudflare | Enable PWP__CLOUDFLARE_PROXY |
| Complex proxy chains | Use PWP__OVERRIDE_BASE_URL |
| Multiple backend instances | Ensure shared encryption keys |
Critical: Multiple Backend Instances
Warning: If you are running multiple Password Pusher application servers behind a load balancer or proxy, all instances must share the same encryption keys.
When using multiple backend instances (e.g., for high availability or load balancing), each instance must be configured with identical values for:
| Environment Variable | Purpose |
|---|---|
PWPUSH_MASTER_KEY |
Encrypts sensitive push data in the database |
SECRET_KEY_BASE |
Session cookie encryption and Rails security |
Why this matters:
PWPUSH_MASTER_KEY: If instances have different encryption keys, a push created on one instance cannot be decrypted by another. Users will experience failures when viewing pushes, especially those with passphrases.SECRET_KEY_BASE: If instances have different session keys, users will be logged out when their requests are routed to a different backend server.
Symptoms of mismatched keys:
- Passphrase-protected pushes fail to display after entering the correct passphrase
- Users are randomly logged out
- “Something went wrong” errors when viewing pushes
- Intermittent failures that depend on which backend handles the request
See Also: Application Encryption for details on generating and managing encryption keys.
Understanding the Problem
A common issue when using Password Pusher behind a proxy is that generated push URLs are incorrect. Instead of using your public URL (e.g., https://pwpush.example.com), the application may generate URLs with:
- The backend server address (e.g.,
http://localhost:5100) - The wrong protocol (HTTP instead of HTTPS)
- The wrong port number
- The internal hostname
Why this happens: Password Pusher needs to know the original request details (host, protocol, port) that the client used to reach the proxy, not the internal connection between the proxy and the application.
Configuration Options
Option 1: Proxy Headers (Recommended)
Password Pusher uses standard X-Forwarded-* headers to determine the original client request. Configure your proxy to forward these headers.
Required Headers
| Header | Description |
|---|---|
X-Forwarded-Host |
The original hostname from the client request |
X-Forwarded-Proto |
The original protocol (http or https) |
X-Forwarded-Port |
The original port (optional, but recommended) |
Optional but useful:
| Header | Description |
|---|---|
X-Forwarded-For |
The original client IP address |
X-Real-IP |
Alternative header for client IP |
Proxy Configuration Examples
Nginx
Add these headers to your location block:
location / {
proxy_pass http://pwpush:5100;
proxy_http_version 1.1;
# Required headers
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
# Optional but recommended
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
# Connection settings
proxy_set_header Connection "";
proxy_read_timeout 3600;
}
Apache
For Apache with mod_proxy, add these headers in your VirtualHost or .htaccess:
ProxyPreserveHost On
ProxyPass / http://localhost:5100/
ProxyPassReverse / http://localhost:5100/
# Required headers
RequestHeader set X-Forwarded-Host "%{HTTP_HOST}e"
RequestHeader set X-Forwarded-Proto "%{REQUEST_SCHEME}e"
RequestHeader set X-Forwarded-Port "%{SERVER_PORT}e"
RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}e"
Caddy
Caddy automatically forwards proxy headers, but you can explicitly configure them:
pwpush.example.com {
reverse_proxy localhost:5100 {
header_up X-Forwarded-Host {host}
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-Port {port}
header_up X-Real-IP {remote}
}
}
Traefik
Traefik automatically adds forward headers. Ensure your service configuration includes:
services:
pwpush:
labels:
- "traefik.http.services.pwpush.loadbalancer.server.port=5100"
- "traefik.http.routers.pwpush.rule=Host(`pwpush.example.com`)"
- "traefik.http.routers.pwpush.entrypoints=websecure"
- "traefik.http.routers.pwpush.tls.certresolver=letsencrypt"
Traefik automatically forwards X-Forwarded-* headers.
Option 2: Override Base URL
If you cannot configure your proxy to forward headers, or need to force a specific base URL, use the PWP__OVERRIDE_BASE_URL environment variable.
When to Use
- Your proxy cannot forward
X-Forwarded-*headers - You need to force a specific URL regardless of request headers
- You’re using complex proxy chains where headers might be lost
- You want a simple, explicit configuration
Note: When PWP__OVERRIDE_BASE_URL is set, it takes precedence over proxy headers. All generated URLs will use this base URL.
Configuration
Set the environment variable without a trailing slash:
# Docker Compose
environment:
PWP__OVERRIDE_BASE_URL: 'https://pwpush.example.com'
# Shell
export PWP__OVERRIDE_BASE_URL='https://pwpush.example.com'
| Format | Valid? |
|---|---|
https://pwpush.example.com |
✅ Yes |
https://pwpush.example.com:8443 |
✅ Yes (non-standard port) |
https://pwpush.example.com/ |
❌ No (trailing slash) |
Security: Trusted Proxies
By default, Password Pusher only trusts proxy headers from requests originating on the local network (127.0.0.1, ::1, and private IP ranges). This prevents header spoofing attacks.
When Configuration is Required
You must configure trusted proxies if:
- Your proxy is on a different server (not localhost)
- You’re using a cloud-based proxy (Cloudflare, AWS CloudFront, etc.)
- Your proxy is in a different network segment
- You’re using a load balancer or CDN
Why this matters: Without proper configuration, an attacker could spoof X-Forwarded-* headers to:
- Make the application generate incorrect URLs
- Potentially bypass security checks
- Cause redirect loops or other issues
Configuration
Environment Variable (Recommended)
Set PWP__TRUSTED_PROXIES with a comma-separated list of IP addresses:
# Docker Compose
environment:
PWP__TRUSTED_PROXIES: '1.2.3.4,2.3.4.5'
# Shell - Single IP
PWP__TRUSTED_PROXIES='1.2.3.4'
# Shell - Multiple IPs
PWP__TRUSTED_PROXIES='1.2.3.4,2.3.4.5,3.4.5.6'
settings.yml File
trusted_proxies:
- '1.2.3.4'
- '2.3.4.5'
- '3.4.5.6'
Finding Your Proxy IP Addresses
| Proxy Type | How to Find IPs |
|---|---|
| Cloud-based (Cloudflare, CloudFront) | Check provider’s documentation for published IP ranges |
| Self-hosted | Use the proxy server’s IP address |
| Docker | Use the container’s IP or service name (if on same network) |
| Load balancers | Check cloud provider documentation (AWS, Azure, GCP publish their ranges) |
Cloudflare Integration
If you’re using Cloudflare as your proxy/CDN, Password Pusher can automatically fetch and configure Cloudflare’s IP ranges.
Automatic Configuration (Recommended)
Enable automatic IP fetching:
# Docker Compose
environment:
PWP__CLOUDFLARE_PROXY: 'true'
# Shell
export PWP__CLOUDFLARE_PROXY='true'
How it works:
- On application startup, Password Pusher fetches Cloudflare’s current IPv4 and IPv6 IP ranges
- These IPs are automatically added to the trusted proxies list
- IP ranges are fetched from Cloudflare’s official endpoints
Note: This adds a small delay (up to 15 seconds per request) on application startup while fetching IPs.
Manual Configuration
If you prefer manual configuration, find the current Cloudflare IP ranges at:
Then add them to PWP__TRUSTED_PROXIES or settings.yml.
Tip: Use PWP__CLOUDFLARE_PROXY=true for automatic updates. If you configure manually, remember to update IPs periodically as Cloudflare may change their ranges.
Environment Variables Reference
| Variable | Description | Default |
|---|---|---|
PWP__OVERRIDE_BASE_URL |
Force a specific base URL for all generated links | None (uses headers) |
PWP__TRUSTED_PROXIES |
Comma-separated list of trusted proxy IPs | Local network only |
PWP__CLOUDFLARE_PROXY |
Automatically trust Cloudflare IP ranges | false |
PWPUSH_MASTER_KEY |
Database encryption key (must match across instances) | Default key |
SECRET_KEY_BASE |
Session encryption key (must match across instances) | Random per startup |
Troubleshooting
Generated URLs are Incorrect
Symptoms:
- Push URLs show
http://localhost:5100instead ofhttps://pwpush.example.com - URLs use HTTP instead of HTTPS
- URLs include wrong port numbers
Solutions:
- Verify proxy headers are being forwarded
- Check your proxy configuration includes
X-Forwarded-Host,X-Forwarded-Proto, andX-Forwarded-Port - Test by checking request headers in Password Pusher logs
- Check your proxy configuration includes
- Check trusted proxies
- Ensure your proxy’s IP is in the trusted proxies list
- For remote proxies, you must explicitly add them
- Use OVERRIDE_BASE_URL as fallback
- If headers aren’t working, set
PWP__OVERRIDE_BASE_URL
- If headers aren’t working, set
Headers Not Being Accepted
Symptoms:
- Proxy headers are configured but ignored
- Application still uses backend URL
Solutions:
- Verify trusted proxies configuration
- Check that your proxy IP is in the trusted proxies list
- For Cloudflare, enable
PWP__CLOUDFLARE_PROXY=true
- Check header format
- Ensure headers are set correctly (case-sensitive)
- Verify headers are reaching the application (check logs)
- Check network connectivity
- Ensure the proxy can reach the application
- Check firewall rules allow proxy → application communication
Cloudflare IPs Not Loading
Symptoms:
- Cloudflare proxy enabled but IPs not trusted
- Application startup delays
Solutions:
- Check network connectivity
- Application must be able to reach
https://www.cloudflare.comon startup - Verify DNS resolution works
- Application must be able to reach
- Check logs
- Look for warnings about failed Cloudflare IP fetches
- Timeout errors indicate network issues
- Use manual fallback
- If automatic fetching fails, manually add Cloudflare IPs to trusted proxies
Best Practices
- Use proxy headers when possible - More flexible than
OVERRIDE_BASE_URL - Always configure trusted proxies - Required for remote proxies and load balancers
- Use Cloudflare auto-config - Enable
PWP__CLOUDFLARE_PROXYif using Cloudflare - Test URL generation - Create a test push and verify the URL is correct
- Monitor logs - Check for proxy-related warnings or errors
- Keep IPs updated - If manually configuring, update when proxy IPs change
- Share encryption keys - For multiple instances, ensure
PWPUSH_MASTER_KEYandSECRET_KEY_BASEare identical
See Also
- Installation Guide - Learn how to set up Password Pusher
- Application Encryption - Encryption key management
- Configuration Strategies - How to set environment variables
- Public Gateway - Using proxies with the public gateway container