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

UPDATE!

Post has moved to https://manios.org/2014/04/12/nginx-https-reverse-proxy-to-wordpress-with-apache-http-and-different-port

About cmanios

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

25 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;
    }

    • Jay Petallar says:

      i have this same setup. However, how do you lockdown wp-admin/wp-login.php from external network? /blog only knows the front end servers where the traffic request came from.

  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

  15. Mathias Aschhoff says:

    Thanks!!!! thats the solution!! great!

  16. Rex says:

    The man! This helped a bunch!

  17. Rajendra says:

    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.

    • cmanios says:

      Hello Rajendra and Happy New year!

      Can you provide us with the full Nginx configuration? Furthermore we have noticed that you perform redirection in Apache which is quite different from the solution in this post.

  18. Rajendra says:

    Reverse proxy is working fine if I define apache server directly in the nginx location block.
    location ~ ^/blog {
    try_files $uri $uri/ @apachewp;
    }

    location @apachewp {
    proxy_http_version 1.1;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Host $host:$server_port;
    add_header X-debug-message “host:server_port:$host:$server_port” always;
    add_header X-debug-message “proxy_port:$proxy_port” always;
    add_header X-debug-message “URI:$uri” always;
    proxy_pass https://host-one:port;
    }

    Suppose if I define the apache server in upstream server reverse proxy is not working.

    upstream wpblog {
    server host-one.com:80;
    }

    location ~ ^/blog {
    try_files $uri $uri/ @apachewp;
    }

    location @apachewp {
    proxy_http_version 1.1;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Host $host:$server_port;
    add_header X-debug-message “host:server_port:$host:$server_port” always;
    add_header X-debug-message “proxy_port:$proxy_port” always;
    add_header X-debug-message “URI:$uri” always;
    proxy_pass https://wpblog;
    }
    When I am accessing the blog, I am experiencing that blog is redirecting to Apache URL. In my case apache and Nginx instances are running on the same host so when I enter the blog URL with nginx port it is redirecting to apache port.

    Also, I defined the below in wp-config.php file.

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

    if (isset($_SERVER[‘HTTP_X_FORWARDED_HOST’])) {
    $_SERVER[‘HTTP_HOST’] = $_SERVER[‘HTTP_X_FORWARDED_HOST’];
    }
    if(isset($_SERVER[‘HTTP_X_FORWARDED_FOR’])) {
    $list = explode(‘,’,$_SERVER[‘HTTP_X_FORWARDED_FOR’]);
    $_SERVER[‘REMOTE_ADDR’] = $list[0];
    }

    Please advise, how to fix this issue.

    Rajendra

    • cmanios says:

      Hi Rajendra,

      I am not sure but I think that you are making some curious things which are very different from my post and the combination will not work:

      1. The use of try_files.
      2. There is a proxy_pass to https.
      3. There is not proxy_redirect.
      4. You have different configuration in wp-config.php

      In my post we have default Apache configuration and the whole trick is prepared in Nginx. I am afraid that you have some things mixed up…

  19. Rajendra says:

    Thanks for your rep;y. I am trying to do reverse proxy from nginx (https) to apache (https), hence I tried with the above configuration. It is working if I hard the URL like proxy_pass https://host-one:port, but it is not working when I use with upstream block. Blog is redirecting to Apache URL when accessing with Nginx URL!

    The other question with me is in production we have multiple environments, these will be served by Nginx servers and Nginx servers will get traffic from external LB same as you provided in the diagram. Do we need to define the public/internet facing URL for ex https://internet-URL/blog in wp-config.php for all the boxes?

    define(‘WP_HOME’, ‘https://bob.org:8080/blog’);
    define(‘WP_SITEURL’, ‘https://bob.org:8080/blog’);

    Please let me know if my understanding is not correct. Also, I tried the above example with two WP machines, Nginx is configured to these machines for reverse proxy setup. Since I don’t have external LB, I defined the above constants with Nginx URL in both WP environments. I see same request is going to both the machines at a time. Please advise, how to fix this issue.
    Your prompt response would be much appreciated. Thanks

    • cmanios says:

      Hello Rajendra,

      In wp-config.php as you said, you have to define the public/internet facing URL for ex https://internet-URL/blog for all the boxes. Otherwise it will not work. The example that you provide is correct. So if your external public (internet) url for blog is https://rajendra.com/blog, then in wp-config.php you will use:

      define(‘WP_HOME’, ‘https://rajendra.com/blog’);
      define(‘WP_SITEURL’, ‘https://rajendra.com/blog’);

      As far as reverse proxying is concerned, you have better proxy https to http as it will save you the CPU time of SSL termination in the WordPress box. Personally I had issues when I proxied https -> https. Thus I prefer https -> http. Don’t get misleaded from the line:

      $_SERVER[‘HTTPS’] = ‘on’;

      This is done on purpose for the external url.
      I hope you found this helpful.
      Best regards,
      Christos

  20. Rajendra says:

    Hi Cmanios,
    Thanks for your reply. I tried by adding the below constants in wp-config.php file, it worked.

    define(‘WP_HOME’, ‘https://public-url/blog’);
    define(‘WP_SITEURL’, ‘https://public-url/blog’);

    I also tried a little different as per WP documentation by adding the below constants in the wp-config.php file.

    define( ‘WP_SITEURL’, ‘https://’ . $_SERVER[‘HTTP_HOST’] . ‘/blog’ );
    define( ‘WP_HOME’, ‘https://’ . $_SERVER[‘HTTP_HOST’] . ‘/blog’ );

    It works as expected.

    Nginx:
    ======
    upstream testblog {
    ip_hash;
    server host-one:8105;
    server host-two:8105;
    }
    location /blog/ {
    try_files $uri $uri/ @apachewp;
    }
    location @apachewp {
    proxy_pass https://testblog;
    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;
    proxy_set_header Host $host:$server_port;
    proxy_redirect off;
    }
    As per WP documentation the recommended is
    define( ‘WP_SITEURL’, ‘http://’ . $_SERVER[‘SERVER_NAME’] . ‘/path/to/WordPress’ );
    Somehow it didn’t worked, need to revisit the configuration.

    Reference :https://codex.wordpress.org/Editing_wp-config.php

    Also, I would like to understand the issues that you faced with https—>https setup. Can you please describe if possible. Thanks.

    • cmanios says:

      The issues are the following:
      1. It was not possible (and cost effective) to issue SSL certificates for all internal servers.
      2. If we issued self signed certificates for all internal servers, then it was time consuming to configure Nginx to ignore the fact that they cannot be validated.
      3. There is no reason to spend CPU cycles for encrypting and decrypting internal communication.

Leave a reply to minijus Cancel reply