wiki(stostayer): ingest stostayer-admin-minio-config — :8090 admin on stostayer MinIO
Fix 2026-07-22: local .NET admin (C:\sites\stostayer\Web.config) S3 providers re-pointed to stostayer MinIO. 3 bugs in original config: wrong creds (AKIAJ2YJP72W6ZHCRE6Q = books-vds root, not stayer_minio), wrong endpoint (minio.stostayer.ru is not S3 API port; prod uses minio-api.stostayer.ru), wrong region (local -> AmazonS3Exception expecting us-west-1). Creds NOT in pass — live in stostayer.new config/default.json. Admin now shares prod storage; manual App_Data mirroring retired. + index.md, log.md. Also carries pending handoff (NEXT_SESSION) + runbook update from 2026-07-21 stostayer-web 0.3.20 deploy session. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,73 +1,50 @@
|
||||
---
|
||||
_last_updated_: 2026-07-21T00:00:00Z
|
||||
session_id: 2026-07-21-ruvds-decomm
|
||||
prev_session_id: 2026-07-20-on-snolla-cutover-done
|
||||
_last_updated_: 2026-07-21T14:45:00Z
|
||||
session_id: 2026-07-21-stostayer-web-0320-deploy
|
||||
prev_session_id: 2026-07-21-ruvds-decomm
|
||||
---
|
||||
|
||||
# Next session handoff
|
||||
|
||||
## Эта сессия — RUVDS DECOMM 2026-07-21. Погашен, забыт.
|
||||
## Эта сессия — деплой цен кондиционеров на stostayer.ru (legacy-web 0.3.20). ЗАВЕРШЁН ✅
|
||||
|
||||
[[ruvds-iis-host]] (80.64.31.36) декоммишнен 2026-07-21. Аудит: на RUVDS не осталось живого — весь snolla-тираж на VDS (стеки 17-22), локальный .NET-админ независим. Финальный offsite-снимок на kreknin верифицирован (8.8G, 7-day retention, прогон 04:30 success). rimiz.ru/www.rimiz.ru (последний публичный домен на RUVDS, мёртвый 404) — DNS переправлен оператором на 89.253.255.94, авторит. NS verified. **На RUVDS — 0 публичных доменов.** Коммиты `535ed617`, `ec3ac792` запушены.
|
||||
`stostayer.new` прислал deploy-request (повышение цен в `packages/web/components/ConditionerPrice.vue`, commit `4bbdbbf`). Задеплоено на прод. По ходу вскрылся и разрешён давний ESM-блокер.
|
||||
|
||||
### ОСТАЁТСЯ ОПЕРАТОРУ (один ручной шаг)
|
||||
- **Отказаться от RUVDS у провайдера** — личный кабинет https://ruvds.com (креды в `pass ruvds-iis/full-env`). Машина выключена/забыта на нашей стороне; cancelling у провайдера = экономия денег. Не горит — daily-бэкап с RUVDS прекратится сам (таска умрёт с хостом), это ОК: offsite-копия уже на kreknin, локальный админ жив.
|
||||
### Что сделано
|
||||
- **ESM-блокер подтверждён + разрешён.** `packages/web` (Nuxt2/CJS) не собирался с master (ESM-миграция `c805e7e` data/api + ESM-переиздание snolla). Ретрофит 5 `require()`→dynamic `import()` (`nuxt.config.js`, `server/index.js`, 2 `serverMiddleware`→CJS). snolla-сессия починила bare-`get`-баг → опубликовала `@snollajs/snolla@0.7.6`. Образ `0.3.20` собран, build+runtime зелёные.
|
||||
- **Деплой на прод.** Push `0.3.20` в `docker.stostayer.ru`, redeploy стека 16 (`0.3.18`→`0.3.20`, Portainer PUT через SSH:20435 + внутренний IP portainer). Контейнер Up, `RestartCount=0`, обслуживает реальный трафик.
|
||||
- **Verify.** `/remont-kondicionerov/{zapravka,diagnostika}-kondicionera` → 200, компонент `ConditionerPrice` рендерит новые цены (4790/3290/6190/3990/7890/4840), старые (4400/2900/5800/7500/4450) ушли. Bare `/remont-kondicionerov` 301→`/remont/remont-kondicionerov` (CMS, без компонента) — verify по sub-страницам.
|
||||
|
||||
### Предыдущая сессия — Task B (on.snolla.com → VDS) DONE 2026-07-20.
|
||||
on.snolla.com live на VDS как Node snolla-app `@snollajs/snolla` 0.42.1, за traefik, LE-серт issued.
|
||||
~~Прод-оракул был RUVDS IIS (80.64.31.36) — не тронут, жив (rollback = revert DNS).~~ **RUVDS DECOMM — rollback только образ-тегом (см. on-snolla-vds-deploy-runbook § Rollback).**
|
||||
### Инцидент по ходу (разрешён)
|
||||
Первый push 3.33GB с VPN → VPN-IP бан у провайдера хоста → `:443` к хосту TLS-fail с операторского IP (сайт для остальных работал). Остановил push, оператор убрал VPN, **resume-push** добил остаток малым egress → без повторного бана. **Урок: единичный large-push тоже триггерит бан** (не только retry-storm). Memory `stostayer-push-ban-single-large-push`.
|
||||
|
||||
🟢 **[on-snolla-vds-migration] ЗАКРЫТА.** Спека: `.wiki/concepts/snolla-local-admin-and-on-snolla-migration-design.md` §Task B.
|
||||
Runbook (as-built + gotchas): `.wiki/concepts/on-snolla-vds-deploy-runbook.md`. Таска: `.tasks/on-snolla-vds-migration.md` (as-built).
|
||||
### ОСТАЁТСЯ (follow-up)
|
||||
- **🔴 ESM-ретрофит НЕ закоммичен/НЕ запушен в stostayer.new master.** stostayer.new-сессия сказала «коммить и пушь ты» (у неё изменений нет локально, ретрофит делался в working-tree .admin-сессии на этой воркстейшн). Commit-message одобрен stostayer.new. **Оператор НЕ дал «го» на пуш в эту сессию** (Rule 4 — пуш в git-master = outward). → Ретрофит лежит **незакоммиченным в `C:/Users/vitya/projects/stostayer.new` working-tree** (5 файлов + `package.json` snolla `^0.7.6` + `yarn.lock` + `.dockerignore`; `.yarnrc.yml` восстановлен в оригинал — чист; `.tasks/*` не трогать — ими stostayer.new управляет). **Следующая сессия: получить «го» оператора → `git add` ретрофит-файлов → commit (message ниже) → `git push origin master`.** НЕ делать `git checkout`/`stash`/`clean` в stostayer.new до коммита — потеряешь ретрофит. Если потерян — реконструируем из образа 0.3.20 (client registry) + ранбука + memory `stostayer-web-esm-retrofit-snolla-076`.
|
||||
- Commit-message (одобрен stostayer.new): `fix(web): ESM-deps retrofit — require()→dynamic import(), pin snolla ^0.7.6` + body (см. письмо `stostayer.new/.claude-inbox/2026-07-21T14-28-00Z-admin.md`).
|
||||
- После пуша stostayer.new тянет master + verify `packages/web` собирается.
|
||||
- **✅ snolla yank 0.7.5 — DONE.** snolla-сессия сняла `@snollajs/snolla@0.7.5` с verdaccio (`npm unpublish --force`), verify: 0.7.x = только 0.7.6, `latest`=0.42.1 не сбит, exact-0.7.5 консьюмеров не было. Линия 0.7.x полностью закрыта.
|
||||
- **Операторский IP 46.151.25.64** может ещё флапать по :443 к stostayer-хосту (бан egress-IP с инцидента) — для оператора; для посетителей сайта ограничений нет. Проходит само.
|
||||
- **Побочная нота (не чинил):** vds-ops `ops.docker.logs` на контейнере `verdaccio` висит 300с (docker-socket-proxy + тяжёлый stdout) — snolla-сессия не смогла взять verdaccio-логи через MCP. Если понадобится独立-verify verdaccio-логов — чинить vds-ops (таймаут/стрим) или грепнуть лог-файл на хосте.
|
||||
|
||||
### As-built
|
||||
- **Репо** `victor/on.snolla.com` (git.kzntsv.site, запушен) — структура-калька tandemmebel.ru. Commit `473923e494db`.
|
||||
- **Образ** `registry.kzntsv.site/on-snolla:473923e494db` (+:latest), собран на VDS (обход traefik-499).
|
||||
- **Стек Portainer 22** (`on-snolla`), `mem_limit 512m`, 8 env-секретов (переиспользованы из tandemmebel стека 20 — общая snolla-инфра), rule `Host(on.snolla.com)`, LE-серт CN=on.snolla.com (YR1, until 2026-10-18).
|
||||
- **DNS**: reg.ru `on.snolla.com` A `80.64.31.36`→`89.253.255.94` (operator flip; авторит. NS ns1/ns2.reg.ru verified → VDS before rule swap, LE-порядок соблюдён).
|
||||
- **Реконструкция**: `views/layout.liquid` = bootstraptor-лендинг **byte-identical** прод-HTML (28413 байт, verified direct diff + live). Content-поля пустые → лендинг baked в layout. Form "Join us" baked (POST `/` → snolla `forms` middleware → `form_ajax_response.liquid`). StaticPages `/yandex_…` + `/4a052808276c.html`. `/c` = 404 dead-link (parity с продом — prod /c тоже 404; snolla sitemap несёт его → 3/3 loc parity).
|
||||
- **Completeness-gate GREEN**: sitemap 3/3 parity {/,/c,/yandex}, homepage + /yandex byte-identical, 0 регрессий. Live-smoke external: TLS verify=0, `/`+`/robots.txt`+`/sitemap.xml`+`/yandex`=200, `/c`=404.
|
||||
### Wiki / memory обновлено
|
||||
- Ранбук `.wiki/concepts/stostayer-web-deploy-runbook.md`: БЛОКЕР→RESOLVED, push-секция (single-large-push gotcha), verify-секция (sub-страницы + smoke→prod-DB gotcha).
|
||||
- Memory: `stostayer-web-esm-retrofit-snolla-076`, `stostayer-push-ban-single-large-push`, `stostayer-smoke-hits-prod-db`.
|
||||
|
||||
### Гочи (в runbook + memory)
|
||||
- **snolla robotsTxt крашится на undefined `app.locals.domain`** — on.snolla.com не имеет row в MoreThenCms `Domains`. Фикс в `apps/web/index.js`: после initApp, если `!app.locals.domain`, synthesized `{robotsTxt: site.robotsTxt}`. Без shared-DB мутации. Memory `snolla-robotstxt-crash-no-domains-row`.
|
||||
- **Form "Join us" не имеет Liquid form-tag** — форма HTML baked в layout, POST — `forms` middleware (мэтч по Path `/`). Legacy reCAPTCHA v1 мертва — parity, не чиним.
|
||||
- **Portainer JWT short-lived** — в node-скрипте GET stack + GET file + PUT: jwt из GET-фазы протух к PUT (первый PUT 401). Re-auth прямо перед PUT.
|
||||
- **hosts override на воркстейшне** — Task A оставил `127.0.0.1 on.snolla.com` в hosts. External verify прод-on.snolla.com = только через `curl --resolve on.snolla.com:443:89.253.255.94`.
|
||||
|
||||
### MinIO upload-acceptance (ручной follow-up оператора — НЕ сделано)
|
||||
Логин в админку on.snolla.com (на RUVDS .NET, `/admin`) → залить тест-ассет → проверить объект в `minio.kzntsv.site` bucket=assets. S3-провайдер был admin-self-test green на RUVDS; Web.config 1:1 → должно работать. Креды админа в `MoreThenCms.dbo.Accounts` (SQL-user `snolla` / SA `pass mssql-vds/sa-password`).
|
||||
|
||||
## Recent commits (.admin)
|
||||
- 4c4d1938 feat(on-snolla): CUTOVER DONE — on.snolla.com live on VDS (stack 22, LE cert)
|
||||
- 6b5cb5fa feat(on-snolla): Portainer stack 22 source-of-truth (staging Host, mem_limit 512m, 8 env secrets)
|
||||
- 73ad7669 (projects-meta) close vehicles-loader-redeploy-per-group-rate-diff 🟢
|
||||
- 019f5bae (projects-meta) close on-snolla-vds-migration 🟢
|
||||
- (on.snolla.com repo) 473923e feat(on-snolla): scaffold snolla-app — byte-identical landing reconstruction
|
||||
### Креды/доступы — не менялись
|
||||
snolla-сессия: commit `63e5c60` (snolla repo, branch `fix/snolla-0.7.6-s3-get`), 0.7.6 в verdaccio. snolla-задача `snolla-074-get-bugfix-republish` закрыта (commit `46fe4040` в victor/snolla .tasks).
|
||||
|
||||
## Open треки
|
||||
|
||||
| Трек | Готовность | Entry-point |
|
||||
|---|---|---|
|
||||
| books-vds → vds-kzntsv консолидация | оценено, не лезет по RAM/disk | Решение за user. |
|
||||
| MinIO upload-acceptance on.snolla (ручной) | ⚪ follow-up оператора | Логин `/admin` (RUVDS) → тест-ассет → MinIO bucket=assets. |
|
||||
| stostayer.new закоммитить ESM-ретрофит | ⚪ за stostayer.new | working-tree stostayer.new (5 файлов + lockfile + .dockerignore) |
|
||||
| snolla yank 0.7.5 | ⚪ за snolla (го дано) | snolla выполнит `npm unpublish @snollajs/snolla@0.7.5 --force` |
|
||||
| books-vds → vds-kzntsv консолидация | оценено, не лезет по RAM/disk | За user. |
|
||||
| MinIO upload-acceptance on.snolla | ⚪ follow-up оператора | из prev handoff |
|
||||
|
||||
## Спроси user'а
|
||||
- (нет pending-решений — Task B закрыт полностью)
|
||||
- **«го» на коммит+пуш ESM-ретрофита в `victor/stostayer.new` master** (незакоммичен в working-tree, stostayer.new ждёт пуш чтобы подтянуть+verify). Без него следующий legacy-web деплой упрётся в ту же ESM-стену.
|
||||
|
||||
## Не делать (preemptive guards)
|
||||
- **НЕ пушить без добла** (Rule 4) — на эту сессию добл был ("разрешаю всё, погнали").
|
||||
- **НЕ сжимать** books на .94; **НЕ netplan** на vds-kzntsv.
|
||||
- **hosts override активен** — `internal.snolla.com` → 127.0.0.1 (локальный админ Task A; алиас `on` переименован в `internal` 2026-07-20). Боевой on.snolla.com (VDS) с воркстейшна — только через `--resolve :443:89.253.255.94` или off-hosts. **Публичного on.snolla.com/admin не существует** (никогда не было) — админка только локальная: `http://internal.snolla.com/admin`.
|
||||
|
||||
### Alias rename `on`→`internal` (2026-07-20, follow-up оператора)
|
||||
- `Sites.Alias`+`LoweredAlias`: `on`→`internal` (siteId B9ECDB50, PrimaryDomain остался `on.snolla.com`).
|
||||
- `C:\sites\snolla\Web.config` `primaryAlias`: `on`→`internal` (иначе catch-all NRE-500 на ВСЕХ запросах — primaryAlias ссылается на переименованный алиас).
|
||||
- hosts: `on.snolla.com`→`internal.snolla.com` под маркером `# snolla-local-admin`.
|
||||
- **Инцидент:** я обнулил hosts своей elevated-правкой (Get-Content -Raw в RunAs-контексте вернул пусто → Set-Content записал пусто). Восстановил: Windows default header + snolla-local-admin блок (с internal.snolla.com). LAN-DNS CMS-перехват через DNS-резолвер, не hosts → потерь нет. Урок в memory `snolla-catch-all-primaryalias-depends-on-alias`.
|
||||
- VDS prod on.snolla.com НЕ затронут (snolla-app использует config.siteId, не alias) — byte-identical, smoke GREEN.
|
||||
- **НЕ откатывать DNS on.snolla.com** без явного запроса — cutover LIVE, RUVDS IIS жив как rollback-target.
|
||||
|
||||
## Memory updates за сессию
|
||||
- **NEW** `snolla-robotstxt-crash-no-domains-row` — snolla sites без Domains row крашатся на /robots.txt; фикс в index.js domain-drop fallback.
|
||||
- (candidate) on.snolla.com мигрирован на VDS 2026-07-20 (stack 22, LE). Тираж snolla на VDS: labtools(17)/emspb(18)/labtools-pro(19)/tandemmebel(20)/kupimknigi(21)/on-snolla(22).
|
||||
- (candidate) обновить entity `windows-recovery-host.md`: on.snolla.com более не обслуживается локальным IIS как прод — прод на VDS; локальный IIS `snolla` = только админ-хаб (hosts override on.snolla.com→127.0.0.1 теперь pointing на админ-копию, не прод).
|
||||
## Не делать
|
||||
- **НЕ пушить упавший push повторно с того же egress** (VPN-ban).
|
||||
- **НЕ коммитить в stostayer.new master** без координации с stostayer.new-сессией (их репо, их ESM-стратегия) — я оставил ретрофит в working-tree, они коммитят.
|
||||
- snolla 0.7.5 yank — за snolla-сессией (го дано, но она исполняет).
|
||||
71
.wiki/concepts/stostayer-admin-minio-config.md
Normal file
71
.wiki/concepts/stostayer-admin-minio-config.md
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: stostayer .NET admin — MinIO S3 providers config (creds/endpoint/region)
|
||||
type: concept
|
||||
tags: [stostayer, morethencms, iis, admin, minio, s3, config, windows]
|
||||
related: [[../entities/ruvds-iis-host]], [[galleries-storage-class-local-not-s3]], [[snolla-admin-appdata-acl-500-after-scp-migration]], [[minio-imgproxy-on-vds]], [[snolla-local-admin-and-on-snolla-migration-design]]
|
||||
updated: 2026-07-22
|
||||
---
|
||||
|
||||
# stostayer .NET admin — MinIO S3 providers
|
||||
|
||||
Локальная MoreThenCms-админка stostayer (`C:\sites\stostayer\Web.config`, IIS :8090) переведена с битых S3-настроек на рабочий stostayer MinIO. После правки админка и боевой `stostayer-web` (0.3.20, Node snolla-app) читают одно хранилище — ручное зеркалирование в `App_Data` больше не нужно.
|
||||
|
||||
## Контекст
|
||||
|
||||
- Боевой `stostayer-web:0.3.20` (legacy @stostayer/web, Nuxt2) читает ассеты/галереи из **stostayer MinIO**, не из локальной ФС. Поток отдачи: картинки галерей/asset → 302 на `imgproxy.stostayer.ru/imgproxy2` → imgproxy тянет из MinIO → webp; прочие ассеты — стримом из MinIO (см. [[../entities/ruvds-iis-host]] ранбук).
|
||||
- Локальная админка = тот же движок MoreThenCms .NET 4.8, conn → `www.stostayer.ru,1433` (DB `stostayer`, user `stayer_site`). S3 drop-in `MoreThenCms.FileStorage.S3` (+ `AWSSDK.Core`/`AWSSDK.S3`) уже лежал в `bin/` — провайдеры в `Web.config` были вставлены, но не работали.
|
||||
|
||||
## Креды stostayer MinIO — НЕ в pass
|
||||
|
||||
Лежат в репо-конфиге `~/projects/stostayer.new/packages/web/config/default.json` → секция `s3`:
|
||||
|
||||
| Параметр | Значение |
|
||||
|---|---|
|
||||
| accessKeyId | `stayer_minio` (bucket-user) |
|
||||
| secretAccessKey | `cXY>AVoWBv#_V-SZn6Vu6Tzx&!M[%UOod` |
|
||||
| endpoint | `https://minio-api.stostayer.ru` |
|
||||
| region | `us-west-1` (см. ниже — НЕ `local`) |
|
||||
| pathStyle / ssl | `true` / `true` |
|
||||
|
||||
imgproxy: `https://imgproxy.stostayer.ru`, basePath `/imgproxy2`, key+salt — там же в `default.json` → `imgproxy`.
|
||||
|
||||
## Три бага в исходном Web.config (почему "смотрит на локальное")
|
||||
|
||||
1. **Чужие креды.** `accessKey=AKIAJ2YJP72W6ZHCRE6Q` + `secretKey=7o0Q4NjE5GL…` — это **books-vds/snolla MinIO root-ключ** (см. [[minio-imgproxy-on-vds]]). На stostayer MinIO не зарегистрирован → `The Access Key Id you provided does not exist in our records`. Видимо, конфиг копипастом из snolla catch-all admin ([[snolla-local-admin-and-on-snolla-migration-design]], тот юзает books-vds `minio.kzntsv.site`), без замены ключей на stostayer-свои.
|
||||
2. **Не API-порт.** `serviceURL=https://minio.stostayer.ru` → MinIO отвечает `S3 API Requests must be made to API port`. Прод юзает `https://minio-api.stostayer.ru`. Оба хоста резолвятся в один IP `2a03:6f01:1:2::c66b`, но `minio.stostayer.ru` — не S3 API-эндпоинт.
|
||||
3. **Регион.** `authenticationRegion="local"` → SigV4-подпись регионом не совпала → `AmazonS3Exception: The authorization header is malformed; the region is wrong; expecting 'us-west-1'` (HTTP 400) на `GalleriesStorage.EnsureKeyPrefixExists` → `S3DirectoryInfo.ExistsWithBucketCheck` (провайдер галерей падал на ините, в трассе `ToolsController.ImagePreview` → `CreatePreview`). stostayer MinIO настроен на регион `us-west-1`. Прод `default.json` пишет `region:"local"`, но то Node aws-sdk (galleries через imgproxy мимо app-S3; для .NET AWSSDK регион обязан быть `us-west-1`).
|
||||
|
||||
## Fix (2026-07-22)
|
||||
|
||||
9 S3-блоков в `fileStorageClients` (galleries/assets/images/scripts/stylesheets/imageCache/watermarks + inert-настройки contentCache/uploadCache) — 3 глобальные замены в `Web.config`:
|
||||
|
||||
```
|
||||
accessKey: AKIAJ2YJP72W6ZHCRE6Q → stayer_minio
|
||||
secretKey: 7o0Q4NjE5GLkdC48r0oZFEnqddjPNLqtCk+ZEh+S → cXY>AVoWBv#_V-SZn6Vu6Tzx&!M[%UOod (XML-escape: > → >, & → &)
|
||||
serviceURL: https://minio.stostayer.ru → https://minio-api.stostayer.ru
|
||||
authenticationRegion: local → us-west-1
|
||||
```
|
||||
|
||||
Бэкап: `C:\sites\stostayer\Web.config.bak-2026-07-22`. IIS авто-recycle по Web.config-изменению. `contentCache`/`uploadCache` остались `storageType="Local"` (inert S3-настройки поправились, storageType не трогал — кэши локально, по рецепту [[snolla-local-admin-and-on-snolla-migration-design]] шаг 4).
|
||||
|
||||
`bucketName` уже был корректен и не менялся: galleries→`galleries`, assets→`assets`, images/scripts/stylesheets/imageCache/watermarks→`themes`. МинIO-бакеты (mc ListBuckets): `assets, galleries, themes, contentcache, imagescache, maxmind, searchindexes, seo, sessions, uploadcache`. Бакет `assets/9cf0a8e52cf144619fd290606a146d35/` несёт реальные файлы (0001.png…); `ownerId` = siteId `9cf0a8e5-2cf1-4461-9fd2-90606a146d35` без дефисов lowercased.
|
||||
|
||||
## Verify
|
||||
|
||||
- `mc alias set stn_api https://minio-api.stostayer.ru stayer_minio "<secret>"` → `mc ls stn_api/` = 10 бакетов. ⚠ `MC_HOST_…` с URL-encoded секретом в mc-урле давал signature-mismatch — юзать `mc alias set` с явными аргументами.
|
||||
- Админка: `:8090/admin/account/login` → 200, лог `C:\Logs\stostayer\log.YYYYMMDD.txt` чист от S3-ошибок после recycle.
|
||||
- **Acceptance (реальный клиент, не curl — см. [[verify-on-real-client-not-own-curl-tests]]):** логин → Asset Manager / превью галереи — картинки грузятся из MinIO. Подтверждено оператором 2026-07-22.
|
||||
|
||||
## Гочи
|
||||
|
||||
- **Секрет с XML-specials.** В `Web.config` value-атрибуте `>` и `&` обязаны быть escaped (`>`, `&`) — иначе XML не парсится / .NET получает обрезанный секрет. `#`, `[`, `%`, `!` — безопасны в double-quoted XML-атрибуте.
|
||||
- **`minio.stostayer.ru` ≠ API-порт.** Только `minio-api.stostayer.ru`.
|
||||
- **Регион `us-west-1`, не `local`.** Для .NET AWSSDK админки — обязателен; прод Node `local` — отдельная история (imgproxy + env-override).
|
||||
- **Креды не в pass** — единственный источник: `stostayer.new` config. Если репо уедет — креды потеряются; имеет смысл переложить в `pass` (отдельная hardening-таска).
|
||||
- **Кэши Local** — `contentCache`/`uploadCache` намеренно Local (не S3), `imageCache` → S3/themes. Не унифицировано с snolla-admin (там все кэши Local) — оставлено как было.
|
||||
|
||||
## Связанные
|
||||
|
||||
- [[galleries-storage-class-local-not-s3]] — snolla-тираж: galleries/assets Local→S3 миграция, snolla catch-all admin на books-vds MinIO.
|
||||
- [[snolla-admin-appdata-acl-500-after-scp-migration]] — split-brain админка(Local)↔боевой app(MinIO) на RUVDS; та же проблема «админка не переключена на S3».
|
||||
- [[minio-imgproxy-on-vds]] — books-vds MinIO (root-ключ `AKIAJ2YJP72W6ZHCRE6Q`), который ошибочно попал в stostayer Web.config.
|
||||
@@ -47,6 +47,8 @@ docker push docker.stostayer.ru/stostayer-web:<tag>
|
||||
```
|
||||
|
||||
> ⚠️ **ОДИН push, без retry-циклов.** Инцидент 2026-06-17: retry-шторм (6 попыток, образ 3.29GB) на `docker.stostayer.ru` засветил egress нашего **VPN** → хостинг-провайдер забанил VPN-IP → ВЕСЬ HTTPS дом→хост (`:443`: сайт + registry + portainer) стал TLS-fail (`schannel: failed to receive handshake`), выглядело как «сайт лёг» (а TCP 443/SSH 20435 — открыты). Лечится сменой VPN. **На client-инфру: одна попытка, сбой → стоп и к человеку, не долбить.** (см. [[verify-on-real-client-not-own-curl-tests]])
|
||||
>
|
||||
> ⚠️ **Инцидент 2026-07-21: единичный large-push ТОЖЕ триггерит бан** (не только retry-storm). Первый push `0.3.20` (3.33GB) с VPN → тот же VPN-IP бан → `:443` к хосту TLS-fail с операторского IP (сайт для остальных посетителей работал — Angie access-log это подтвердил; SSH:20435 оставался открыт). **Бан НЕ IP-специфичный для всех — для остальных сайт жив, режется только egress-IP источника push'а.** Митигация: (a) **resume-push после смены egress** — `docker push` resumable, уже залитые слои «Layer already exists» (без re-upload), добивается только остаток + manifest → egress мал → повторный бан не триггерится; (b) **build-on-host + push в localhost-registry** (registry-контейнер на хосте, `127.0.0.1` — вообще без внешнего egress) — самый чистый путь для крупных образов. **Не пытаться долбить упавший push повторно с того же egress.**
|
||||
|
||||
### 3. Передеплой стека — с ХОСТА, мимо Angie BA
|
||||
|
||||
@@ -78,11 +80,25 @@ docker ps --format '{{.Names}}\t{{.Image}}\t{{.Status}}' | grep stostayer-web
|
||||
docker logs --tail 20 stostayer-web # чистый старт Nuxt, без ошибок/краш-лупа
|
||||
```
|
||||
|
||||
**Verify контента (напр. цен) — с хоста, прямым curl в nuxt-контейнер** (Angie даёт 403 на no-UA запрос с самого хоста; обход — `localhost:3000`, host-network):
|
||||
```bash
|
||||
# на хосте (sudo docker + host-network контейнер на :3000)
|
||||
curl -s -H "Host: www.stostayer.ru" -A "Mozilla/5.0" http://localhost:3000/<page> -o /tmp/v.html
|
||||
grep -c "<expected-text>" /tmp/v.html
|
||||
```
|
||||
**Гоча verify-URL:** bare `/remont-kondicionerov` 301-редиректит на `/remont/remont-kondicionerov` (DB-driven `oldPageRedirect`/unit-slug mapping) — это CMS-контент-страница БЕЗ nuxt-компонента. Компоненты `pages/<dir>/*.vue` реально live на своих nuxt-маршрутах (напр. `/remont-kondicionerov/{zapravka,diagnostika}-kondicionera`) — верифицируй по ним, не по bare-URL.
|
||||
|
||||
**Гоча локального smoke-контейнера:** `packages/web/config/default.json` содержит **прод-БД** (`www.stostayer.ru:3306` MariaDB + `:1433` MSSQL), и `www.stostayer.ru` резолвится в публичный IP хоста → smoke-контейнер без env-overrides **подключается к prod-БД клиента по интернету** (read-only SSR, без writes, но всё равно нежелательно). Для чистого локального smoke — переопределяй `data.sequelize.*.host` env'ом на localhost/заглушку, либо глуши контейнер сразу после `Server Listening`.
|
||||
|
||||
### Откат
|
||||
|
||||
Тот же PUT с прежним тегом (`<NEWTAG>` → `0.3.18`), `pullImage:true`. 0.3.18 на хосте есть. RTO ~30-60с (пересоздание контейнера).
|
||||
|
||||
## ⛔ БЛОКЕР: легаси web НЕ пересобирается с текущего master (ESM-стена)
|
||||
## ✅ БЛОКЕР РАЗРЕШЁН 2026-07-21 (retrofit + snolla 0.7.6)
|
||||
|
||||
> **Legacy web снова собирается+запускается с master.** Решение: ретрофит `packages/web` (`require()`→dynamic `import()` в 5 местах, 2 serverMiddleware → CJS) + фикс `@snollajs/snolla@0.7.6` (bare-`get`-баг, см. ниже). Образ `0.3.20` собран, запушен, передеплоен на прод stostayer.ru, verify зелёный. Ретрофит лежит в working-tree stostayer.new (незакоммичен на 2026-07-21) — **stostayer.new должен закоммитить** его в master, иначе следующий legacy-web деплой упрётся в ту же стену. Секция ниже оставлена как история.
|
||||
|
||||
## ⛔ БЛОКЕР (история, 2026-06-17): легаси web НЕ пересобирается с текущего master (ESM-стена)
|
||||
|
||||
> На 2026-06-17 фикс формы жалоб (`120bc07`, задача `stostayer-web-complaint-form-deploy`) **выкатить не удалось** — два ESM-барьера:
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever
|
||||
- [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)
|
||||
- [snolla-live-prod-inplace-image-bump](concepts/snolla-live-prod-inplace-image-bump.md) — переиспользуемый рецепт обновления образа на ЖИВОМ snolla-стеке VDS in-place (build→throwaway-staging-acceptance С VDS→env-preserving Portainer PUT→live-smoke); вкл. `put-stack.js`; отработан на тираже 0.42.1 (4 сайта: labtools/emspb/labtools.pro 2026-07-05 + tandemmebel 2026-07-12)
|
||||
- [stostayer-web-deploy-runbook](concepts/stostayer-web-deploy-runbook.md) — деплой легаси web (`www.stostayer.ru`) на прод клиента: build→registry→Portainer-стек 16 через container-IP API с хоста; **БЛОКЕР: легаси не пересобрать с master (ESM-стена: top-level await @stostayer/data на build, ERR_REQUIRE_ESM @snollajs/snolla в рантайме)**; гоча — один push без retry (VPN-IP банится хостером)
|
||||
- [stostayer-admin-minio-config](concepts/stostayer-admin-minio-config.md) — локальная .NET-админка stostayer (:8090) на stostayer MinIO: креды НЕ в pass (в stostayer.new config), endpoint `minio-api.stostayer.ru` (minio.stostayer.ru — не API-порт), region `us-west-1` (не local); fix 2026-07-22 — 3 замены в Web.config, админка=прод единое хранилище
|
||||
- [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-клиентов**
|
||||
- [recovery-architecture-snapshot](concepts/recovery-architecture-snapshot.md) — текущая recovery architecture (2026-05-19/21, attempt 2)
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
Append-only log of wiki operations (ingests, promotions, lints, migrations).
|
||||
|
||||
## [2026-07-22] fix | NEW concepts/stostayer-admin-minio-config.md — локальная .NET-админка stostayer (`C:\sites\stostayer\Web.config`, IIS :8090) переведена на рабочий stostayer MinIO. Исходно S3-провайдеры (`MoreThenCms.FileStorage.S3` в `bin/`) уже стояли, но с 3 багами: (1) чужие креды `AKIAJ2YJP72W6ZHCRE6Q` = books-vds/snolla root-ключ (копипаст из snolla catch-all admin, не заменён на stostayer-свои → "Access Key Id does not exist"); (2) `serviceURL=https://minio.stostayer.ru` — НЕ S3 API-порт ("S3 API Requests must be made to API port"), прод юзает `minio-api.stostayer.ru`; (3) `authenticationRegion="local"` → SigV4 регион-мismatch → `AmazonS3Exception: the region is wrong; expecting 'us-west-1'` (400) на `GalleriesStorage.EnsureKeyPrefixExists` (`ToolsController.ImagePreview` → `CreatePreview`). Креды stostayer MinIO **не в pass** — лежат в `~/projects/stostayer.new/packages/web/config/default.json` → `s3`: accessKey `stayer_minio`, endpoint `https://minio-api.stostayer.ru`, region `us-west-1`. Fix: 3 глобальные замены × 9 S3-блоков в Web.config (accessKey/secretKey[XML-escaped `>`/`&`]/serviceURL) + region `local`→`us-west-1`; бэкап `Web.config.bak-2026-07-22`; IIS recycle, лог чист. mc `alias set` + ListBuckets OK (10 бакетов: assets/galleries/themes/…); `assets/9cf0a8e52cf144619fd290606a146d35/` несёт реальные файлы. Acceptance оператором: картинки грузятся. Админка=прод единое хранилище, ручное зеркалирование в `App_Data` упразднено. +index.md concepts-строка. Cross-ref [[galleries-storage-class-local-not-s3]], [[snolla-admin-appdata-acl-500-after-scp-migration]], [[minio-imgproxy-on-vds]].
|
||||
|
||||
## [2026-07-14] ingest | sources/de-vds-3xui-setup-2026-07-14.md (new) + entities/de-vds-3xui.md (sources: привязан) — полноценный ingest DE-сессии: sources-хроника с борьбой против 3x-ui 3.5.0 (CSRF-403 на login → `CSRFMiddleware`/`X-CSRF-Token`/`GET {BP}csrf-token`; прямой DB-insert в `inbounds` не рендерит → client-tables `clients`/`client_inbounds`/`client_traffics` заполняются только `AddInbound` → panel API `POST {BP}panel/api/inbounds/add` с stringified settings/streamSettings/sniffing; wrapper `x-ui setting` не применяет креды → бинарник). Эталон JSON снят с рабочего nl-vds 32030. +index.md sources-строка. Real RF-client confirmed.
|
||||
|
||||
## [2026-07-14] decision | entities/de-vds-3xui.md — real-client из РФ подтверждён (user подключён через 32030, сессия идёт через узел). Plain VLESS = proven-working на обоих NL+DE. Задача [de-vds-3xui-setup] закрыта. Перекрестил `Проверено` блок ✅.
|
||||
|
||||
Reference in New Issue
Block a user