# Никаких секретов в выводе плейбуков **Приоритет:** Высокий `inv pl` всегда запускает `ansible-playbook --diff`, поэтому любая задача `template`/`copy`, чей целевой файл содержит переменную vault, печатает значение в терминал — целой строкой, при каждом изменении файла. `no_log: true` стоит ровно в одном месте на весь репозиторий (`roles/secrets`), и именно поэтому miniflux деплоится молча, а остальные — нет. Это тот же класс, что инцидент 24 июля: секрет попадает не в vault-файл, а в поток вывода, у которого нет никакой модели угроз. Скроллбек терминала, мультиплексор, лог CI, транскрипт агента — всё это места, куда расшифрованному значению попадать не должно, и куда оно попадает бесплатно. ## Инвентарь (сверено 2026-07-25) Задачи без `no_log`, рендерящие файл с секретом: - **backups** — `config.template.toml`, `restic-shell.template.sh`, `rclone.template.conf`: пароли репозиториев restic, ключи S3, доступ rclone - **authelia** — `configuration.template.yml`: jwt-секрет, секрет сессий, ключ шифрования хранилища, hmac и jwks OIDC, четыре client secret, SMTP; плюс `users.secrets.yml` — vault-файл копируется как есть, дифф покажет его расшифрованным - **transcriber** — `config.secrets.toml`, тоже vault-файл копией - **bifrost** — `config.template.json`: ключ DeepSeek, ключ шифрования - **apprise** — `server.template.cfg`: токен бота Telegram, SMTP - **remembos** — `config.template.toml`: токены memos и Telegram - **outline, tududi, wakapi, wanderer, gramps, gitea** — секреты в `environment:` docker-compose, см. серию задач `secrets-file-*` Чисто: miniflux (образец), memos, calibre, tuwunel, dashboard, caddy, netdata, dozzle, goaccess, rssbridge, homepage. Отдельным пунктом — `docker_login` в homepage, transcriber и remembos: `yc_oauth_token` идёт параметром модуля. По умолчанию аргументы не печатаются, но всплывают при `-v` и в отчёте о падении. Закрывается тем же `no_log`, а совсем уходит после [local-image-build](local-image-build.md). ## Рычаги и их цена - **`no_log: true`** на задачу — прячет результат целиком, включая дифф. Так уже сделано в `roles/secrets`. Цена: не видно, что именно изменилось; на отладке снимать руками. - **`diff: false`** на задачу — прячет только содержимое диффа, статус `changed` остаётся виден. Хирургичнее, но не закрывает вывод при падении задачи, поэтому для файлов, состоящих из одних секретов, слабее. - **Структурный вынос** — секрет живёт в отдельном файле, который рендерит роль `secrets` под `no_log`, а основной файл ссылается на путь. Тогда дифф основного файла остаётся полезным. Это серия `secrets-file-*`, но она про `environment:` и не покрывает конфиги. - **Убрать `--diff` из `inv pl`** или выставить глобальный `ANSIBLE_NO_LOG` — режет обзор на всех задачах разом ради десятка проблемных. Не годится. ## Порядок 1. ~~`no_log: true` на весь инвентарь выше~~ — **сделано** (коммит `b7b1f49`, 2026-07-25): пятнадцать задач-рендеров и три `docker_login`, всего 13 плейбуков. Не под `no_log` осталась одна задача — compose miniflux: он тянет из vault только `miniflux_postgres_user` и `miniflux_postgres_database`, а это имя пользователя и имя базы, не секреты (в `secrets_vars` роли `secrets` их нет). Дифф образцового файла оставлен читаемым сознательно. 2. Где файл смешанный (compose, конфиг authelia) — вернуться и вынести секреты в отдельные файлы, сняв `no_log` с основного: он нужен ради диффа, который сейчас и теряется. Что именно умеет каждое приложение — матрица в [справке](../drafts/secrets-file-support.md), сверенная по исходникам, и задачи `secrets-file-*` по одной на приложение. Для authelia (конфиг на тысячу строк, дифф там самый ценный) ответ такой: пять полей закрываются `AUTHELIA_..._FILE`, оставшиеся два — только template-фильтром, а четыре `client_secret` штатно хранятся хэшем и тогда вообще перестают быть секретами. Для tududi и wanderer ответа нет: они не умеют читать секреты из файлов, и `no_log` для них — не первый шаг, а единственный. 3. Защита от дрейфа: проверка в lefthook или CI — если шаблон ссылается на переменную, которой нет в открытых `group_vars`/`vars`, задача, которая его рендерит, обязана иметь `no_log`. Иначе следующее приложение заведут по образцу без него. Единственное исключение на сегодня — miniflux (см. шаг 1); чище не заводить исключение в правиле, а перенести `miniflux_postgres_user` и `miniflux_postgres_database` из vault в `group_vars/all/main.yml` — секретами они не являются. Правка в зашифрованном файле, поэтому за пользователем. Готово, когда первый (создающий все файлы) прогон любого плейбука не печатает ни одного значения из vault, и это держится проверкой, а не вниманием. Попутно стоит выяснить, почему молчит правило `no-log-password` в ansible-lint: похоже, оно смотрит на список модулей с параметром `password`, а не на содержимое шаблонов — тогда на него в этой задаче полагаться нельзя. Связано: tasks.py (`inv pl`), roles/secrets (образец), files/backups, files/authelia, files/bifrost, files/apprise, files/remembos, files/transcriber/config.secrets.toml, [vault-password-storage](vault-password-storage.md), [narrow-secret-scopes](narrow-secret-scopes.md).