From f30820bb9ab16360cd077591c4e0d3742b958639 Mon Sep 17 00:00:00 2001 From: bot-backend Date: Tue, 18 Aug 2026 09:42:53 +0300 Subject: [PATCH] =?UTF-8?q?fix(infra/caddy):=20site-=D0=B1=D0=BB=D0=BE?= =?UTF-8?q?=D0=BA=D0=B8=20=D1=81=20=D1=81=D0=B5=D0=BA=D1=80=D0=B5=D1=82?= =?UTF-8?q?=D0=B0=D0=BC=D0=B8=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B6=D0=B8=D0=B2?= =?UTF-8?q?=D0=B0=D1=8E=D1=82=20=D0=B4=D0=B5=D0=BF=D0=BB=D0=BE=D0=B9=20?= =?UTF-8?q?=E2=80=94=20import=20caddy/local/*.caddy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Деплой делает `git reset --hard origin/main`, поэтому любой site-блок, вписанный руками в /opt/gendesign/Caddyfile, живёт до первого пуша в main. 16.08 так и вышло с garmin.gendsgn.ru: контейнер остался healthy, а хост исчез из конфига — TLS-хендшейк стал падать `alert internal error`, потому что сертификат для него Caddy больше не держит. Класть такой блок в git нельзя: у него единственный рубеж аутентификации — секрет в пути URL (апстрим-MCP аутентификации не имеет, а claude.ai connector кастомные заголовки не шлёт). Развязка: в репозитории только `import caddy/local/*.caddy` и сам каталог (держится .gitignore'ом), файлы с секретами лежат на VPS untracked — reset --hard их не трогает. Пустой glob для Caddy не ошибка, `caddy validate` проходит, на машинах без локальных блоков import — no-op. Проверено `caddy validate` 2.11.4 на VPS: и с пустым каталогом, и с реальным блоком garmin — Valid configuration. --- Caddyfile | 16 ++++++++++++++++ caddy/local/.gitignore | 4 ++++ docker-compose.prod.yml | 4 ++++ 3 files changed, 24 insertions(+) create mode 100644 caddy/local/.gitignore diff --git a/Caddyfile b/Caddyfile index a43e8e9d..f5208996 100644 --- a/Caddyfile +++ b/Caddyfile @@ -504,3 +504,19 @@ git.gendsgn.ru { } } # Test deploy flow 2026-05-15T21:43:32Z + +# ───────────────────────────────────────────────────────────────────────────── +# Локальные site-блоки, которых не может быть в git. +# +# Мотив: garmin.gendsgn.ru (личный remote MCP на этом же VPS). Апстрим-сервер +# аутентификации не имеет вовсе, а claude.ai custom connector ходит на голый URL +# без кастомных заголовков — единственный доступный рубеж это секрет в пути. +# Секрет в git класть нельзя, а блок, вписанный руками прямо сюда, сносится +# первым же деплоем (`git reset --hard origin/main`; 2026-08-16 так и вышло — +# контейнер остался жив, но хост пропал вместе со своим сертификатом). +# +# Поэтому: сам блок лежит на VPS как untracked `caddy/local/*.caddy` (reset +# --hard untracked не трогает), а в репозитории живёт только этот import. +# Пустой glob для Caddy не ошибка — `caddy validate` проходит, на машинах без +# локальных блоков строка просто ничего не делает. +import caddy/local/*.caddy diff --git a/caddy/local/.gitignore b/caddy/local/.gitignore new file mode 100644 index 00000000..f4e427bf --- /dev/null +++ b/caddy/local/.gitignore @@ -0,0 +1,4 @@ +# Локальные site-блоки Caddy с секретами (см. import в конце Caddyfile). +# Кладутся руками на VPS и намеренно не версионируются — в git только каталог. +* +!.gitignore diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 8ee650cb..ed8408d2 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -423,6 +423,10 @@ services: volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - ./caddy/users.caddy.snippet:/etc/caddy/caddy/users.caddy.snippet:ro + # Untracked локальные site-блоки (см. import в конце Caddyfile). Каталог + # держится в git через caddy/local/.gitignore — иначе docker создал бы + # отсутствующий bind-source сам, root-owned пустышкой. + - ./caddy/local:/etc/caddy/caddy/local:ro - ./preview:/srv/preview:ro - caddy_data:/data - caddy_config:/config -- 2.45.3