feat: put the log in the volume, so the container can be read-only
Build docker image and push to registry.bitdeals.org / main-build-job (push) Successful in 1m4s
Build docker image and push to registry.bitdeals.org / main-build-job (push) Successful in 1m4s
/var/log/letsencrypt was the only thing this image wrote outside its volumes, and it is what stopped `read_only: true` from working. --logs-dir moves it to /etc/letsencrypt/logs, beside the account key and the renewal config it already keeps there. The second gain is the one that matters more here. This is the service whose breakage does not announce itself: a renewal that stops working is an expired certificate sixty days later, and the log is what says why. On the root filesystem it died with every container the registry replaced; in the volume it outlives them. Nothing else about the container needs to change to be confined. It never changes user, the files it touches are its own, the ACME challenge is served on 380 rather than a privileged port, and the HAProxy runtime socket it writes to is group-owned by root -- so it reaches it by permission rather than by CAP_DAC_OVERRIDE, and `cap_drop: ALL` takes nothing away. Measured on the live relay: no file under /etc/letsencrypt or /etc/certificates is owned by anyone but root, and the socket is srw-rw---- 1001:0. Both READMEs say what a caller should set now, stop_grace_period included -- the entrypoint has asked for that one since it was written.
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 \
|
||||
|
||||
Reference in New Issue
Block a user