Certbot is a very useful tool to setup auto renewal of certificates. Here is how I’m setting up certbot and nginx quick and easy.

Initial Setup

Here is the docker-compose.yaml file with nginx and certbot

services:
  nginx:
    image: "nginx:alpine"
    container_name: app_nginx
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./platform/config/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./platform/config/certbot/www:/var/www/certbot:ro
      - ./platform/config/certbot/conf:/etc/letsencrypt:ro
    restart: always

  certbot:
    image: certbot/certbot
    container_name: app_certbot
    volumes:
      - ./platform/config/certbot/www:/var/www/certbot:rw
      - ./platform/config/certbot/conf:/etc/letsencrypt:rw

Every file that’s generated by certbot will be stored in ./platform/config/certbot

The nginx config file is stored in ./platform/config/nginx/nginx.conf

Initially we need to setup nginx with only 80 ( no ssl ) and generate certificates using certbot.

nginx.conf

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    server {
        listen 80;
        listen [::]:80;
        server_name <your_domain>;

        location /.well-known/acme-challenge/ {
            root /var/www/certbot;
        }

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

Using this config, we can run the nginx container.

Note: we may also need to change necessary permissions for the volumes. eg: sudo chmod 777 -R ./platform/config/certbot

Create certificates

Once the nginx container is running, we can run the certbot container.

docker compose run certbot certonly --webroot -webroot-path /var/www/certbot -d <your_domain>

This will generate a certificate for the domain and store it in the ./platform/config/certbot/conf/live/<your_domain> directory.

Update nginx config

Now that we have the certificate, we need to update the nginx config file.

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    server {
        listen 80;
        listen [::]:80;
        server_name <your_domain>;

        location /.well-known/acme-challenge/ {
            root /var/www/certbot;
        }

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

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

        ssl_certificate /etc/letsencrypt/live/<your_domain>/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/<your_domain>/privkey.pem;
        
        location / {
            root /usr/share/nginx/html;
            index index.html;
        }

        # Other location configs
    }
}

After updating the config, we can restart the nginx container and we have our SSL setup done.

The certbot container will keep renewing the certificates automatically.