Trusted SSL certificates with Let’s Encrypt and NGINX is the new awesomeness that happened to SSL on the web. Forget over-priced trusted certificates or self-signed certs for your side & pro bono projects. Try trusted SSL in seconds for free instead :). If you choose to use Let’s Encrypt I want to show you what needs to be done on a pretty average Fedora VPS with NGINX server and how to avoid certbot errors like urn:acme:error:unauthorized and urn:acme:error:unknownHost.

Since I don’t plan to duplicate what’s already said on and so go read that first. In short Let’s Encrypt will generate certificate for your (sub)domains for free on the fly on your server using the program called certbot. But before that certbot has to actually check that your server is serving your domain and that you have access to it.

So before running certbot you will need to check that your DNS records are in tact. Go to your DNS settings and check A records:

# Example: these are A records for (redirect) and (main site)	1800	A	        1800	A

This says what (sub)domains point to which IP address. If you want to generate SSL that is valid for your redirects as well, do not forget A records for them! With correct DNS settings you should be already safe from getting urn:acme:error:unknownHost.

Secondly you will need for certbot to check you have root access on the server mentioned in the A record. In our case that will be by specifying --webroot and --webroot-path options. Depending on your server that path might be able to serve the generated file in question (in $WEBROOT/.well-known/*). If needed add a specific entry for this to NGINX:

server {
  location ~* ^/.well-known {
    root $YOUR_ROOT;
    allow all;

You can easily check this by placing a random HTML file under this path and see if it will be served ($YOUR_ROOT can be your public assets directory for instance). That should eliminate another common error where the bot cannot access your server on the generated URL and so it is saying that you are unauthorized to place its file under by raising urn:acme:error:unauthorized error.

If you feel confident that all is set, run the certbot:

$ sudo dnf install certbot -y
$ sudo certbot certonly --webroot -d -d -m your@contact.mail --agree-tos --webroot-path $WEBROOT -n

-n is for non-interactive mode, so you can script this step.

If all is well, you should see something along this lines:

Generating key (2048 bits): /etc/letsencrypt/keys/0002_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0002_csr-certbot.pem

 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/ Your
   cert will expire on 2017-08-11. To obtain a new or tweaked version
   of this certificate in the future, simply run certbot-auto again.
   To non-interactively renew *all* of your certificates, run
   "certbot-auto renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:
   Donating to EFF:          

The last step is obvious, replace your old NGINX SSL settings with the new one :).


server {
   ssl_certificate /etc/letsencrypt/live/;
   ssl_certificate_key /etc/letsencrypt/live/;

And systemctl restart nginx!


I wrote a complete guide on web application deployment. Ruby with Puma, Python with Gunicorn, NGINX, PostgreSQL, Redis, networking, processes, systemd, backups, and all your usual suspects.

More →