Nginx https reverse proxy to WordPress with Apache, http and different port

Today I had to hide a WordPress 3.8.1 blog behind an Nginx reverse proxy configured to use only https. Nginx was behind an external firewall which forwarded https://bob.org:8080/blog to Nginx using https (port 4443). The difficulty was that whe WordPress blog was installed in an Apache HTTP server in port 80 and it worked using http!. Lets say that my site was https://bob.org and I had to put the blog in https://bob.org:8080/blog. Thus my list of burdens was the following:

  1. Configure Nginx to use only https and redirect http to https.
  2. Reverse proxy in Nginx from bob.org:8080/blog to 192.168.1.10/wordpress in Apache.
  3. Force WordPress links to use port 8080

The following is the diagram summarised my server configuration:

    +--------------+
    |  Firewall    |
    | bob.org:8080 | 
    +------+-------+
           |
           |
           v
     +–––––––––+                  +––––––––––––––+
     |  Nginx  |      http        |  WordPress   |
     | (https) |+---------------->| Apache HTTP  |
     |         |                  | (port 80)    |
     +–––––––––+                  +––––––––––––––+ 

So you will say: “Are you completely insane ??!!”

I was asked to do it! That is my answer!

Finally after one hour of searching I used a combination of two support articles (post1, post2), some PHP knowledge and experience and a little of imagination, I created a solution:

  1. Configure Nginx to reverse proxy all requests to /blog

    This is a fragment of my /etc/nginx/sites-available/default-ssl Nginx configuration file:

    upstream blog-webservers {
        server 192.168.1.10:80;
    }
    
    # redirect http to https
    # http://serverfault.com/a/171238
    server {
        listen 80;
        rewrite ^(.*) https://$host$1 permanent;
    }
    
    server {
        listen *:443;
    
        ssl on;
        ssl_certificate     /etc/nginx/crypto/server.crt;
        ssl_certificate_key /etc/nginx/crypto/server.key;
    
        ssl_client_certificate /etc/nginx/crypto/ca.crt;
        ssl_verify_client optional;
        ssl_verify_depth 10;
    
        # pem key asking for password problem
        # http://pandemoniumillusion.wordpress.com/2008/04/21/nginx-ssl-passphrase-at-startup/
    
        server_name bob.org;
        access_log  /var/log/nginx/ssl.access.log;
        error_log   /var/log/nginx/ssl.error.log;
        error_page  404 /404.html;
    
    
        # reverse proxy to blog web servers
        location /blog { 
            proxy_pass http://blog-webservers/wordpress/;
            proxy_redirect https://server_name http://blog-webservers/wordpress;
    	
            proxy_read_timeout       3500;
            proxy_connect_timeout    3250;
    
            proxy_set_header   X-Real-IP          $remote_addr;
            proxy_set_header   Host               $host;
            proxy_set_header   X-Forwarded-For    $proxy_add_x_forwarded_for;
            proxy_set_header   X-Forwarded-Proto  https;
           
     
            proxy_set_header   SSL_PROTOCOL $ssl_protocol;
            proxy_set_header   SSL_CLIENT_CERT $ssl_client_cert;
            proxy_set_header   SSL_CLIENT_VERIFY $ssl_client_verify;
            proxy_set_header   SSL_SERVER_S_DN $ssl_client_s_dn;
        }
    }
    

  2. Configure WordPress wp-config.php
    I added the following lines on top of wp-config.php file:

    // If WordPress is behind reverse proxy 
    // which proxies https to http
    if ( (!empty( $_SERVER['HTTP_X_FORWARDED_HOST'])) ||
         (!empty( $_SERVER['HTTP_X_FORWARDED_FOR'])) ) { 
    
        // http://wordpress.org/support/topic/wordpress-behind-reverse-proxy-1
        $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
    
        define('WP_HOME', 'https://bob.org:8080/blog');
        define('WP_SITEURL', 'https://bob.org:8080/blog');
    
        // rewrite blog word with wordpress
        $_SERVER['REQUEST_URI'] = str_replace("wordpress", "blog",
        $_SERVER['REQUEST_URI']);
    
        // http://wordpress.org/support/topic/compatibility-with-wordpress-behind-a-reverse-proxy
        $_SERVER['HTTPS'] = 'on';
    }
    

If you want to debug the former PHP code fragment you can print $_SERVER variables before and after configuration changing command inside the if block:

echo '<br>Before:';
echo '<br>$_SERVER[\'HTTP_HOST\'] : ' . $_SERVER['HTTP_HOST'];
echo '<br>$_SERVER[\'HTTP_X_FORWARDED_HOST\']: ' . $_SERVER['HTTP_X_FORWARDED_HOST'];
echo '<br>$_SERVER[\'REQUEST_URI\']: ' . $_SERVER['REQUEST_URI'];
echo '<br>$_SERVER[\'HTTP_X_FORWARDED_SERVER\']: ' . $_SERVER['HTTP_X_FORWARDED_SERVER'];
echo '<br>$_SERVER[\'HTTP_X_FORWARDED_FOR\']: ' . $_SERVER['HTTP_X_FORWARDED_FOR'];
echo '<br>$_SERVER[\'HTTP_X_FORWARDED_FOR\']: ' . $_SERVER['HTTP_X_FORWARDED_FOR'];
echo '<br>$_SERVER[\'HTTPS\']: ' . $_SERVER['HTTPS'];
echo '<br>$_SERVER[\'REMOTE_ADDR\']: ' . $_SERVER['REMOTE_ADDR'];    
echo '<br>$_SERVER[\'SERVER_NAME\']: ' . $_SERVER['SERVER_NAME'];
echo '<br>$_SERVER[\'SERVER_PROTOCOL\']: ' . $_SERVER['SERVER_PROTOCOL'];
echo '<br>WP_HOME: ' . WP_HOME;
echo '<br>WP_SITEURL : ' . WP_SITEURL;

I am exhausted, just writting it down! Be patient!

Advertisements

About cmanios

programming
This entry was posted in Linux, Nginx, Server and tagged , , , , , , , , . Bookmark the permalink.

14 Responses to Nginx https reverse proxy to WordPress with Apache, http and different port

  1. If some one needs expert view concerning running a blog then i recommend him/her
    to go to see this website, Keep up the pleasant work.

  2. This paragraph will help the internet users forr
    building up new webpage or even a weblog from staft to end.

  3. You are a fucking legend.

    Thanks for posting this solution.

  4. seb says:

    your post is gold thanks!

  5. bao nguyen says:

    Thanks, I sent several hours with colleagues !!!

  6. minijus says:

    Hi Christos,
    we have a similar issue and our administrator is unable to solve this problem. Our setup: Apache server with WP installation under blog.domain.com (no SSL) and domain.com server running with NGINX (SSL). And goal is to access blog through domain.com/blog. If you are interested and could consult us, please get back to me 🙂

  7. Alexandre FRANTZ says:

    I searched for hours , you’re a genius !

  8. Hi I am using Nginx and I did exactly what you asked, my configuration is some like this:

    main website: http://mysite.com
    blog is hosted at: some-ip-address

    location ^~ /blog {
    proxy_read_timeout 3500;
    proxy_connect_timeout 3250;
    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-Real-IP $remote_addr;
    proxy_set_header Host $host;
    rewrite ^/(.*)/$ /$1 last;
    rewrite ^/blog/?(.*)$ /$1 break;
    proxy_pass http://some-ip-address:80/;
    proxy_redirect https://mysite.com/blog http://some-ip-address:80;
    }

  9. geekonweb says:

    saved my day … thanks 🙂

  10. Pingback: The trick to get your wordpress behind a reverse proxy – Chmouel's Blog

  11. blakeimeson says:

    Great write-up! Just now stumbled on this researching AFTER we hassled through a similar issue.

    We did something very similar if anyone wants to check it out.

    WordPress Multisite Reverse Proxy Setup on WPENGINE

  12. Claudio says:

    Thanks so much! I was spending Hours trying to make this exact setup works!

  13. Pingback: Nginx https reverse proxy to WordPress with Apache, http and different port | Blog của Yên

  14. Pingback: Hosting WordPress on NixOS – 0x9b

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s