--- 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 >> /opt/stacks/registry/auth/htpasswd # затем: docker rmi httpd:2-alpine (не оставлять образ на VDS — диск) ``` Проверка: `curl -u : -I -H 'Accept: application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json' https://registry.kzntsv.site/v2//manifests/` → 200. **Важно:** без правильного `Accept` (включая manifest-list + oci) HEAD вернёт 404 даже при существующем теге — это media-type mismatch, не отсутствие образа. ## GC / cleanup Не через Gitea API. Чистка standalone-реестра: - **mark-delete:** registry v2 `DELETE /v2//manifests/` (`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).