My first direct engagement with Ngnix, employing its vaunted reverse proxy capability. When it came time to deploy Discourse, I had to go hands-on to support 2 sites (/ and https://forum.bobhy.com) on the same server and at the same network address. As a side benefit, Nginx performs TLS encryption for both sites centrally and will support any additional sites I choose to add.

The narrative

  • Discourse, running Nginx in a container wanted to use 80/443, but Ghost in the parent server was already Ngnix on those ports.
  • To enable sharing, I found this detailed explanation which showed exactly how Nginx can route by host header to different sites operating at the same network address. (And now I see why being a reverse proxy is Nginx's great trick!)
  • I could have retained the default behavior of each site using its own SSL cert, or could have marginally improved on that by getting one cert with an enumerated list of sites in Subject Alternative Name. Let's Encrypt supports either of these with automation that I can make work in Ubuntu. But I didn't want to have to update the cert every time I add a new site, so I opted for getting a wildcard cert for the whole domain (*.bobhy.com). However, I have not bothered to automate the challenge via domains.google.com, I'll do this when the first renewal notice comes in.

The code

The script for getting the wildcard cert:

sudo certbot certonly \
                 --manual \
                 --domains '*.bobhy.com' \
                 --cert-name bobhy.com
                 --preferred-challenges dns

The Nginx configuration for Discourse in the top level Nginx (including an oh, by the way, redirection of http://forum.bobhy.com to https://forum.bobhy.com).
Note that Discourse itself runs in a container and receives http from Nginx via a unix socket

server {
    listen 80;
    listen [::]:80;

    server_name forum.bobhy.com;  # <-- change this

    return 301 https://$host$request_uri;
}

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

    server_name forum.bobhy.com;  # <-- change this

    ssl_certificate      /etc/letsencrypt/live/bobhy.com/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/live/bobhy.com/privkey.pem;
    include /etc/nginx/snippets/ssl-params.conf;

    http2_idle_timeout 5m; # up from 3m default

    location / {
        proxy_pass http://unix:/var/discourse/shared/standalone/nginx.http.sock:;
        proxy_set_header Host $http_host;
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

The Ghost server blocks are similar, specifically with identical path references for SSL cert and key.