diff --git a/.wiki/concepts/books-vds-no-gitea-actions.md b/.wiki/concepts/books-vds-no-gitea-actions.md index 98f1fa5..7b5a4a5 100644 --- a/.wiki/concepts/books-vds-no-gitea-actions.md +++ b/.wiki/concepts/books-vds-no-gitea-actions.md @@ -20,10 +20,21 @@ tags: [books-vds, ci, gitea-actions, build, decision] ## Процедура локальной сборки + публикации (проверена 2026-08-23) 1. `git archive | tar -x -C /c/tmp/build` (чистый контекст, без node_modules/.git) 2. `VERDACCIO_TOKEN= docker build --secret id=verdaccio_token,env=VERDACCIO_TOKEN -f packages//Dockerfile -t : .` -3. `docker save` → tar (OCI layout: `index.json` + `blobs/sha256/*`) +3. `docker save` → tar. **Docker 29 на этой машине сразу отдаёт OCI-layout** (`oci-layout` + `index.json` + `blobs/sha256/*`) — конвертация не нужна, `--format oci` отсутствует и не требуется. `index.json` → OCI **index** (multi-arch: amd64 child + attestation `platform: unknown/unknown`). Дочерний **amd64-манифест** лежит в `blobs/sha256/` (прочитать index-блоб, взять `manifests[]` с `platform.architecture == 'amd64'`). 4. Заливка блобов curl'ом: HEAD-check → если нет — `POST /v2//blobs/uploads/` → `PUT &digest=sha256:` с телом (монолитный, Content-Length). Большой слой: `cat blob | curl -X PATCH -T -` (chunked) + финальный `PUT &digest` (Location брать из PATCH-ответа). Перед большим чтением файла — `sync; echo 3 > /proc/sys/vm/drop_caches` (books-vds 3.9GB RAM → OOM на 2GB файле). 5. Манифест: если `index.json` → OCI index (multi-arch, у Docker Desktop так) — **класть дочерний amd64-манифест** (`application/vnd.oci.image.manifest.v1+json`), не индекс (реестр: MANIFEST_INVALID). 6. Креды реестра: `docker login registry.kzntsv.site -u books-ci --password-stdin` (актуальный пароль books-ci — в `/opt/books/sched/docker-config.json` на books-vds; в `/root/.docker/config.json` был УСТАРЕВШИЙ → 401 на push). ## Gotcha: большие пуши через traefik умирают `docker buildx --push` 1.5-2GB слоёв через `registry.kzntsv.site` (traefik buffering middleware `maxRequestBodyBytes=4GB`) → `Client Closed Request`: traefik буферизует тело в RAM vds-kzntsv (1GB free) + чтение с buildkit-кэша медленное + OOM. curl монолитными PUT/PATCH работает (54MB/s). Связано: [[registry-traefik-buffering-gotcha]]. + +## Деплой: Portainer PUT gotchas (2026-08-23, деплой master-a448cad) + +**`PUT /api/stacks/?endpointId=1` — синхронный и тянет образ ВНУТРИ запроса** (676МБ с registry через интернет = минуты). Клиентский таймаут (90с urllib) рвёт ожидание, но операция НЕ отменяется — Portainer доделывает server-side (файл стека обновляется, pull идёт, контейнер пересоздаётся). Правильный флоу: `PUT` с timeout 900+, при обрыве — НЕ пере-PUT (задвоит деплой), а проверить контейнеры: + +``` +GET /api/endpoints/1/docker/containers/json?all=1 # фильтр по Names: books-web / bookva-web → Image + Status +GET /api/endpoints/1/docker/images/json # образ уже на VDS? (показывает in-flight pull) +``` + +Смоук/верификация: `DELETE /api/fbs/pickingLists/:id` → `{taskId}`, статус `GET /api/fbs/tasks/`, run в sched daemon: `docker exec books-sched node -e 'fetch("http://localhost:3031/api/runs?task=&limit=3",{headers:{"Authorization":"Bearer "}})...'` (**curl в контейнере нет**, node fetch есть; ключ — из env стека). Nuxt-прокси `/admin/scheduler/**` для внешних проверок бесполезен: гейтится `requireAdmin` (JWT isAdmin), `?token=` API-ключ → 403. diff --git a/.wiki/index.md b/.wiki/index.md index 1d914d7..260e17c 100644 --- a/.wiki/index.md +++ b/.wiki/index.md @@ -21,7 +21,7 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever - [windows-recovery-host](entities/windows-recovery-host.md) — Windows Recovery Host (рабочий PC пользователя) ## Concepts -- [books-vds-no-gitea-actions](concepts/books-vds-no-gitea-actions.md) — решение vitya 2026-08-23: Gitea Actions выпилены везде (books+vds-ops-mcp workflow удалены, раннер books-vds вычищен), сборка только локально (docker build+curl-upload, OCI-index→amd64 child), большие пуши через traefik умирают (Client Closed Request) +- [books-vds-no-gitea-actions](concepts/books-vds-no-gitea-actions.md) — решение vitya 2026-08-23: Gitea Actions выпилены везде (books+vds-ops-mcp workflow удалены, раннер books-vds вычищен), сборка только локально (docker build+curl-upload, OCI-index→amd64 child; docker save сразу даёт OCI), деплой Portainer PUT (синхронный, тянет образ внутри запроса), смоук sched через docker exec node fetch; большие пуши через traefik умирают (Client Closed Request) - [registry-traefik-buffering-gotcha](concepts/registry-traefik-buffering-gotcha.md) — большие (>1.5GB) пуши в registry через traefik buffering middleware (4GB) умирают: traefik буферизует body в RAM (1GB free) + OOM на books-vds; обход — curl монолитными PUT / PATCH стримом + finalize, drop_caches перед большим ридом - [config-custom-env-mapping-in-mounted-dirs](concepts/config-custom-env-mapping-in-mounted-dirs.md) — npm config: env читается только если custom-environment-variables.json лежит в ПРИМОНТИРОВАННОМ конфиг-дире (маунт затеняет образ); mapping не создаёт свойство без env; проверка docker exec с правильным cwd - [sched-runtime-to-file-managed-migration](concepts/sched-runtime-to-file-managed-migration.md) — перевод sched slovo+bookva на file-managed (durable config, #991): почему runtime хрупкий (расписания в памяти демона, сироты без data), рецепт миграции (файл in-place → live-sync НЕ конвертирует runtime → DELETE /tasks+/schedules → verify), gotchas (id=taskName vs UUID, ghost-таски, task-runner config кэш→рестарт, SMTP from==auth, URL-encode) diff --git a/.wiki/log.md b/.wiki/log.md index 0010810..f5d2c32 100644 --- a/.wiki/log.md +++ b/.wiki/log.md @@ -13,6 +13,7 @@ ## [2026-08-12] implement | NEW concepts/keenetic-rci-api.md — разобрана автоматизация KeeneticOS 5.1.3 (RCI: GET /rci/show/*, POST /rci/ массив parse-команд). Через API добавлены DNS-записи git.kreknin.site/kreknin.site → 192.168.1.43 (решение сломанного hairpin). Проверено с LAN: всё 200. Правила порт-форвардинга в 5.x лежат в ip.static (to-host=MAC). ## [2026-08-12] implement | UPDATE entities/kreknin-synology.md — Gitea 1.27.1 + postgres 16 на kreknin (для Алексея), traefik починен (restart policy), LE-серт git.kreknin.site, проброс 80/443→8000/4443 на Keenetic. KeeneticOS Viva API закрыт — правила в GUI. NAT loopback сломан → нужен DNS-override git.kreknin.site→192.168.1.43. Пароли: pass kreknin/keenetic + pass kreknin/gitea. # Wiki op-log +## [2026-08-23] ingest | UPDATE concepts/books-vds-no-gitea-actions.md — деплой books-web `master-a448cad` (фикс 8 embed-api роутов, оба тенанта, инцидент DELETE-404 закрыт). Уроки в ранбук: (1) `docker save` на Docker 29 сразу даёт OCI-layout (index.json+blobs) — конвертация не нужна, amd64 child manifest в `blobs/sha256/`; (2) `PUT /api/stacks/` синхронный, тянет образ ВНУТРИ запроса — клиентский таймаут рвёт ожидание, оп доделывается server-side, НЕ пере-PUT, проверять контейнеры через `/api/endpoints/1/docker/containers/json` + images/json; (3) смоук sched: `docker exec node -e fetch(localhost:3031/api/runs)` (curl в контейнере нет), Nuxt `/admin/scheduler/**` требует JWT isAdmin — `?token=` 403. Процедура сборки шаг 3 уточнён. ## [2026-08-23] ingest | NEW concepts/sched-ozon-creds-stub-contract.md — контракт кредов Ozon slovo/bookva: мисматч-пары в обеих БД — намеренные заглушки (анти-утечка после tenant-split). Урок: .admin «починил» заглушку (slovo seller 1 ← bookva-ключ) → откат 12:07Z по подтверждению владельца; зеркальная заглушка bookva seller 2 (12:15Z). Безопасность: break-on-error 2a38fb5 задеплоен (фейл-фаст без спина). verify по SHA2 (d6227b = slovo-ключ, f700f3 = bookva-ключ). НЕ чинить. Связано: инцидент 2026-08-23, перевод slovo → file-managed (887bbae). ## [2026-08-14] ingest | NEW concepts/snolla-smtp-mail-delivery-2026-08.md — postmortem SMTP-инцидента 12–14.08: 525 SMTP disabled (Яндекс 360, доменка) → переезд на e-16513832@yandex.ru (app-password); 554 SPAM на 2+ получателях от холодного ящика → @snolla/mailer@0.9.0 per-recipient (forms-api 0.2.0, web 0.44.0); 550 from not owned → mailSettings.from во всех production.json + шаблон pilorama98checkoutconfirm. Монитор SMTP на VDS (cron 08:00, ntfy) + parity-чек Portainer env. Рецепт деплоя тиража (порядок, гочи: ad-hoc контейнер vs Portainer, regex-парсинг image, yarn up -R data).