- install.sh: .agent/src/ (PROTOCOLS, COMMANDS, TEMPLATES, install.sh/ps1, GUIDE)
- .temp/ добавлен в .gitignore
- .agent/checkpoints.json: phases.init=completed, project_type=existing
- .agent/rules/project-rules.md: R1-R5 (инварианты, ловушки, куда лезть, проверки)
- .agent/context/analysis-report.md: стек, архитектура, конвенции, кандидаты CI
- .agent/context/project-state.md: сжатый слепок (хосты, сервисы, ADR)
- .agent/roadmap/sources.md: открытые вопросы слоёв 0-11 (бывший invariants.md)
- .agent/tasks/manifest.{json,md}: 16 задач A1-F + 23 в backlog
- .agent/decisions/0001-sops-secrets-paths.md: ADR для инварианта S1
- AGENTS.md: metaagent-шапка + сжатая выжимка nixos (yaml frontmatter сохранён)
- удалены docs/arch/{map,invariants,todo}.md
5.5 KiB
ADR-0001: sops-пути — только через config.sops.secrets.<name>.path
Статус: accepted
Дата: 2026-10-09
Контекст:
sops-nix материализует секреты на /run/secrets/<attr> по умолчанию.
Атрибут sops-блока (config.sops.secrets.<attr>) — единственный источник
истины для on-disk пути. Любой path = override на sops-блоке плюс хардкод
"/run/secrets/<attr>" в потребителе делает потребителя молча
сломанным: nixos-rebuild проходит, сервис стартует, файл читается — но
контент от прошлой версии или пустой. Симптом приходит из рантайма, не из CI.
До этой правки (см. «Обратное») в кодовой базе были хардкоды путей в 5
местах: authelia.nix, open-webui.nix, tape-rotation.nix, remnawave.nix.
В remnawave.nix тот же риск был двойной: путь хардкожен и в генераторе,
и в контейнере → расхождение двух копий = silent breakage.
Рассматриваемые альтернативы:
- A.
${config.sops.secrets.<attr>.path}— единая точка истины. Любойpath =override автоматически подхватывается потребителем. - B. Хелпер
sopsPath = name: "/run/secrets/${name}"— был вauthelia.nix:51до правки. Компактнее в написании, но тащит хардкод/run/secrets/в API и делает невозможнымpath =override без правки потребителя. - C.
let envFile = "/run/secrets/${name}"; in { … }для композитных случаев — дляremnawave.nix, где один и тот же env-файл читается и генератором, и контейнером. Используется, но с явным комментарием.
Решение: выбран вариант A для прямого доступа к одному секрету и
вариант C для композитных env-файлов в remnawave.nix (с комментарием).
Обоснование:
- Единая точка истины. Атрибут sops-блока — единственное место, где
определяется on-disk путь. Потребитель ссылается на
${config.sops.secrets.<attr>.path}. - Симметрия с
mkUserSecret.users.nix:33-41уже использует этот паттерн (config.sops.secrets.<name>.path) — единый стиль по репо. - Без хелпера.
sopsPath = name: "/run/secrets/${name}"выглядит компактнее, но скрывает хардкод/run/secrets/. Когда кто-то добавитpath = "/var/lib/..."в sops-блок, потребитель через хелпер молча сломается. - Двухкопийный env-файл в remnawave.nix — композитный случай, где
let-биндинг в одном scope с комментарием «не дублировать литерал» делает связь явной.
Последствия:
- Позитивные:
nix flake check(после T1, T2) ловит несоответствие путей в compile-time.path =override в sops-блоке не ломает потребителя молча.- Единый стиль по репо: 5 мест исправлены, новые пишутся по образцу.
- Негативные:
- Длиннее в написании, чем
"/run/secrets/${name}".
- Длиннее в написании, чем
- Риски:
- Если кто-то добавит нового потребителя sops и напишет литерал
/run/secrets/<name>— молчаливое расхождение. Защита: код-ревью + кандидат в CI-проверки (secrets/missing-paths.nixили grep).
- Если кто-то добавит нового потребителя sops и напишет литерал
Invariant:
Любой потребитель sops-секрета в
modules/ссылается на путь через${config.sops.secrets.<attr>.path}, а не через литерал"/run/secrets/<attr>". Атрибут sops-блока — единственный источник истины для on-disk пути.
Зафиксировано в .agent/rules/project-rules.md (R1.7) + analysis-report.md §8.
Обратное (где было сломано до этой правки):
modules/server/authelia.nix:51,108,109— через хелперsopsPath = name: "/run/secrets/${name}".modules/containers/open-webui.nix:95— литеральный хардкод.modules/containers/tape-rotation.nix:61— литеральный хардкод.modules/containers/remnawave.nix:61, 129, 136— литеральный хардкод, в двух местах (генератор + контейнер).
Затронутые файлы (после правки):
modules/server/authelia.nix:107-108modules/containers/open-webui.nix:101modules/containers/tape-rotation.nix:63modules/containers/remnawave.nix:16, 70, 138, 145—let-биндинг для композитного env-файла (вариант C).