Free tools Windows power users keep installed
One-click scans. No signup required.
Put NGINX at the public edge, keep WordPress on a private origin, and make the proxy preserve the public host, client identity, and HTTPS scheme. The reliable sequence is: prepare and test the origin, configure proxy_pass, forward the required headers, tell WordPress when the original request was HTTPS, align every canonical URL, and only then consider caching.
Antihost offers managed WordPress hosting with free migration, one-click staging and a 14-day free trial.
What a reverse proxy changes in a WordPress deployment
A reverse proxy is the server visitors reach first. In the common arrangement, the request path is browser → TLS/NGINX reverse proxy → WordPress origin. The origin can run Apache or NGINX with PHP; it no longer needs to be directly exposed to the Internet.
As an Amazon Associate I earn from qualifying purchases.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
NGINX accepts the public connection, terminates TLS when configured to do so, applies edge rules, and forwards the request to the origin. WordPress still generates the page, handles authentication, processes uploads, and serves its REST endpoints. NGINX does not replace WordPress; it becomes the public edge in front of it.
This separation is useful when you want one place for certificates, redirects, access controls, connection handling, or carefully scoped caching while retaining an existing Apache or WordPress stack. It also creates a strict contract: the origin must know which public host and scheme the visitor used. If that information is lost, WordPress can emit the wrong links, redirect to an internal hostname, or repeatedly redirect between HTTP and HTTPS.
#1 Best Overall
Choose the topology before writing configuration
Decide where TLS ends and which hop is encrypted. The choice determines the headers WordPress must trust and the failure modes you will troubleshoot.
| Topology | Public connection | Proxy-to-origin hop | Important considerations |
|---|---|---|---|
| NGINX terminates TLS, origin uses HTTP | HTTPS to NGINX | HTTP | Forward X-Forwarded-Proto: https and map it to $_SERVER['HTTPS'] in WordPress. Protect the origin network because the internal hop is unencrypted. |
| NGINX terminates TLS, origin uses HTTPS | HTTPS to NGINX | HTTPS | Encrypts the internal hop as well. The origin still needs a consistent public host and scheme; do not assume encryption alone fixes URL generation. |
| NGINX in front of Apache | HTTPS or HTTP to NGINX | HTTP or HTTPS to Apache | Retains Apache’s application features while NGINX handles the public edge. Ensure Apache accepts the forwarded host and scheme without adding conflicting redirects. |
| NGINX as the only web server with PHP | HTTPS or HTTP to NGINX | Usually local PHP-FPM | This is not a reverse-proxy hop to another web server, but the same canonical URL and HTTPS considerations apply if another edge proxy sits in front. |
For the rest of this guide, assume NGINX terminates TLS and forwards to a WordPress origin at wordpress_origin:8080. Replace that name and port with an address reachable from the proxy. If a load balancer or CDN sits in front of NGINX, define which layer is authoritative for the original scheme and client address; never blindly trust headers supplied by an untrusted client.
Prepare and verify the WordPress origin
Restrict direct access
Where possible, allow the origin to accept traffic only from the reverse proxy’s private address or network. Keep administrative access separate from the public web path. A private origin reduces the chance that visitors bypass the proxy’s TLS, redirects, rate limits, or access policy.
Confirm the origin’s own response
Before adding NGINX, request the origin from the proxy host using the host value the origin expects. Confirm that it returns the intended homepage, a pretty permalink, media, and the login page. Fix origin-level PHP, database, filesystem, or rewrite errors first; a proxy cannot repair an unhealthy upstream.
Record the public canonical URL
Write down the exact hostname and scheme visitors should use, such as https://example.com. Decide whether the canonical host includes www. The choice must be identical in NGINX’s server_name, WordPress’s home and siteurl options, any WP_HOME or WP_SITEURL constants, certificate names, and redirect rules.
Check the origin’s URL settings before cutover
Inspect the WordPress General Settings values or the corresponding home and siteurl options. Existing absolute URLs in content, plugins, theme settings, and serialized data may still point at an old hostname. Change those deliberately with a WordPress-aware tool or migration procedure; do not run an indiscriminate text replacement over the database, because serialized values can be corrupted.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesRank #2
Build the public NGINX server block
Use an HTTP-to-HTTPS redirect only at the public edge
If NGINX is the TLS terminator, the public HTTP listener can redirect to the canonical HTTPS URL. The redirect should be generated by the edge, not repeatedly added by both NGINX and the origin. If another trusted layer already performs the redirect, remove the duplicate rule or document which layer owns it.
server {
listen 80;
server_name example.com;
return 301 https://example.com$request_uri;
}
Use the actual canonical hostname. A redirect to $host is appropriate only when every accepted host is valid; otherwise an unexpected Host header can produce an unwanted destination. A separate catch-all server can reject unknown hosts instead of redirecting them.
Configure TLS and proxying
The following location follows the documented NGINX reverse-proxy pattern. The certificate paths are examples for a host named example.com; use certificates issued for your real hostname.
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://wordpress_origin:8080;
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-Host $server_name;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
}
}
proxy_pass selects the upstream. The Host line preserves the public host that WordPress uses when constructing absolute URLs. X-Real-IP carries the immediate client address, while X-Forwarded-For appends the address to the existing forwarding chain. X-Forwarded-Host records the public server name, and X-Forwarded-Proto records whether the visitor used HTTP or HTTPS. proxy_redirect off prevents NGINX from rewriting upstream redirect locations behind your back; WordPress should emit redirects for the public canonical URL once its settings are correct.
Do not copy a client-supplied forwarding header through unchanged. The proxy should overwrite or construct the values it trusts. If traffic can arrive at NGINX through another proxy, configure that proxy’s address range as trusted and establish a single, documented interpretation of the forwarded chain.
Make WordPress recognize HTTPS behind NGINX
When TLS ends at NGINX and the hop to WordPress is HTTP, PHP may see an ordinary HTTP connection even though the visitor used HTTPS. WordPress documents that this mismatch can cause an infinite redirect loop. Add the following logic in wp-config.php before WordPress finishes loading, adapting it to your trusted-proxy policy:
Rank #3
if ( isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false ) {
$_SERVER['HTTPS'] = 'on';
}
Only honor this header when requests can reach WordPress through your controlled proxy path. If the origin is publicly reachable, an attacker could submit a forged header and influence scheme-sensitive behavior. Restricting the origin and overwriting the header at NGINX are the primary controls; the PHP condition is the application-side mapping.
Do not add several competing HTTPS-detection snippets from different plugins, web servers, and hosting panels. Multiple layers can disagree about the scheme and send the browser back and forth. Keep one documented rule at the layer that owns the trust decision.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Align WordPress’s canonical URLs
Use the public URL in constants when constants are required
If you define URL constants in wp-config.php, use the public address, not the origin’s private name or port:
define('WP_HOME', 'https://example.com');
define('WP_SITEURL', 'https://example.com');
WP_HOME is the address visitors use for the site. WP_SITEURL is where the WordPress files are located from WordPress’s perspective. In a conventional single-site deployment they are often identical, as shown above. Do not define them with a trailing path unless WordPress is genuinely installed in that path.
Keep database options consistent
The constants do not automatically repair conflicting database values. The database home and siteurl options must agree with the public URL, or WordPress can redirect to an old domain even when NGINX is correct. Change one authoritative configuration at a time, then verify the resulting values in the dashboard or with your normal WordPress administration tooling.
Do not derive the canonical host from an arbitrary request
WordPress notes that HTTP_HOST is derived from the request’s Host header. That header is useful only after NGINX has validated the host and forwarded the intended public value. A configuration that builds canonical URLs from any incoming Host can create host-header redirects, password-reset links, or cookie scopes for an attacker-controlled domain.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Rank #4
Review generated and stored URLs
After the change, inspect the HTML source, canonical link, Open Graph URLs, feed links, REST links, media paths, and email links. Search for the origin hostname, an HTTP scheme, and alternate public hostnames. Update plugin or theme settings that store their own base URL. A correct homepage does not prove that every stored URL is correct.
Validate safely before reloading production traffic
- Check the configuration syntax. Run the NGINX configuration test appropriate to your installation, commonly
sudo nginx -t. Do not reload if the test reports an error. - Reload only after a successful test. On a systemd installation this is commonly
sudo systemctl reload nginx. A reload applies the new configuration without unnecessarily terminating existing connections. - Resolve the public hostname. Confirm DNS points to the edge address and that the certificate covers the exact host, including the chosen
wwwor non-wwwform. - Inspect the first response. Use a header request such as
curl -I https://example.com/and verify the status,Location, cache headers, and cookies. Follow redirects with a limited count, for examplecurl -I -L --max-redirs 5 https://example.com/, to expose loops. - Test the origin from the proxy host. Request the upstream directly with the expected Host value. If this fails, investigate networking, DNS, firewall rules, the upstream port, or the origin service before changing WordPress.
- Exercise authenticated and write paths. Log in, log out, open
/wp-admin/, edit a post, upload media, submit a comment if enabled, and call the REST API. These paths reveal cookie, method, body-size, and cache mistakes that a homepage check misses.
Use a functional test matrix after cutover
| Area | What to test publicly | Expected result |
|---|---|---|
| Canonical redirects | HTTP, alternate host, and trailing-slash variants | One deliberate redirect to the chosen HTTPS hostname, with no loop. |
| Homepage and pretty permalink | Root URL and a published post or page | 200 response, correct absolute links, and no origin hostname in the HTML. |
| Administration | /wp-admin/, login, logout, and dashboard navigation |
Session remains authenticated and every admin link stays on the public HTTPS host. |
| Cookies | Inspect login and preference cookies in browser developer tools | Secure and path/domain attributes match the public site; cookies are not scoped to an internal host. |
| Media and uploads | Existing image, new upload, attachment page, and thumbnail | Files load through the public host and upload requests complete without mixed-content errors. |
| REST and callbacks | /wp-json/, editor requests, webhooks, and payment or form callbacks used by the site |
Methods, request bodies, and callback URLs reach the origin and return the expected status. |
| Failure handling | Temporarily stop or block the origin in a controlled window | NGINX returns a deliberate 502 or 504 response and logs enough detail to identify the upstream problem. |
Test from outside the proxy’s private network as well as from the proxy host. Internal success can hide public DNS, certificate, firewall, or header problems.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Add caching only as a separate change
A functioning reverse proxy is not automatically a cache. Treat HTML caching as a second deployment with its own key, exclusion, purge, and privacy rules. The WordPress NGINX handbook documents FastCGI-cache patterns and cookie/request exclusions; NGINX’s cache documentation covers disk storage and purge controls.
Never cache personalized or state-changing requests
At minimum, bypass or do not store responses for:
- Logged-in sessions and requests carrying authentication or WordPress session cookies.
/wp-admin/,/wp-login.php, previews, and editor endpoints.- POST, PUT, PATCH, DELETE, comment submission, search forms, and other requests with a body or side effect.
- Carts, checkout, account pages, membership areas, and any response that varies by user, geography, experiment, or cookie.
- Webhook, callback, API, and nonce-sensitive endpoints unless you have a deliberate API caching policy.
Use response headers and request cookies as part of the policy, not just the URL path. A public-looking URL can still return private content for an authenticated visitor.
Recommended Free Tools
Define freshness and purge behavior
Before enabling storage, decide how a post publication, edit, deletion, menu change, or widget update invalidates affected pages. Test a purge and verify that a newly edited page is not served from an old object. Purge existing objects after changing cache rules so an unsafe response cannot remain available under the previous policy.
Cache static assets differently from HTML
Versioned CSS, JavaScript, fonts, and images can generally have longer browser and edge lifetimes than HTML, provided filenames change when content changes. Keep HTML’s lifetime conservative until you have verified invalidation, cookies, and preview behavior. Do not quote a universal speed or throughput gain: there is no authoritative figure that applies to every WordPress reverse-proxy deployment. Measure page latency, origin request rate, cache hit rate, and error rate for your own traffic before and after the change.
Best Value
Troubleshoot by symptom
Infinite HTTPS redirects
- Confirm the public NGINX location sends
X-Forwarded-Proto $scheme. - Confirm the origin receives the header and the
wp-config.phpmapping sets$_SERVER['HTTPS']toonfor a trusted HTTPS request. - Check that
WP_HOME,WP_SITEURL, and the database URL options all use the same HTTPS hostname. - Look for a second proxy, Apache rule, plugin, or hosting panel that forces a different scheme.
- Use
curl -I -L --max-redirs 5and record eachLocationvalue. The first response that changes the scheme identifies the layer to inspect.
Redirects to an internal or wrong domain
Check the forwarded Host and X-Forwarded-Host values, then compare them with WP_HOME, WP_SITEURL, and the database’s home and siteurl. Inspect plugin settings and stored content for the old hostname. Ensure the certificate and NGINX server_name match the address users actually enter.
Broken images or mixed-content warnings
Inspect the image URL in the browser and page source. If it uses HTTP, fix the canonical URL or the setting that generated it; do not hide the warning with a browser-only workaround. If it uses the origin hostname, correct the host forwarding and stored media URLs. Confirm that uploads and thumbnail requests pass through the same public location.
Login loops, missing sessions, or immediate logout
Inspect the response and request cookies for domain, path, and Secure attributes. The cookie must be valid for the public host and HTTPS scheme. Remove competing SSL or URL redirects and verify that the proxy preserves Set-Cookie behavior. WordPress identifies conflicting SSL, URL, CDN, proxy, NGINX, and Apache settings as common causes; change one layer at a time and retest in a private browser session.
502 Bad Gateway or 504 Gateway Timeout
- Verify the upstream hostname resolves from the proxy host and that the configured port and protocol match the origin.
- Check firewall rules, security groups, container networks, and whether the origin service is listening on the expected interface.
- Request the origin directly from the proxy host with the intended Host header.
- Read the NGINX error log and the origin web-server and PHP logs at the same timestamp.
- Distinguish connection refusal, DNS failure, and a slow upstream response; they require different fixes.
Stale or private content appears for the wrong visitor
Disable HTML caching, purge existing objects, and retest while logged in and logged out. Review cache keys, bypass conditions, cookies, and responses containing Set-Cookie. Do not re-enable storage until authenticated, administrative, POST, checkout, preview, and other personalized paths are demonstrably excluded.
Operational safeguards after launch
- Document the trust boundary: list which proxy addresses may set forwarded headers and which headers the origin consumes.
- Keep the origin health visible: monitor upstream connection failures, response time, 5xx responses, disk space, PHP worker exhaustion, and database errors.
- Renew certificates before expiry: test renewal and reload behavior in advance, then verify the public certificate and complete chain.
- Preserve request correlation: retain NGINX and origin timestamps, request IDs where available, status codes, and upstream timing so a browser error can be traced across both layers.
- Review configuration after changes: run the syntax test before every reload and keep a known-good configuration available for rollback.
- Re-test special paths after plugin updates: editors, login, REST requests, uploads, webhooks, and checkout flows can change independently of the proxy.
The safest rollout is incremental: establish a correct, uncached proxy; verify every public and authenticated path; then introduce narrowly scoped performance features with explicit exclusions and a tested purge process.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




