From c370ff8248a1b7e547f1bc51ccf4d044eddcb796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Thu, 25 Jun 2026 09:07:24 +0300 Subject: [PATCH] =?UTF-8?q?fix(ops):=20=D0=B7=D0=B0=D0=BA=D1=80=D1=8B?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BF=D0=BE=D0=B2=D1=82=D0=BE=D1=80=20=D0=BA?= =?UTF-8?q?=D0=B2=D0=B8=D1=80=D0=BA=D0=B0=20107=20=E2=80=94=20optimize=20?= =?UTF-8?q?=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=D0=B4=D0=BD=D0=B8=D0=BC=20=D0=B2?= =?UTF-8?q?=20redeploy=20+=20=D0=B2=D0=B0=D0=BB=D0=B8=D0=B4=D0=B0=D1=82?= =?UTF-8?q?=D0=BE=D1=80=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D1=8F=D0=B5?= =?UTF-8?q?=D1=82=20=D1=87=D0=B8=D1=82=D0=B0=D0=B5=D0=BC=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Проверено на боевом 25.06: config.php = ubuntu:www-data mode 775, www-data ЧИТАЕТ его через группу, портал HTTP 200 — реального дефекта НЕТ. Квирк «лечили» несколько раз, гонясь за строгой проверкой «владелец == www-data», тогда как важна читаемость. Две первопричины повтора закрыты: 1. deploy/redeploy.sh: optimize перенесён в КОНЕЦ (после chown -R ubuntu:www-data bootstrap/cache). Раньше optimize шёл ДО chown'а → chown переписывал владельца свежего config.php обратно на ubuntu. Теперь кэши пишутся после chown и остаются www-data:www-data. 2. .claude/agents/prod-deploy-validator.md П1: критерий сменён на ЧИТАЕМОСТЬ www-data (sudo -u www-data test -r config.php) вместо строгого владельца. Владелец ubuntu при группе www-data+775 больше НЕ даёт ложный NO-GO. Свежесть (mtime ≥ .env, квирк 104) сохранена. Описание квирка 107 и формат рапорта обновлены. Прод не трогали — он здоров. После следующего redeploy config.php станет www-data-owned. Co-Authored-By: Claude Opus 4.8 (1M context) --- .claude/agents/prod-deploy-validator.md | 24 ++++++++++++++++-------- deploy/redeploy.sh | 7 ++++++- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/.claude/agents/prod-deploy-validator.md b/.claude/agents/prod-deploy-validator.md index 9af4d728..cf2ad8c7 100644 --- a/.claude/agents/prod-deploy-validator.md +++ b/.claude/agents/prod-deploy-validator.md @@ -41,7 +41,7 @@ Symptom: `queue:work` стартует, через ~60 секунд процес ### Квирк 107 — `config:cache` не из-под `www-data` → 500 на всём портале (24.05 живой инцидент) -Symptom: HTTP 500 на главной + во всех путях, в `storage/logs/laravel.log` пусто или «file not found» для cache. Cause: владелец `bootstrap/cache/config.php` ≠ `www-data` → PHP-FPM под `www-data` не может прочитать кэш → fallback на defaults → APP_KEY=NULL и DB=sqlite. Фикс: `sudo -u www-data php artisan config:cache`. +Symptom: HTTP 500 на главной + во всех путях, в `storage/logs/laravel.log` пусто или «file not found» для cache. Cause: PHP-FPM под `www-data` **не может прочитать** `bootstrap/cache/config.php` (напр. owner=root без доступа группе) → fallback на defaults → APP_KEY=NULL и DB=sqlite. **Критерий — читаемость www-data, а не строгий владелец:** штатный `ubuntu:www-data` mode `775` читаем группой и НЕ вызывает 500 (проверено 25.06: портал HTTP 200). Фикс при NOT_READABLE: `sudo -u www-data php artisan config:cache` (пере-кэш под www-data) либо `sudo chmod 775 bootstrap/cache/config.php` + группа www-data. ### Квирк 108 — NTFS junction для worktree node_modules @@ -51,22 +51,30 @@ Symptom: HTTP 500 на главной + во всех путях, в `storage/lo Каждая проверка — это одна SSH-команда + ожидаемый формат вывода + критерий зелёного. Если вывод не совпадает с ожидаемым форматом — это автоматически NO-GO + эскалация. -### П1 — `bootstrap/cache/config.php` владелец и свежесть (Квирк 107, самый важный) +### П1 — `bootstrap/cache/config.php` читаемость www-data и свежесть (Квирк 107, самый важный) + +**ВАЖНО (исправлено 25.06.2026):** реальный корень инцидента 24.05 — PHP-FPM под `www-data` +**не смог ПРОЧИТАТЬ** cache-файл (был owner=root без доступа группе). Поэтому критерий — +**читаемость www-data**, а НЕ строгое «владелец == www-data». redeploy.sh штатно оставляет +config.php как `ubuntu:www-data` mode `775` — www-data читает его через группу, портал +работает (HTTP 200). Прежняя строгая проверка владельца давала **ложный NO-GO** (квирк +«лечили» зря несколько раз). Проверяем то, что реально важно: может ли www-data читать. ```bash -ssh -o ConnectTimeout=10 liderra "stat -c '%U %Y' /var/www/liderra/app/bootstrap/cache/config.php 2>/dev/null; stat -c '%Y' /var/www/liderra/app/.env 2>/dev/null" +ssh -o ConnectTimeout=10 liderra "sudo -u www-data test -r /var/www/liderra/app/bootstrap/cache/config.php && echo READABLE || echo NOT_READABLE; stat -c '%U:%G %a %Y' /var/www/liderra/app/bootstrap/cache/config.php 2>/dev/null; stat -c '%Y' /var/www/liderra/app/.env 2>/dev/null" ``` -Ожидаемый формат — 2 строки: +Ожидаемый формат — 3 строки (1-я — вердикт читаемости, 2-я — владелец:группа режим mtime, 3-я — mtime .env): ``` -www-data 1234567890 +READABLE +ubuntu:www-data 775 1234567890 1234567880 ``` -Зелёный = (1) владелец `www-data` И (2) mtime config.php ≥ mtime .env. +Зелёный = (1) `READABLE` (www-data может прочитать config.php) И (2) mtime config.php ≥ mtime .env. -Красный = владелец ≠ `www-data` ИЛИ mtime config.php < mtime .env ИЛИ файл config.php отсутствует. Цитировать квирк 107 в reason. +Красный = `NOT_READABLE` (www-data НЕ может прочитать — настоящий риск 500) ИЛИ mtime config.php < mtime .env (квирк 104 — stale cache) ИЛИ файл config.php отсутствует. Цитировать квирк 107 в reason. NB: владелец `ubuntu` сам по себе **НЕ** красный, если файл читаем группой www-data. ### П2 — `.env` line endings (квирк 105) @@ -173,7 +181,7 @@ ssh liderra "cd /var/www/liderra/app && php artisan migrate:status 2>&1 | grep - === PROD-DEPLOY-VALIDATOR RAPORT === Brief: <из входных данных> Проверки: - П1 config:cache владелец [GREEN / RED] — <вывод | причина> + П1 config.php читаем www-data [GREEN / RED] — <вывод | причина> П2 .env line endings [GREEN / RED] — <вывод | причина> П3 свободное место [GREEN / RED] — <вывод | причина> П4 свежесть бэкапа БД [GREEN / RED] — <вывод | причина> diff --git a/deploy/redeploy.sh b/deploy/redeploy.sh index 3c917865..07dc68f6 100644 --- a/deploy/redeploy.sh +++ b/deploy/redeploy.sh @@ -14,9 +14,14 @@ sudo chown -R www-data:www-data vendor # НЕ применяются ("must be owner") — применять ВРУЧНУЮ под `sudo -u postgres` ДО запуска # скрипта + INSERT в migrations, тогда строка ниже = no-op. Иначе set -e порвёт деплой. php artisan migrate --force -sudo -u www-data php artisan optimize sudo chmod -R a+rX public/build sudo chown -R ubuntu:www-data storage bootstrap/cache sudo chmod -R 775 storage bootstrap/cache +# optimize ПОСЛЕДНИМ под www-data: до 25.06 он стоял ДО chown'а выше, и chown -R +# на bootstrap/cache переписывал владельца свежесозданного config.php обратно на +# ubuntu (квирк 107 «лечили» зря несколько раз). Теперь optimize пишет кэши +# (config/route/event/view) ПОСЛЕ chown — они остаются www-data:www-data. +# (Портал работал и так — www-data читал config.php через группу+775 — но так чище.) +sudo -u www-data php artisan optimize sudo systemctl restart php8.3-fpm liderra-queue echo "Redeploy done at $(date -u +%FT%TZ)"