No description
Find a file
2026-07-09 23:42:15 +00:00
.env.example init 2026-07-10 03:41:54 +04:00
.gitignore init 2026-07-10 03:41:54 +04:00
deploy-hook.sh init 2026-07-10 03:41:54 +04:00
docker-compose.yml init 2026-07-10 03:41:54 +04:00
expand.sh init 2026-07-10 03:41:54 +04:00
issue.sh init 2026-07-10 03:41:54 +04:00
README.md init 2026-07-10 03:41:54 +04:00

certbot — автоматический выпуск и обновление Let's Encrypt сертификатов

Самодостаточный compose-модуль: выпускает один SAN-сертификат (HTTP-01, webroot) на все домены из .env и обновляет его каждые 12 часов. После успешного обновления перезагружает nginx в соседнем compose-проекте через Docker Engine API (unix-socket), без docker-cli и без кастомного образа.

Состав

Файл Назначение
docker-compose.yml сервис certbot (цикл renew каждые 12 ч) + named volumes letsencrypt, certbot-webroot
.env.example шаблон конфигурации (DOMAINS, LE_EMAIL, NGINX_CONTAINER)
issue.sh первый выпуск сертификата; принимает доп. флаги certbot (--staging, --force-renewal, …)
expand.sh добавление домена: дописывает в .env и перевыпускает с --expand
deploy-hook.sh хук certbot: nginx -s reload через docker.sock

Имя сертификата фиксировано первым доменом из DOMAINS (--cert-name whitera.space), поэтому пути в nginx-конфигах (/etc/letsencrypt/live/whitera.space/…) не меняются при добавлении доменов.

Настройка стороны nginx

1. Volumes в compose-проекте nginx

Оба volume создаются этим модулем с фиксированными именами — в nginx-проекте подключайте их как external, только на чтение:

services:
  nginx:
    # ...
    volumes:
      - letsencrypt:/etc/letsencrypt:ro
      - certbot-webroot:/var/www/certbot:ro

volumes:
  letsencrypt:
    external: true
  certbot-webroot:
    external: true

Монтировать нужно весь /etc/letsencrypt, а не только live/: в live/ лежат симлинки на archive/, и без него они «повиснут».

2. ACME-challenge в каждом HTTP(80) server-блоке

Location должен стоять до редиректа на https:

server {
    listen 80;
    server_name whitera.space git.whitera.space ts.whitera.space;

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

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

3. Миграция с хостового bind-mount

Если сертификаты уже есть на хосте в /etc/letsencrypt, скопируйте их внутрь volume один раз — тогда первый выпуск не нужен, renew подхватит существующие:

# volume должен уже существовать: docker compose up -d (или docker volume create letsencrypt)
docker run --rm \
  -v letsencrypt:/dst \
  -v /etc/letsencrypt:/src:ro \
  alpine cp -a /src/. /dst/

cp -a сохраняет симлинки live/ -> archive/ и права на приватные ключи. После копирования уберите старый bind-mount /etc/letsencrypt из compose nginx и замените на external volume (см. п. 1).

Либо чистый старт: certbot delete не нужен — просто выпустите заново в пустой volume через issue.sh.

Первый запуск

cp .env.example .env      # заполнить DOMAINS и LE_EMAIL
docker compose up -d      # создаёт volumes и запускает цикл renew

# 1. Пробный выпуск на staging (не тратит rate-limit Let's Encrypt):
./issue.sh --staging

# 2. Боевой выпуск (перезаписывает staging-сертификат):
./issue.sh --force-renewal

# 3. Проверка, что автообновление сработает:
docker compose run --rm --entrypoint certbot certbot renew --dry-run

Порядок важен: сначала должен быть настроен nginx (volumes + acme-location из разделов выше), иначе HTTP-01 challenge не пройдёт.

Добавление домена

./expand.sh new.whitera.space

Скрипт допишет домен в DOMAINS в .env и перевыпустит сертификат с --expand. Имя сертификата (и пути live/whitera.space/) не изменятся. Не забудьте добавить новый домен в server_name nginx и DNS A-запись заранее.

Как работает перезагрузка nginx

deploy-hook.sh монтируется в контейнер certbot и вызывается после каждого успешного обновления. Внутри — два запроса к Docker Engine API через /var/run/docker.sock (exec create + exec start), эквивалент docker exec $NGINX_CONTAINER nginx -s reload. Если в образе certbot нет curl, хук доставит его через apk add (требуется выход в интернет из контейнера).

Отладка

docker compose logs -f certbot                 # цикл renew
docker volume inspect letsencrypt              # где лежат сертификаты
docker compose run --rm --entrypoint certbot certbot certificates   # список сертификатов