Skip to main content

Setting up Certbot Auto-renewal for NGINX (Maintenance Mode)

Shenzhen, China

Download the Let’s Encrypt Client

First, download the Let’s Encrypt client, certbot.

apt update
apt install certbot
apt install python3-certbot-nginx

Set Up NGINX

Specify your domain name with the server_name directive:

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    root /var/www/html;
    server_name example.com www.example.com;
}

Save the file, then run this command to verify the syntax of your configuration and restart NGINX:

nginx -t && nginx -s reload

Obtain the SSL/TLS Certificate

Run the following command to generate certificates with the NGINX plug‑in:

certbot --nginx -d example.com -d www.example.com

Check Certificate

certbot certificates

Manual Update Certificate

certbot --nginx

Respond to prompts from certbot to configure your HTTPS settings, which involves entering your email address and agreeing to the Let’s Encrypt terms of service.

Automatically Renew Let’s Encrypt Certificates

Here we add a cron job to an existing Crontab file to do this:

crontab -e

Add the certbot command to run daily. In this example, we run the command every day at noon. The command checks to see if the certificate on the server will expire within the next 30 days, and renews it if so. The --quiet directive tells certbot not to generate output.

0 12 * * * /usr/bin/certbot renew --quiet

Save and close the file. All installed certificates will be automatically renewed and reloaded.

Remove a Certificate

Check the certificate name:

certbot certificates

and run the delete command:

certbot delete --cert-name example.com

Maintenance Mode

Adding a maintenance mode to your web site:

location / {
      error_page 403 = @deny;
       # allow 204.79.197.200;
       allow 204.79.197.200;
       deny all;
       proxy_pass http://127.0.0.1:6081;
}

Send all IP's to @deny that aren't whitelisted. Whitelisted IP's are forwarded regularly to your service frontend.

Options for the @deny block:

Redirect

All denied Traffic is redirected to a different domain:

location @deny {
    return 301 http://example.com/comingsoon;
}

Send String

All denied Traffic is send a string containing the WAN IP address of the accessing client - very convenient to copy the address and add to your whitelist:

location @deny {
        default_type text/html;
        return 503 '$REMOTE_ADDR :: Webshop Maintenance';
    }

Return HTML Page

Return a styled Maintenance HTML page:

location @deny {
        # Return /usr/share/nginx/html/maintenance.html
        rewrite ^(.*)$ /maintenance.html break;
    }

Combine all Domains in a Single Certificate

Delete existing certs:

certbot delete --cert-name one.example.com --cert-name one.example.de --cert-name two.example.com --cert-name two.example.de

E.g. for adding redirects (Apache this time):

nano /etc/apache2/sites-available/two.example.de.conf

<VirtualHost \*>
ServerName two.example.de
Redirect 301 / https://two.example.com/
</VirtualHost>

nano /etc/apache2/sites-available/one.example.de.conf

<VirtualHost \*>
ServerName one.example.de
Redirect 301 / https://one.example.com/
</VirtualHost>

Enable new sites:

a2ensite one.example.de.conf
a2ensite two.example.de.conf
systemctl reload apache2

And run Certbot to add the certificate:

certbot --installer apache -d one.example.com -d one.example.de -d two.example.com -d two.example.de

Error Messages

Failed to parse PID from file

Active: active (running) since Thu 2022-03-24 07:35:10 CET; 26min ago
systemd[1]: Starting A high performance web server and a reverse proxy server...
systemd[1]: nginx.service: Failed to parse PID from file /run/nginx.pid: Invalid argument
systemd[1]: Started A high performance web server and a reverse proxy server.

Add ExecStartPost=/bin/sleep 1 to NGINX service file:

nano /lib/systemd/system/nginx.service
[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=network.target nss-lookup.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecStartPost=/bin/sleep 1
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed

[Install]
WantedBy=multi-user.target
systemctl daemon-reload
service nginx restart