Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan Now×
Skip to content
World desk12 min

How to Set Up a Reverse Proxy for a WordPress Site with NGINX

A practical NGINX reverse-proxy setup for WordPress, including topology choices, proxy headers, HTTPS detection, canonical URLs, validation, caching exclusions, and troubleshooting.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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:

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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

  1. 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.
  2. 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.
  3. Resolve the public hostname. Confirm DNS points to the edge address and that the certificate covers the exact host, including the chosen www or non-www form.
  4. 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 example curl -I -L --max-redirs 5 https://example.com/, to expose loops.
  5. 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.
  6. 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.Support on Ko-Fi

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

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.php mapping sets $_SERVER['HTTPS'] to on for 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 5 and record each Location value. 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.