Compare commits
14
Commits
daa4379dbe
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5217607b1
|
||
|
|
856bf72560
|
||
|
|
70372ee028
|
||
|
|
16f0712a31
|
||
|
|
3bb85b85f6
|
||
|
|
7e64d76d02
|
||
|
|
6bb0d61183
|
||
|
|
304263e7b1
|
||
|
|
25886d1be0
|
||
|
|
b9be642c5c
|
||
|
|
9c75a52529
|
||
|
|
a909442d8f
|
||
|
|
6ff11061d9
|
||
|
|
a9d9eb8d83
|
@@ -17,24 +17,20 @@ _(sec-ревью)_ — три независимых security-ревью на м
|
|||||||
|
|
||||||
## Высокий
|
## Высокий
|
||||||
|
|
||||||
- [Закрыть admin API Caddy (localhost вместо всей сети)](caddy-admin-api-localhost.md) — `admin :2019` слушает всю docker-сеть; любой контейнер может переписать маршрутизацию и снять forward_auth _(sec-ревью)_
|
|
||||||
- [Убрать группу `docker` у сервисных пользователей](service-users-docker-group.md) — `docker` = root на хосте; ~все app-аккаунты фактически root, изоляция «юзер на сервис» обнуляется _(sec-ревью)_
|
|
||||||
- [Изолировать/запаролить сессионный redis Authelia](authelia-redis-isolation.md) — стор сессий SSO в общей сети без пароля; запись в него = hijack SSO всех сервисов _(sec-ревью)_
|
- [Изолировать/запаролить сессионный redis Authelia](authelia-redis-isolation.md) — стор сессий SSO в общей сети без пароля; запись в него = hijack SSO всех сервисов _(sec-ревью)_
|
||||||
- [Алерты на проблемные контейнеры](container-alerts.md) — wakapi крутился в restart-loop несколько дней незамеченным; healthcheck в compose + алерты Netdata
|
- [Алерты на проблемные контейнеры](container-alerts.md) — wakapi крутился в restart-loop несколько дней незамеченным; healthcheck в compose + алерты Netdata
|
||||||
- [Никаких секретов в выводе плейбуков](no-secrets-in-playbook-output.md) — `inv pl` всегда с `--diff`, и каждая задача, рендерящая файл с секретом, печатает его в терминал; `no_log` стоит ровно в одном месте из четырнадцати
|
- [Никаких секретов в выводе плейбуков](no-secrets-in-playbook-output.md) — `inv pl` всегда с `--diff`, и каждая задача, рендерящая файл с секретом, печатает его в терминал; `no_log` стоит ровно в одном месте из четырнадцати
|
||||||
|
|
||||||
## Средний
|
## Средний
|
||||||
|
|
||||||
|
- [Дампы бэкапов без группы `docker`](backup-dump-without-docker-group.md) — у miniflux/gitea/outline группа осталась: их backup.sh дампит через `docker compose exec` из-под самого приложения
|
||||||
- [Захардить мониторинг-стек (netdata / dozzle / goaccess)](harden-monitoring-stack.md) — netdata/dozzle: лишние привилегии + docker.sock + доверие Remote-User в общей сети; socket-proxy + monitoring_network _(sec-ревью)_
|
- [Захардить мониторинг-стек (netdata / dozzle / goaccess)](harden-monitoring-stack.md) — netdata/dozzle: лишние привилегии + docker.sock + доверие Remote-User в общей сети; socket-proxy + monitoring_network _(sec-ревью)_
|
||||||
- [Ограничить эндпоинт `/metrics` Miniflux](miniflux-metrics-restrict.md) — `METRICS_ALLOWED_NETWORKS=0.0.0.0/0` + прокси без ограничения пути отдаёт метрики публично _(sec-ревью)_
|
|
||||||
- [Закрыть calibre-web forward-auth и проверить дефолтные креды](calibre-forward-auth.md) — домен без forward_auth, защита на встроенной авторизации с дефолтом `admin/admin123` _(sec-ревью)_
|
- [Закрыть calibre-web forward-auth и проверить дефолтные креды](calibre-forward-auth.md) — домен без forward_auth, защита на встроенной авторизации с дефолтом `admin/admin123` _(sec-ревью)_
|
||||||
- [Понизить log level Authelia с debug до info](authelia-log-level.md) — `debug` в проде утекает детали аутентификации и OIDC через `docker logs`/dozzle _(sec-ревью)_
|
|
||||||
- [Включить автообновления безопасности](security-autoupdates.md) — патчи openssh/libssl только вручную; окна в недели между CVE и фиксом _(sec-ревью)_
|
- [Включить автообновления безопасности](security-autoupdates.md) — патчи openssh/libssl только вручную; окна в недели между CVE и фиксом _(sec-ревью)_
|
||||||
- [Запретить SSH-вход под root](ssh-disable-root-login.md) — `PermitRootLogin yes` пускает root по ключу; наименьшие привилегии + defense-in-depth (пароль уже off) _(sec-ревью)_
|
- [Запретить SSH-вход под root](ssh-disable-root-login.md) — `PermitRootLogin yes` пускает root по ключу; наименьшие привилегии + defense-in-depth (пароль уже off) _(sec-ревью)_
|
||||||
- [Gitea runner on-demand в Yandex Cloud](gitea-runner-on-demand.md) — раннер активен только во время сборки; webhook→Cloud Function стартует ВМ, probe/decide гасят по idle; экономия ~95%
|
- [Gitea runner on-demand в Yandex Cloud](gitea-runner-on-demand.md) — раннер активен только во время сборки; webhook→Cloud Function стартует ВМ, probe/decide гасят по idle; экономия ~95%
|
||||||
- [Синхронизация общих Ansible-ролей между репозиториями](shared-roles-sync.md) — `owner`/`eget`/`secrets` дублируются между репозиториями и дрейфуют; канон в ansible-shared + rsync-таски invoke
|
- [Синхронизация общих Ansible-ролей между репозиториями](shared-roles-sync.md) — `owner`/`eget`/`secrets` дублируются между репозиториями и дрейфуют; канон в ansible-shared + rsync-таски invoke
|
||||||
- [Уведомления о размере приложений и заполнении диска](disk-usage-alerts.md) — алерты на заполнение диска и аномальный рост data-томов; сервер ресурсно ограничен _(tududi)_
|
- [Уведомления о размере приложений и заполнении диска](disk-usage-alerts.md) — алерты на заполнение диска и аномальный рост data-томов; сервер ресурсно ограничен _(tududi)_
|
||||||
- [Handlers рестарта для оставшихся приложений](handlers-remaining-apps.md) — apprise/dashboard/transcriber/miniflux монтируют конфиг в контейнер, но рестарта нет вовсе; правка конфига не подхватывается
|
|
||||||
- [Composable-роль `backup`](ansible-backup-role.md) — бэкап — самый чистый шов для extraction (одинаков у всех, различается только список targets) _(ансибл-ревью)_
|
- [Composable-роль `backup`](ansible-backup-role.md) — бэкап — самый чистый шов для extraction (одинаков у всех, различается только список targets) _(ансибл-ревью)_
|
||||||
- [Вывести из оборота секреты с широкими правами](narrow-secret-scopes.md) — `yc_oauth_token` (весь аккаунт Yandex Cloud) уже выведен; осталось проставить радиус остальным переменным vault и сузить широкие
|
- [Вывести из оборота секреты с широкими правами](narrow-secret-scopes.md) — `yc_oauth_token` (весь аккаунт Yandex Cloud) уже выведен; осталось проставить радиус остальным переменным vault и сузить широкие
|
||||||
- [outline: секреты из файлов](secrets-file-outline.md) — умеет generic `<NAME>_FILE` для всех пяти секретов; единственное приложение, где выносится вообще всё, включая пароль БД
|
- [outline: секреты из файлов](secrets-file-outline.md) — умеет generic `<NAME>_FILE` для всех пяти секретов; единственное приложение, где выносится вообще всё, включая пароль БД
|
||||||
@@ -44,10 +40,8 @@ _(sec-ревью)_ — три независимых security-ревью на м
|
|||||||
|
|
||||||
## Низкий
|
## Низкий
|
||||||
|
|
||||||
- [Мелкий хардненинг Caddy](caddy-hardening-nits.md) — HSTS-заголовок, убрать лишний `NET_ADMIN`, убрать leftover-листенер `:29999` _(sec-ревью)_
|
|
||||||
- [Мелкий хардненинг контейнеров](container-hardening-nits.md) — `no-new-privileges`, non-root `user:`, homepage off `:latest`, соглашение о `127.0.0.1:` портах _(sec-ревью)_
|
- [Мелкий хардненинг контейнеров](container-hardening-nits.md) — `no-new-privileges`, non-root `user:`, homepage off `:latest`, соглашение о `127.0.0.1:` портах _(sec-ревью)_
|
||||||
- [Унифицировать ACL техпанелей Authelia](authelia-acl-unify.md) — rssbridge (SSRF) и dashboard за `one_factor` без subject; свести к `group:admins` + `two_factor` _(sec-ревью)_
|
- [Унифицировать ACL техпанелей Authelia](authelia-acl-unify.md) — rssbridge (SSRF) и dashboard за `one_factor` без subject; свести к `group:admins` + `two_factor` _(sec-ревью)_
|
||||||
- [Причесать роль `owner` под конвенции](ansible-owner-role-cleanup.md) — `assert` вместо `fail`+`when`, `loop` вместо `with_*`, добавить `meta`/README _(ансибл-ревью)_
|
|
||||||
- [Инвентарь: `host_vars`, именованные группы, точечный `become`](ansible-inventory-hostvars.md) — хост-специфику в `host_vars/server.yml`, хост в именованную группу, глобальный root → точечный become _(ансибл-ревью)_
|
- [Инвентарь: `host_vars`, именованные группы, точечный `become`](ansible-inventory-hostvars.md) — хост-специфику в `host_vars/server.yml`, хост в именованную группу, глобальный root → точечный become _(ансибл-ревью)_
|
||||||
- [Фоновая зачистка стиля и конфигурации Ansible](ansible-style-nits.md) — sudoers.d, профиль ansible-lint, `ansible.cfg`, кавычки, `cache_valid_time` _(ансибл-ревью)_
|
- [Фоновая зачистка стиля и конфигурации Ansible](ansible-style-nits.md) — sudoers.d, профиль ansible-lint, `ansible.cfg`, кавычки, `cache_valid_time` _(ансибл-ревью)_
|
||||||
- [Logrotate для логов бэкапов](backup-logs-logrotate.md) — логи `backup-all.py`/restic копятся без ротации _(tududi)_
|
- [Logrotate для логов бэкапов](backup-logs-logrotate.md) — логи `backup-all.py`/restic копятся без ротации _(tududi)_
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
# Причесать роль `owner` под конвенции
|
|
||||||
|
|
||||||
**Приоритет:** низкий
|
|
||||||
|
|
||||||
Роль `owner` разошлась по стилю с `eget`/`secrets`:
|
|
||||||
|
|
||||||
- **`roles/owner/tasks/main.yml:2-10`** — валидация аргументов через `fail` +
|
|
||||||
`when`, причём две задачи с **идентичным именем**. `eget` для того же делает
|
|
||||||
`assert` (`roles/eget/tasks/main.yml:15`). Привести к одному стилю — `assert`
|
|
||||||
либо декларативный `meta/argument_specs.yml`.
|
|
||||||
- **`roles/owner/tasks/main.yml:32,53`** — устаревшие `with_items`/`with_dict`;
|
|
||||||
конвенция — `loop` (`loop: "{{ owner_ssh_keys }}"`,
|
|
||||||
`loop: "{{ owner_env_dict | dict2items }}"`).
|
|
||||||
- У `owner` нет `meta/main.yml` и README, тогда как у `eget` и `secrets` есть.
|
|
||||||
- Имена задач с точкой на конце (`"Prepare env variables."`) — ansible-lint в
|
|
||||||
строгом профиле это ловит.
|
|
||||||
|
|
||||||
Контекст: [docs/drafts/ansible-review.md](../drafts/ansible-review.md) §5.
|
|
||||||
|
|
||||||
Связано: roles/owner, roles/eget (образец), roles/secrets.
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# Понизить log level Authelia с debug до info
|
|
||||||
|
|
||||||
**Приоритет:** средний
|
|
||||||
|
|
||||||
`files/authelia/configuration.template.yml` — `log.level: "debug"`. Debug-логи
|
|
||||||
Authelia содержат детали запросов аутентификации, имена пользователей, заголовки и
|
|
||||||
внутренние подробности OIDC-потоков — они не нужны в обычной эксплуатации и
|
|
||||||
расширяют поверхность утечки через `docker logs`/dozzle (который сам открыт
|
|
||||||
админам). Поставить `info` (или `warn`), debug включать точечно при отладке.
|
|
||||||
|
|
||||||
Из sec-ревью (fable, 2026-07-13).
|
|
||||||
|
|
||||||
Связано: files/authelia/configuration.template.yml.
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Дампы бэкапов без группы `docker` у сервисных пользователей
|
||||||
|
|
||||||
|
**Приоритет:** средний
|
||||||
|
|
||||||
|
Группу `docker` (= root на хосте) убрали у всех сервисных пользователей, кроме
|
||||||
|
трёх: `miniflux`, `gitea`, `outline`. Их `backup.sh` делает `docker compose exec`
|
||||||
|
(pg_dump, `gitea dump`), а `files/backups/backup-all.py` запускает такие скрипты
|
||||||
|
через `su --login <app_user>`, то есть от имени самого приложения — без членства
|
||||||
|
в группе дамп упадёт.
|
||||||
|
|
||||||
|
Дампить снаружи докера нельзя: postgres порт не публикует, `gitea dump` живёт
|
||||||
|
только внутри контейнера.
|
||||||
|
|
||||||
|
Варианты, как развязать:
|
||||||
|
|
||||||
|
- **A. sudo-обёртка на дамп.** Плейбук кладёт `/usr/local/sbin/backup-<app>-dump.sh`
|
||||||
|
(root:root, 0755 — сам app_user его не перепишет) с единственным
|
||||||
|
`docker compose exec …`, в sudoers — `<app_user> ALL=(root) NOPASSWD:` ровно на
|
||||||
|
этот файл, а `backup.sh` дёргает его через `sudo`. Пользователь получает право
|
||||||
|
на одну фиксированную команду вместо права на весь докер. Механизм в проекте
|
||||||
|
уже обкатан: так `playbook-backups.yml` разрешает `primary_user` запускать
|
||||||
|
`backup-all.py`.
|
||||||
|
- **B. root-скрипты в оркестраторе.** Новый контракт в `backup-all.py`: если у
|
||||||
|
приложения есть `backup-root.sh` с владельцем root — запускать его без `su`.
|
||||||
|
Механизм один на всех, но от root пойдёт скрипт целиком, включая
|
||||||
|
`keep-files.py`, и дампы станут root-овыми файлами в директориях приложения.
|
||||||
|
- **C. оставить как есть** — три аккаунта как осознанное исключение,
|
||||||
|
задокументированное в плейбуках.
|
||||||
|
|
||||||
|
Предпочтение на момент записи — A.
|
||||||
|
|
||||||
|
Связано: playbook-miniflux.yml, playbook-gitea.yml, playbook-outline.yml,
|
||||||
|
files/*/backup.template.sh, files/backups/backup-all.py.
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# Закрыть admin API Caddy (localhost вместо всей сети)
|
|
||||||
|
|
||||||
**Приоритет:** высокий
|
|
||||||
|
|
||||||
`files/caddyproxy/Caddyfile.template:8` — `admin :2019`: admin API слушает на всех
|
|
||||||
интерфейсах контейнера, а в `web_proxy_network` сидят все приложения. Любой
|
|
||||||
скомпрометированный контейнер (rssbridge, tududi, calibre, ...) может POST-ом в
|
|
||||||
`http://caddyproxy:2019/config/` переписать маршрутизацию, снять `forward_auth`,
|
|
||||||
перехватить трафик или сертификаты. Порт реально нужен только netdata для метрик
|
|
||||||
(`files/netdata/go.d/prometheus.conf`). Фикс: вернуть `admin localhost:2019`, а
|
|
||||||
метрики отдать отдельным site-блоком `:2019 { metrics }` — netdata продолжит
|
|
||||||
скрейпить, admin API станет недоступен из сети.
|
|
||||||
|
|
||||||
Из sec-ревью (fable, 2026-07-13).
|
|
||||||
|
|
||||||
Связано: files/caddyproxy/Caddyfile.template, files/netdata/go.d/prometheus.conf.
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# Мелкий хардненинг Caddy
|
|
||||||
|
|
||||||
**Приоритет:** низкий
|
|
||||||
|
|
||||||
- **HSTS**: заголовок `Strict-Transport-Security` не выставляется нигде в
|
|
||||||
`files/caddyproxy/Caddyfile.template`. Одна строка `header
|
|
||||||
Strict-Transport-Security "max-age=31536000"` в общем сниппете (рядом с
|
|
||||||
`access_log`) закрывает downgrade/SSL-strip для всех поддоменов разом.
|
|
||||||
- **Лишний `NET_ADMIN`** (`files/caddyproxy/docker-compose.template.yml`) —
|
|
||||||
reverse-proxy эта capability не нужна (требуется лишь для тюнинга UDP-буферов
|
|
||||||
HTTP/3, работает и без неё с warning). Убрать у edge-контейнера, торчащего в
|
|
||||||
интернет.
|
|
||||||
- **Leftover-листенер `:29999`** в `Caddyfile.template` (site `status.vakhrushev.me,
|
|
||||||
:29999`) — наследие прямого доступа к netdata; убрать, оставив только доменный
|
|
||||||
site-блок.
|
|
||||||
|
|
||||||
Из sec-ревью (fable, 2026-07-13).
|
|
||||||
|
|
||||||
Связано: files/caddyproxy/Caddyfile.template, files/caddyproxy/docker-compose.template.yml.
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# Handlers рестарта для оставшихся приложений
|
|
||||||
|
|
||||||
**Приоритет:** средний
|
|
||||||
|
|
||||||
Паттерн `handlers` + `notify` внедрён в caddyproxy, netdata, authelia, bifrost,
|
|
||||||
remembos (см. задачу `ansible-handlers-restart`, закрыта). Остались плейбуки, где
|
|
||||||
конфиг bind-моунтится в контейнер, но рестарта нет **вообще** — правка конфига без
|
|
||||||
изменения docker-compose.yml не подхватывается до следующего пересоздания
|
|
||||||
контейнера:
|
|
||||||
|
|
||||||
- `playbook-apprise.yml` — `server.cfg` → `config_dir:/config`.
|
|
||||||
- `playbook-dashboard.yml` — `config/*.yaml` → `config_dir:/app/config`.
|
|
||||||
- `playbook-transcriber.yml` — `config.toml` bind-моунтится **отдельным файлом**
|
|
||||||
(`{{ config_file }}:/config/config.toml:ro`). Худший случай: `template`
|
|
||||||
перезаписывает файл с новым inode, и контейнер продолжает видеть старый до
|
|
||||||
рестарта.
|
|
||||||
- `playbook-miniflux.yml` — файлы секретов роли `secrets` → `secrets_dir:/secrets:ro`,
|
|
||||||
читаются через `*_FILE` при старте.
|
|
||||||
|
|
||||||
Заодно проверить `playbook-goaccess.yml`: конфиг там не монтируется, но
|
|
||||||
`Dockerfile`/`entrypoint.sh` меняются без изменения compose-файла — надо
|
|
||||||
убедиться, что `build: always` действительно пересоздаёт контейнер.
|
|
||||||
|
|
||||||
Отдельный кандидат: caddy сейчас перезапускается целиком, хотя умеет
|
|
||||||
`caddy reload` — применение Caddyfile без разрыва соединений на реверс-прокси,
|
|
||||||
через который идёт весь трафик. В `playbook-caddyproxy.yml` для этого уже лежит
|
|
||||||
закомментированный блок с `docker_compose_v2_exec`.
|
|
||||||
|
|
||||||
Связано: playbook-apprise.yml, playbook-dashboard.yml, playbook-transcriber.yml,
|
|
||||||
playbook-miniflux.yml, playbook-goaccess.yml, playbook-caddyproxy.yml.
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# Ограничить эндпоинт `/metrics` Miniflux
|
|
||||||
|
|
||||||
**Приоритет:** средний
|
|
||||||
|
|
||||||
В `files/miniflux/docker-compose.template.yml` заданы `METRICS_COLLECTOR=1` и
|
|
||||||
`METRICS_ALLOWED_NETWORKS=0.0.0.0/0`, а Caddy проксирует весь
|
|
||||||
`miniflux.vakhrushev.me` без ограничения пути. За прокси Miniflux видит приватный
|
|
||||||
IP контейнера Caddy (попадает в `0.0.0.0/0`), поэтому
|
|
||||||
`https://miniflux.vakhrushev.me/metrics` отдаётся публично без аутентификации —
|
|
||||||
утечка эксплуатационной статистики. Сузить `METRICS_ALLOWED_NETWORKS` до подсети
|
|
||||||
`monitoring_network` (netdata скрейпит по внутреннему имени) или заблокировать
|
|
||||||
путь `/metrics` в Caddy.
|
|
||||||
|
|
||||||
Из sec-ревью (fable, 2026-07-13).
|
|
||||||
|
|
||||||
Связано: files/miniflux/docker-compose.template.yml, files/caddyproxy/Caddyfile.template.
|
|
||||||
@@ -25,7 +25,7 @@ miniflux деплоится молча, а остальные — нет.
|
|||||||
расшифрованным
|
расшифрованным
|
||||||
- **transcriber** — `config.secrets.toml`, тоже vault-файл копией
|
- **transcriber** — `config.secrets.toml`, тоже vault-файл копией
|
||||||
- **bifrost** — `config.template.json`: ключ DeepSeek, ключ шифрования
|
- **bifrost** — `config.template.json`: ключ DeepSeek, ключ шифрования
|
||||||
- **apprise** — `server.template.cfg`: токен бота Telegram, SMTP
|
- **apprise** — `backups.template.cfg`: SMTP, пароль matrix-бота
|
||||||
- **remembos** — `config.template.toml`: токены memos и Telegram
|
- **remembos** — `config.template.toml`: токены memos и Telegram
|
||||||
- **outline, tududi, wakapi, wanderer, gramps, gitea** — секреты в
|
- **outline, tududi, wakapi, wanderer, gramps, gitea** — секреты в
|
||||||
`environment:` docker-compose, см. серию задач `secrets-file-*`
|
`environment:` docker-compose, см. серию задач `secrets-file-*`
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
# Убрать группу `docker` у сервисных пользователей
|
|
||||||
|
|
||||||
**Приоритет:** высокий
|
|
||||||
|
|
||||||
Все приложения заводят системного пользователя с `owner_extra_groups: ["docker"]`
|
|
||||||
(во всех `playbook-*.yml`), но docker.sock реально монтируют только netdata и
|
|
||||||
dozzle. Членство в группе `docker` эквивалентно root на хосте (`docker run -v
|
|
||||||
/:/host`), поэтому выделенные «непривилегированные» аккаунты (authelia, outline,
|
|
||||||
gitea и т.д.) фактически все имеют root — изоляция «пользователь на сервис», ради
|
|
||||||
которой их и заводили, обнуляется. Контейнерами рулит Ansible от root (become),
|
|
||||||
сервисам группа не нужна. Убрать `docker` из `owner_extra_groups` у всех, кроме
|
|
||||||
тех, кому он действительно нужен для самостоятельного управления своим compose (и
|
|
||||||
тем — лучше через socket-proxy). За `primary_user` группу оставить для ручных
|
|
||||||
операций (`inv ssh`).
|
|
||||||
|
|
||||||
Из sec-ревью (fable, 2026-07-13). Усиливает риск из серии `secrets-file-*`
|
|
||||||
(секреты в `environment:` контейнеров): членство в группе `docker` — как раз тот
|
|
||||||
доступ, которым такие переменные и вычитываются.
|
|
||||||
|
|
||||||
Связано: все playbook-*.yml (owner_extra_groups), roles/owner, playbook-docker.yml.
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
mailtos://{{ postbox_user }}:{{ postbox_pass }}@{{ postbox_host }}:{{ postbox_port }}/?from=notifications@vakhrushev.me&to={{ notifications_email }}
|
||||||
|
# Пароль бота экранируем дважды: jinja-фильтр urlencode оставляет '/' как есть
|
||||||
|
# (safe='/'), а в пароле он развалил бы путь URL. После urlencode литеральных
|
||||||
|
# процентов в строке нет, поэтому замена '/' на %2F безопасна.
|
||||||
|
matrix://apprise:{{ notifications_matrix_bot_password | urlencode | regex_replace('/', '%2F') }}@tuwunel:6167/{{ notifications_matrix_room }}?msgtype=text
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
tgram://{{ notifications_tg_bot_token }}/{{ notifications_tg_chat_id }}
|
|
||||||
mailtos://{{ postbox_user }}:{{ postbox_pass }}@{{ postbox_host }}:{{ postbox_port }}/?from=notifications@vakhrushev.me&to={{ notifications_email }}
|
|
||||||
@@ -121,7 +121,7 @@ server:
|
|||||||
##
|
##
|
||||||
log:
|
log:
|
||||||
## Level of verbosity for logs: info, debug, trace.
|
## Level of verbosity for logs: info, debug, trace.
|
||||||
level: "debug"
|
level: "info"
|
||||||
|
|
||||||
## Format the logs are written as: json, text.
|
## Format the logs are written as: json, text.
|
||||||
format: "json"
|
format: "json"
|
||||||
|
|||||||
@@ -44,4 +44,4 @@ RCLONE_CONFIG = "{{ rclone_config_file }}"
|
|||||||
[notifier.apprise]
|
[notifier.apprise]
|
||||||
type = "apprise"
|
type = "apprise"
|
||||||
api_url = "{{ apprise_external_url }}"
|
api_url = "{{ apprise_external_url }}"
|
||||||
tag = "server"
|
tag = "backups"
|
||||||
|
|||||||
@@ -5,21 +5,38 @@
|
|||||||
grace_period 15s
|
grace_period 15s
|
||||||
|
|
||||||
# Admin API слушает только loopback контейнера: на :2019 его видела бы вся
|
# Admin API слушает только loopback контейнера: на :2019 его видела бы вся
|
||||||
|
# web_proxy_network, и любое приложение могло бы переписать маршрутизацию
|
||||||
|
# или снять forward_auth. Метрики вынесены в отдельный site-блок ниже, и
|
||||||
|
# порт у него другой: сайт на :2019 перехватывал бы IPv6-петлю (admin висит
|
||||||
|
# только на IPv4), и `caddy reload` молча ничего не применял бы.
|
||||||
|
admin localhost:2019
|
||||||
|
|
||||||
# Enable metrics in Prometheus format
|
# Enable metrics in Prometheus format
|
||||||
# https://caddyserver.com/docs/metrics
|
# https://caddyserver.com/docs/metrics
|
||||||
metrics
|
metrics
|
||||||
}
|
}
|
||||||
|
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
|
# Metrics
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Prometheus-метрики для netdata (files/netdata/go.d/prometheus.conf).
|
||||||
|
# Наружу порт не публикуется — доступен только внутри web_proxy_network.
|
||||||
|
http://:2020 {
|
||||||
|
metrics /metrics
|
||||||
|
}
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------
|
||||||
# Snippets
|
# Snippets
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
|
|
||||||
# Общие настройки всех сайтов: access-лог и HSTS.
|
# Общие настройки всех сайтов: access-лог и HSTS.
|
||||||
# Mode 644 lets read-only consumers (goaccess and ad-hoc host-side tail)
|
#
|
||||||
# read the file; lumberjack would otherwise default to 0600.
|
# Лог общий для всех сайтов, его разбирает GoAccess. Mode 644 нужен, чтобы
|
||||||
(access_log) {
|
# файл читали потребители на хосте (goaccess и ad-hoc tail): lumberjack иначе
|
||||||
log {
|
# ставит 0600.
|
||||||
|
(common) {
|
||||||
|
log {
|
||||||
output file /var/log/caddy/access.log {
|
output file /var/log/caddy/access.log {
|
||||||
mode 644
|
mode 644
|
||||||
roll_size 100mib
|
roll_size 100mib
|
||||||
@@ -29,6 +46,12 @@
|
|||||||
format json
|
format json
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# HSTS: браузер, однажды увидевший заголовок, целый год ходит на это имя только
|
||||||
|
# по https, минуя редирект с http, — закрывает downgrade и SSL-strip.
|
||||||
|
# Без includeSubDomains: политика по каждому имени своя, а под vakhrushev.me
|
||||||
|
# есть поддомены не с этого сервера (например photo.vakhrushev.me).
|
||||||
|
header Strict-Transport-Security "max-age=31536000"
|
||||||
|
}
|
||||||
|
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
# Applications
|
# Applications
|
||||||
@@ -37,7 +60,7 @@
|
|||||||
vakhrushev.me {
|
vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
# Matrix federation delegation: tells other servers/clients that the
|
# Matrix federation delegation: tells other servers/clients that the
|
||||||
# homeserver for vakhrushev.me lives at matrix.vakhrushev.me.
|
# homeserver for vakhrushev.me lives at matrix.vakhrushev.me.
|
||||||
# https://spec.matrix.org/latest/server-server-api/#server-discovery
|
# https://spec.matrix.org/latest/server-server-api/#server-discovery
|
||||||
@@ -65,7 +88,7 @@ vakhrushev.me {
|
|||||||
start.vakhrushev.me {
|
start.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
forward_auth authelia_app:9091 {
|
forward_auth authelia_app:9091 {
|
||||||
uri /api/authz/forward-auth
|
uri /api/authz/forward-auth
|
||||||
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
||||||
@@ -79,7 +102,7 @@ start.vakhrushev.me {
|
|||||||
matrix.vakhrushev.me {
|
matrix.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
reverse_proxy {
|
reverse_proxy {
|
||||||
to tuwunel_app:6167
|
to tuwunel_app:6167
|
||||||
}
|
}
|
||||||
@@ -88,14 +111,14 @@ matrix.vakhrushev.me {
|
|||||||
auth.vakhrushev.me {
|
auth.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
reverse_proxy authelia_app:9091
|
reverse_proxy authelia_app:9091
|
||||||
}
|
}
|
||||||
|
|
||||||
status.vakhrushev.me {
|
status.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
forward_auth authelia_app:9091 {
|
forward_auth authelia_app:9091 {
|
||||||
uri /api/authz/forward-auth
|
uri /api/authz/forward-auth
|
||||||
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
||||||
@@ -107,7 +130,7 @@ status.vakhrushev.me, :29999 {
|
|||||||
git.vakhrushev.me {
|
git.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
reverse_proxy {
|
reverse_proxy {
|
||||||
to gitea_app:3000
|
to gitea_app:3000
|
||||||
}
|
}
|
||||||
@@ -116,7 +139,7 @@ git.vakhrushev.me {
|
|||||||
outline.vakhrushev.me {
|
outline.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
reverse_proxy {
|
reverse_proxy {
|
||||||
to outline_app:3000
|
to outline_app:3000
|
||||||
}
|
}
|
||||||
@@ -125,7 +148,7 @@ outline.vakhrushev.me {
|
|||||||
gramps.vakhrushev.me {
|
gramps.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
reverse_proxy {
|
reverse_proxy {
|
||||||
to gramps_app:5000
|
to gramps_app:5000
|
||||||
}
|
}
|
||||||
@@ -134,16 +157,25 @@ gramps.vakhrushev.me {
|
|||||||
miniflux.vakhrushev.me {
|
miniflux.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
# /metrics наружу не отдаём. METRICS_ALLOWED_NETWORKS тут не помогает: за
|
# /metrics наружу не отдаём. METRICS_ALLOWED_NETWORKS тут не помогает: за
|
||||||
|
# прокси Miniflux видит приватный IP контейнера Caddy, а не адрес клиента.
|
||||||
|
# Netdata скрейпит miniflux_app:8080/metrics напрямую по докер-сети, мимо Caddy.
|
||||||
|
handle /metrics {
|
||||||
|
respond 404
|
||||||
|
}
|
||||||
|
|
||||||
|
handle {
|
||||||
|
reverse_proxy {
|
||||||
to miniflux_app:8080
|
to miniflux_app:8080
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wakapi.vakhrushev.me {
|
wakapi.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
reverse_proxy {
|
reverse_proxy {
|
||||||
to wakapi_app:3000
|
to wakapi_app:3000
|
||||||
}
|
}
|
||||||
@@ -152,7 +184,7 @@ wakapi.vakhrushev.me {
|
|||||||
wanderer.vakhrushev.me {
|
wanderer.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
reverse_proxy {
|
reverse_proxy {
|
||||||
to wanderer_web:3000
|
to wanderer_web:3000
|
||||||
}
|
}
|
||||||
@@ -161,7 +193,7 @@ wanderer.vakhrushev.me {
|
|||||||
memos.vakhrushev.me {
|
memos.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
reverse_proxy {
|
reverse_proxy {
|
||||||
to memos_app:5230
|
to memos_app:5230
|
||||||
}
|
}
|
||||||
@@ -172,7 +204,7 @@ memos.vakhrushev.me {
|
|||||||
tududi.vakhrushev.me {
|
tududi.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
reverse_proxy {
|
reverse_proxy {
|
||||||
to tududi_app:3002
|
to tududi_app:3002
|
||||||
}
|
}
|
||||||
@@ -181,7 +213,7 @@ tududi.vakhrushev.me {
|
|||||||
remembos.vakhrushev.me {
|
remembos.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
forward_auth authelia_app:9091 {
|
forward_auth authelia_app:9091 {
|
||||||
uri /api/authz/forward-auth
|
uri /api/authz/forward-auth
|
||||||
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
||||||
@@ -195,7 +227,7 @@ remembos.vakhrushev.me {
|
|||||||
calibre.vakhrushev.me {
|
calibre.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
reverse_proxy {
|
reverse_proxy {
|
||||||
to calibre_web_app:8083
|
to calibre_web_app:8083
|
||||||
}
|
}
|
||||||
@@ -204,7 +236,7 @@ calibre.vakhrushev.me {
|
|||||||
wanderbase.vakhrushev.me {
|
wanderbase.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
forward_auth authelia_app:9091 {
|
forward_auth authelia_app:9091 {
|
||||||
uri /api/authz/forward-auth
|
uri /api/authz/forward-auth
|
||||||
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
||||||
@@ -218,7 +250,7 @@ wanderbase.vakhrushev.me {
|
|||||||
rssbridge.vakhrushev.me {
|
rssbridge.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
forward_auth authelia_app:9091 {
|
forward_auth authelia_app:9091 {
|
||||||
uri /api/authz/forward-auth
|
uri /api/authz/forward-auth
|
||||||
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
||||||
@@ -232,7 +264,7 @@ rssbridge.vakhrushev.me {
|
|||||||
dozzle.vakhrushev.me {
|
dozzle.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
forward_auth authelia_app:9091 {
|
forward_auth authelia_app:9091 {
|
||||||
uri /api/authz/forward-auth
|
uri /api/authz/forward-auth
|
||||||
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name Remote-Filter
|
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name Remote-Filter
|
||||||
@@ -252,7 +284,7 @@ dozzle.vakhrushev.me {
|
|||||||
{{ goatcounter_sites | join(', ') }} {
|
{{ goatcounter_sites | join(', ') }} {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
reverse_proxy {
|
reverse_proxy {
|
||||||
to goatcounter_app:8080
|
to goatcounter_app:8080
|
||||||
}
|
}
|
||||||
@@ -261,7 +293,7 @@ dozzle.vakhrushev.me {
|
|||||||
goaccess.vakhrushev.me {
|
goaccess.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
forward_auth authelia_app:9091 {
|
forward_auth authelia_app:9091 {
|
||||||
uri /api/authz/forward-auth
|
uri /api/authz/forward-auth
|
||||||
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
||||||
@@ -281,7 +313,7 @@ goaccess.vakhrushev.me {
|
|||||||
bifrost.vakhrushev.me {
|
bifrost.vakhrushev.me {
|
||||||
tls anwinged@ya.ru
|
tls anwinged@ya.ru
|
||||||
import common
|
import common
|
||||||
|
|
||||||
forward_auth authelia_app:9091 {
|
forward_auth authelia_app:9091 {
|
||||||
uri /api/authz/forward-auth
|
uri /api/authz/forward-auth
|
||||||
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ services:
|
|||||||
- "80:80"
|
- "80:80"
|
||||||
- "443:443"
|
- "443:443"
|
||||||
- "443:443/udp"
|
- "443:443/udp"
|
||||||
cap_add:
|
|
||||||
- NET_ADMIN
|
|
||||||
volumes:
|
volumes:
|
||||||
- "{{ caddy_file_dir }}:/etc/caddy"
|
- "{{ caddy_file_dir }}:/etc/caddy"
|
||||||
- "{{ data_dir }}:/data"
|
- "{{ data_dir }}:/data"
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
services:
|
services:
|
||||||
|
|
||||||
dashboard_app:
|
dashboard_app:
|
||||||
image: "{{ homepage_image }}"
|
# See versions: https://github.com/gethomepage/homepage/releases
|
||||||
|
image: ghcr.io/gethomepage/homepage:v2.1.2
|
||||||
container_name: dashboard_app
|
container_name: dashboard_app
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
user: "{{ app_owner_uid }}:{{ app_owner_gid }}"
|
user: "{{ app_owner_uid }}:{{ app_owner_gid }}"
|
||||||
@@ -18,7 +19,7 @@ services:
|
|||||||
- "/etc/localtime:/etc/localtime:ro"
|
- "/etc/localtime:/etc/localtime:ro"
|
||||||
- "/etc/timezone:/etc/timezone:ro"
|
- "/etc/timezone:/etc/timezone:ro"
|
||||||
environment:
|
environment:
|
||||||
# homepage 1.x требует явный whitelist Host за реверс-прокси, иначе отдаёт
|
# homepage требует явный whitelist Host за реверс-прокси, иначе отдаёт
|
||||||
# «Host validation failed». Пускаем только адрес из Caddy.
|
# «Host validation failed». Пускаем только адрес из Caddy.
|
||||||
- HOMEPAGE_ALLOWED_HOSTS={{ homepage_domain }}
|
- HOMEPAGE_ALLOWED_HOSTS={{ homepage_domain }}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ services:
|
|||||||
- "USER_GID={{ owner_create_result.group }}"
|
- "USER_GID={{ owner_create_result.group }}"
|
||||||
- "GITEA__server__SSH_PORT=2222"
|
- "GITEA__server__SSH_PORT=2222"
|
||||||
|
|
||||||
|
# Ветка по умолчанию в новых репозиториях (у Gitea по умолчанию main)
|
||||||
|
- "GITEA__repository__DEFAULT_BRANCH=master"
|
||||||
|
|
||||||
# Mailer
|
# Mailer
|
||||||
- "GITEA__mailer__ENABLED=true"
|
- "GITEA__mailer__ENABLED=true"
|
||||||
- "GITEA__mailer__PROTOCOL=smtp+starttls"
|
- "GITEA__mailer__PROTOCOL=smtp+starttls"
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ services:
|
|||||||
- OAUTH2_PROVIDER=oidc
|
- OAUTH2_PROVIDER=oidc
|
||||||
- OAUTH2_REDIRECT_URL=https://miniflux.vakhrushev.me/oauth2/oidc/callback
|
- OAUTH2_REDIRECT_URL=https://miniflux.vakhrushev.me/oauth2/oidc/callback
|
||||||
- OAUTH2_USER_CREATION=1
|
- OAUTH2_USER_CREATION=1
|
||||||
|
# Метрики скрейпит netdata по докер-сети (miniflux_app:8080/metrics).
|
||||||
|
# Сузить METRICS_ALLOWED_NETWORKS нельзя: netdata и Caddy сидят в одной
|
||||||
|
# web_proxy_network, по IP их не различить. Наружу /metrics закрыт в Caddy.
|
||||||
- METRICS_COLLECTOR=1
|
- METRICS_COLLECTOR=1
|
||||||
- METRICS_ALLOWED_NETWORKS=0.0.0.0/0
|
- METRICS_ALLOWED_NETWORKS=0.0.0.0/0
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ update_every: 15
|
|||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
- name: caddyproxy
|
- name: caddyproxy
|
||||||
url: http://caddyproxy:2019/metrics
|
url: http://caddyproxy:2020/metrics
|
||||||
selector:
|
selector:
|
||||||
allow:
|
allow:
|
||||||
- "caddy_http_*"
|
- "caddy_http_*"
|
||||||
|
|||||||
@@ -9,7 +9,11 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
user: "{{ owner_create_result.uid }}:{{ owner_create_result.group }}"
|
user: "{{ owner_create_result.uid }}:{{ owner_create_result.group }}"
|
||||||
networks:
|
networks:
|
||||||
- "web_proxy_network"
|
web_proxy_network:
|
||||||
|
# Алиас без подчёркивания: по нему в homeserver ходят соседние
|
||||||
|
# контейнеры (apprise шлёт уведомления в matrix-комнату).
|
||||||
|
aliases:
|
||||||
|
- "tuwunel"
|
||||||
volumes:
|
volumes:
|
||||||
- "{{ data_dir }}:/var/lib/tuwunel"
|
- "{{ data_dir }}:/var/lib/tuwunel"
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ services:
|
|||||||
|
|
||||||
wanderer_db:
|
wanderer_db:
|
||||||
container_name: wanderer_db
|
container_name: wanderer_db
|
||||||
image: "flomp/wanderer-db:{{ wanderer_version }}"
|
image: flomp/wanderer-db:v0.18.3
|
||||||
user: "{{ owner_create_result.uid }}:{{ owner_create_result.group }}"
|
user: "{{ owner_create_result.uid }}:{{ owner_create_result.group }}"
|
||||||
depends_on:
|
depends_on:
|
||||||
wanderer_search:
|
wanderer_search:
|
||||||
@@ -53,7 +53,7 @@ services:
|
|||||||
|
|
||||||
wanderer_web:
|
wanderer_web:
|
||||||
container_name: wanderer_web
|
container_name: wanderer_web
|
||||||
image: "flomp/wanderer-web:{{ wanderer_version }}"
|
image: flomp/wanderer-web:v0.18.3
|
||||||
user: "{{ owner_create_result.uid }}:{{ owner_create_result.group }}"
|
user: "{{ owner_create_result.uid }}:{{ owner_create_result.group }}"
|
||||||
depends_on:
|
depends_on:
|
||||||
wanderer_search:
|
wanderer_search:
|
||||||
|
|||||||
+245
-245
@@ -1,246 +1,246 @@
|
|||||||
$ANSIBLE_VAULT;1.1;AES256
|
$ANSIBLE_VAULT;1.1;AES256
|
||||||
33616165353931656432336130616463663066336561643964346139376535633630313039313831
|
62666365313535383334366166313961303933373163323236626565303038396662363239376438
|
||||||
3163663434323730343337333137313366333832313330330a383833386138666139313536353763
|
3738323565643363323865663630303330306530303263350a393336646463663563666362643362
|
||||||
39666132343135613236326436633630663662373036623030623336366433356132376233623333
|
61313337363936313363316635376163646633383032613265363936396536386437306139396461
|
||||||
6366333565326331320a353037383539653766653765343365633134643032323739363436633637
|
3963656162316562620a393737383636343965656433346466316333613331303435323732363239
|
||||||
65356435313961613266326664393165376335313534343832366436303339666233333132313865
|
39313834373536396237333264303930393762383333633363333265363039373061353334613530
|
||||||
34323865633337386561643237383133613566613534383664333664383562366634396361646363
|
33633161373631363061383564633465633962383835633237623938343865303363633461313830
|
||||||
64663530613337643461643133376637663462363261343464373238393730393939323762303263
|
36383865663932666562333733653935626166663066363233303962643364343739663463396364
|
||||||
30313432613136366330343930383263313436663233346630366263643939343530353661633638
|
34353034656130343739336532393334306261366331353030306161636437363464336536386638
|
||||||
30666266353161396163636236666665643035336237613037323361303361323934333933613464
|
62653362633363393838366564313165346262653432663563366362616364396633323563643239
|
||||||
34373639323163363835666633656133363731326665383261346633633835663937346233326135
|
35333232396239383233656231333264663938373364313730623364393436626361653736613939
|
||||||
61356134656165373136396634306164646361303536653633613732613635626234643961396437
|
64393833353765346633363334656631343064656333383664373039393966346332393134303030
|
||||||
64313164306130666364653561306562633732663561346562626538353462386461623662626232
|
36373436343766323038303438386436376666393239643636366330336336333761356436376234
|
||||||
35313634303163666435326230636464323038346137353164663837663734306536666233393736
|
33383266663030643931626662383636333637616539313366326539383139616334363939626161
|
||||||
62356562396663356535613634313639653363623030373661666333663138366630386630343831
|
34346263643031363236313334623162343236636665383262393666306366383064343965373639
|
||||||
30373231373466303866653933303739613835313734396564303339373439323436613235363934
|
34323062656633386661343332306664633361396233656238613436636530323839653838376563
|
||||||
30326338346635663030393135363836663332333031633239346435623734303932366466346430
|
33336664643365363930366636656138616236626639663564613132653465636462633364646166
|
||||||
66646432613165666665396535626634316161316334653830386365626631393466363439656135
|
36393966326365373530663839653737656438646662373730333666376137653337303834383032
|
||||||
34323332643035313835616636623038613137336262366630663864663866393164373832613938
|
33363636376435623064646566323065383466623138323938303630353330663132636431333830
|
||||||
65646133353131333430386631616464663162373533303838633335393737653465663762346639
|
30313434333262616138343634303438386236326330636161336462363333386561643462666439
|
||||||
62303166323761373164383163616539313835356134343039326166636630653337316334623535
|
35343837653934613338313537336232656564663337666262656361383736363939383433623938
|
||||||
31643431616337313266383736646162383765663630613332323733303233656432633666376331
|
32633965633931643836346362356334666230663734643130656566353937636331303633323934
|
||||||
30303763636131636330626635323639316161343365333864396633356631653431396438613335
|
62656634643263333566343739666634663061386137373539383736613864656230373566666162
|
||||||
61326365356130316263353034336131303835323535376466313534666230393766386333636265
|
32616363633534313933613533373265623366303766626232623966623531373930613831643034
|
||||||
65336538346136303038393566373131313762343465313539373961333739623433393532626237
|
64306236353164643138666564616464383638636263326531633866363732653664313364386661
|
||||||
62383564376232613138323262343064626338633934383536633537336462336664386463363564
|
30633536623336353532363261623938353232396336343662643965353839333761376463363631
|
||||||
64333164613234373033333463323662376533333165363461393533666566376135356338356430
|
66353862646131343961363363303432336431633761313633386235383435336563383333613830
|
||||||
61333732653863376266616436356537663761333531396237393637383062663532373633633531
|
62333864373362663538326363656531643733356232643632396631323636376164653333316137
|
||||||
36613537633063636539363961666133316338353439613432386139376435396464386330306433
|
39626336333139323733653535663132333030323938303166396336356136653231366332613039
|
||||||
33623037383761656231646331306561633763306135386638383366356232616230373465393733
|
30346237353532623065303033326534663034333938663365303264323061613964313139316538
|
||||||
39656133313062356633663865353137336235663532363661336231343139343561643639623466
|
32633537346165616136623431653766383535393230303064383433626634386331356434323561
|
||||||
66356535633031363231313966653566383137383436376166613863633235343061303037333032
|
31646137623339373662626631356337616666303131633138366433356163373766616531383138
|
||||||
38353961386562353336343764383938633633363761396563373065353266666434306235313230
|
33366361323935363163363731636631643135636332316439303335616661373039346433356138
|
||||||
62306337373430656531353430303131343239323739303434333632396365613236613861643136
|
34613061646138626637316262623632303339653633346161353836623330313432396333323464
|
||||||
31356662653162323465316334623733666331323064353337376639343563663436346461323965
|
30346232646661643839663835373439323031623462386432623332316535623764343039333039
|
||||||
31623731613334636361353961306163626666376162313165333665626439613339663138376338
|
62313031663731306539303634666461376133643138363235383531366239643331313238623666
|
||||||
61333234663239353562336632613662323139306639363234623830643736653536613063393165
|
62656631333030626337333765646339643561396537333462643166616165636261323663333963
|
||||||
30663836393039373665336461316632616431626165376631643566613932633036613537383663
|
32656336353837323231643561306134323065396131343965373534656530376237616134343034
|
||||||
36633166386139636539303463623266633333326137666135643338303239353436323232386233
|
61313430376531333261323530346430303163313864333033663536386561633939383030666430
|
||||||
37376630366635666533646538636539363633666634346462623635623539623361336362626563
|
30633864316363383631386636656331323234356438643132633637623637646536316532373639
|
||||||
30393464666336393230393334613665643231373633653631333965633632303437353634376333
|
38313535663930666335333239623935393232633432343561663938343335356565626266353630
|
||||||
37313836666630313963626536626537333434383663383538313538343134326664323032363666
|
35666134383431653163356230663038336563366433623562333333313733383536353635613835
|
||||||
64653562313433386661396133373534636362656666646563376166313361643031333537393837
|
35366539306437623336623230343666366438333334613765393930313234383365623466393934
|
||||||
62326231373431616633633862396334393133393832383231373433353230303638653139653065
|
32633931363164626464396534333431666630316365323265376161313138313232646665323532
|
||||||
35643637623361346439613831636137663531613638396232623632363837616435323836383036
|
39353563393235353632323930326537643162386430383461306136306339306535363565633662
|
||||||
38323161343066653563616638663631616636356339373932623237306639333065613430643864
|
35336434343938353538363563373363393464623633313638346236633662623837633263633166
|
||||||
34613635633131663433363862333732353562353731333165666533356331363964343731636364
|
64666630346235613664356433653436616166643762653431376666306364623237363363613333
|
||||||
35313537336366336435333831313834353565343635386434303362333238623930623461393037
|
31316533363966633362366266613863353136353662313636393234303361396531333063623863
|
||||||
34653163626331326364343364393963373739326430336533653462313833626262323232383263
|
30343534643835613462353739613730633331643837383836326236636235623965356333343961
|
||||||
61643636316630353530633234666462363032333135303431613361366530306538623133306336
|
32396135393564653537613731316133633665653061386664343233396537383332643163356639
|
||||||
32323265623863613037653962323361393966666464346539636239336164366635396262383032
|
36653134303361656438666635396339323332346133623439613031613764666665303335613738
|
||||||
61643231356235643532333666626366633430643262626263656135636436333030663739366638
|
64303537616531643237633835613937663739313466346463323037636432373235363038393461
|
||||||
35303462633731373437306330363265663965663664633237646334386532653462373431306133
|
66363162323562646264323133306538633430303538356231326436313432323931623135306262
|
||||||
63303434643630323461363135386233346662616236343736306339653662396330383664656334
|
30666132383131343262326531303931343539646130356332333964613938363033623731633463
|
||||||
37616634366566613934656132316434643162353233396331323033313332653230316135336564
|
36363635366165663064653934623235323930336538643634623233383535323930386664313530
|
||||||
66373735303535303130666639626139333664383232343938336133396164393362333237653966
|
65383264623736373261343331353339313361383539653262373338316163353063663038656465
|
||||||
35363931326336336262313266653931366239363931373134346464353164313639353738396231
|
35356133353465303137373039363535336232326233353937643465323539343263363739663531
|
||||||
66636533353536373532623032626333356266633439613961633137326439633964353634363362
|
66666566373835336433353761336338336533353463386230306665616638393864646264373563
|
||||||
62353461366637366531316433616334343762376239376562356230346534353530356531313339
|
33313339646237626264366263613036373931666366326663313964633738393164633534623839
|
||||||
32656131343430383035333264393331643262346632623166343433313262323234383064613636
|
39613132396661393761343230633135323732613836383661353665663831623766616639343331
|
||||||
62336330636136346162393961353432353236633630666239646138316366363739616464353765
|
62623862343737643930373432323563663264366234646533353835353264333333623734313435
|
||||||
35326661313864313235633462623231623634343662626131346530333762313535393937336437
|
62316666306437643835386235303139616534303932363263373863653633613464363431356132
|
||||||
31376437313936383232633231386538396664346465666130353061656133306163653734313862
|
32653661373365623364316663393262303538633039366138316630643031626565316335613436
|
||||||
64653736366232333561313435306335623730313635333938353965313762313334373932653030
|
36356137653139303334616631396634376262396133633161306233336162643632383635333333
|
||||||
35366266626636356234386631373838653337646361343233336461633330653632333338356361
|
65373633666637343666366463323765656633303732323631393064353739376430303934333232
|
||||||
64396331326638333264633837326364636137633861333338643733393361633637656162616262
|
63393831386363343233363732326234643039396637383132336162326336363033393436383931
|
||||||
63366333376534663932626635363239396134303362323239646339363836306531666266363765
|
37323763326461643837393139613165346136316663646464343338613061323936303030356466
|
||||||
37646362336465346666376135373738663363653334393334616166396537333535353436393134
|
39636138376632653063643963306334396339666665323234336135396561393166643236663733
|
||||||
63373535666535373432396134316363646239383733653638343661306266633831313935633639
|
32316364623831626134306163393239303564313466636663393166336662613739323864346637
|
||||||
30386139323464343234336230363037373336383566376431363031326534653235656465373061
|
38393064313362663935666632386339393561663735656639373633623933306635363330333736
|
||||||
30616531323365326639366431656437643435343739623563346266333865363062376464346366
|
62633966653138633231346331393533633333623835666463666330333835316631666238396334
|
||||||
30353437663063396532323134323436323966326662643632663936316564336464303364643235
|
33343232396135383834383564636235663634346336373536663539653861633862653332633962
|
||||||
39306532393838336235303335653537386530376131666236366363393132663931323534306639
|
36343136633532323565316431396630313837363138343833316363366165383337343930626361
|
||||||
34383134666664613066663965303363336138613033343863373661376132333633646435383038
|
66633535643839396463343264313336663430326137356465663166353833636134356434613839
|
||||||
63373330363532303339373934653264613761353962633061303936383336653338323065646131
|
39313439323431633966636533336530346138353935663433333661353634316632646333363434
|
||||||
36376566643032663863623835613263663163376462356135376664313239653532333363656633
|
33326165653033663965333934363633353235363931626463383565393331366566663666633733
|
||||||
39303063623136363238393761376166303837356334663734623736633662626566353164313134
|
32643863653661633137313263646630373465343434666234663236393832313761383535613363
|
||||||
33383532363462396363356230623136313436646536666234363562333534303665333335633332
|
65346335626535383335643361653531366139363637333838376562326138386361623562616165
|
||||||
66353635323162373836393033653937633336386531623966646663643832356162373661383663
|
37333730663134666466666130396662616138663962366630323330616333323539623532613733
|
||||||
33353262643163316232316261353939303939336231366331366432393738333137303963383034
|
62373531653564636662316334646338346337616433333533346539363066366338333233616337
|
||||||
65376637356539643138343039373237376231386438616566666562333938636431373037643166
|
33666130323330356364326633623165366465326331383361323630363330633833363536373930
|
||||||
34376361363930326465353563653236396230656333316338623165366330653034333234653632
|
64393464383533383335623263613136336632363132373663326263303162636331666164646234
|
||||||
34363033613939316330386264373630376633646130636539633561333233343135623636393564
|
32316133313438616563376230636537636334346637356339336533333264643461666439643238
|
||||||
66356664363562353564613137363239343830393639333130383435396630396439633834623734
|
66376461643136336665643366643363366365373636613537636462653737303131643661336364
|
||||||
64323633666564363736623035646235393064313733386635353365366461383634643939393264
|
34323261313632663064346263336463363932646261613232643030383038613137303532343766
|
||||||
35363631666630373138656233623966613437666432633666333436663537363932343463373734
|
36663366396338306534633062616436333133316438666261396136323535613436356337613339
|
||||||
36313962363538326537343931353538333030643936633364316439343236306338333730373830
|
33626565663137666265316533306231643435376465333566643366633638346631663435306534
|
||||||
63396337316130393036323266643063353665303539386265623134313164656534633131303565
|
37373836366438336365326265653433306334313630373737343630363534313131386332633134
|
||||||
31646564323630343964306235386165663438336465343764633964623262626237636436343032
|
65373862643431313031626236356565626133633663613564613238313962323934633437383930
|
||||||
66653962333838303432316435316663383964333036313339343437323238333466313237336166
|
65393765313934393438663338343239353732316130366466323638656439613234643036356265
|
||||||
31336330353530373862656139626365303539343537393964326434653765646363373238383539
|
36646631313362663833343934363930373536333531626161623038396331373065633965643735
|
||||||
65353861366239343034316365343262656136353931353834663639666132343531313433306431
|
37666162343930383133306139306131356232636530306234616464633736636538346431613066
|
||||||
65306163393162653531343838633061336666363461336262636338653332396163353432383230
|
31396630653338623733663262663335623466613430316663316435653233653837623131396462
|
||||||
35626231656431653064373630303936353432373332316130383831343463653339626639383834
|
31633531356239326538663737313437303735363565316263323131383362306235363835333830
|
||||||
39343131393032613034623237383738666634393635343034333639363034373832646137383864
|
64333438633837356633633435643830633938396637326662666137333934613531316538626633
|
||||||
35363438376131656262323364623836623137663662343036356561396262386336346261353133
|
62346431626662663538303431336234613164383536313363303932643062316538343332386165
|
||||||
37633634626439663039396564646639663162646436646162393138333561653331363338313763
|
62653937663135353638383363333634383031383362663039646133666634356661313537303566
|
||||||
37353138626232376236366432663262333566323533646665396234656366313939376132373562
|
32316361613261313830363532336238616265393661343133373231633964323535656530336136
|
||||||
32653964333538666430313230666262666362306231303637623539623238643862353532306166
|
38393163626133336235346162633165396333633339316462306433656262623736376332336330
|
||||||
35353831653063393664343061393166323962303564383166626539366464373935616164313066
|
63363733363263636336633432366633393533373566653836663165626162363735363963316532
|
||||||
34666330656462326338313837653666653037363566333062313765383136636436363732346265
|
66376238303538386537363233376431393833303263383733303261386237623136613435613530
|
||||||
39363161643738303433663838326163383534636463346264343232393564653230636566653563
|
34383738646330336636363336346264323132393962666334613134313635393165656236623234
|
||||||
38363138383637653963376432633161616565663663333038363736653362383261646337356633
|
35333535353562656463376135353562386532366235363865343038316561663933373339356336
|
||||||
61613235303765613830633866636461363861646439633566323938643738613932656431383330
|
35393830623430323365613863393932633535376436663666356562386461336239366665333436
|
||||||
65373933323161303761366639633331366531383664376435646337353365653332643163336438
|
32626534373830386134666233346333393064343933323830336462666136386538306463313531
|
||||||
61393533643962383863626530363534396134633030313865306263343139376165663239323761
|
65303263366530356138363162333833376631626631316435663631333438363833366234646131
|
||||||
66363737366662373862323938373764333261386639313433346539656664383063353336363031
|
33633236326533643139343766366131313834366663336361623563376465646338623537343934
|
||||||
37303962663834623062346166616461373737656435313365373863383761646466616535633163
|
35653665363665343264333237313663663431386530333230643832643537373464393836356365
|
||||||
32353562636333636661623461653264666439396230326437613361336434363238666238613866
|
31306465623539653361323233613136373464643334366466616561356336363161306566353033
|
||||||
39633365386639363263373439623431643964393934383831353733646264393838643430643134
|
39313735653062643361313538353464393566303435303839643061326631346434316537346561
|
||||||
31616338366663653036353633656230646232636532353431336535353137663832376261333665
|
35326536316233613035366532316132396531646561633834346530386337636532313233326433
|
||||||
31356565316636396137336536326631393439303330316635363464393434643333336334623261
|
31383364313331623433323364356566373433323034373531653736653866636539383639383163
|
||||||
66643938313739623135636365346566636435663662343932346238633431313730623661396237
|
61663362303435363539343331373931313065343662353964366566656537633664383239343430
|
||||||
63323833313732353762313237396633316137313335313536623530323465386231623265666463
|
62623865623665616638623937343361376133306564383461336136313035333731313837393762
|
||||||
38636461643233333733323030346231663833646339653037353065316363343031353066373665
|
34393936373865653761363139393530386135626538353031333736646235366165623535323338
|
||||||
37643764613933666630376563353662623461643866303335383237373532646331356361343036
|
33313964643732633032643037323064323461313930623836623438366261633033666439396535
|
||||||
38353964623237393133383063376135353538373035653831633333333133626165333538326264
|
31326131303738383237643566306561393635383831303433323963646133346534396663616338
|
||||||
64303464646261306536393264326636663035323638633034626139326331646161393334663365
|
33343139663162636134346637333330333637643063373330376134373533663864663338653264
|
||||||
64386561663564613636613163353732646362383931646366616333316463633830626539346137
|
31313530623933653934313530663139313439373662613130636135666630346261623933393833
|
||||||
32303831326435326235623836643031633863333562613438643465363339663561333239383835
|
30306166303938336439333833373434346139366162623736663662353931626639663139336462
|
||||||
66366561653733323638623736363265366434393835326263623962343832623230303337663637
|
39353336653163316136656238643031626563326238353064356430313533376536376635373262
|
||||||
31383361323434353232383363386339366232626264343137623432656234633532666436623837
|
62343534643661326435663031653634663130323035303063656163303436386131643435383733
|
||||||
64353239373736366330306331316331393065323633613235343666663932386563623764353661
|
30653061623439376262376338366166353836353535343939646134393335623630383866306539
|
||||||
32386361373537613838393536303031303630613637613961303863356231316364643230333139
|
30343862636131393863643831656338346334313930356164393135303166643265656138366266
|
||||||
30343362636265373265363937363965313939663039356335396161376530626433363362393231
|
64646636306339656662616239356666633330666237653166393663653565343533316337316237
|
||||||
39356139333633393433646166303762623330323763336464626537643837643134343639623331
|
36663930323730653236653235626437366338333263333135633634346434383530386331333166
|
||||||
32386230653535636663366433333765613230373761363236663665303665393635623631613530
|
38346563393934303830633932323564343166363936313035623034666436303831643265646433
|
||||||
30316561393063653732343137356638636263373530336266653239316431666464353861323633
|
36616362633230666132313937626136653530623865663037383239313939393739656663373166
|
||||||
37656664393035366337343262616532626262356263653433373739373865356139383033376536
|
37393233653533646664623865333865623862333263383635643238343538333137383461623565
|
||||||
36333564333039623663353162383531653066306332306436346366633030636632336637343566
|
65663036356666323137666536323435376565653234376530393166393939666663373361343530
|
||||||
66393966613239633638313161636266313936346630623132633966383535336630316462306265
|
36363466323162383930316637326333393937333232363537643065383231396236323936643364
|
||||||
64396537346538383364343336333734343863623663663238653134613737383966326436386438
|
64653061323033363135353436333036326636306639653139363064386366653562383539356131
|
||||||
32646266373533376434613262383432363633613031613632633233633863343834313864316365
|
31366432656634323730336665353132323862636339313036643234396339646165313764303734
|
||||||
33646661653534376437613061386532363035646561613533366134393739373565663334383134
|
34303737353466306537386633623261393537613735313032643033383434363233393061386538
|
||||||
64303539393838383466343437386139616361393139363231663737303730353663663334653037
|
35313834396533633735313237316433643835323465306431336331306638383165306234303366
|
||||||
61306165316135373633373630336466623036666134353436393834346638636165646165333065
|
64626239636439643538323734343966366535616437383632363631363731636463653133313266
|
||||||
34636333646331346334303565363338396463373831353265636231623130313539323437343732
|
62653036653761333166643432653563613264616362316463326538653536383763363237653238
|
||||||
37653030636464343962613764626264353166356161336239386631616339383063653138656530
|
37303564386266653239333636303034633538383232623630366232626638373664343336336462
|
||||||
34343133366537666238616132376331303933366135666231643662633139383134646533656438
|
38393038633737376562626131343131653236376432653230343833393366366566363334343263
|
||||||
66306232363562653231653865316561373264306333646663373062653535623136393038613231
|
39323062663565373132343131303530353464626133643731666239316363373437313335626232
|
||||||
34623562313666346131316462346131613761383733643161336266343639626132636536396334
|
39393931333033643265646535663935363831306163303966623164303264626161303434646538
|
||||||
37336263326532376336363030383864626534343937303134666564636230396462343862353431
|
37656232396336336635643335303165323361366562303137333831343832653763323937373061
|
||||||
34306165616662663535346330656130636131656663353232656361643137306562623765373061
|
35326263356263363636383861356339623966323564366430663632316664373536613462623838
|
||||||
38366266376530613636306664383865393631616462333830386535393734366239313834666338
|
33356462363038623633393337303161393536646665663339653234336137393139336132353235
|
||||||
30613162343361646433666366346637333837346664323230653037383366613431313361343366
|
37613138333065363731623535346138643833343663656162376139376638303231653537326131
|
||||||
66346535333436303335313337623362623231303363323566366166346636623263326465663536
|
31376334383564623331623733613365643161393165376563313235663930323037343161343866
|
||||||
30396538353934323465323165626132396563326333303066313862316634336661303433333637
|
37383336303138393064663265363939343535376433326433353165356564656132366565613839
|
||||||
32366562396666363333653461313866376332373065623063333335313538633861656639396638
|
65643365343038316139653665396334613131396238663162666365393339353539613634383935
|
||||||
39323636656432656630666531336661366134346635623464313031323037633137356633613330
|
64333535386661333363383437653864636434323832303932666364376333663633326434383064
|
||||||
36323065613562663865393033616661666136633063653163303665373535303135623565616539
|
31333464323331303939353732353763643562383538356363613739353135326630613334323037
|
||||||
32343166366536333261653138333433656635646462623035646537353035663861306463363638
|
35363335346464373064363231393435306534323431616365623765646362373738653738326232
|
||||||
61646664366465383134386365353537656266363065653937646530326639663739626539663837
|
30323563326466373766363935636535626632623138343537333038333964396262323831353038
|
||||||
31353537393438386239376631366661386439343132616536333463366665396161633337653630
|
34383665346430396361306437613339366437626266626231626239363362613065396137343962
|
||||||
33366133333363383034663832346561316136613438326130663733376664623831396135383336
|
36333463313130353165373365316563623330356638356233383333653661663462383161303136
|
||||||
30343335356532363534373539616334383034356336663962373636303866653031623366626535
|
36633038386563376335376236646537316563633739393235663930656131613030666133363430
|
||||||
32303762383738663764313434333864373739386436643333356264383333396636333831383833
|
62386263373338653161376636623061386234356632626636366232313639353138636332616630
|
||||||
30313235363932616633383462633335613534343361313837393236336539303333336663656435
|
61353435353239633630323163336133353462356263316130626638656238653264663361323135
|
||||||
34616437323931326436306430366436336338326339323037316230383262343032343765613461
|
37633038373433313863393965633661613231396536613835653361373837356232333833633236
|
||||||
36396231656363333566643232306639376466613636336265363333333066626263636530623365
|
32313439633632363465366337303739303137323839366261653836343332373230643264666535
|
||||||
39333935626161623263383739663461613262306437343366633862643935613633613236303334
|
35313865613632636437323462316639323531326432633334333432323266386435366366333838
|
||||||
37393765326665303636303563393634373933313838353063386533396234623837343333663861
|
38633830313731326638306634323565366265343130333339373032643832346166613737663430
|
||||||
63353536633061343066326437306233373736626539353637623266306434633932343138326562
|
62336434316264376361353830633562313065653433393363373734666134323263653537653830
|
||||||
66663530323438313664383132613139643562643966386664613964613865306231663566303762
|
62643838333065376234646166666332376462373536373234666163636562333865636134313766
|
||||||
35396137376435623636346531626434393737656437376533356564333130346464663232613333
|
39376237626137316366306366393038616631346161316263343237666430323966396331353065
|
||||||
30363834643863353139313664383061623061656537386536633236663165666665643435363132
|
30363437356262643034643330303534333331323464623662616534653932646130653466653332
|
||||||
30386666303461353534623963343732646564613939393365353763303563623265653631343539
|
62363030343833316133666164383037323936336232356266326261383964396364633233643737
|
||||||
36653934653661303533346339633665346165333162643334396134366162616266656139353033
|
32663635613939363265323936336263663465646666333263626139636162373462373064613362
|
||||||
36343864373264633735316236323733346131646330326564396132613661636165323462346639
|
65636266616665633033626337363136303066343232353537346635633431336266333535353131
|
||||||
39636238383832316132376534373034363136646335303835336539633431666330316330363432
|
66316266643335313033386432373962343332326238356430323435363238373334653036393839
|
||||||
36663835313166386235653639396333316236333162316266306566623765393135363033393434
|
65643337663034326232646464383934323661326432373061376662633765613861613466653937
|
||||||
34353839623362626163346531643030613632303263663331386462613038303033363461346133
|
30363065316561666235383332623364353938303734323537643064343333393864313339656161
|
||||||
65353966336635623234643136363439313461393831306334393036623733386232333766383033
|
36663264363363353430663930653965613761353630373034336166633864386234653831343636
|
||||||
35343936663731633665303866333632663066346535383737356262383736643237343637353039
|
32383934633666646235366534303130306436636665326338626566323362616664383162333837
|
||||||
32386166653565623638376531396639373432346163366130333765666534666637373639616534
|
39636539313737653933386261326262633963396364626430633631653735303934353436633532
|
||||||
36386532386133333264376637333666323438336561643636353936636531353934316335323537
|
63373866326666323565663435613530616130323035613438313634393264353266333838333131
|
||||||
33626239346261663833643037623232343839306231363365616634636262363238633034633331
|
33626236366633656365656534643538623431323635313133323630333365653132313932653863
|
||||||
37363831666630336232623762643862323762303765373062363336303463666562643436663164
|
32396139306437353839303933663432376434633462376335386264373934316339616663646130
|
||||||
66613466396235623732613337666430646461313136333437663635613661363937663234323936
|
34363130333061626433663636363032366237346136633966356139663462393836623562626532
|
||||||
66336535646430333536626632643334336234616166636166393762643536333566633163323633
|
35633930306639326639383632363561306164336535303139316162306431313236633036333964
|
||||||
63353366323339643563313939303734656561393137643434346339373439643363343239306235
|
33353063653561343764653235613330613331656338343337623431326564333761633731636531
|
||||||
37316563643138356433333934363965646635353764366338393563656237666435646566343838
|
38616539356239663861363237333733386635353532333039636631663639316434623633323634
|
||||||
36333831333837336532393934323264353661383530623932343132666461656639323764646134
|
64663139356536643864373836303335316464636163303464376264633630633738313064663630
|
||||||
32656361663037396430666333336538336235623337373065393664633739353630633431333833
|
30626363636265383064373764376538626235316138303831306262643932316332323733356535
|
||||||
34363461373234393534393431306565623862356634333161303964343761333735303162636364
|
39306564393236653530393864346261333434663232393765626265626166343864623931636133
|
||||||
66653964383362323034643566343930623731613433333965623466613161356530306233646364
|
37636532333762306339666466633939376432326230306437386337666630393530336163306335
|
||||||
32643039333233613964623463313462326331613936353162386435336337333462306331393836
|
62353037303265656534646262623836633030326636356566363362353161353764636639663538
|
||||||
62373333616438373261383634383262393738613933323935343132323565613565653363356339
|
65373831613431373665383565623361313235333036376239313039616433626539626432373363
|
||||||
30353062313538366161336366396264653437346138323830363637633837313864383539363862
|
37396232626663636165363863346533396132376531306139616664363261323339333239373639
|
||||||
66343235306330323261633261623236663163316139323463363635616636363237343431363862
|
30383136383232323837396665373235363433613864373437623834633164613266383165653966
|
||||||
61333662623166343263343737306539333734323137336238316131333938363233636136646635
|
35336337656361633435363531346134303435633262623465383938626639383332363736356630
|
||||||
62636333306330366561646165346136343932316566363533343038656437303839333362646133
|
32316637613233303531386562386636636361323163633732633732356630636165663266363532
|
||||||
63376431373930653437333731633634326636343238653133633261623663663166316530666434
|
66626433633938663262323464653335396662373634653466653964343065336139313539646536
|
||||||
38653131393163323136643061373065626534653963343935323534623561373932643262376637
|
39663134333530343537323764646566323635303361323032613633626536646236616465343365
|
||||||
32326230656632373334633563366161643033383638623537386562636537323832343330636230
|
39646336626632633839626461303633656633613939393139346639343935333966383564393263
|
||||||
38333163663436373136323162646333616234336133383965323939306137386132356330356137
|
32623639366134636563306463643230656337303666393634386432386332333137316534333361
|
||||||
66373864336433663239393563623061313137633963303438393665623132316232656336376234
|
34646631663137653139343131343236323930373036366263666162306230376664313331636238
|
||||||
32396266343237366532353766663332666165393263346261646363373263623938616161336333
|
31666465343633323931343063376530363838613934623537643338643236323237386163633131
|
||||||
61383563653239633433303835613835633464376434636434616365326234313638323430636535
|
32663263613265646662393339346463353166393630306665343534373238666235663538366637
|
||||||
61613061343665343865643735623132303066323035383533373962376439336563633262633631
|
34306664313462366462643732376365343464393833633035353863663933393566633065663531
|
||||||
38353466353265636233666632373464376165366364376231393438653364313737363765626566
|
64386231363931323363653665613732313438323630373430613634636437666565363734643730
|
||||||
35663439643832353334613462636432343166313334396638326237616235303463373133646635
|
61383265383938643336333666643434356166643831383765343736373436653430376561666338
|
||||||
38666166663630373962376539333237343164333632396165396462323534663234303639663839
|
36373033643665343431303464663838373766306466636534396634323232623434653736316531
|
||||||
66656639356639393665653833613635393239323666376533663534353036623739303837366638
|
32383365396330666333396364663561336663333965323866316131356331363633383437643230
|
||||||
39643332653337363039303366353231623263656230326466353236343136626661633539643964
|
33653337386534316537613830393337336630373436343130623535343938616133376138663236
|
||||||
65383762326661353330616139386535356266336265306135373335353836366434346636313230
|
39363133663735303037396631333062656566393461643337663161646361303739343161653731
|
||||||
36343336313463316661663834376361663935663633303236373734613864323563626436353262
|
38383636623238323261383038326433303532353039383035393666366265653334346630663839
|
||||||
64616635653864366433663135323763393630386234343064656631653730316434333435653463
|
65343336666462366432383764646137623336636662633731386534636463656364383465626531
|
||||||
66363566646461346363343363396266623764363934653561313962643662336662363439643736
|
30663631663932303161366332663964643662626631313732333764353763363764623234323030
|
||||||
30323737653532653665326363306163666439396265656537653766393239336633363033623039
|
36356330313261626134326363346133393638383834623830636165316631613432666261613032
|
||||||
63363164343334663066643863383731666233663164303661346362376231363233333564616162
|
31393231333837623266363130633331646531636136343163376166653261343464623133323635
|
||||||
62343163393961626638303131346130646564373866633561363836316531333230313638616334
|
61333636313962383961393831366262373837316531363166313964316538363634386430343739
|
||||||
62653939623663336665666163393166663434383234323531636563366636336631663065326163
|
64343363373165663934643833613064353264373539666139343734393663643735393736393065
|
||||||
61343238386236643937336530626131616266333463383866626435663834376537313365346133
|
37393262366564616561663532373137336262393439393031383439333336636535323834393138
|
||||||
66313364356634663831316332663634333632363263373332666232626461623933353534633764
|
63613734326238613762616366653533636130326631383631336433343635656230343266343365
|
||||||
33643063313065313637653732313066343661383637353565646637306337303830356630343338
|
35613033356130656632303339643236643330646339333037363830646431313032366363643336
|
||||||
66333836303331346233353434343964356162353432616333353930613431663365396166313563
|
36306332376436356639323738306638333866373532363632373861613863633133323862393036
|
||||||
66343133333061363636303736336536336562333638386131366633303335646432353239333562
|
61653637323635636163386139353038373039623937353533623336653565633730336330353936
|
||||||
34633235303934626661653839643664326564356565386436363863336331306530616261646132
|
61343431633635346339626536376464306663656262333531373438333363666237333832316238
|
||||||
30326266316530346534393566316630616366336262383434383635636139316261383161323437
|
38613336646263633932636233393734626338336433326232326164613436363232616334383230
|
||||||
61363231653037623836356438623039373331323930306465653739323061613334623763353334
|
31616333646361346638613065343065393736313735646234663333633534636331356663323463
|
||||||
30356532636133626639653638326330616138366234623637396332633132613436633463303634
|
35383261396563623363353432356431303539363666653261326363646464373865666531636131
|
||||||
38356166636231653938333832373838376262316337373130383936353335333034636236313434
|
61386634383337656539643338353066373932313134613266373366366630656236313664366164
|
||||||
61613930383065623630643034643539623439626335633733613832623930386362646235633537
|
64633163386431366232383835633235323130376462313832353736343262663737353739303934
|
||||||
35313036366465363461333461633965666664333262396163323537646634643066316532333935
|
62323436326631616134343831376561633965373561303039386266313935336164386636316139
|
||||||
39306538393362386164626334363936313666353633343431343362623738376437353830373432
|
37653238666631306161396537343462376638653263343134633234366236633966373438383639
|
||||||
61343866316338336538666635393631373665623834333231616266666133346531373138643866
|
35356532363534363133353264346661663437656162353739656265373130363931356239366339
|
||||||
33393433333865323730363730386366623032383534396261656134323132663536363331306464
|
38356538616137353737323132366130396335363262646635383763356534306465343463646632
|
||||||
63376232653762313539633137623039633862613236303465383838666133363931393034663834
|
64613431666435333330623035646463666532323131356538343034373936333762303931616463
|
||||||
66646265623162646466636264646265396331346634613138663861363761363334613239323536
|
35346231393338353065326430313032653966666362653438623333323466303431313135323733
|
||||||
63623138373766336664636266336239346331343063373564313265663166633430613366633630
|
39306466666532383933346164323931366337313937623730313162623261373666613363323233
|
||||||
62363961653431366431316536633735646563333732613163386236636138616239636333316534
|
63313161316266323561343363353038326439343661613439336132636361316563373766643164
|
||||||
62363465333865323564336366396463626339386135316130343131626261376631376433356465
|
31646536643439643536303864386530633439646135396336383332646266613461623837656431
|
||||||
34616133653739646236636538383366333163383832656632366230316635313535326435393961
|
30356266356664666436323764316363636330633636646630633536626266343262383731633436
|
||||||
35336330303066346165656561386663656333653234326162363262363163353131343764316562
|
62313964646436366130313730623332613530386538363533633263623866663735386531353861
|
||||||
66363835336339376336323430313764653632646131633330323230376233353365333661386434
|
61363361663739333637353436336435306162643638383134653338656665326531356264343137
|
||||||
39623235626666633862356438303734303965653837376266323932353861633362383630636438
|
61303262373531646634313239393361323835376233633964613937313966643132653264663265
|
||||||
34643763306461353038376563666334386334383038376161636436343233633331313738333463
|
30386334353335343237353734303132643534316130376437386663363937366432303866346231
|
||||||
31653031646266633462663136353039626432613462343763623733663135383366616565633037
|
32616639383462363333373237343663383332343364373465646633383034383034376534396162
|
||||||
63303266356566636163303230613734656132643963613063366135313834313436343563643333
|
61643739323330353130333361396335363634373131653835363036333563613239383966343663
|
||||||
65346663333238353466656336626535666534363733616330386538356436396237393937396166
|
35306362353435663762656461666539393139616264306666393066333764663039623764323937
|
||||||
65376663363864393262353332343064626261363030323333323533376564313436376533666533
|
63643539386161353237343230333832326137666539613539346366353239623265626562386562
|
||||||
65643062396461383635393865363032366234336339633464386166386331376630306632313434
|
39623361376430633461336562613232393631623733326164643637343632633538666437626235
|
||||||
33343933363032633332646638393132613666633166356638313431323330313266306664316464
|
34393638363839653136646562336131376335303661373339326661353935623164316232653034
|
||||||
37363632333737616630373961306237323332613733623864396665366537353533316665376531
|
37306134323561616631313838336364343463303631343765393130623163346365636664333061
|
||||||
36363334613462306535653738663762333265616630626638396132386434313432353538396236
|
33356133626535383765636463326138646266363061326430393934343330356136323664326630
|
||||||
6637
|
66356161356332383739353531366432383966366137653866336666633631636532
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
- name: 'Configure system'
|
- name: 'Configure system'
|
||||||
ansible.builtin.import_playbook: playbook-system.yml
|
ansible.builtin.import_playbook: playbook-system.yml
|
||||||
|
|
||||||
|
- name: 'Configure firewall'
|
||||||
|
ansible.builtin.import_playbook: playbook-ufw.yml
|
||||||
|
|
||||||
- name: 'Configure docker'
|
- name: 'Configure docker'
|
||||||
ansible.builtin.import_playbook: playbook-docker.yml
|
ansible.builtin.import_playbook: playbook-docker.yml
|
||||||
|
|
||||||
|
|||||||
+30
-3
@@ -11,6 +11,15 @@
|
|||||||
config_dir: "{{ (base_dir, 'config') | path_join }}"
|
config_dir: "{{ (base_dir, 'config') | path_join }}"
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
|
# Apprise молча не доставит уведомление, если id комнаты записан без
|
||||||
|
# префикса: значение без '!' и '#' плагин matrix трактует как алиас.
|
||||||
|
- name: "Check matrix room id format"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- notifications_matrix_room is match('^[!#]')
|
||||||
|
fail_msg: "notifications_matrix_room: нужен '!room_id:server' или '#alias:server'"
|
||||||
|
quiet: true
|
||||||
|
|
||||||
- name: "Create user and environment"
|
- name: "Create user and environment"
|
||||||
ansible.builtin.import_role:
|
ansible.builtin.import_role:
|
||||||
name: owner
|
name: owner
|
||||||
@@ -18,7 +27,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create application internal directories"
|
- name: "Create application internal directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
@@ -31,15 +39,23 @@
|
|||||||
- "{{ base_dir }}"
|
- "{{ base_dir }}"
|
||||||
- "{{ config_dir }}"
|
- "{{ config_dir }}"
|
||||||
|
|
||||||
|
# Бандл назывался server, пока источник уведомлений был один. Файл остался
|
||||||
|
# бы на сервере с прежними секретами, поэтому удаляем его явно.
|
||||||
|
- name: "Remove renamed apprise config"
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ config_dir }}/server.cfg"
|
||||||
|
state: "absent"
|
||||||
|
|
||||||
- name: "Copy apprise config"
|
- name: "Copy apprise config"
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
src: "./files/{{ app_name }}/server.template.cfg"
|
src: "./files/{{ app_name }}/backups.template.cfg"
|
||||||
dest: "{{ config_dir }}/server.cfg"
|
dest: "{{ config_dir }}/backups.cfg"
|
||||||
owner: "{{ app_user }}"
|
owner: "{{ app_user }}"
|
||||||
group: "{{ app_user }}"
|
group: "{{ app_user }}"
|
||||||
mode: "0640"
|
mode: "0640"
|
||||||
# Файл содержит секреты из vault — без no_log их печатает --diff.
|
# Файл содержит секреты из vault — без no_log их печатает --diff.
|
||||||
no_log: true
|
no_log: true
|
||||||
|
notify: "Restart application"
|
||||||
|
|
||||||
- name: "Copy docker compose file"
|
- name: "Copy docker compose file"
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
@@ -56,3 +72,14 @@
|
|||||||
remove_orphans: true
|
remove_orphans: true
|
||||||
tags:
|
tags:
|
||||||
- run-app
|
- run-app
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
# Приложение читает конфиги только при старте, а `state: present` не
|
||||||
|
# пересоздаёт контейнер, если docker-compose.yml не изменился, — поэтому
|
||||||
|
# правку конфига применяет только явный рестарт.
|
||||||
|
- name: "Restart application"
|
||||||
|
community.docker.docker_compose_v2:
|
||||||
|
project_src: "{{ base_dir }}"
|
||||||
|
state: "restarted"
|
||||||
|
tags:
|
||||||
|
- run-app
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create internal application directories"
|
- name: "Create internal application directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create application internal directories"
|
- name: "Create application internal directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|||||||
+10
-16
@@ -23,7 +23,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create internal application directories"
|
- name: "Create internal application directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
@@ -74,7 +73,7 @@
|
|||||||
owner: "{{ app_user }}"
|
owner: "{{ app_user }}"
|
||||||
group: "{{ app_user }}"
|
group: "{{ app_user }}"
|
||||||
mode: "0640"
|
mode: "0640"
|
||||||
notify: "Restart application"
|
notify: "Reload caddy configuration"
|
||||||
|
|
||||||
- name: "Copy docker compose file"
|
- name: "Copy docker compose file"
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
@@ -92,21 +91,16 @@
|
|||||||
tags:
|
tags:
|
||||||
- run-app
|
- run-app
|
||||||
|
|
||||||
# - name: "Reload caddy"
|
|
||||||
# community.docker.docker_compose_v2_exec:
|
|
||||||
# project_src: '{{ base_dir }}'
|
|
||||||
# service: "{{ service_name }}"
|
|
||||||
# command: caddy reload --config /etc/caddy/Caddyfile
|
|
||||||
# tags:
|
|
||||||
# - run-app
|
|
||||||
|
|
||||||
handlers:
|
handlers:
|
||||||
# Приложение читает конфиги только при старте, а `state: present` не
|
# `state: present` не пересоздаёт контейнер, если docker-compose.yml не
|
||||||
# пересоздаёт контейнер, если docker-compose.yml не изменился, — поэтому
|
# изменился, — правку Caddyfile надо применять отдельно. Через прокси идёт
|
||||||
# правку конфига применяет только явный рестарт.
|
# весь трафик, поэтому не рестарт, а `caddy reload`: конфиг применяется без
|
||||||
- name: "Restart application"
|
# разрыва соединений. Конфиг указываем явно — без --config caddy берёт файл
|
||||||
community.docker.docker_compose_v2:
|
# из своего рабочего каталога и молча перезагружает не то.
|
||||||
|
- name: "Reload caddy configuration"
|
||||||
|
community.docker.docker_compose_v2_exec:
|
||||||
project_src: "{{ base_dir }}"
|
project_src: "{{ base_dir }}"
|
||||||
state: "restarted"
|
service: "{{ service_name }}"
|
||||||
|
command: "caddy reload --config /etc/caddy/Caddyfile"
|
||||||
tags:
|
tags:
|
||||||
- run-app
|
- run-app
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create application internal directories"
|
- name: "Create application internal directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|||||||
+13
-4
@@ -10,11 +10,9 @@
|
|||||||
base_dir: "{{ (application_dir, app_name) | path_join }}"
|
base_dir: "{{ (application_dir, app_name) | path_join }}"
|
||||||
config_dir: "{{ (base_dir, 'config') | path_join }}"
|
config_dir: "{{ (base_dir, 'config') | path_join }}"
|
||||||
|
|
||||||
# gethomepage.dev — проверь актуальный тег перед обновлением.
|
|
||||||
homepage_image: "ghcr.io/gethomepage/homepage:v1.13.2"
|
|
||||||
# Внутренний порт контейнера; наружу не публикуется, ходим только через Caddy.
|
# Внутренний порт контейнера; наружу не публикуется, ходим только через Caddy.
|
||||||
homepage_port: 3000
|
homepage_port: 3000
|
||||||
# Домен, на котором Caddy отдаёт дашборд. homepage 1.x требует явный whitelist
|
# Домен, на котором Caddy отдаёт дашборд. homepage требует явный whitelist
|
||||||
# Host за реверс-прокси, иначе «Host validation failed».
|
# Host за реверс-прокси, иначе «Host validation failed».
|
||||||
homepage_domain: "start.vakhrushev.me"
|
homepage_domain: "start.vakhrushev.me"
|
||||||
|
|
||||||
@@ -32,7 +30,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create application internal directories"
|
- name: "Create application internal directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
@@ -53,6 +50,7 @@
|
|||||||
group: "{{ app_user }}"
|
group: "{{ app_user }}"
|
||||||
mode: "0640"
|
mode: "0640"
|
||||||
loop: "{{ config_files }}"
|
loop: "{{ config_files }}"
|
||||||
|
notify: "Restart application"
|
||||||
|
|
||||||
- name: "Copy docker compose file"
|
- name: "Copy docker compose file"
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
@@ -70,3 +68,14 @@
|
|||||||
pull: "always"
|
pull: "always"
|
||||||
tags:
|
tags:
|
||||||
- run-app
|
- run-app
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
# Приложение читает конфиги только при старте, а `state: present` не
|
||||||
|
# пересоздаёт контейнер, если docker-compose.yml не изменился, — поэтому
|
||||||
|
# правку конфига применяет только явный рестарт.
|
||||||
|
- name: "Restart application"
|
||||||
|
community.docker.docker_compose_v2:
|
||||||
|
project_src: "{{ base_dir }}"
|
||||||
|
state: "restarted"
|
||||||
|
tags:
|
||||||
|
- run-app
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create internal application directories"
|
- name: "Create internal application directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|||||||
@@ -19,6 +19,10 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
|
# Группа docker = root на хосте, поэтому её не выдаём никому, кроме
|
||||||
|
# приложений, чей backup.sh делает docker compose exec: оркестратор
|
||||||
|
# запускает такие скрипты через su от имени этого пользователя.
|
||||||
|
# См. docs/backlog/backup-dump-without-docker-group.md.
|
||||||
owner_extra_groups: ["docker"]
|
owner_extra_groups: ["docker"]
|
||||||
|
|
||||||
- name: "Create internal application directories"
|
- name: "Create internal application directories"
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create internal application directories"
|
- name: "Create internal application directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
@@ -83,6 +82,9 @@
|
|||||||
- { name: "Dockerfile", mode: "0640" }
|
- { name: "Dockerfile", mode: "0640" }
|
||||||
- { name: "entrypoint.sh", mode: "0750" }
|
- { name: "entrypoint.sh", mode: "0750" }
|
||||||
|
|
||||||
|
# Handler рестарта здесь не нужен: конфиг в контейнер не монтируется, а
|
||||||
|
# правку Dockerfile/entrypoint.sh применяет `build: always` — пересобранный
|
||||||
|
# образ получает новый id, и compose пересоздаёт по нему контейнер (проверено).
|
||||||
- name: "Run application with docker compose"
|
- name: "Run application with docker compose"
|
||||||
community.docker.docker_compose_v2:
|
community.docker.docker_compose_v2:
|
||||||
project_src: "{{ base_dir }}"
|
project_src: "{{ base_dir }}"
|
||||||
|
|||||||
@@ -29,7 +29,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create application internal directories"
|
- name: "Create application internal directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create application internal directories"
|
- name: "Create application internal directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create application internal directories"
|
- name: "Create application internal directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create application internal directories"
|
- name: "Create application internal directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|||||||
+23
-1
@@ -21,6 +21,10 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
|
# Группа docker = root на хосте, поэтому её не выдаём никому, кроме
|
||||||
|
# приложений, чей backup.sh делает docker compose exec: оркестратор
|
||||||
|
# запускает такие скрипты через su от имени этого пользователя.
|
||||||
|
# См. docs/backlog/backup-dump-without-docker-group.md.
|
||||||
owner_extra_groups: ["docker"]
|
owner_extra_groups: ["docker"]
|
||||||
|
|
||||||
- name: "Create internal directories"
|
- name: "Create internal directories"
|
||||||
@@ -37,9 +41,13 @@
|
|||||||
- "{{ postgres_data_dir }}"
|
- "{{ postgres_data_dir }}"
|
||||||
- "{{ postgres_backups_dir }}"
|
- "{{ postgres_backups_dir }}"
|
||||||
|
|
||||||
|
# notify на import_role наследуется всеми задачами роли: рестарт нужен,
|
||||||
|
# если изменился любой файл секретов — miniflux читает их через *_FILE
|
||||||
|
# только при старте.
|
||||||
- name: "Copy secrets"
|
- name: "Copy secrets"
|
||||||
ansible.builtin.import_role:
|
ansible.builtin.import_role:
|
||||||
name: secrets
|
name: secrets
|
||||||
|
notify: "Restart application"
|
||||||
vars:
|
vars:
|
||||||
secrets_dest: "{{ secrets_dir }}"
|
secrets_dest: "{{ secrets_dir }}"
|
||||||
secrets_user: "{{ app_user }}"
|
secrets_user: "{{ app_user }}"
|
||||||
@@ -72,7 +80,21 @@
|
|||||||
community.docker.docker_compose_v2:
|
community.docker.docker_compose_v2:
|
||||||
project_src: "{{ base_dir }}"
|
project_src: "{{ base_dir }}"
|
||||||
state: "present"
|
state: "present"
|
||||||
recreate: "always"
|
|
||||||
remove_orphans: true
|
remove_orphans: true
|
||||||
tags:
|
tags:
|
||||||
- run-app
|
- run-app
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
# Приложение читает секреты только при старте, а `state: present` не
|
||||||
|
# пересоздаёт контейнер, если docker-compose.yml не изменился, — поэтому
|
||||||
|
# правку применяет только явный рестарт.
|
||||||
|
- name: "Restart application"
|
||||||
|
community.docker.docker_compose_v2:
|
||||||
|
project_src: "{{ base_dir }}"
|
||||||
|
# Только сам miniflux: базу дёргать незачем, пароль postgres читается
|
||||||
|
# из тех же секретов лишь при инициализации кластера.
|
||||||
|
services:
|
||||||
|
- "miniflux_app"
|
||||||
|
state: "restarted"
|
||||||
|
tags:
|
||||||
|
- run-app
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create internal application directories"
|
- name: "Create internal application directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|||||||
@@ -25,6 +25,10 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
|
# Группа docker = root на хосте, поэтому её не выдаём никому, кроме
|
||||||
|
# приложений, чей backup.sh делает docker compose exec: оркестратор
|
||||||
|
# запускает такие скрипты через su от имени этого пользователя.
|
||||||
|
# См. docs/backlog/backup-dump-without-docker-group.md.
|
||||||
owner_extra_groups: ["docker"]
|
owner_extra_groups: ["docker"]
|
||||||
|
|
||||||
- name: "Create internal directories"
|
- name: "Create internal directories"
|
||||||
|
|||||||
@@ -30,7 +30,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create application internal directories"
|
- name: "Create application internal directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create internal application directories"
|
- name: "Create internal application directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create application internal directories"
|
- name: "Create application internal directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
@@ -48,6 +47,7 @@
|
|||||||
# Vault-файл: ansible расшифровывает его при копировании, и без no_log
|
# Vault-файл: ansible расшифровывает его при копировании, и без no_log
|
||||||
# --diff покажет содержимое открытым текстом.
|
# --diff покажет содержимое открытым текстом.
|
||||||
no_log: true
|
no_log: true
|
||||||
|
notify: "Restart application"
|
||||||
|
|
||||||
- name: "Copy docker compose file"
|
- name: "Copy docker compose file"
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
@@ -64,3 +64,15 @@
|
|||||||
remove_orphans: true
|
remove_orphans: true
|
||||||
tags:
|
tags:
|
||||||
- run-app
|
- run-app
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
# Конфиг монтируется отдельным файлом, а `copy` подменяет его новым inode:
|
||||||
|
# запущенный контейнер продолжает видеть старый файл по старому inode.
|
||||||
|
# Bind-моунт переустанавливается при старте контейнера, поэтому применяет
|
||||||
|
# правку только явный рестарт.
|
||||||
|
- name: "Restart application"
|
||||||
|
community.docker.docker_compose_v2:
|
||||||
|
project_src: "{{ base_dir }}"
|
||||||
|
state: "restarted"
|
||||||
|
tags:
|
||||||
|
- run-app
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create application internal directories"
|
- name: "Create application internal directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create application internal directories"
|
- name: "Create application internal directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|||||||
@@ -1,7 +1,19 @@
|
|||||||
---
|
---
|
||||||
|
# ufw фильтрует только цепочку INPUT, то есть хостовые сервисы (sshd,
|
||||||
|
# zabbix-агент). Порты, опубликованные докером (80, 443, 2222), идут через
|
||||||
|
# PREROUTING/FORWARD мимо ufw — закрыть их можно только правкой `ports:` в
|
||||||
|
# docker-compose соответствующего приложения.
|
||||||
- name: "Configure UFW firewall"
|
- name: "Configure UFW firewall"
|
||||||
hosts: all
|
hosts: all
|
||||||
|
|
||||||
|
vars:
|
||||||
|
# Опросчики Zabbix у Timeweb: только им нужен доступ к агенту на хосте.
|
||||||
|
# Список — из Server= в /etc/zabbix/zabbix_agentd.conf.
|
||||||
|
zabbix_poller_ips:
|
||||||
|
- "92.53.116.12"
|
||||||
|
- "92.53.116.111"
|
||||||
|
- "92.53.116.119"
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- name: "Ensure UFW is installed"
|
- name: "Ensure UFW is installed"
|
||||||
ansible.builtin.apt:
|
ansible.builtin.apt:
|
||||||
@@ -49,6 +61,17 @@
|
|||||||
port: "443"
|
port: "443"
|
||||||
proto: udp
|
proto: udp
|
||||||
|
|
||||||
|
# Агент хостера слушает 0.0.0.0:10050 и сам проверяет адрес источника,
|
||||||
|
# но держать порт открытым для всего интернета незачем.
|
||||||
|
- name: "Allow Zabbix agent on port 10050 from Timeweb pollers"
|
||||||
|
community.general.ufw:
|
||||||
|
rule: allow
|
||||||
|
src: "{{ item }}"
|
||||||
|
port: "10050"
|
||||||
|
proto: tcp
|
||||||
|
comment: "Timeweb zabbix poller"
|
||||||
|
loop: "{{ zabbix_poller_ips }}"
|
||||||
|
|
||||||
- name: "Enable UFW"
|
- name: "Enable UFW"
|
||||||
community.general.ufw:
|
community.general.ufw:
|
||||||
state: enabled
|
state: enabled
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create application internal directories"
|
- name: "Create application internal directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
backups_dir: "{{ (base_dir, 'backups') | path_join }}"
|
backups_dir: "{{ (base_dir, 'backups') | path_join }}"
|
||||||
gobackup_config: "{{ (base_dir, 'gobackup.yml') | path_join }}"
|
gobackup_config: "{{ (base_dir, 'gobackup.yml') | path_join }}"
|
||||||
|
|
||||||
wanderer_version: "v0.18.3"
|
|
||||||
wanderer_origin: "https://wanderer.vakhrushev.me"
|
wanderer_origin: "https://wanderer.vakhrushev.me"
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
@@ -23,7 +22,6 @@
|
|||||||
owner_name: "{{ app_user }}"
|
owner_name: "{{ app_user }}"
|
||||||
owner_uid: "{{ app_owner_uid }}"
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
owner_gid: "{{ app_owner_gid }}"
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
owner_extra_groups: ["docker"]
|
|
||||||
|
|
||||||
- name: "Create application internal directories"
|
- name: "Create application internal directories"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# owner
|
||||||
|
|
||||||
|
Заводит системного пользователя и группу под одно приложение: фиксированные
|
||||||
|
uid/gid, ssh-ключи и переменные окружения в `~/.env`.
|
||||||
|
|
||||||
|
Один сервис — один пользователь: контейнеры приложения работают от его uid/gid,
|
||||||
|
и файлы в `base_dir` принадлежат ему же. Роль вызывается первой задачей почти
|
||||||
|
каждого `playbook-<app>.yml`.
|
||||||
|
|
||||||
|
## Что делает
|
||||||
|
|
||||||
|
1. **Группа и пользователь.** Создаёт группу `owner_group` с `owner_gid` и
|
||||||
|
пользователя `owner_name` с `owner_uid` и шеллом `/bin/bash`. Номера задаёт
|
||||||
|
плейбук приложения (соглашение по нумерации — в `AGENTS.md`).
|
||||||
|
2. **SSH-ключи.** Прописывает `owner_ssh_keys` в `authorized_keys`.
|
||||||
|
3. **Переменные окружения.** Рендерит `~/.env` из `owner_env` плюс `USER_UID` и
|
||||||
|
`USER_GID` — их подставляют docker-compose шаблоны приложений. В `.bashrc`
|
||||||
|
добавляет строку, подгружающую `~/.env` целиком, и вычищает старые построчные
|
||||||
|
`export`-ы, оставшиеся от прежней схемы.
|
||||||
|
|
||||||
|
## Результат для плейбука
|
||||||
|
|
||||||
|
Роль регистрирует `owner_create_result` — результат модуля `user`. Плейбуки и
|
||||||
|
compose-шаблоны берут оттуда `owner_create_result.uid` и
|
||||||
|
`owner_create_result.group` (это gid) для `user:` в docker-compose.
|
||||||
|
|
||||||
|
## Переменные
|
||||||
|
|
||||||
|
Полный список и значения по умолчанию — в `defaults/main.yml`.
|
||||||
|
|
||||||
|
| Переменная | Обязательная | Описание |
|
||||||
|
| --------------------- | ------------ | --------------------------------------------------- |
|
||||||
|
| `owner_name` | да | Имя пользователя; по умолчанию оно же имя группы |
|
||||||
|
| `owner_uid` | да | Uid пользователя |
|
||||||
|
| `owner_group` | нет | Имя группы, по умолчанию `owner_name` |
|
||||||
|
| `owner_gid` | нет | Gid группы, по умолчанию `owner_uid` |
|
||||||
|
| `owner_extra_groups` | нет | Дополнительные группы; по умолчанию пусто |
|
||||||
|
| `owner_ssh_keys` | нет | Список публичных ключей для `authorized_keys` |
|
||||||
|
| `owner_env` | нет | Словарь переменных окружения, попадающих в `~/.env` |
|
||||||
|
|
||||||
|
## Про группу `docker`
|
||||||
|
|
||||||
|
Членство в группе `docker` равносильно root на хосте (`docker run -v /:/host`),
|
||||||
|
поэтому сервисным пользователям её не выдаём: контейнерами рулит Ansible от
|
||||||
|
root. Исключение — приложения, чей `backup.sh` дампит базу через
|
||||||
|
`docker compose exec`: оркестратор бэкапов запускает такие скрипты от имени
|
||||||
|
самого приложения. См. `docs/backlog/backup-dump-without-docker-group.md`.
|
||||||
|
|
||||||
|
## Пример использования
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: "Create user and environment"
|
||||||
|
ansible.builtin.import_role:
|
||||||
|
name: owner
|
||||||
|
vars:
|
||||||
|
owner_name: "{{ app_user }}"
|
||||||
|
owner_uid: "{{ app_owner_uid }}"
|
||||||
|
owner_gid: "{{ app_owner_gid }}"
|
||||||
|
```
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
role_name: owner
|
||||||
|
author: "Anton Vakhrushev"
|
||||||
|
description: "Системный пользователь приложения: группа, uid/gid, ssh-ключи и переменные окружения"
|
||||||
|
license: "MIT"
|
||||||
|
min_ansible_version: "2.14"
|
||||||
|
platforms:
|
||||||
|
- name: Ubuntu
|
||||||
|
versions:
|
||||||
|
- all
|
||||||
|
- name: Debian
|
||||||
|
versions:
|
||||||
|
- all
|
||||||
|
galaxy_tags:
|
||||||
|
- users
|
||||||
|
- system
|
||||||
|
- environment
|
||||||
|
|
||||||
|
dependencies: []
|
||||||
+28
-20
@@ -1,21 +1,24 @@
|
|||||||
---
|
---
|
||||||
- name: 'Check app requirements for user "{{ owner_name }}".'
|
# tasks file for owner
|
||||||
ansible.builtin.fail:
|
|
||||||
msg: You must set owner name.
|
|
||||||
when: not owner_name
|
|
||||||
|
|
||||||
- name: 'Check app requirements for user "{{ owner_name }}".'
|
- name: "Validate owner role arguments"
|
||||||
ansible.builtin.fail:
|
ansible.builtin.assert:
|
||||||
msg: You must set owner uid.
|
that:
|
||||||
when: not owner_uid
|
- owner_name is string and owner_name | length > 0
|
||||||
|
- owner_uid | int > 0
|
||||||
|
- owner_gid | int > 0
|
||||||
|
fail_msg: >-
|
||||||
|
Роль owner требует непустой owner_name и положительные owner_uid/owner_gid
|
||||||
|
(owner_name={{ owner_name }}, owner_uid={{ owner_uid }}, owner_gid={{ owner_gid }})
|
||||||
|
quiet: true
|
||||||
|
|
||||||
- name: 'Create group "{{ owner_group }}".'
|
- name: "Create group {{ owner_group }}"
|
||||||
ansible.builtin.group:
|
ansible.builtin.group:
|
||||||
name: "{{ owner_group }}"
|
name: "{{ owner_group }}"
|
||||||
gid: "{{ owner_gid }}"
|
gid: "{{ owner_gid }}"
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
- name: 'Create user "{{ owner_name }}".'
|
- name: "Create user {{ owner_name }}"
|
||||||
ansible.builtin.user:
|
ansible.builtin.user:
|
||||||
name: "{{ owner_name }}"
|
name: "{{ owner_name }}"
|
||||||
group: "{{ owner_group }}"
|
group: "{{ owner_group }}"
|
||||||
@@ -24,20 +27,21 @@
|
|||||||
shell: /bin/bash
|
shell: /bin/bash
|
||||||
register: owner_create_result
|
register: owner_create_result
|
||||||
|
|
||||||
- name: 'Set up user ssh keys for user "{{ owner_name }}".'
|
- name: "Set up ssh keys for user {{ owner_name }}"
|
||||||
ansible.posix.authorized_key:
|
ansible.posix.authorized_key:
|
||||||
user: "{{ owner_name }}"
|
user: "{{ owner_name }}"
|
||||||
key: "{{ item }}"
|
key: "{{ item }}"
|
||||||
state: present
|
state: present
|
||||||
with_items: "{{ owner_ssh_keys }}"
|
loop: "{{ owner_ssh_keys }}"
|
||||||
when: owner_ssh_keys | length > 0
|
|
||||||
|
|
||||||
- name: "Prepare env variables."
|
# USER_UID/USER_GID кладём в окружение всегда: их подставляют docker-compose
|
||||||
|
# шаблоны приложений, чтобы контейнер работал от того же пользователя.
|
||||||
|
- name: "Prepare env variables"
|
||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
# yamllint disable-line rule:line-length
|
owner_env_dict: >-
|
||||||
owner_env_dict: '{{ owner_env | combine({"USER_UID": owner_create_result.uid, "USER_GID": owner_create_result.group}) }}'
|
{{ owner_env | combine({"USER_UID": owner_create_result.uid, "USER_GID": owner_create_result.group}) }}
|
||||||
|
|
||||||
- name: 'Set up environment variables for user "{{ owner_name }}".'
|
- name: "Set up environment variables for user {{ owner_name }}"
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
src: env.template
|
src: env.template
|
||||||
dest: "/home/{{ owner_name }}/.env"
|
dest: "/home/{{ owner_name }}/.env"
|
||||||
@@ -45,14 +49,18 @@
|
|||||||
group: "{{ owner_group }}"
|
group: "{{ owner_group }}"
|
||||||
mode: "0640"
|
mode: "0640"
|
||||||
|
|
||||||
- name: 'Remove from bashrc absent environment variables for user "{{ owner_name }}".'
|
# Раньше переменные писались в .bashrc построчно; теперь источник истины —
|
||||||
|
# ~/.env, поэтому старые строки вычищаем.
|
||||||
|
- name: "Remove from bashrc absent environment variables for user {{ owner_name }}"
|
||||||
ansible.builtin.lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
path: "/home/{{ owner_name }}/.bashrc"
|
path: "/home/{{ owner_name }}/.bashrc"
|
||||||
regexp: "^export {{ item.key }}="
|
regexp: "^export {{ item.key }}="
|
||||||
state: absent
|
state: absent
|
||||||
with_dict: "{{ owner_env_dict }}"
|
loop: "{{ owner_env_dict | dict2items }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.key }}"
|
||||||
|
|
||||||
- name: 'Include in bashrc environment variables for user "{{ owner_name }}".'
|
- name: "Include in bashrc environment variables for user {{ owner_name }}"
|
||||||
ansible.builtin.lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
path: "/home/{{ owner_name }}/.bashrc"
|
path: "/home/{{ owner_name }}/.bashrc"
|
||||||
regexp: "^export \\$\\(grep -v"
|
regexp: "^export \\$\\(grep -v"
|
||||||
|
|||||||
Reference in New Issue
Block a user