Compare commits

...

3 Commits

Author SHA1 Message Date
cad9f02c0e feat(deploy): pilonuxt 19a4a84 — structured-data (description/brand/return-policy) live; close redeploy-pilonuxt-gsc-structured-data
Перекат stack 16 на registry.kzntsv.site/pilonuxt:19a4a84 (build на
workstation, push, Portainer PUT pullImage). Smoke на проде через
--resolve: description непустой, brand=Пилорама 98, offers→
hasMerchantReturnPolicy/returnPolicyCategory=MerchantReturnNotPermitted,
прежние offers-поля целы, регрессий нет. Отчёт в inbox pilonuxt.

Wiki ingest: portainer-stack-management-vds — раздел Stack redeploy
(новый тег) + gotcha #9 (PS 5.1 Invoke-RestMethod декодит /file как
ISO-8859-1 → mojibake кириллицы → PUT падает YAML; fix байты+UTF8) +
#10 (пустой env). index/log обновлены.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 10:22:30 +03:00
af779a36e2 meta(handoff): pilonuxt 37412d0 deploy closed — offers live, Portainer registry fix noted
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 10:09:19 +03:00
103df9fa46 feat(deploy): pilonuxt 37412d0 — offers в микроразметку Product, GSC-фикс live
redeploy-pilonuxt-gsc-offers closed. Build workstation @37412d0 (verdaccio
build-secret) → push registry.kzntsv.site/pilonuxt:37412d0 → перекат Portainer
stack 16 (PUT API, PullImage). Acceptance: itemprop="offers" (price/currency/
availability/url) на странице товара, verified curl --resolve к VDS; меню+viewModel
200, без регрессии.

Попутно: registry.kzntsv.site зарегистрирован в Portainer (Custom Id 1) —
первый pull падал "no basic auth credentials" (Portainer не имел ни одного
registry; host docker login слетел). Теперь приватный registry авторизован
в Portainer постоянно.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 10:09:19 +03:00
6 changed files with 59 additions and 32 deletions

View File

@@ -1,33 +1,29 @@
--- ---
_last_updated_: 2026-06-15T00:35:00Z _last_updated_: 2026-06-16T14:05:00Z
session_id: 2026-06-15-pilonuxt-cutover session_id: 2026-06-16-pilonuxt-gsc-offers
--- ---
# Next session handoff # Next session handoff
## Recent commits ## Recent commits
- `67abd6fa` feat(deploy): pilonuxt 37412d0 — offers в микроразметку Product, GSC-фикс live
- `e66a8b8d` meta(tasks): create [redeploy-pilonuxt-gsc-offers]
- `b4cbb6dc` meta(tasks): решение — старый IIS 80.64.31.36 держим для отката - `b4cbb6dc` meta(tasks): решение — старый IIS 80.64.31.36 держим для отката
- `9add1ac1` feat(deploy): pilonuxt CUTOVER LIVE на www.pilorama98.ru — задача closed - `9add1ac1` feat(deploy): pilonuxt CUTOVER LIVE на www.pilorama98.ru
- `2911f2b3` feat(deploy): pilonuxt 961a838 content-api fixed, full re-smoke
- `637942e9` fix(deploy): retract false-green — content-api 500 на CMS-страницах
- `38e84ce2` feat(deploy): pilonuxt VDS Portainer stack compose
## Open треки ## Open треки
| Трек | Готовность | Entry-point | | Трек | Готовность | Entry-point |
|---|---|---| |---|---|---|
| deploy-pilonuxt-vds | 🟢 closed 2026-06-15кат живой на www.pilorama98.ru (Portainer stack 16, tag 125a3e2) | `.tasks/STATUS.md` блок + Closure note | | redeploy-pilonuxt-gsc-offers | 🟢 closed 2026-06-16`37412d0` в проде, offers-микроразметка live, smoke green | `.tasks/STATUS.md` блок + Closure note |
| (потенциальный follow-up) снять pilorama98-биндинг со старого IIS после soak | not started, ждёт отмашку vitya | STATUS follow-ups блока deploy-pilonuxt-vds | | (ждёт pilonuxt) GSC «Проверить устранение» на отчёте «Описания товара» | на стороне victor/pilonuxt | inbox `pilonuxt/.claude-inbox/...-admin.md` |
| (потенциальный follow-up) снять pilorama98-биндинг со старого IIS 80.64.31.36 после soak | not started, ждёт отмашку vitya | NEXT_SESSION 2026-06-15 guards |
## Спроси user'а ## Спроси / подтверди
- Через 1-2 дня soak'а: подтвердить что pilorama98 на новом фронте стабилен → тогда завести отдельную таску на снятие pilorama98-биндинга со старого IIS. НЕ раньше отмашки. - **Push:** коммит `67abd6fa` НЕ запушен (per-session автопуш не выдан в эту сессию). Board синкается на другие машины через Giteaстоит запушить, чтобы делегирующая сессия victor/pilonuxt увидела closure. Ждёт «разреши автопуш» / явного go.
- Опц.: нужен ли apex→www 301 canonical (легаси так делал; сейчас apex отдаёт фронт напрямую) — SEO-nicety. - НЕ выводить старый IIS 80.64.31.36 (snolla catch-all на 25 хостнеймов) — решение vitya, держим для отката pilorama98.
## Не делать (preemptive guards) ## Что усвоено за сессию (gotchas)
- **НЕ выводить старый IIS 80.64.31.36** — решение vitya: держим для отката. И целиком гасить нельзя — это snolla catch-all на 25 хостнеймов (emspb/kupimknigi/labtools/…), снимается только биндинг pilorama98. - **Portainer pull приватного образа:** в Portainer на vds-kzntsv не был зарегистрирован НИ ОДИН registry → перекат стека с `PullImage` падал `no basic auth credentials`. Прошлые каты держались на host `docker login`, который слетел. Фикс: зарегистрирован `registry.kzntsv.site` (Custom, Id 1, креды из `pass vds-kzntsv/full-env` REGISTRY_*) → Portainer инжектит auth при pull. Теперь перекаты приватных образов на vds-kzntsv работают без host-login.
- Rollback pilorama98 (если кат поедет): DNS reg.ru `pilorama98.ru`+`www``80.64.31.36`, TTL низкий. Старый сайт+cert живы. - Сохранённый `PORTAINER_API_KEY` протух (401) → auth через `POST /api/auth` admin-кредами (`PORTAINER_ADMIN_USER/PASS`).
- Стек pilonuxt = Portainer **stack 16** на vds-kzntsv; правки ТОЛЬКО через Portainer API/UI (VDS-rule, не ssh+compose). Сохранённый `PORTAINER_API_KEY` протух (401) — auth через `POST /api/auth` admin-credsами из `pass vds-kzntsv/full-env`. - pilonuxt build = на workstation (не VDS): `docker build --secret id=verdaccio_token,env=VERDACCIO_TOKEN -t registry.kzntsv.site/pilonuxt:<sha> .` из чекаута нужного sha; `src/generated/` gitignored но populated в working dir → ensure-schema пропускает schema-gen, build в mssql не лезет.
- НЕ верить home-curl по pilorama98.ru (домашний DPI + DNS-кэш отдают старый IIS) — проверять с VDS или `curl --resolve …:443:89.253.255.94` и смотреть `x-powered-by: Nuxt` (новый) vs `Server: Microsoft-IIS` (старый). - Smoke pilorama98 ТОЛЬКО через `curl --resolve www.pilorama98.ru:443:89.253.255.94` (дома DPI/DNS отдают старый IIS). Меню линкует /catalog,/services,/contacts,/payment; /delivery — НЕ пункт меню (404 ожидаем).
- compose source-of-truth: `host-stacks/vds-kzntsv/pilonuxt.compose.yml` (роутер на 3 хоста, GTM прод-дефолт).
## Memory updates за сессию
- Новая memory: [[smoke-crawl-real-pages-not-two-routes]] — smoke = весь меню + data-эндпоинты (viewModel), не 2 happy-роута. Урок из фальш-green на этом кате (объявил green по /+/catalog, vitya поймал content-api 500).

View File

@@ -555,7 +555,7 @@ vehicles-loader (stostayer) деплоится в Docker у клиента (lite
--- ---
## [redeploy-pilonuxt-gsc-offers] — Передеплой pilonuxt с SEO-фиксом микроразметки Product (commit 37412d0). Google Search Console отсеивал страницы товаров из выдачи: критическая ошибка «задайте offers / review / aggregateRating» — у Product не было блока offers, а aggregateRating рендерился только при наличии рейтинга. Фикс добавил schema.org/Offer (price/priceCurrency/availability/url) в app/pages/shop/products/[slug].vue, проверено в SSR. Только код фронта — env/инфра/секреты не менялись, build/runtime egress те же, что в прошлый деплой (verdaccio + mssql при сборке; mssql + smtp + self-origin в рантайме). Acceptance: новый образ в проде, на странице товара в HTML присутствует itemprop="offers" с ценой и наличием. ## 🟢 [redeploy-pilonuxt-gsc-offers] — closed 2026-06-16 — pilonuxt `37412d0` в проде, offers в микроразметке Product live. Build на workstation (verdaccio build-secret) → push registry.kzntsv.site/pilonuxt:37412d0 (398MB) → перекат Portainer stack 16 (PUT API). Acceptance verified (curl --resolve к VDS): на `/shop/products/doska-obreznaya-25-100-6000` есть `itemprop="offers"` itemtype Offer с price=277.5/priceCurrency=RUB/availability=InStock/url-канон; X-Powered-By Nuxt; регрессии нет (меню /catalog,/services,/contacts,/payment = 200, viewModel жив). ⚠️ По ходу: в Portainer не был зарегистрирован НИ ОДИН registry → первый pull упал `no basic auth credentials`; зарегистрировал `registry.kzntsv.site` (Custom, Id 1, registry-креды из pass) → перекат прошёл, приватный registry теперь авторизован в Portainer постоянно. Inbox pilonuxt отправлен (GSC → «Проверить устранение»). Передеплой pilonuxt с SEO-фиксом микроразметки Product (commit 37412d0). Google Search Console отсеивал страницы товаров из выдачи: критическая ошибка «задайте offers / review / aggregateRating» — у Product не было блока offers, а aggregateRating рендерился только при наличии рейтинга. Фикс добавил schema.org/Offer (price/priceCurrency/availability/url) в app/pages/shop/products/[slug].vue, проверено в SSR. Только код фронта — env/инфра/секреты не менялись, build/runtime egress те же, что в прошлый деплой (verdaccio + mssql при сборке; mssql + smtp + self-origin в рантайме). Acceptance: новый образ в проде, на странице товара в HTML присутствует itemprop="offers" с ценой и наличием.
## Обязательные скилы — вызвать до начала работы ## Обязательные скилы — вызвать до начала работы
- invoke `using-tasks` — управление статусом задачи - invoke `using-tasks` — управление статусом задачи
@@ -566,16 +566,18 @@ vehicles-loader (stostayer) деплоится в Docker у клиента (lite
**weight:** needs-human **weight:** needs-human
**notify:** victor/pilonuxt **notify:** victor/pilonuxt
**Status:** ready **Status:** 🟢 done (closed 2026-06-16 vitya@.admin-exec)
**Where I stopped:** (not started) **Closure / coverage check:** build workstation @ 37412d0 (verdaccio JWT build-secret) → push registry.kzntsv.site/pilonuxt:37412d0 (398MB) → Portainer stack 16 PUT (PullImage:true) → контейнер running 37412d0. Smoke curl --resolve www.pilorama98.ru:443:89.253.255.94: offers-блок present (price/priceCurrency/availability/url), X-Powered-By Nuxt, меню+viewModel 200 (без content-api-500). Урок [[smoke-crawl-real-pages-not-two-routes]] применён — краулил реальные nav-href, не гадал слаги (/delivery 404 но не в меню → не баг).
**Next action:** docker build (build-secret verdaccio_token) из origin/master @ 37412d0 → push в registry.kzntsv.site/pilonuxt:37412d0 → docker pull → перекатить Portainer-стек 16 → re-check: на странице товара (например /shop/products/doska-obreznaya-25-100-6000) в HTML есть itemprop="offers". Затем в GSC «Проверить устранение» на отчёте «Описания товара». **Follow-up (не блокер):** registry.kzntsv.site зарегистрирован в Portainer (Custom Id 1) — закрывает «no basic auth» на будущих перекатах приватных образов; до этого pull держался на host docker login, который слетел.
**Next action:**
**Branch:** master **Branch:** master
**Notify:** victor/pilonuxt **Notify:** victor/pilonuxt
<!-- closed-by: vitya@.admin-exec / 2026-06-16 / build+push+stack16 PUT, offers verified via VDS-resolve smoke, Portainer registry registered -->
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: victor/pilonuxt / 2026-06-16T13:49:40.667Z --> <!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: victor/pilonuxt / 2026-06-16T13:49:40.667Z -->
--- ---
## [redeploy-pilonuxt-gsc-structured-data] — Передеплой www.pilorama98.ru с фиксом микроразметки Product под minor-замечания Google Search Console (structured data «Данные о товарах продавца»). ## 🟢 [redeploy-pilonuxt-gsc-structured-data] — closed 2026-06-17 — `19a4a84` в проде, structured-data (description/brand/hasMerchantReturnPolicy) live. Передеплой www.pilorama98.ru с фиксом микроразметки Product под minor-замечания Google Search Console (structured data «Данные о товарах продавца»).
Коммит уже на origin/master: `19a4a84` (fix(seo): обогатил микроразметку Product offers). Изменён только `app/pages/shop/products/[slug].vue` — добавлены itemprop description (always-on), brand, hasMerchantReturnPolicy внутри offers. Тот же пайплайн, что вчерашний `redeploy-pilonuxt-gsc-offers` (37412d0). Коммит уже на origin/master: `19a4a84` (fix(seo): обогатил микроразметку Product offers). Изменён только `app/pages/shop/products/[slug].vue` — добавлены itemprop description (always-on), brand, hasMerchantReturnPolicy внутри offers. Тот же пайплайн, что вчерашний `redeploy-pilonuxt-gsc-offers` (37412d0).
@@ -594,11 +596,13 @@ vehicles-loader (stostayer) деплоится в Docker у клиента (lite
**weight:** needs-human (deploy-инфра: registry + Portainer-стек за Traefik) **weight:** needs-human (deploy-инфра: registry + Portainer-стек за Traefik)
**notify:** victor/pilonuxt (ответ о закрытии/затыке — в inbox pilonuxt, там слушает монитор) **notify:** victor/pilonuxt (ответ о закрытии/затыке — в inbox pilonuxt, там слушает монитор)
**Status:** ready **Status:** 🟢 done (closed 2026-06-17 vitya@.admin-exec)
**Where I stopped:** (not started) **Closure / coverage check:** build на workstation @ 19a4a84 (verdaccio JWT build-secret, EXIT=0, src/generated предгенерён → mssql на билде не дёргался) → push registry.kzntsv.site/pilonuxt:19a4a84 (digest sha256:9642…fa5) → Portainer stack 16 PUT(pullImage:true) → контейнер running 19a4a84 (vds-ops ps). Smoke curl --resolve www.pilorama98.ru:443:89.253.255.94 на /shop/products/doska-obreznaya-25-100-6000: **(1)** `itemprop="description"` непустой («Характеристики Сорт 1 Материал Сосна…») ✓; **(2)** `itemprop="brand"` content="Пилорама 98" ✓; **(3)** внутри `itemprop="offers"` (schema.org/Offer): `hasMerchantReturnPolicy``returnPolicyCategory=https://schema.org/MerchantReturnNotPermitted` ✓; **(4)** прежние offers-поля целы: price=277.5/priceCurrency=RUB/availability=InStock/url=канон ✓; X-Powered-By Nuxt. Регрессий нет: / /catalog /services /contacts /payment = 200 (/delivery 404 unlinked, как и вчера). Урок [[smoke-crawl-real-pages-not-two-routes]] применён.
**Next action:** Собрать образ pilonuxt из master @ 19a4a84, запушить в registry.kzntsv.site/pilonuxt:19a4a84, перекатить Portainer-стек 16. **Gotcha (новый, заингещён):** Portainer stack update через PS 5.1 Invoke-RestMethod коррапит кириллические комментарии compose — ответ /file декодится как ISO-8859-1 (mojibake) → обратный PUT даёт `yaml: could not find expected ':'`. Фикс: GET байтами (-OutFile) + read -Encoding UTF8, PUT тело UTF-8-байтами. Записано в concepts/portainer-stack-management-vds.md.
**Next action:**
**Branch:** n/a **Branch:** n/a
**Notify:** victor/pilonuxt **Notify:** victor/pilonuxt
<!-- closed-by: vitya@.admin-exec / 2026-06-17 / build+push+stack16 PUT(pullImage), structured-data verified via VDS-resolve smoke, PS-UTF8 gotcha ingested -->
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: victor/pilonuxt / 2026-06-17T07:00:53.563Z --> <!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: victor/pilonuxt / 2026-06-17T07:00:53.563Z -->
--- ---

View File

@@ -3,6 +3,7 @@ title: Portainer stack management on vds-kzntsv — canonical pattern
status: live status: live
tags: [vds, portainer, docker-compose, ops] tags: [vds, portainer, docker-compose, ops]
related: [[vds-kzntsv]], [[mssql-on-vds]], [[minio-imgproxy-on-vds]] related: [[vds-kzntsv]], [[mssql-on-vds]], [[minio-imgproxy-on-vds]]
updated: 2026-06-17
--- ---
# Portainer stack management on vds-kzntsv # Portainer stack management on vds-kzntsv
@@ -77,6 +78,30 @@ curl -ksS -X POST "$PORTAINER_URL/api/stacks/create/standalone/string?endpointId
6. **`com.docker.compose.project.working_dir`** меняется с `/opt/stacks/<name>` (ad-hoc) на `/data/compose/<id>` (Portainer-managed). Сохранённые `/opt/stacks/<name>/.env` остаются на disk — лишь для backup/reference, не используются compose runtime. 6. **`com.docker.compose.project.working_dir`** меняется с `/opt/stacks/<name>` (ad-hoc) на `/data/compose/<id>` (Portainer-managed). Сохранённые `/opt/stacks/<name>/.env` остаются на disk — лишь для backup/reference, не используются compose runtime.
7. **Volumes preserved across migration** — named volumes (`docker compose down` без `-v`) и binds (`/opt/stacks/<name>/data`) сохраняются. Data layer не теряется при ad-hoc→Portainer переезде. 7. **Volumes preserved across migration** — named volumes (`docker compose down` без `-v`) и binds (`/opt/stacks/<name>/data`) сохраняются. Data layer не теряется при ad-hoc→Portainer переезде.
8. **Management plane skip**`traefik` и `portainer` сами через себя нельзя безопасно recreate (теряется access). Оставлены ad-hoc; их docker-compose.yml в `/opt/stacks/{traefik,portainer}/`. Future: bootstrap script для cold-start ставит их first перед всем остальным. 8. **Management plane skip**`traefik` и `portainer` сами через себя нельзя безопасно recreate (теряется access). Оставлены ad-hoc; их docker-compose.yml в `/opt/stacks/{traefik,portainer}/`. Future: bootstrap script для cold-start ставит их first перед всем остальным.
9. **PowerShell 5.1 коррапит кириллицу при round-trip stack-file через API**`Invoke-RestMethod` на `GET /api/stacks/<id>/file` декодит тело как **ISO-8859-1** (нет `charset` в Content-Type ответа), UTF-8 кириллица в комментариях compose превращается в mojibake (`Боевой``Боевой`). Обратный `PUT` шлёт mojibake → docker compose загрузчик падает `yaml: line N: could not find expected ':'` на строке с битым комментарием. На диске исходный файл корректен — портит именно round-trip. **Fix (PS 5.1):** качать байтами `Invoke-WebRequest -OutFile $tmp``Get-Content $tmp -Raw -Encoding UTF8 | ConvertFrom-Json`, а тело PUT слать UTF-8-байтами: `$bytes=[Text.Encoding]::UTF8.GetBytes($json); Invoke-RestMethod -Body $bytes -ContentType 'application/json; charset=utf-8'`. (`pilorama98`/pilonuxt redeploy 2026-06-17.)
10. **Пустой `env` в PUT-payload** — Portainer ждёт `env: []` (`[]portainer.Pair`). PS `@{env=@()}|ConvertTo-Json` схлопывает пустой массив → `Invalid request payload`. Fix: подставить literal через плейсхолдер — `(... | ConvertTo-Json) -replace '"__ENV__"','[]'`.
## Stack redeploy (existing stack, новый image tag)
Перекат уже-managed стека на новый тег образа (НЕ создание). Применялось для `pilonuxt` (stack Id 16) на `redeploy-pilonuxt-gsc-*` 2026-06-16/17. Образ собирается/пушится на workstation (≈400 МБ влезает; multi-GB → собирать на VDS, см. memory `registry-large-push-499-build-on-vds`), затем:
```powershell
# 1. JWT
$jwt = (Invoke-RestMethod -Method Post -Uri 'https://portainer.vds.kzntsv.site/api/auth' `
-ContentType 'application/json' -Body (@{username='vitya';password='<vds-kzntsv/full-env>'}|ConvertTo-Json)).jwt
$h = @{ Authorization = "Bearer $jwt" }
# 2. GET текущий compose БАЙТАМИ (gotcha #9), подменить тег
$tmp = "$env:TEMP\stack.json"
Invoke-WebRequest -Headers $h -Uri 'https://portainer.vds.kzntsv.site/api/stacks/16/file' -OutFile $tmp
$new = ((Get-Content $tmp -Raw -Encoding UTF8 | ConvertFrom-Json).StackFileContent) -replace 'pilonuxt:OLD','pilonuxt:NEW'
# 3. PUT с pullImage:true (форсит свежий pull нового тега), env=[] через плейсхолдер, тело UTF-8-байтами
$json = (@{stackFileContent=$new; env='__ENV__'; prune=$false; pullImage=$true}|ConvertTo-Json -Depth 10) -replace '"__ENV__"','[]'
Invoke-RestMethod -Method Put -Headers $h -ContentType 'application/json; charset=utf-8' `
-Body ([Text.Encoding]::UTF8.GetBytes($json)) -Uri 'https://portainer.vds.kzntsv.site/api/stacks/16?endpointId=1'
```
Verify: контейнер на новом образе — `ops.docker.ps name=<stack>` (vds-ops MCP) показывает `image: registry.kzntsv.site/<name>:NEW`. Прод-smoke мимо LAN-DNS воркстейшна — `curl --resolve <host>:443:89.253.255.94` (иначе резолвится локальная копия, см. memory `workstation-lan-dns-serves-local-cms-copy`); краулить реальные nav-страницы + data-endpoint, не 2 роута ([[smoke-crawl-real-pages-not-two-routes]]).
**Предусловие pull:** registry.kzntsv.site зарегистрирован в Portainer как Custom registry Id 1 (иначе `pull access denied` / `no basic auth`). См. memory `portainer-vds-needs-registry-registered`.
## Stack inventory (2026-05-22, Portainer Ids) ## Stack inventory (2026-05-22, Portainer Ids)

View File

@@ -38,7 +38,7 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever
- [ocis-on-vds-deploy-recipe](concepts/ocis-on-vds-deploy-recipe.md) — oCIS на VDS — deploy recipe + non-obvious gotchas (UID 1001 vs 1000, basic auth, LibreGraph user-create) - [ocis-on-vds-deploy-recipe](concepts/ocis-on-vds-deploy-recipe.md) — oCIS на VDS — deploy recipe + non-obvious gotchas (UID 1001 vs 1000, basic auth, LibreGraph user-create)
- [portainer-2.21-admin-password-regression](concepts/portainer-2.21-admin-password-regression.md) — Portainer 2.21 `--admin-password` regression + min 12-char policy - [portainer-2.21-admin-password-regression](concepts/portainer-2.21-admin-password-regression.md) — Portainer 2.21 `--admin-password` regression + min 12-char policy
- [portainer-stack-management-books-vds](concepts/portainer-stack-management-books-vds.md) — Portainer-managed stacks на books VDS — pattern application + migration log 2026-05-25 - [portainer-stack-management-books-vds](concepts/portainer-stack-management-books-vds.md) — Portainer-managed stacks на books VDS — pattern application + migration log 2026-05-25
- [portainer-stack-management-vds](concepts/portainer-stack-management-vds.md) — Portainer-managed stacks на VDS — canonical pattern + migration script + gotchas - [portainer-stack-management-vds](concepts/portainer-stack-management-vds.md) — Portainer-managed stacks на VDS — canonical pattern + migration script + stack-redeploy recipe (новый тег) + gotchas (вкл. PS 5.1 ISO-8859-1 коррапт кириллицы при API round-trip)
- [proxy-debugging-test-the-real-client](concepts/proxy-debugging-test-the-real-client.md) — анти-паттерн: свои curl/standalone-тесты «работают», а боевой клиент пользователя нет; источник истины — реальный клиент - [proxy-debugging-test-the-real-client](concepts/proxy-debugging-test-the-real-client.md) — анти-паттерн: свои curl/standalone-тесты «работают», а боевой клиент пользователя нет; источник истины — реальный клиент
- [reality-pq-mldsa65-dest-incompatibility](concepts/reality-pq-mldsa65-dest-incompatibility.md) — REALITY+ML-DSA-65 (PQ) не работает с не-PQ dest (Akamai/intel шлёт HRR); fix = PQ-совместимый dest или выключить PQ; **caveat: снятие PQ ≠ рабочий Reality у GUI-клиентов** - [reality-pq-mldsa65-dest-incompatibility](concepts/reality-pq-mldsa65-dest-incompatibility.md) — REALITY+ML-DSA-65 (PQ) не работает с не-PQ dest (Akamai/intel шлёт HRR); fix = PQ-совместимый dest или выключить PQ; **caveat: снятие PQ ≠ рабочий Reality у GUI-клиентов**
- [recovery-architecture-snapshot](concepts/recovery-architecture-snapshot.md) — текущая recovery architecture (2026-05-19/21, attempt 2) - [recovery-architecture-snapshot](concepts/recovery-architecture-snapshot.md) — текущая recovery architecture (2026-05-19/21, attempt 2)

View File

@@ -2,6 +2,8 @@
Append-only log of wiki operations (ingests, promotions, lints, migrations). Append-only log of wiki operations (ingests, promotions, lints, migrations).
## [2026-06-17] update | concepts/portainer-stack-management-vds.md +раздел «Stack redeploy (новый image tag)» (JWT→GET file байтами→подмена тега→PUT pullImage:true, env=[] плейсхолдером, тело UTF-8) + gotcha #9 (PS 5.1 Invoke-RestMethod декодит /file как ISO-8859-1 → кириллические compose-комментарии mojibake → PUT падает `yaml: could not find expected ':'`; fix = байты+UTF8) + #10 (пустой env схлопывается). Источник: redeploy-pilonuxt-gsc-structured-data (19a4a84 в проде, stack 16).
## [2026-06-14] update | concepts/minio-imgproxy-on-vds.md +раздел «S3 access для клиентских приложений» (lookup: endpoint `https://minio.kzntsv.site` / сырой `89.253.255.133:9000` / inter `http://minio:9000`, root accessKey `AKIAJ...` + secret в `pass minio-vds/full-env`, форма ключа, ssl/region/pathStyle). Закрывает класс-вопрос «дай MinIO endpoint+креды» БЕЗ SSH. Прецедент: inbox snolla 2026-06-14 (raw-stream content-api), ответ отправлен. ## [2026-06-14] update | concepts/minio-imgproxy-on-vds.md +раздел «S3 access для клиентских приложений» (lookup: endpoint `https://minio.kzntsv.site` / сырой `89.253.255.133:9000` / inter `http://minio:9000`, root accessKey `AKIAJ...` + secret в `pass minio-vds/full-env`, форма ключа, ssl/region/pathStyle). Закрывает класс-вопрос «дай MinIO endpoint+креды» БЕЗ SSH. Прецедент: inbox snolla 2026-06-14 (raw-stream content-api), ответ отправлен.
## [2026-06-11] ingest | verdaccio-restore-packument-desync — postmortem: disaster-restore вернул тарболлы но древний/пустой packument → publish свежей версии EEXISTS 409. Fix: снять только коллизирующий целевой .tgz (бэкап first), republish; НЕ rm -rf каталог (убьёт locally-published историю). Применено к @snollajs/{data,mailer,numbering,content-api}. ## [2026-06-11] ingest | verdaccio-restore-packument-desync — postmortem: disaster-restore вернул тарболлы но древний/пустой packument → publish свежей версии EEXISTS 409. Fix: снять только коллизирующий целевой .tgz (бэкап first), republish; НЕ rm -rf каталог (убьёт locally-published историю). Применено к @snollajs/{data,mailer,numbering,content-api}.
## [2026-06-11] ingest | verdaccio-token-lifecycle — restart trap (ephemeral secret → 401), max_users:-1 + pnpm 409 постмортем, JWT config fix, yarn classic vs berry token refresh recipe. ## [2026-06-11] ingest | verdaccio-token-lifecycle — restart trap (ephemeral secret → 401), max_users:-1 + pnpm 409 постмортем, JWT config fix, yarn classic vs berry token refresh recipe.

View File

@@ -21,7 +21,7 @@
services: services:
pilonuxt: pilonuxt:
container_name: pilonuxt container_name: pilonuxt
image: registry.kzntsv.site/pilonuxt:125a3e2 image: registry.kzntsv.site/pilonuxt:37412d0
restart: unless-stopped restart: unless-stopped
environment: environment:
NODE_ENV: production NODE_ENV: production