From 630f3e6e766b3bff2452b8e561ad978ef8d9e13d Mon Sep 17 00:00:00 2001 From: bot-backend Date: Thu, 27 Aug 2026 12:58:15 +0300 Subject: [PATCH] =?UTF-8?q?fix(observability):=20=D0=BA=D0=BE=D0=BD=D1=84?= =?UTF-8?q?=D0=B8=D0=B3=20Alertmanager=20=D1=87=D0=B8=D1=82=D0=B0=D0=B5?= =?UTF-8?q?=D1=82=D1=81=D1=8F=20=D0=BA=D0=BE=D0=BD=D1=82=D0=B5=D0=B9=D0=BD?= =?UTF-8?q?=D0=B5=D1=80=D0=BE=D0=BC=20=E2=80=94=20=D0=B3=D0=B5=D0=B9=D1=82?= =?UTF-8?q?=20=D0=BF=D0=B0=D0=B4=D0=B0=D0=BB=20=D0=BD=D0=B0=20=D1=81=D0=B2?= =?UTF-8?q?=D0=BE=D0=B8=D1=85=20=D0=B6=D0=B5=20=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B0=D1=85=20(#3078)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Как только канал алертов реально включился (#3126), профиль alerts впервые дошёл до проверки конфига — и деплой встал: amtool: error: failed to validate 1 file(s) Checking '/tmp/am.yml' FAILED: open /tmp/am.yml: permission denied Отрендеренный конфиг пишется с правами 600 и принадлежит деплой-пользователю, а и amtool, и сам Alertmanager в образе prom/alertmanager работают под nobody (65534). Прочитать чужой файл 600 они не могут. Проверка падала не на содержимом конфига, а на доступе к нему — и контейнер после подъёма упал бы ровно там же. Дефект не поймали раньше по понятной причине: без токена профиль alerts не включался, и эта ветка не исполнялась НИ РАЗУ с момента появления гейта в #3111. Проверка, которая никогда не запускалась, ничем не отличается от отсутствующей — это ровно тот класс тихой поломки, ради которого весь стек и заводится. Права не ослабляем: в файле лежит токен бота. Вместо chmod 644 (который внёс бы токен в список файлов, читаемых любым локальным пользователем машины) отдаём файл во владение 65534 одноразовым контейнером от root — passwordless sudo на хосте нет, а бинд-маунт правит host-инод напрямую. Доступ остаётся ровно у того, кто конфиг читает. Следствие, которое легко проглядеть: после смены владельца `>` в этот файл на следующем деплое уже не запишет, поэтому добавлен rm перед рендером — каталог принадлежит деплой-пользователю, пересоздать файл он может. --- .forgejo/workflows/deploy-metrics.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.forgejo/workflows/deploy-metrics.yml b/.forgejo/workflows/deploy-metrics.yml index 336f322a..ce23046c 100644 --- a/.forgejo/workflows/deploy-metrics.yml +++ b/.forgejo/workflows/deploy-metrics.yml @@ -153,11 +153,33 @@ jobs: METRICS_TELEGRAM_BOT_TOKEN="$METRICS_TELEGRAM_BOT_TOKEN" \ METRICS_TELEGRAM_CHAT_ID="$METRICS_TELEGRAM_CHAT_ID" \ METRICS_TELEGRAM_TOPIC_LINE="$METRICS_TELEGRAM_TOPIC_LINE" \ + # rm перед записью обязателен: после chown ниже файл принадлежит + # 65534 с правами 600, и на СЛЕДУЮЩЕМ деплое `>` в него уже не + # запишет. Каталог принадлежит деплой-пользователю, поэтому + # пересоздать файл он может, а перезаписать — нет. + rm -f ops/metrics/alertmanager/alertmanager.yml envsubst '${METRICS_TELEGRAM_BOT_TOKEN} ${METRICS_TELEGRAM_CHAT_ID} ${METRICS_TELEGRAM_TOPIC_LINE}' \ < ops/metrics/alertmanager/alertmanager.yml.tmpl \ > ops/metrics/alertmanager/alertmanager.yml chmod 600 ops/metrics/alertmanager/alertmanager.yml + # В файле лежит токен бота, поэтому 600 не ослабляем. Но и amtool + # ниже, и сам Alertmanager в образе prom/alertmanager работают под + # `nobody` (65534) и файл владельца-деплойщика прочитать не могут: + # проверка падала на `open /tmp/am.yml: permission denied`, а + # контейнер после подъёма упал бы ровно там же. Гейт не поймали + # раньше только потому, что без токена профиль alerts вообще не + # включался и эта ветка не исполнялась ни разу. + # + # Отдаём файл тому, кто его читает. chown делаем одноразовым + # контейнером от root: passwordless sudo на хосте нет, а + # бинд-маунт правит host-инод напрямую. + # + # Почему не 644: это внесло бы токен в список файлов, читаемых + # любым локальным пользователем машины. Владение 65534 при 600 + # оставляет доступ ровно у контейнера, и ни у кого больше. + docker run --rm --user 0:0 -v "$PWD/ops/metrics/alertmanager/alertmanager.yml:/tmp/am.yml" --entrypoint chown "$(grep -oE 'prom/alertmanager:[^ ]+' docker-compose.metrics.yml | head -1)" 65534:65534 /tmp/am.yml + # Проверяем ДО подъёма, как и Caddyfile ниже. Битый конфиг # Alertmanager не «деградирует» — контейнер не стартует вовсе, и # алертинг молча исчезает целиком. amtool берём из того же образа,