Proxies & Password Pusher

Settings for configuring Password Pusher with a Proxy.

This article applies to: OSS Self-Hosted

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

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

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.

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:5100 instead of https://pwpush.example.com
  • URLs use HTTP instead of HTTPS
  • URLs include wrong port numbers

Solutions:

  1. Verify proxy headers are being forwarded
    • Check your proxy configuration includes X-Forwarded-Host, X-Forwarded-Proto, and X-Forwarded-Port
    • Test by checking request headers in Password Pusher logs
  2. Check trusted proxies
    • Ensure your proxy’s IP is in the trusted proxies list
    • For remote proxies, you must explicitly add them
  3. Use OVERRIDE_BASE_URL as fallback
    • If headers aren’t working, set PWP__OVERRIDE_BASE_URL

Headers Not Being Accepted

Symptoms:

  • Proxy headers are configured but ignored
  • Application still uses backend URL

Solutions:

  1. Verify trusted proxies configuration
    • Check that your proxy IP is in the trusted proxies list
    • For Cloudflare, enable PWP__CLOUDFLARE_PROXY=true
  2. Check header format
    • Ensure headers are set correctly (case-sensitive)
    • Verify headers are reaching the application (check logs)
  3. 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:

  1. Check network connectivity
    • Application must be able to reach https://www.cloudflare.com on startup
    • Verify DNS resolution works
  2. Check logs
    • Look for warnings about failed Cloudflare IP fetches
    • Timeout errors indicate network issues
  3. Use manual fallback
    • If automatic fetching fails, manually add Cloudflare IPs to trusted proxies

Best Practices

  1. Use proxy headers when possible - More flexible than OVERRIDE_BASE_URL
  2. Always configure trusted proxies - Required for remote proxies and load balancers
  3. Use Cloudflare auto-config - Enable PWP__CLOUDFLARE_PROXY if using Cloudflare
  4. Test URL generation - Create a test push and verify the URL is correct
  5. Monitor logs - Check for proxy-related warnings or errors
  6. Keep IPs updated - If manually configuring, update when proxy IPs change
  7. Share encryption keys - For multiple instances, ensure PWPUSH_MASTER_KEY and SECRET_KEY_BASE are identical

See Also