The default certbot certonly –standalone is quite useful for a quick start to run a standalone server and get the SSL certificate. But nowadays everyone is running their own server. Which would cause the issue of binding port 80 fail. In order to fix this would be using –webroot instead.

Firstly, create a new folder for nginx to serve static file

mkdir -p /var/www/letsencrypt/.well-known/acme-challenge

Secondly, in each server config that you want to have SSL add the followings, E.g. inside into the server listen 80 block.

location ^~ /.well-known/acme-challenge/ {
root /var/www/letsencrypt;

It tells nginx when matching path /.well-known/acme-challenge/, go to /var/www/letsencrypt/.well-known/acme-challenge/ to find the file.

Thirdly, run nginx reload and

certbot certonly --webroot --webroot-path /var/www/letsencrypt/ --agree-tos -m -d yourdomain

Letsencrypt will put a text file inside /var/www/letsencrypt/.well-known/acme-challenge and fire a get request to achieve it in order to finish the justification. You can tail the nginx log to see the requests to debug.

Fourthly, you add the listen 443 block into your domain’s nginx config file

listen 443;
ssl on;
ssl_certificate /etc/letsencrypt/live/;
ssl_certificate_key /etc/letsencrypt/live/;
ssl_prefer_server_ciphers On;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

Lastly, create a cron job task file in /etc/cron.d/

@monthly root /bin/bash -c "/usr/bin/letsencrypt certonly --webroot -w /var/www/letsencrypt -d"

Hope that helps!