In order to setup Nginx Reverse Proxy to accept SSL connections, we need to make couple modifications to our virtual.conf file. In this basic tutorial, we will assume that you have a working Nginx reverse proxy server running and you have already generated SSL certificate files for your domain. We will be modifying a virtual.conf file for a WordPress website. If you don’t know how to setup Nginx reverse proxy for WordPress, please read our previous article.
How To Enable SSL on Nginx ?
This is actually very simple to do. Basically, make sure that you have port 443 open to public on your firewall and then edit your virtual.conf as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 | server { listen 443; ssl on; ssl_certificate /etc/ssl/bundle.crt; #This crt file comes from the company you bought the SSL from. ssl_certificate_key /etc/ssl/yourdomain.com.key; #This file is used create CSR server_name www.yourdomain.com; charset utf-8; location / { try_files $uri $uri/ =404; } } |
As you can see from our comments above, all you have to do is to define a new server configuration for port 443 and give SSL file paths to Nginx. Once you restart Nginx server, then Nginx is ready to accept SSL connections. However, our goal is to create a configuration for a reverse proxy. So how are we going to accomplish this?
Enabling SSL For A WordPress Site Behind Nginx Reverse Proxy
Let’s assume our Nginx is listening port 80 and reverse proxying requests to an Apache server on port 82. If we want to enable SSL for this domain and redirect all requests to our SSL site then we should make a copy of the block of directives previously defined for port 80 in our virtual.conf and then modify that configuration block so that we can use it for SSL. The new configuration for port 80 should redirect requests to port 443. Let’s look at a new virtual.conf file to make things more clear:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | proxy_cache_path /home/nginxcache levels=1:2 keys_zone=my_zone:120m max_size=5G inactive=1M; server { listen 80; server_name yourdomain.com www.yourdomain.com; return 301 https://www.yourdomain.com$request_uri; #We are redirecting to SSL } server { listen 443; ssl on; ssl_certificate /etc/ssl/bundle.crt; ssl_certificate_key /etc/ssl/yourdomain.com.key; server_name www.yourdomain.com; charset utf-8; location / { set $skip_cache 0; # POST requests and urls with a query string should always go to PHP if ($request_method = POST) { set $skip_cache 1; } if ($query_string != "") { set $skip_cache 1; } # Don't cache uris containing the following segments if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp- comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(_index)?.xml|[a-z0-9_-]+-sitemap([0-9]+)?.xml)") { set $skip_cache 1; } # Don't use the cache for logged in users or recent commenters if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") { set $skip_cache 1; } proxy_cache my_zone; add_header X-Proxy-Cache $upstream_cache_status; proxy_set_header Host www.yourdomain.com; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Ssl on; #MUST HAVE THIS OTHERWISE SHIT CAN HAPPEN add_header X-Proxy-Serve TEST; proxy_pass http://localhost:82; proxy_cache_valid 200 301 302 3m; proxy_cache_valid 404 1m; proxy_cache_bypass $skip_cache; proxy_cache_bypass $http_pragma $http_authorization; #Respect pragma no cache proxy_cache_key "$scheme$request_method$host$request_uri"; } error_page 403 500 502 503 504 /500.html; location = /500.html { root /var/www/errorpages; allow all; } location ~ ^/(wp-admin|wp-login\.php) { allow XXX.XXX.XXX.XXX; # IP restriction for admin page deny all; 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-Ssl on; #MUST HAVE THIS OTHERWISE WP-ADMIN FAILS proxy_pass http://localhost:82$uri$is_args$args; proxy_cache_bypass 1; } } |
In the configuration above, we are making sure that our Nginx reverse proxy forwards SSL to our Apache server where our WordPress installation runs. As we have previously stated, Nginx redirects request that come to port 80 to our SSL site. This ensures that our website does not have both http and https versions available. Of course, you can get rid of this but it’s not recommended if you are running a WordPress site.
You should make sure that “proxy_set_header X-Forwarded-Ssl on” is definitely included in your virtual.conf file, otherwise you will run into redirection loop problems.