Compare commits
2 Commits
53c2756265
...
202b7c32af
| Author | SHA1 | Date | |
|---|---|---|---|
| 202b7c32af | |||
| 28de8e60e0 |
@@ -1,4 +1,5 @@
|
||||
# Admin Task Board
|
||||
_Updated: 2026-06-18 — 🔵 **[books-task-runner-registry-auth-cred] blocked.** Кред books-ci (секция `registry`, baseUrl+username+password — полная, bind-mount затеняет config образа) положен в task-runner config-volume на books-vds; mode 644 root сохранён (бэкап `.bak-pre-registry-2026-06-18`, EACCES-инцидент 25.05→18.06 не повторён), container restart→healthy, `config.get('registry.*')` резолвится. books-ci валиден: `/v2/_catalog`→200, репы books-* видны, 401 нет. **Блокер:** работающий образ (88f2bee, 17.06) содержит СТАРЫЙ registryGc (Gitea API), тега `master-a3734d5` в реестре нет → CI не собрал v2-DELETE rewrite. In-app dryRun ждёт build+deploy. Inbox-ответ books отправлен._
|
||||
_Updated: 2026-06-13 — 🟢 **[migrate-assets-originals-to-s3] closed.** assets-оригиналы (весь `App_Data\assets`: 4750 obj / 215.5 MiB, 145 owner-папок) залиты в новый MinIO bucket `assets` (books-vds) rclone'ом с RUVDS IIS, ключи `<ownerId>/<storageFilename>` verbatim. Verify count+size == source. Smoke (мимо LAN-DNS): brevno.jpg → 200 image/webp 64556 B (был 404), валидно-подписанный несуществующий объект → 404 (негатив-контроль). Код snolla не менялся (path A); scope намеренно шире pilorama98 — закрывает класс-404 для всех тенантов snolla, регрессии нет (shared bucket, как galleries). ⚠️ snolla-side остаётся `content-api/routes/assets.js` (пустой stub) — без него картинки не рендерятся на сайте. Inbox victor/snolla отправлен._
|
||||
_Updated: 2026-06-12 (4) — 🟢 **[migrate-gallery-originals-to-s3] closed (scope pilorama98).** Галереи snolla не отдавались (imgproxy 404) т.к. в legacy `storageClient="galleries"` = тип **Local** (диск `App_Data\galleries\<siteId>`), НЕ S3 — оригиналы никогда туда не заливались (продукты — заливались, bucket `pilorama98`). Развилка A/B закрыта фактами MinIO → **A**: создан bucket `galleries`, залиты 301 файл (77 MiB) pilorama98 (siteId `37e67fc4…`) с RUVDS IIS через rclone → `s3://galleries/<siteId>/<guid>.jpg` verbatim (== ровно то, что строит `middleware/galleries.js:47`). Код snolla НЕ менялся. Verify: count+size == source. Smoke с books-vds: реальный объект imgproxy → 200 webp, fake → 404. Уточнение инфра: `imgproxy.kzntsv.site` с 08.06 на **books-vds** (стек 29/30), не на windows-host — `minio-imgproxy-on-vds.md` был stale. Inbox victor/snolla отправлен._
|
||||
_Updated: 2026-06-12 (3) — 🟢 **bookva-es snapshot done** (не отложен). Portainer stack 37 пересоздан с `path.repo=/snapshots`+bind (PUT API, том цел, epz/products уцелели), repo `kreknin` зарегистрирован, snapshot-блок в `run.sh`. Поймана коллизия basename `snapshots` (оба ES-каталога одноимённы → сливались в один dest-репо, порча обоих) → источник bookva-es = родительский `/usr/docker/bookva-es`. Verified: `BOOKS-VDS backup OK 10m28s`, на kreknin раздельно `snapshots/`(slovo index-41) + `bookva-es/snapshots/`(index-4). Таска `bookva-es-snapshot-repo` 🟢 closed._
|
||||
@@ -715,7 +716,7 @@ Approach ратифицирован человеком (вариант A): ко
|
||||
|
||||
---
|
||||
|
||||
## ⚪ [books-task-runner-registry-auth-cred] — Положить кред books-ci в **task-runner** config-volume, чтобы заработал переписанный `registryGc` (чистка Docker registry через Registry v2 DELETE).
|
||||
## 🔵 [books-task-runner-registry-auth-cred] — Положить кред books-ci в **task-runner** config-volume, чтобы заработал переписанный `registryGc` (чистка Docker registry через Registry v2 DELETE).
|
||||
|
||||
Контекст: registryGc раньше бил в Gitea packages API и никогда не отрабатывал (образы books-* живут в standalone registry:2 на registry.kzntsv.site за htpasswd). Переписан на Registry v2 REST с Basic-auth кредом books-ci (commit books@a3734d5). Кред books-ci уже есть в **job-scheduler** config-volume (для docker pull) — нужен тот же и в **task-runner** (registryGc бежит там, http-runner, отдельный volume).
|
||||
|
||||
@@ -746,11 +747,13 @@ Approach ратифицирован человеком (вариант A): ко
|
||||
**weight:** needs-human — секрет + доступ к VPS config-volume, критичная инфра.
|
||||
**notify:** OpeItcLoc03/books
|
||||
|
||||
**Status:** ready
|
||||
**Where I stopped:** (not started) — код registryGc уже переписан и закоммичен в books (a3734d5), ждёт только кред
|
||||
**Next action:** Добавить секцию registry в task-runner config-volume и положить пароль books-ci
|
||||
**Status:** 🔵 blocked — кред положен+verified, но новый registryGc (a3734d5) НЕ задеплоен
|
||||
**Where I stopped:** Секция `registry` (baseUrl+username+password books-ci, полная — bind-mount затеняет config образа) добавлена в `/opt/books/task-runner/config/default.json` (books-vds, 644 root сохранён, бэкап `.bak-pre-registry-2026-06-18`, только ключ registry added). Container restart → healthy, `config.get('registry.*')` резолвится. Кред books-ci валиден: `/v2/_catalog`→200, репы books-* видны, 401 нет. **НО** работающий образ (88f2bee, 2026-06-17 20:23) содержит СТАРЫЙ registryGc (Gitea packages API, `config.gitea.token`), а в реестре нет тега `master-a3734d5` → CI не собрал новый код. In-app dryRun нового v2-DELETE прогнать нельзя.
|
||||
**Next action:** Дождаться build+deploy `a3734d5` в `books-task-runner:master` (CI → registry → pull на books-vds). По появлении `master-a3734d5` в реестре + подтянутом образе — прогнать `registryGc {dryRun:true}` через /scheduler, проверить repos books-* в отчёте без 401 → close. Inbox-ответ books отправлен (2026-06-18T08-38-57Z-admin.md).
|
||||
**Blocker:** books CI ещё не собрал/задеплоил `a3734d5` (registryGc v2-DELETE rewrite). Owner блокера — books-сессия (notify OpeItcLoc03/books).
|
||||
**Branch:** n/a
|
||||
**Notify:** OpeItcLoc03/books
|
||||
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: victor/books / 2026-06-18T08:28:09.066Z -->
|
||||
<!-- blocked-by: vitya@.admin-exec / 2026-06-18 / cred placed+verified at registry-level; new registryGc code (a3734d5) not built/deployed — running image has old Gitea-API version -->
|
||||
|
||||
---
|
||||
|
||||
44
.wiki/concepts/bindmount-config-edit-preserve-mode.md
Normal file
44
.wiki/concepts/bindmount-config-edit-preserve-mode.md
Normal file
@@ -0,0 +1,44 @@
|
||||
---
|
||||
title: Правка bind-mounted config'а — сохранять file mode (иначе EACCES crash-loop у non-root контейнера)
|
||||
type: concept
|
||||
tags: [docker, bind-mount, permissions, gotcha, postmortem, books-vds, eacces]
|
||||
updated: 2026-06-18
|
||||
---
|
||||
|
||||
# Bind-mounted config: сохраняй mode при правке
|
||||
|
||||
Когда правишь config-файл, **bind-mounted в контейнер, который бежит под non-root юзером** (например books `node`, uid 1000), атомарная запись через `mktemp`+`mv` **теряет исходный режим файла** и роняет контейнер в crash-loop с `EACCES`.
|
||||
|
||||
## Механизм
|
||||
|
||||
```bash
|
||||
jq ... > "$(mktemp)" && mv tmp default.json # ← баг
|
||||
```
|
||||
`mktemp` создаёт файл `0600 root`. `mv` (rename) **заменяет inode**, перенося права temp-файла на цель — **режим назначения НЕ сохраняется** (в отличие от `cp`/`install`). Исходный был `0644`; после правки `others`-read бит пропал → контейнерный uid 1000 не может открыть файл → падение ещё в загрузчике config'а (node lib `config`, `util.parseFile`), до любого прикладного кода:
|
||||
|
||||
```
|
||||
Error: Config file .../default.json cannot be read. Error code is: EACCES
|
||||
```
|
||||
|
||||
## Правильно
|
||||
|
||||
Восстановить mode/owner после mv — проще всего по до-правочному бэкапу (`cp -a` его сохраняет):
|
||||
```bash
|
||||
chmod --reference="$backup" "$f" && chown --reference="$backup" "$f"
|
||||
```
|
||||
Альтернативы: `install -m 644`, либо запись **в тот же inode** (сохраняет mode):
|
||||
```bash
|
||||
jq ... > "$f.new" && cat "$f.new" > "$f" && rm "$f.new"
|
||||
```
|
||||
Всегда `ls -l` после — убедиться, что `others`-read бит на месте для контейнерного uid.
|
||||
|
||||
## Инцидент 2026-06-18 (worked example)
|
||||
|
||||
Добавлял `docker.registryAuth` (кред [`books-ci`](registry-kzntsv-auth-model.md)) в `/opt/books/job-scheduler/config/default.json` на [`books-vds`](../entities/books-vds.md) через `jq>mktemp && mv`. Режим слетел `644 → 600 root`. На ближайшем деплое books (`all`-tenant пересоздаёт контейнеры) `books-job-scheduler` ушёл в `Restarting (1)` каждые ~60с — **прод-даун, slovo-cron'ы стояли**. Корень — не код books и не деплой, а мой способ записи.
|
||||
|
||||
Фикс: `chmod/chown --reference=<backup>` → `-rw-r--r-- root root`. Контейнер сам поднялся на следующей попытке restart-policy (отдельный рестарт не нужен — policy уже крутила). `registryAuth` остался цел.
|
||||
|
||||
## Связанные uid-гочи
|
||||
|
||||
- [`ocis-on-vds-deploy-recipe`](ocis-on-vds-deploy-recipe.md) — UID 1001 vs 1000 на oCIS (тот же класс: контейнерный uid ≠ root, права host-файлов должны это учитывать).
|
||||
- [`registry-kzntsv-auth-model`](registry-kzntsv-auth-model.md) — что за кред клали, когда словили инцидент.
|
||||
56
.wiki/concepts/registry-kzntsv-auth-model.md
Normal file
56
.wiki/concepts/registry-kzntsv-auth-model.md
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
title: registry.kzntsv.site auth model — standalone registry:2 + htpasswd (НЕ Gitea-packages)
|
||||
type: concept
|
||||
tags: [registry, vds-kzntsv, htpasswd, docker, auth, gotcha]
|
||||
sources: [../sources/vds-kzntsv-bootstrap-2026-05-20.md]
|
||||
updated: 2026-06-18
|
||||
---
|
||||
|
||||
# registry.kzntsv.site — auth model
|
||||
|
||||
`registry.kzntsv.site` — это **отдельный `registry:2.8.3` + Joxit UI** на [`vds-kzntsv`](../entities/vds-kzntsv.md) (fresh-install 2026-05-20, см. [bootstrap](../sources/vds-kzntsv-bootstrap-2026-05-20.md) Phase 3.3). Auth — **htpasswd Basic**:
|
||||
|
||||
```
|
||||
GET https://registry.kzntsv.site/v2/ → 401
|
||||
Www-Authenticate: Basic realm="Registry" ← Basic, не Bearer/token
|
||||
```
|
||||
|
||||
## Это НЕ Gitea package registry
|
||||
|
||||
Частая ошибка (books-сессия 2026-06-18 на ней споткнулась): принять реестр за Gitea container-registry. Следствия неверны:
|
||||
|
||||
- **Нет** robot-токенов, scope `read:package`/`delete:package`, per-package visibility, public-read флага. Это не Gitea — таких понятий тут нет.
|
||||
- htpasswd-auth **бинарный**: любой аутентифицированный юзер = full **pull + push + delete** по всем репо. Per-repo ACL нет (без token-auth-сервера, которого тут нет). «Read-only кред» физически невозможен — максимум изоляции = отдельный htpasswd-юзер на потребителя (отзывается точечно).
|
||||
|
||||
## Юзеры (htpasswd)
|
||||
|
||||
Файл: `/opt/stacks/registry/auth/htpasswd` (на vds-kzntsv, `vitya:vitya` rw — sudo не нужен), mount `:ro` в контейнер.
|
||||
|
||||
| Юзер | Кред | Назначение |
|
||||
|---|---|---|
|
||||
| `vitya` | `pass vds-kzntsv/full-env` (Pryakhin9) | master / push с CI |
|
||||
| `books-ci` | `pass vds-kzntsv/registry-books-ci` | books job-scheduler docker-runner pull (createPickingListPdf и др.), заведён 2026-06-18 |
|
||||
|
||||
## Добавить юзера
|
||||
|
||||
Реестр **hot-reload'ит htpasswd при изменении файла — рестарт не нужен** (проверено 2026-06-18). bcrypt-строку проще всего сгенерить через httpd-образ, пароль — через stdin (не в argv):
|
||||
|
||||
```bash
|
||||
printf '%s' "$PW" | docker run --rm -i httpd:2-alpine htpasswd -niB <user> >> /opt/stacks/registry/auth/htpasswd
|
||||
# затем: docker rmi httpd:2-alpine (не оставлять образ на VDS — диск)
|
||||
```
|
||||
|
||||
Проверка: `curl -u <user>:<pw> -I -H 'Accept: application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json' https://registry.kzntsv.site/v2/<repo>/manifests/<tag>` → 200. **Важно:** без правильного `Accept` (включая manifest-list + oci) HEAD вернёт 404 даже при существующем теге — это media-type mismatch, не отсутствие образа.
|
||||
|
||||
## GC / cleanup
|
||||
|
||||
Не через Gitea API. Чистка standalone-реестра:
|
||||
- **mark-delete:** registry v2 `DELETE /v2/<repo>/manifests/<digest>` (`REGISTRY_STORAGE_DELETE_ENABLED=true` уже выставлен). Тот же htpasswd-кред (бинарный auth = delete разрешён).
|
||||
- **disk-reclaim:** только `registry garbage-collect` на host'е — см. [`registry-gc-mount-and-modify-flag`](registry-gc-mount-and-modify-flag.md). Это host-cron, не job из приложения. v2 DELETE сам место не возвращает.
|
||||
- Ручная альтернатива — Joxit UI (`DELETE_IMAGES=true`) на `registry-ui.vds.kzntsv.site`.
|
||||
|
||||
## Связь
|
||||
|
||||
- Хост: [`vds-kzntsv`](../entities/vds-kzntsv.md) (registry-строка в hostnames).
|
||||
- Класс ошибки «no basic auth» в Portainer-стеках: тот же бинарный htpasswd → [`portainer-stack-management-vds`](portainer-stack-management-vds.md).
|
||||
- Инцидент при заведении books-ci кред-файла: [`bindmount-config-edit-preserve-mode`](bindmount-config-edit-preserve-mode.md).
|
||||
@@ -72,7 +72,7 @@ Production CMS (MoreThenCms) **остаётся на** [`windows-recovery-host`]
|
||||
| `traefik.vds.kzntsv.site` | Traefik dashboard | basicAuth vitya / Pryakhin9 | Traefik runtime view |
|
||||
| `git.kzntsv.site` | Gitea | kreknin users restored | Git hosting |
|
||||
| `verdaccio.kzntsv.site` | Verdaccio | kreknin htpasswd (vitya) | Private npm |
|
||||
| `registry.kzntsv.site` | Docker Registry | htpasswd Basic: `vitya` / Pryakhin9; `books-ci` (pass `vds-kzntsv/registry-books-ci`, заведён 2026-06-18 для books job-scheduler pull). **Standalone `registry:2`, НЕ Gitea-packages** — auth бинарный (любой юзер = full pull/push/delete), per-repo ACL нет | Docker images |
|
||||
| `registry.kzntsv.site` | Docker Registry | htpasswd Basic: `vitya` / Pryakhin9; `books-ci` (pass `vds-kzntsv/registry-books-ci`, заведён 2026-06-18). **Standalone `registry:2`, НЕ Gitea-packages** — модель auth + добавление юзеров + GC: [`registry-kzntsv-auth-model`](../concepts/registry-kzntsv-auth-model.md) | Docker images |
|
||||
| `registry-ui.vds.kzntsv.site` | Joxit Registry UI | (proxied к registry, та же auth) | GUI cleanup |
|
||||
| `owncloud.kzntsv.site` | oCIS (ownCloud Infinite Scale) | admin + vitya (pass `owncloud/*`); basic auth enabled для WebDAV/LibreGraph | Personal cloud, replace мёртвой Synology ownCloud (см. [`ocis-on-vds-deploy-recipe`](../concepts/ocis-on-vds-deploy-recipe.md)) |
|
||||
| `postgres.vds.kzntsv.site:5432` | Postgres TLS | postgres / hex32 | Shared DB |
|
||||
|
||||
@@ -23,6 +23,7 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever
|
||||
|
||||
- [admin-infra-project](concepts/admin-infra-project.md) — design + migration plan для OpeItcLoc03/admin (canonical)
|
||||
- [backup-inventory-2026-06](concepts/backup-inventory-2026-06.md) — карта всех машин × что реально бэкапится (с доказательством); дыры по приоритету (kreknin SPOF, nl-vds x-ui.db, bookva-*, openwrt) — триггер: MSSQL 3-нед gap
|
||||
- [bindmount-config-edit-preserve-mode](concepts/bindmount-config-edit-preserve-mode.md) — правка bind-mounted config'а через mktemp+mv роняет режим 644→600 → non-root контейнер (uid 1000) EACCES crash-loop; chmod --reference=backup. Инцидент books-job-scheduler 2026-06-18
|
||||
- [vds-kzntsv-ssh-access](concepts/vds-kzntsv-ssh-access.md) — SSH access audit на vds-kzntsv (infra VDS), retained keys + add/revoke processes (was misnamed `books-ssh-access` до 2026-05-25 — content всегда был про vds-kzntsv)
|
||||
- [compose-bcrypt-escape-trap](concepts/compose-bcrypt-escape-trap.md) — Docker Compose ест `$` в bcrypt hashes
|
||||
- [db-tls-self-signed-via-traefik-raw-tcp](concepts/db-tls-self-signed-via-traefik-raw-tcp.md) — DB TLS через traefik raw TCP с self-signed certs
|
||||
@@ -44,6 +45,7 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever
|
||||
- [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)
|
||||
- [registry-gc-mount-and-modify-flag](concepts/registry-gc-mount-and-modify-flag.md) — Docker Registry GC mount layout + `-m` flag
|
||||
- [registry-kzntsv-auth-model](concepts/registry-kzntsv-auth-model.md) — registry.kzntsv.site = standalone registry:2 + htpasswd Basic (бинарный доступ, НЕ Gitea-packages, нет per-repo ACL/robot-токенов); как заводить htpasswd-юзеров (hot-reload), GC через v2 DELETE; юзеры vitya + books-ci
|
||||
- [rusonyx-vps-onboarding-quirks](concepts/rusonyx-vps-onboarding-quirks.md) — Rusonyx VPS onboarding quirks (Astra Облако / myvm.rusonyx.ru)
|
||||
- [traefik-acme-json-to-iis-cert-import](concepts/traefik-acme-json-to-iis-cert-import.md) — Экспорт LE certs из traefik acme.json в IIS (PFX + SNI bindings)
|
||||
- [traefik-file-watch-wsl2-broken](concepts/traefik-file-watch-wsl2-broken.md) — Traefik file-watch broken под Docker Desktop Windows (WSL2 9p mount)
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
Append-only log of wiki operations (ingests, promotions, lints, migrations).
|
||||
|
||||
## [2026-06-18] ingest | concepts/registry-kzntsv-auth-model.md (new) + concepts/bindmount-config-edit-preserve-mode.md (new) — registry.kzntsv.site = standalone registry:2 + htpasswd Basic (бинарный доступ, НЕ Gitea-packages; нет per-repo ACL/robot-токенов; hot-reload htpasswd; GC через v2 DELETE + host garbage-collect; завёл юзера books-ci для books job-scheduler pull, кред в pass vds-kzntsv/registry-books-ci). Постмортем: правка bind-mounted `default.json` через mktemp+mv уронила режим 644→600 → `books-job-scheduler` EACCES crash-loop (прод-даун slovo-cron), fix chmod/chown --reference=backup. +entities/vds-kzntsv.md (registry-строка) +index.md. Источник: консультация+инфра-деплой books registry-auth + инцидент 2026-06-18.
|
||||
|
||||
## [2026-06-17] ingest | concepts/stostayer-web-deploy-runbook.md (new) — ранбук деплоя легаси web на прод stostayer: канал build(offline)→push docker.stostayer.ru→Portainer-стек 16 через container-IP API (172.18.0.2:9000) с хоста мимо Angie BA; rollback; БЛОКЕР ESM-стена (top-level await @stostayer/data на build + ERR_REQUIRE_ESM @snollajs/snolla в рантайме d02f740) → 0.3.18 остаётся; гоча VPN-IP бан хостером при retry-push-шторме. Источник: попытка деплоя `stostayer-web-complaint-form-deploy` 2026-06-17 (откат на 0.3.18). +index.md.
|
||||
|
||||
## [2026-06-17] update | entities/windows-recovery-host.md — уточнён live-state двух stostayer-IIS-сайтов: добавлена таблица порт→connection string→БД (`stostayer` :8090→`www.stostayer.ru,1433` внешний прод + S3 minio.stostayer.ru; `stostayer.old` :8091→`mssql.kzntsv.site,1433` наш VDS), путь админок `/admin`, live-проверка 2026-06-17 (W3SVC Running, :8090/:8091 LISTENING, :80 нет). Пофикшена стейловая строка в «Ключевые папки» (stostayer.old conn localhost→mssql.kzntsv.site). Источник: live-аудит IIS на DESKTOP-NSEF0UK.
|
||||
|
||||
Reference in New Issue
Block a user