Reverse Proxy and WordPress – Nginx, Apache, SSL Termination, and Cache
Published: April 14, 2026 · Author: Marcin Szewczyk-Wilgan
A reverse proxy sits in front of WordPress and handles client connections on its behalf. This architecture unlocks capabilities that a direct web server setup cannot provide: serving multiple applications on a single IP, SSL termination with certificate centralization, full-page caching independent of WordPress, load balancing across multiple PHP backends, and blue-green deployments without downtime. At the same time, it introduces a set of WordPress-specific pitfalls – broken HTTPS detection, wrong visitor IPs, cached cart pages, redirect loops – that this guide addresses in detail.
Forward Proxy vs Reverse Proxy vs CDN
These three concepts are frequently confused. Understanding the difference clarifies when a reverse proxy makes sense for WordPress.
Use Cases for a Reverse Proxy with WordPress
A reverse proxy makes sense in these scenarios:
Multiple services, one IP
A single server running WordPress on / and a Node.js API on /api/, or two separate WordPress installations on different subdomains, all sharing one public IP. The proxy routes requests to the appropriate backend based on Host header or URL path.
Centralizing certificate management
The proxy handles all SSL/TLS, including certificate renewal, cipher selection, and HTTP/2. Backend servers receive plain HTTP, eliminating the need to configure SSL on each application server. Simplifies certificate management on multi-app servers.
Full-page cache at the proxy layer
Nginx proxy_cache or Varnish in front of WordPress can serve cached responses far more efficiently than WordPress's own page cache plugins. The proxy serves cached pages at near-static speed while WordPress handles only cache misses and authenticated requests.
Multiple PHP backends
For high-traffic sites, distribute PHP requests across multiple backend servers. The proxy load balances across the pool, detects backend failures with health checks, and drains connections gracefully during deployments – enabling zero-downtime updates.
Critical WordPress Pitfalls Behind a Proxy
Several things break predictably when WordPress runs behind a reverse proxy. Address all of these before the site goes live.
X-Forwarded-Proto: https, then add to wp-config.php: if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') { $_SERVER['HTTPS'] = 'on'; }X-Forwarded-For, then use Nginx's set_real_ip_from and real_ip_header X-Forwarded-For (or Apache's mod_remoteip) so WordPress sees the real client IP in REMOTE_ADDR.woocommerce_items_in_cart cookie, the wordpress_logged_in_* cookie, on POST requests, and for /cart/, /checkout/, and /my-account/ URLs unconditionally.proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; in Nginx. Without this, WebSocket connections fail silently.proxy_pass http://backend (no trailing slash) in Nginx to pass the URL unmodified, then let WordPress handle its own permalink normalization.Nginx Proxy Configuration
A complete Nginx reverse proxy configuration for WordPress with caching, cache bypass, and rate limiting:
proxy_cache_path /var/cache/nginx/wordpress levels=1:2 keys_zone=WP_CACHE:100m inactive=60m max_size=5g use_temp_path=off;Define in the
http {} block. A 5 GB disk cache handles large WordPress media sites; for content-only sites 1–2 GB is sufficient. The key zone in RAM (100m) stores cache keys for fast lookup.set $skip_cache 0; if ($request_method = POST) { set $skip_cache 1; } if ($query_string != "") { set $skip_cache 1; } if ($request_uri ~* "/wp-(admin|login|cron)|/cart|/checkout|/my-account") { set $skip_cache 1; } if ($http_cookie ~* "comment_author|wordpress_logged_in|woocommerce") { set $skip_cache 1; }proxy_cache WP_CACHE; proxy_cache_bypass $skip_cache; proxy_no_cache $skip_cache; proxy_cache_valid 200 301 302 60m; proxy_cache_use_stale error timeout updating; add_header X-Cache-Status $upstream_cache_status;The
X-Cache-Status header in responses lets you verify cache hits (HIT/MISS/BYPASS) during testing.proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;These headers tell the WordPress backend the original Host, client IP, and protocol. All four are required for WordPress to function correctly behind the proxy.
limit_req_zone $binary_remote_addr zone=wp_login:10m rate=5r/m; in the http block, then in the server block: location = /wp-login.php { limit_req zone=wp_login burst=3 nodelay; proxy_pass http://wordpress_backend; }Apache Proxy Configuration
Apache with mod_proxy and mod_proxy_balancer provides a mature reverse proxy implementation with load balancing support.
mod_proxy and mod_proxy_http
Enable: a2enmod proxy proxy_http proxy_balancer lbmethod_byrequests headers. In VirtualHost: ProxyPass / http://127.0.0.1:8080/ ProxyPassReverse / http://127.0.0.1:8080/. ProxyPassReverse rewrites Location headers in redirect responses so they point to the proxy, not the backend.
mod_proxy_balancer
<Proxy "balancer://wordpress"> BalancerMember http://10.0.1.10:8080 BalancerMember http://10.0.1.11:8080 ProxySet lbmethod=byrequests </Proxy> ProxyPass / balancer://wordpress/ ProxyPassReverse / balancer://wordpress/. Add status=+H to a BalancerMember to designate it as a hot standby.
Forwarding visitor info
RequestHeader set X-Forwarded-Proto "https" RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}e". Apache's mod_remoteip handles real IP extraction: RemoteIPHeader X-Forwarded-For RemoteIPInternalProxy 10.0.1.0/24.
Proxy-level caching
Apache's mod_cache can cache proxy responses similarly to Nginx proxy_cache. Enable with a2enmod cache cache_disk and configure CacheRoot /var/cache/apache2/proxy. However, Varnish Cache in front of Apache is more commonly used for serious proxy caching on Apache-based stacks due to its far more powerful VCL configuration language.
When NOT to Use a Reverse Proxy
A reverse proxy adds complexity and potential failure points. It is not the right choice for every WordPress deployment.
For a single WordPress site on a single VPS where Nginx or Apache serves WordPress directly, adding a proxy layer provides no benefit. The common pattern of “Nginx as proxy in front of Apache” was once popular because Apache+mod_php was slow and Nginx handled static files better. With Apache MPM Event + PHP-FPM, this split is unnecessary – Apache serves static files efficiently and delegates PHP to FPM directly. Use a reverse proxy when you genuinely need multi-application routing, cross-server load balancing, or centralized SSL termination for a complex infrastructure. Do not add it because it seems more “professional” for a simple single-site deployment.
See also: Nginx for WordPress · Apache for WordPress · WordPress Caching


