How to set up HTTPS/SSL in WordPress behind Proxy (nginx, HAProxy, Apache, lighttpd)

Today I changed the accessibility of my blog from HTTP (unencrypted) to HTTPS/SSL. My blog is running WordPress behind an nginx proxy server. However, while the pages themselves loaded successfully from HTTPS, the embedded static resources like JavaScripts, Images, CSS files etc. did not. Here’s how I fixed it.

The cause of this issue is that WordPress doesn’t seem to detect the original protocol scheme (HTTPS) correctly when running behind a proxy. Thus, if the connection between your user’s browser and your proxy/loadbalancer is HTTPS, but the connection between your proxy server and WordPress is HTTP only, WordPress thinks that it’s running on HTTP instead of HTTPS. Therefore it places sets the absolute URLs incorrectly to HTTP.

This results in mixed content warnings. Modern browsers prevent loading resources from HTTP when the embedding page had been loaded from HTTPS.

To fix this, taking the following steps worked for me:


  1. Make sure that your proxy or load balancer adds the “X-Forwarded-*” HTTP request headers when proxying incoming requests to your WordPress backend server. My nginx configuration contains these lines:
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
  2. Install and activate the “SSL Insecure Content Fixer” plugin in your WordPress installation’s admin panel.
  3. Navigate to Settings -> SSL Insecure Content.
  4. Set “HTTPS detection” to “HTTP_X_FORWARDED_PROTO (e.g. load balancer, reverse proxy, NginX)”.
    Screen Shot 2016-08-27 at 11.06.01
  5. Navigate to Settings -> General.
  6. Set the “WordPress Address (URL)” and “Site Address (URL)” to your new HTTPS address.
    Screen Shot 2016-08-27 at 11.08.02
  7. Check if everything is working as expected.

13 thoughts on “How to set up HTTPS/SSL in WordPress behind Proxy (nginx, HAProxy, Apache, lighttpd)”

  1. Thank you.

    I was just resigning myself to a week of head-scratching when I discovered this post. Worked for me using WordPress behind HAProxy and SSL termination – instant fix.

  2. Doesn’t work for me – after following these instructions, I get Chrome telling me my site “redirected you too many times.” I appear to have created a redirect loop somehow.

    I’ve just installed wordpress and then followed these instructions.

    Any ideas?

      1. Just remove the https from step 6 and add this in your wp-config.php
        if ($_SERVER[‘HTTP_X_FORWARDED_PROTO’] == ‘https’ ) {
        $_SERVER[‘HTTPS’] = ‘on’;
        }

  3. Hi, Settings work fine for me but I was not able to run Jetpack with this settings. Do you use it? If yes, are there some more tweeks necessary?

  4. Much thanks, just what I needed. Only thing is it works (or seems to have done) without the final plugin stage just needed the extra forwards on the nginx setup on WP 4.9.1

  5. Hi, I have tried with the above configuration in my environment with plain http connection for apache/wordpress, it is not working for me. My configuration details are as below.
    nginx:
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For
    $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;

    apache .htaccess:
    # BEGIN WordPress

    RewriteEngine On
    RewriteBase /blog/
    RewriteRule ^index\.php$ – [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /blog/index.php [L]

    wp-config.php:
    if ( (!empty( $_SERVER[‘HTTP_X_FORWARDED_HOST’])) || (!empty( $_SERVER[‘HTTP_X_FORWARDED_FOR’])) ) {
    $_SERVER[‘HTTPS’] = ‘on’;
    }

    $_SERVER[‘REQUEST_URI’] = “/blog”.$_SERVER[‘REQUEST_URI’];

    When I am hitting nginx URL, apache/wordpress port is appearing in the browser URL. https://host-one:8080/blog/ instead https://host-one:9443/blog (My Nginx https port is 9443). Can you please advise, what is missing in my configuration. Thanks.

    1. I have the same problem. I tackled by using “X-Custom_Forwarded-Proto” instead of “X-Forwarded-Proto”.
      I think it is a parsing bug of NGINX

  6. Hi, Nginx reverse proxy is working if I define the wordpress/apache server in the location /blog/, but it is not working if I define it in the upstream section. My configuration is below.

    location /blog/ {
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    #proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Custom_Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_pass https://upstream/blog;
    }
    Also, I appended the below in wp-config.php file.

    if ($_SERVER[‘HTTP_X_FORWARDED_PROTO’] == ‘https’)
    $_SERVER[‘HTTPS’]=’on’;

    if (isset($_SERVER[‘HTTP_X_FORWARDED_HOST’])) {
    $_SERVER[‘HTTP_HOST’] = $_SERVER[‘HTTP_X_FORWARDED_HOST’];
    }

    I notice Nginx is redirecting to apache port instead of serving the request with Nginx port. Please let me know what could be the issue.

Leave a Reply

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