diff --git a/README.md b/README.md index eb37542..d8b2997 100644 --- a/README.md +++ b/README.md @@ -174,3 +174,13 @@ Container images are configured using parameters passed at runtime. same domain counts against them; test changes against `--server https://acme-staging-v02.api.letsencrypt.org/directory` before letting a loop retry every 12 hours. +- **Nothing here needs a capability, and after `--logs-dir` nothing writes + outside its volumes.** The container never changes user, the files it touches + are its own, and the ACME challenge is served on 380 rather than a privileged + port, so `cap_drop: ALL` costs it nothing. The log used to be the exception: + `/var/log/letsencrypt`, on the root filesystem. It now goes to the + `letsencrypt` volume beside the rest of the state, which is what makes + `read_only: true` possible and what keeps the log of a failed renewal after + the container is replaced. Give the service a `stop_grace_period` too -- a + signal arriving while a pass is issuing is deferred until that pass returns, + and an issuance can outlast docker's ten seconds. diff --git a/README.ru-RU.md b/README.ru-RU.md index 1568912..8d162f5 100644 --- a/README.ru-RU.md +++ b/README.ru-RU.md @@ -179,3 +179,13 @@ docker push registry.bitdeals.org/certbot выпуска на один домен в них засчитываются; проверяйте изменения на `--server https://acme-staging-v02.api.letsencrypt.org/directory`, прежде чем оставлять цикл повторять их каждые 12 часов. +- **Ни одна capability здесь не нужна, а после `--logs-dir` не остаётся и + записи за пределы томов.** Контейнер не меняет пользователя, трогает только + свои файлы, а ACME-челлендж отдаёт на порту 380, а не на привилегированном, + поэтому `cap_drop: ALL` ему ничего не стоит. Исключением был журнал: + `/var/log/letsencrypt` на корневой файловой системе. Теперь он пишется в том + `letsencrypt`, рядом с остальным состоянием, и именно это делает возможным + `read_only: true` и сохраняет журнал неудавшегося продления после замены + контейнера. Задайте сервису и `stop_grace_period`: сигнал, пришедший во время + выпуска, откладывается до конца прохода, а выпуск умеет тянуться дольше + десяти секунд, которые даёт docker. diff --git a/docker/scripts/1-ensure-cert.sh b/docker/scripts/1-ensure-cert.sh index 52f48c2..9d78027 100644 --- a/docker/scripts/1-ensure-cert.sh +++ b/docker/scripts/1-ensure-cert.sh @@ -74,8 +74,17 @@ if [ -n "$CERTBOT_DOMAIN" ]; then # changed list updates that certificate instead of starting a second one # beside it; with the lineage named, certbot needs no --expand to accept an # added name non-interactively. + # + # --logs-dir moves certbot's log out of /var/log on the root filesystem and + # into the volume the rest of its state already lives in. Two things follow. + # The container can be run with `read_only: true`, which the log was the only + # thing standing in the way of. And the log of a renewal that failed outlives + # the container, which matters here more than anywhere else: this is the one + # service whose breakage surfaces sixty days later, and the log is what says + # why. certbot certonly --standalone \ --non-interactive --agree-tos --http-01-port=380 \ + --logs-dir /etc/letsencrypt/logs \ "$@" \ --cert-name "${CERTBOT_DOMAIN%%,*}" \ --keep-until-expiring \