Posted in: https, ngnix, Uncategorized

Lets Encrypt ssl certs for nginx reverse proxy

This post explains how to setup a ssl certificates for a reverse proxy.

The example I have used is running ubiqiti’s self hosted UNMS network manager (see

  • FreeBSD 11.4
  • nginx 1.18
  • certbot 1.50 (uses python 3 (3.7.9)

Lets encrypt is a free service that allows people to automatically create 90 day ssl certificates. It uses a small piece of code ( the webserver to place a request file in a known location and then calls an api on the Letsencrypt system’s which fetches the request and returns the certificates. For simplicity the certbot client needs to be run on the server where the certificate needs to be installed, in our case the nginx reverse proxy.

To solve this the configuration of nginx needs to be setup to allow files created by certbot to be directly accessible from the letsencrypt servers. nginx needs to listen both on ssl (80) and non ssl (443) ports to handle both the requests that Letsencrypt sends and the https website we wish to serve too. non ssl URL’s other than the let’s encrypt ones should be passed through to the back end web server for redirects if appropriate. lets encrypt uses the following url path –

server {
        listen       80;

        access_log      logs/unms-access.log;
        error_log       logs/unms-error.log;

        location ^~ /.well-known/acme-challenge/ { # for urls that match .well-known/acme-challenge
                default_type "text/plain";         #
                root /usr/local/www/nginx;         # serve files from here.
        }                                          #

        location / {                               # Else pass as instructed below
                proxy_pass; #Backend server redirects to SSL
                proxy_buffering off;
                proxy_http_version 1.1;
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $remote_addr;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection
    server {
        listen       443 ssl;

        ssl_certificate /usr/local/etc/letsencrypt/live/;
        ssl_certificate_key     /usr/local/etc/letsencrypt/live/;

        ssl_session_timeout  5m;

        access_log      logs/ssl-access-unms.log;
        error_log       logs/ssl-error-unms.log;
        ssl_ciphers         EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;
        #ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
        ssl_prefer_server_ciphers on;
        ssl_protocols       TLSv1.2;
        ssl_session_cache   shared:SSL:10m;
        #ssl_protocols  SSLv2 SSLv3 TLSv1 TLSv1.2;
        #ssl_ciphers  RC4:HIGH:!aNULL:!MD5;
        #ssl_prefer_server_ciphers   on;
        keepalive_timeout       60;
        client_max_body_size 60M;
        ssl_session_cache       shared:SSL:10m;

        location / {
                proxy_set_header Host $host;
                proxy_set_header        X-Forwarded-Proto https;
                proxy_set_header X-Forwarded-For $remote_addr;

Using certbot to request and get the certificate. The first time certbot is run there are some terms to accept, but only the first time.

certbot --webroot --webroot-path /usr/local/www/nginx -d -m certonly

Links to references I’ve used to create this page