Files
admin/.wiki/concepts/bindmount-config-edit-preserve-mode.md
vitya 28de8e60e0 docs(wiki): registry.kzntsv.site auth-model concept + bind-mount config-mode postmortem
- concepts/registry-kzntsv-auth-model.md (new): standalone registry:2 + htpasswd
  Basic, binary access, NOT Gitea-packages; how to add htpasswd users (hot-reload),
  GC via v2 DELETE + host garbage-collect; users vitya + books-ci.
- concepts/bindmount-config-edit-preserve-mode.md (new): mktemp+mv drops file mode
  644->600 -> non-root container (uid 1000) EACCES crash-loop; chmod --reference.
  Worked example: books-job-scheduler prod-down incident 2026-06-18.
- vds-kzntsv entity registry row links the auth-model concept.
- index.md + log.md updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 11:28:58 +03:00

3.3 KiB
Raw Blame History

title, type, tags, updated
title type tags updated
Правка bind-mounted config'а — сохранять file mode (иначе EACCES crash-loop у non-root контейнера) concept
docker
bind-mount
permissions
gotcha
postmortem
books-vds
eacces
2026-06-18

Bind-mounted config: сохраняй mode при правке

Когда правишь config-файл, bind-mounted в контейнер, который бежит под non-root юзером (например books node, uid 1000), атомарная запись через mktemp+mv теряет исходный режим файла и роняет контейнер в crash-loop с EACCES.

Механизм

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 его сохраняет):

chmod --reference="$backup" "$f" && chown --reference="$backup" "$f"

Альтернативы: install -m 644, либо запись в тот же inode (сохраняет mode):

jq ... > "$f.new" && cat "$f.new" > "$f" && rm "$f.new"

Всегда ls -l после — убедиться, что others-read бит на месте для контейнерного uid.

Инцидент 2026-06-18 (worked example)

Добавлял docker.registryAuth (кред books-ci) в /opt/books/job-scheduler/config/default.json на books-vds через 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 — UID 1001 vs 1000 на oCIS (тот же класс: контейнерный uid ≠ root, права host-файлов должны это учитывать).
  • registry-kzntsv-auth-model — что за кред клали, когда словили инцидент.