I once set up nginx reverse proxy before, but I was just pasting stuff from online tutorials, not really understanding what I was doing. So when earlier today I decided I’d set up nginx to serve as a reverse proxy both for Apache and for node.js and Rails projects (soon to be) running on my server, I basically had to learn it all from scratch again.

Since everything on my server is now secured with SSL, I had to combine the methods from various sources on Git, Stack Overflow and Digital Ocean. My idea of the request flow was like this:

  1. redirect all port 80 (unencrypted) requests to port 443 (HTTPS)
  2. forward requests based on the host/path to the local port where the respective server is running

First, I made a default nginx config file for step 1.

server {
  listen 80;
  listen [::]:80;
  server_name _;
  return 301 https://$host$request_uri;

Next I made nginx sites for each of the services I thought of running (though at this moment it’s only the main domain valerauko.net and this blog).

server {
  listen 443 ssl default_server;
  listen [::]:443 ssl default_server;

  server_name valerauko.net www.valerauko.net;

  access_log /var/log/nginx/valerauko.net.log;

  ssl on;
  ssl_certificate /etc/letsencrypt/live/valerauko.net-0001/cert.pem;
  ssl_certificate_key /etc/letsencrypt/live/valerauko.net-0001/privkey.pem
  ssl_session_cache shared:SSL:10m;

  location / {
    proxy_set_header Host $host;
    proxy_redirect http:// https://;

I then added a similar config file for the blog’s subdomain. I also had to config Apache not to listen on any of the standard ports (in its ports.conf and site config files), but only on the generally-not-used ports I picked randomly.

I also added a client_max_body_size setting for the blog, so that WordPress uploads would work. It seems that the default setting isn’t very high because it would break for 2-3 megabyte images already.

I still have to see if I have to set up any header proxying. So far it stuff seems to be working just fine without.

The command netstat -lpt was extremely useful debugging in the process, as it shows what servers are listening on what ports. /etc/init.d services (apache2, nginx etc) also have status commands, which helped too.