Recraftory

Setup Certbot Menggunakan Docker

docker-compose.yml


services:
  nginx:
    image: nginx:1.29
    container_name: nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./nginx/html:/usr/share/nginx/html
      - ./nginx/logs:/var/log/nginx
      - ./certbot/www:/var/www/certbot
      - ./certbot/conf:/etc/letsencrypt
    restart: unless-stopped
    networks:
      - app-network

  certbot:
    image: certbot/certbot
    container_name: certbot
    volumes:
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
    networks:
      - app-network

networks:
  app-network:
    driver: bridge
  1. Set nginx untuk server http saja (port 80), but vhost dengan config berikut
server {
    listen 80;
    server_name example.com

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

Ini penting karena certbot akan melakukan validasi http ke url http://example.com/.well-known/acme-challenge/[code] dan restart docker contianer.

  1. buat certificate
#!/bin/bash

domains=(example.com)
email="email@user.com"

docker compose up -d nginx

for domain in "${domains[@]}"; do
  docker compose -f docker-compose.yml run --rm --entrypoint "\
    certbot certonly --webroot -w /var/www/certbot \
      --email $email \
      -d $domain \
      --rsa-key-size 4096 \
      --agree-tos \
      --non-interactive \
      --force-renewal" certbot
done
  1. setelah certificate berhasil dibuat, update nginx config untuk server https (port 443)

server {
    listen 80;
    server_name example.com;

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

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


server {
    listen 443 ssl;
    listen [::]:443;
    server_name example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
}