Migration: transfer data and run apps

This commit is contained in:
2026-05-23 17:51:07 +03:00
parent a3e53b21e6
commit 02ea9a3735
3 changed files with 942 additions and 713 deletions
+239
View File
@@ -8,6 +8,245 @@
--- ---
## Шаг 13 — приложения подняты на target, cutover завершён (2026-05-23, выполнено)
После rsync'а (Шаг 12) — финальный прогон ансибла без `--skip-tags`,
поэтапно по приложениям. К ~16:30 DNS уже указывал на target (Шаг
переключения 15:45 + TTL 20 мин, пропагация подтверждена в 16:20),
так что Caddy при старте сразу пошёл за LE-сертификатами без задержек.
Прогоны делал поштучно через `inv pl -- <app>` (после Шага
переключения `HOSTS_FILE = "timeweb.yml"` в `tasks.py`), не всем
сразу — чтобы видеть каждый плейбук чисто.
### Что подтверждено работающим в браузере
- `vakhrushev.me` — homepage отдаёт страницу.
- `auth.vakhrushev.me` — Authelia, логин работает.
- `matrix.vakhrushev.me` — Tuwunel поднялся, Element подключается.
- `git.vakhrushev.me` — Gitea, репозитории и issue tracker на месте.
- `outline.vakhrushev.me` — документы видны.
- `gramps.vakhrushev.me` — генеалогическое дерево открывается.
- `wakapi.vakhrushev.me` — статистика времени видна.
- `status.vakhrushev.me` — Netdata собирает и рисует метрики.
Точечно зашёл в outline / gramps / wakapi / gitea — данные на месте,
ничего не потерялось при rsync'е.
### Отложенные на «потом по ходу дела» проверки
- `miniflux`, `memos`, `remembos`, `wanderer`, `calibre`, `rssbridge`,
`dozzle`, `goaccess` — открыть и убедиться, что отдают свои данные.
- **SMTP-test** — reset-password из gitea/authelia. Проверит, что
Postbox после разблокировки в панели Timeweb принимает наши письма.
- **Backup-cron в 1:00** — самый поздний smoke-тест системы. Покажет,
что `backup-all.py` отработал на target, restic пишет в S3 с новым
`host_name`, apprise шлёт уведомление.
- `docker pull cr.yandex/...` руками — повторная проверка
OAuth-аутентификации.
### Отклонения от плана сегодня
1. **VPS пересоздан в СПб** (Шаг 8) — первая выдача попала на
гипервизор с битой сетью.
2. **Docker Hub rate limit** на pull'е netdata — anonymous лимит
подсети Timeweb уже выбран соседями. Лечится ручным
`sudo docker login` на target (через free-аккаунт + PAT).
**Backlog:** добавить `community.docker.docker_login` для
`docker.io` в `playbook-docker.yml`, по аналогии с cr.yandex (Шаг
3). Креды в vault как `dockerhub_username` / `dockerhub_token`.
3. **Postbox SMTP не доступен извне YC** — оказалось, что в плане
(`timeweb.md:81`) предпосылка «Postbox доступен извне YC по тем же
credentials» неверна. Yandex Cloud Postbox дропает SMTP от не-YC
источников; 443 при этом отвечает. Дополнительно Timeweb по
умолчанию **сам** блокирует egress SMTP (25/465/587) — toggle в
панели Timeweb снимает блок, после чего Postbox отвечает баннером.
Authelia в exit-loop'е поднялась после рестарта. Запись в auto-
memory `project_timeweb_smtp_block.md` — пригодится при следующих
миграциях.
4. **Bug ordering в `playbook-goaccess.yml`** (см. Шаг 9, фикс
зашит) — латентный bug, проявившийся только на чистой машине.
### Что осталось до полной заморозки
По плану (`timeweb.md:464-473`):
- **≥ 24 часа** держим источник в выключенном состоянии (docker уже
остановлен, daemon отключён через `disable`), как горячее запасное.
- Если за сутки ничего не всплыло — выключить VM в YC.
- Подождать ещё неделю-две — на всякий случай.
- Удалить VM и связанные compute-ресурсы. **S3-бакет с
restic-бэкапами и Container Registry — оставляем**, они продолжают
использоваться.
- Удалить `production.yml`, переименовать `timeweb.yml`
`production.yml`, откатить `HOSTS_FILE = "production.yml"` в
`tasks.py`. Закоммитить.
---
## Шаг 12 — rsync данных с источника на target (2026-05-23, выполнено)
Перенос `/mnt/applications/` на YC → `/srv/applications/` на Timeweb
после заморозки источника (Шаг 11). Это финальный канал переноса
данных — основной для всех приложений, единственный для `caddyproxy`,
`remembos`, `transcriber` (у которых нет backup-механизма, см. Шаг 7b).
### Пилотный прогон на remembos
Прежде чем гнать всё дерево, проверил рецепт на самом маленьком
приложении (~35 КБ всего):
```bash
sudo -E rsync -aAX --info=progress2 --delete --rsync-path="sudo rsync" \
-e "ssh -o StrictHostKeyChecking=accept-new" \
major@158.160.46.255:/mnt/applications/remembos/ \
/srv/applications/remembos/
```
Проверка после прогона:
```
$ sudo ls -la /srv/applications/remembos/
drwxr-x--- 4 remembos remembos 4096 Apr 30 13:22 .
drwxr-x--- 2 remembos remembos 4096 Feb 12 17:22 config
drwxr-x--- 2 remembos remembos 4096 May 23 12:41 data
-rw-r----- 1 remembos remembos 494 Apr 30 13:22 docker-compose.yml
```
Owner отрисован именами (`remembos:remembos`, не numeric `1103:1103`)
— значит на обеих сторонах ансибл создал юзера с одним и тем же uid,
mapping сошёлся. Mode (750) и mtime сохранены.
### Засада с agent-forwarding'ом под sudo
Первая попытка упала с `Permission denied (publickey)`. Причина:
rsync запускается через `sudo` на target, а sudo по дефолту чистит
`SSH_AUTH_SOCK` из env (`Defaults env_reset` в /etc/sudoers) — ssh
внутри sudo не видит проброшенный agent, пытается парольную
аутентификацию, проваливается.
Лечится разрешением sudo проносить именно эту переменную:
```bash
echo 'Defaults env_keep += "SSH_AUTH_SOCK"' | sudo tee -a /etc/sudoers.d/major
sudo visudo -cf /etc/sudoers.d/major
```
Безопасно: сокет агента принадлежит `major`, root к нему имеет доступ
по определению; мы просто говорим sudo не вычищать переменную с путём
к нему. После этого `sudo -E rsync …` отрабатывает.
### Полный прогон по всем приложениям
```bash
sudo -E rsync -aAX --info=progress2 --delete --exclude='lost+found' \
--rsync-path="sudo rsync" \
-e "ssh -o StrictHostKeyChecking=accept-new" \
major@158.160.46.255:/mnt/applications/ \
/srv/applications/
```
### Что делает каждый флаг
- **`sudo -E`** — локальный rsync на target запускается под root
(нужно, чтобы писать файлы с любым owner'ом / mode); `-E` сохраняет
env, в первую очередь `SSH_AUTH_SOCK` для agent forwarding.
- **`-a`** (`--archive`) — собирательный флаг `-rlptgoD`: recursive +
symlinks как symlinks + permissions + times + group + owner +
special files. Базовое «копировать всё как есть».
- **`-A`** — сохранить POSIX ACL.
- **`-X`** — сохранить extended attributes (xattrs), включая
security-атрибуты типа capabilities или SELinux-меток.
- **`--info=progress2`** — совокупный прогресс по всему transfer'у,
а не per-file (для больших деревьев читабельнее).
- **`--delete`** — стереть на target всё, чего нет на источнике.
Безопасно в нашем случае: после rsync'а прогоняем ансибл, он
перерендерит конфиги и пересоздаст любые отсутствующие структурные
каталоги. Стирается, по сути, только содержимое, отрендеренное
плейбуком на Шаге 9 без `run-app`.
- **`--exclude='lost+found'`** — на YC `/mnt/applications/` это mount
point внешнего диска, в его корне может лежать системный
`lost+found`. Нам он не нужен и на target такого монтирования
больше нет (`mount_external_storage: false`).
- **`--rsync-path="sudo rsync"`** — критично: на удалённой стороне
(источнике) rsync запускается через sudo. Иначе он стартует под
`major`, у которого нет прав читать чужие `/mnt/applications/<app>/`
(mode 750, owner — приложение). У `major` на источнике NOPASSWD
sudo, так что sudo прокатывает молча.
- **`-e "ssh -o StrictHostKeyChecking=accept-new"`** — кастомная
команда транспорта. По умолчанию rsync запускает чистый `ssh`; мы
добавляем флаг для автопринятия host key источника (на target
`known_hosts` ещё пустой).
- **`major@158.160.46.255:/mnt/applications/`** — источник. Trailing
slash важен: «копировать содержимое каталога», а не сам каталог.
Без слэша получили бы `/srv/applications/applications/...`.
- **`/srv/applications/`** — назначение. Trailing slash для
симметрии — содержимое кладётся в существующий каталог,
созданный ансиблом на Шаге 9.
### Результат
```
22,613,081,829 99% 7.11MB/s 0:50:34 (xfr#21837, to-chk=0/31024)
```
- Объём — ~22.6 ГБ, файлов — 31 024.
- Длительность — 50 минут 34 секунды, средняя скорость ~7 МБ/с
(предсказуемо для YC↔Timeweb).
- `du -s` после прогона: источник 22 088 224 КБ, target 22 164 172 КБ
— разница ~76 МБ (0.34%). Это не рассинхрон данных, а разница в
аллокации блоков ФС и метаданных между источником и target (разные
inode-таблицы, journal, group descriptors). Содержимое файлов
совпадает — rsync'у на это указали checksum'ы, errors не было.
Окно даунтайма с момента стопа docker'а (Шаг 11) до конца rsync'а
около часа. С учётом параллельно запущенного DNS-переключения
(Шаг между 11 и 12, 15:45) к моменту запуска приложений на target
пропагация уже прошла (16:20).
---
## Шаг 11 — источник заморожен (docker + cron остановлены) (2026-05-23, выполнено)
Сразу после финального бэкапа (Шаг 10) — отключил docker и cron на
источнике, чтобы зафиксировать состояние данных перед rsync'ом и
исключить случайные записи в `/mnt/applications/` во время переноса.
```bash
sudo systemctl stop docker.service docker.socket
sudo systemctl disable docker.service docker.socket
sudo systemctl stop cron
```
`disable` — страховка от автостарта docker'а при возможной
перезагрузке источника (если вернёмся для отката или проверки).
`cron stop` — чтобы ночной `backup-all.py` не запустился впустую без
работающего daemon'а.
С этого момента источник «мёртв» для пользователей — окно даунтайма
открыто. Следующий шаг — переключить DNS и параллельно гнать rsync.
---
## Шаг 10 — финальный бэкап на источнике (2026-05-23, выполнено)
Прогнал `backup-all.py` на источнике, пока docker ещё жив (он нужен
для `pg_dump` и других in-container backup-команд внутри
`backup.sh`-скриптов отдельных приложений).
```bash
sudo /usr/local/sbin/backup-all.py 2>&1 | tee /tmp/final-backup.log
```
Свежий restic-снапшот в `yandex_cloud_s3` зафиксирован — страховочный
канал на случай, если rsync пойдёт криво (для приложений с
`backup.sh` можно будет восстановить из S3; для `caddyproxy`,
`remembos`, `transcriber` страховки нет, для них только rsync).
После прогона можно гасить docker без риска потерять backup-окно.
---
## Шаг 9 — раскатана база и приложения без запуска (2026-05-23, выполнено) ## Шаг 9 — раскатана база и приложения без запуска (2026-05-23, выполнено)
На свежей Timeweb-машине прогнаны два плейбука без даунтайма источника На свежей Timeweb-машине прогнаны два плейбука без даунтайма источника
+72 -82
View File
@@ -104,7 +104,7 @@ server:
## Configure the authz endpoints. ## Configure the authz endpoints.
authz: authz:
forward-auth: forward-auth:
implementation: 'ForwardAuth' implementation: "ForwardAuth"
# authn_strategies: [] # authn_strategies: []
# ext-authz: # ext-authz:
# implementation: 'ExtAuthz' # implementation: 'ExtAuthz'
@@ -121,10 +121,10 @@ server:
## ##
log: log:
## Level of verbosity for logs: info, debug, trace. ## Level of verbosity for logs: info, debug, trace.
level: 'debug' level: "debug"
## Format the logs are written as: json, text. ## Format the logs are written as: json, text.
format: 'json' format: "json"
## File path where the logs will be written. If not set logs are written to stdout. ## File path where the logs will be written. If not set logs are written to stdout.
# file_path: '/config/authelia.log' # file_path: '/config/authelia.log'
@@ -136,7 +136,6 @@ log:
## Telemetry Configuration ## Telemetry Configuration
## ##
telemetry: telemetry:
## ##
## Metrics Configuration ## Metrics Configuration
## ##
@@ -151,7 +150,7 @@ telemetry:
## Square brackets indicate optional portions of the format. Scheme must be 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd'. ## Square brackets indicate optional portions of the format. Scheme must be 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd'.
## The default scheme is 'unix' if the address is an absolute path otherwise it's 'tcp'. The default port is '9959'. ## The default scheme is 'unix' if the address is an absolute path otherwise it's 'tcp'. The default port is '9959'.
## If the path is not specified it defaults to `/metrics`. ## If the path is not specified it defaults to `/metrics`.
address: 'tcp://:9959/metrics' address: "tcp://:9959/metrics"
## Metrics Server Buffers configuration. ## Metrics Server Buffers configuration.
# buffers: # buffers:
@@ -320,7 +319,6 @@ telemetry:
## ##
## This configuration tunes the identity validation flows. ## This configuration tunes the identity validation flows.
identity_validation: identity_validation:
## Reset Password flow. Adjusts how the reset password flow operates. ## Reset Password flow. Adjusts how the reset password flow operates.
reset_password: reset_password:
## Maximum allowed time before the JWT is generated and when the user uses it in the duration common syntax. ## Maximum allowed time before the JWT is generated and when the user uses it in the duration common syntax.
@@ -330,7 +328,7 @@ identity_validation:
# jwt_algorithm: 'HS256' # jwt_algorithm: 'HS256'
## The secret key used to sign and verify the JWT. ## The secret key used to sign and verify the JWT.
jwt_secret: '{{ identity_validation__jwt_secret }}' jwt_secret: "{{ identity_validation__jwt_secret }}"
## Elevated Session flows. Adjusts the flow which require elevated sessions for example managing credentials, adding, ## Elevated Session flows. Adjusts the flow which require elevated sessions for example managing credentials, adding,
## removing, etc. ## removing, etc.
@@ -408,7 +406,6 @@ identity_validation:
## ##
## The available providers are: `file`, `ldap`. You must use only one of these providers. ## The available providers are: `file`, `ldap`. You must use only one of these providers.
authentication_backend: authentication_backend:
## Password Change Options. ## Password Change Options.
password_change: password_change:
## Disable both the HTML element and the API for password change functionality. ## Disable both the HTML element and the API for password change functionality.
@@ -606,7 +603,7 @@ authentication_backend:
## Important: Kubernetes (or HA) users must read https://www.authelia.com/t/statelessness ## Important: Kubernetes (or HA) users must read https://www.authelia.com/t/statelessness
## ##
file: file:
path: '/config/users.yml' path: "/config/users.yml"
# watch: false # watch: false
# search: # search:
# email: false # email: false
@@ -719,33 +716,33 @@ authentication_backend:
access_control: access_control:
## Default policy can either be 'bypass', 'one_factor', 'two_factor' or 'deny'. It is the policy applied to any ## Default policy can either be 'bypass', 'one_factor', 'two_factor' or 'deny'. It is the policy applied to any
## resource if there is no policy to be applied to the user. ## resource if there is no policy to be applied to the user.
default_policy: 'deny' default_policy: "deny"
rules: rules:
## Rules applied to everyone ## Rules applied to everyone
- domain: 'status.vakhrushev.me' - domain: "status.vakhrushev.me"
subject: 'group:admins' subject: "group:admins"
policy: 'two_factor' policy: "two_factor"
- domain: 'dozzle.vakhrushev.me' - domain: "dozzle.vakhrushev.me"
subject: 'group:admins' subject: "group:admins"
policy: 'two_factor' policy: "two_factor"
- domain: 'goaccess.vakhrushev.me' - domain: "goaccess.vakhrushev.me"
subject: 'group:admins' subject: "group:admins"
policy: 'two_factor' policy: "two_factor"
- domain: 'wanderbase.vakhrushev.me' - domain: "wanderbase.vakhrushev.me"
subject: 'group:admins' subject: "group:admins"
policy: 'two_factor' policy: "two_factor"
- domain: 'remembos.vakhrushev.me' - domain: "remembos.vakhrushev.me"
subject: 'group:admins' subject: "group:admins"
policy: 'two_factor' policy: "two_factor"
- domain: 'rssbridge.vakhrushev.me' - domain: "rssbridge.vakhrushev.me"
subject: 'group:admins' subject: "group:admins"
policy: 'one_factor' policy: "one_factor"
## Domain Regex examples. Generally we recommend just using a standard domain. ## Domain Regex examples. Generally we recommend just using a standard domain.
# - domain_regex: '^(?P<User>\w+)\.example\.com$' # - domain_regex: '^(?P<User>\w+)\.example\.com$'
@@ -826,18 +823,17 @@ access_control:
session: session:
## The secret to encrypt the session data. This is only used with Redis / Redis Sentinel. ## The secret to encrypt the session data. This is only used with Redis / Redis Sentinel.
## Secret can also be set using a secret: https://www.authelia.com/c/secrets ## Secret can also be set using a secret: https://www.authelia.com/c/secrets
secret: '{{ session__secret }}' secret: "{{ session__secret }}"
## Cookies configures the list of allowed cookie domains for sessions to be created on. ## Cookies configures the list of allowed cookie domains for sessions to be created on.
## Undefined values will default to the values below. ## Undefined values will default to the values below.
cookies: cookies:
- - ## The name of the session cookie.
## The name of the session cookie. name: "authelia_session"
name: 'authelia_session'
## The domain to protect. ## The domain to protect.
## Note: the Authelia portal must also be in that domain. ## Note: the Authelia portal must also be in that domain.
domain: 'vakhrushev.me' domain: "vakhrushev.me"
## Required. The fully qualified URI of the portal to redirect users to on proxies that support redirections. ## Required. The fully qualified URI of the portal to redirect users to on proxies that support redirections.
## Rules: ## Rules:
@@ -845,7 +841,7 @@ session:
## - The above 'domain' option MUST either: ## - The above 'domain' option MUST either:
## - Match the host portion of this URI. ## - Match the host portion of this URI.
## - Match the suffix of the host portion when prefixed with '.'. ## - Match the suffix of the host portion when prefixed with '.'.
authelia_url: 'https://auth.vakhrushev.me' authelia_url: "https://auth.vakhrushev.me"
## Optional. The fully qualified URI used as the redirection location if the portal is accessed directly. Not ## Optional. The fully qualified URI used as the redirection location if the portal is accessed directly. Not
## configuring this option disables the automatic redirection behaviour. ## configuring this option disables the automatic redirection behaviour.
@@ -904,7 +900,7 @@ session:
## Important: Kubernetes (or HA) users must read https://www.authelia.com/t/statelessness ## Important: Kubernetes (or HA) users must read https://www.authelia.com/t/statelessness
## ##
redis: redis:
host: 'authelia_redis' host: "authelia_redis"
port: 6379 port: 6379
## Use a unix socket instead ## Use a unix socket instead
# host: '/var/run/redis/redis.sock' # host: '/var/run/redis/redis.sock'
@@ -1022,7 +1018,7 @@ storage:
## The encryption key that is used to encrypt sensitive information in the database. Must be a string with a minimum ## The encryption key that is used to encrypt sensitive information in the database. Must be a string with a minimum
## length of 20. Please see the docs if you configure this with an undesirable key and need to change it, you MUST use ## length of 20. Please see the docs if you configure this with an undesirable key and need to change it, you MUST use
## the CLI to change this in the database if you want to change it from a previously configured value. ## the CLI to change this in the database if you want to change it from a previously configured value.
encryption_key: '{{ storage__encryption_key }}' encryption_key: "{{ storage__encryption_key }}"
## ##
## Local (Storage Provider) ## Local (Storage Provider)
@@ -1034,7 +1030,7 @@ storage:
## ##
local: local:
## Path to the SQLite3 Database. ## Path to the SQLite3 Database.
path: '/data/authelia_storage.sqlite3' path: "/data/authelia_storage.sqlite3"
## ##
## MySQL / MariaDB (Storage Provider) ## MySQL / MariaDB (Storage Provider)
@@ -1212,22 +1208,22 @@ notifier:
## (configure in tls section) ## (configure in tls section)
smtp: smtp:
## The address of the SMTP server to connect to in the address common syntax. ## The address of the SMTP server to connect to in the address common syntax.
address: 'smtp://{{ postbox_host }}:{{ postbox_port }}' address: "smtp://{{ postbox_host }}:{{ postbox_port }}"
## The connection timeout in the duration common syntax. ## The connection timeout in the duration common syntax.
# timeout: '5 seconds' # timeout: '5 seconds'
## The username used for SMTP authentication. ## The username used for SMTP authentication.
username: '{{ postbox_user }}' username: "{{ postbox_user }}"
## The password used for SMTP authentication. ## The password used for SMTP authentication.
## Can also be set using a secret: https://www.authelia.com/c/secrets ## Can also be set using a secret: https://www.authelia.com/c/secrets
password: '{{ postbox_pass }}' password: "{{ postbox_pass }}"
## The sender is used to is used for the MAIL FROM command and the FROM header. ## The sender is used to is used for the MAIL FROM command and the FROM header.
## If this is not defined and the username is an email, we use the username as this value. This can either be just ## If this is not defined and the username is an email, we use the username as this value. This can either be just
## an email address or the RFC5322 'Name <email address>' format. ## an email address or the RFC5322 'Name <email address>' format.
sender: 'Authelia <authelia@vakhrushev.me>' sender: "Authelia <authelia@vakhrushev.me>"
## HELO/EHLO Identifier. Some SMTP Servers may reject the default of localhost. ## HELO/EHLO Identifier. Some SMTP Servers may reject the default of localhost.
# identifier: 'localhost' # identifier: 'localhost'
@@ -1237,7 +1233,7 @@ notifier:
## This address is used during the startup check to verify the email configuration is correct. ## This address is used during the startup check to verify the email configuration is correct.
## It's not important what it is except if your email server only allows local delivery. ## It's not important what it is except if your email server only allows local delivery.
startup_check_address: '{{ smtp__startup_check_address }}' # startup_check_address: '{{ smtp__startup_check_address }}'
## By default we require some form of TLS. This disables this check though is not advised. ## By default we require some form of TLS. This disables this check though is not advised.
# disable_require_tls: false # disable_require_tls: false
@@ -1285,7 +1281,6 @@ notifier:
## Identity Providers ## Identity Providers
## ##
identity_providers: identity_providers:
## ##
## OpenID Connect (Identity Provider) ## OpenID Connect (Identity Provider)
## ##
@@ -1294,13 +1289,12 @@ identity_providers:
oidc: oidc:
## The hmac_secret is used to sign OAuth2 tokens (authorization code, access tokens and refresh tokens). ## The hmac_secret is used to sign OAuth2 tokens (authorization code, access tokens and refresh tokens).
## HMAC Secret can also be set using a secret: https://www.authelia.com/c/secrets ## HMAC Secret can also be set using a secret: https://www.authelia.com/c/secrets
hmac_secret: '{{ oidc__hmac_secret }}' hmac_secret: "{{ oidc__hmac_secret }}"
## The JWK's issuer option configures multiple JSON Web Keys. It's required that at least one of the JWK's ## The JWK's issuer option configures multiple JSON Web Keys. It's required that at least one of the JWK's
## configured has the RS256 algorithm. For RSA keys (RS or PS) the minimum is a 2048 bit key. ## configured has the RS256 algorithm. For RSA keys (RS or PS) the minimum is a 2048 bit key.
jwks: jwks:
- - ## Key ID embedded into the JWT header for key matching.
## Key ID embedded into the JWT header for key matching.
## Must be an alphanumeric string with 7 or less characters. ## Must be an alphanumeric string with 7 or less characters.
## This value is automatically generated if not provided. It's recommended to not configure this. ## This value is automatically generated if not provided. It's recommended to not configure this.
# key_id: 'example' # key_id: 'example'
@@ -1352,8 +1346,8 @@ identity_providers:
authorization_policies: authorization_policies:
outline_policy: outline_policy:
rules: rules:
- policy: 'one_factor' - policy: "one_factor"
subject: 'group:outline' subject: "group:outline"
## The lifespans configure the expiration for these token types in the duration common syntax. In addition to this ## The lifespans configure the expiration for these token types in the duration common syntax. In addition to this
## syntax the lifespans can be customized per-client. ## syntax the lifespans can be customized per-client.
@@ -1390,34 +1384,32 @@ identity_providers:
## It's recommended you read the documentation before configuration of a registered client. ## It's recommended you read the documentation before configuration of a registered client.
## See: https://www.authelia.com/c/oidc/registered-clients ## See: https://www.authelia.com/c/oidc/registered-clients
clients: clients:
- - client_name: "Miniflux"
client_name: 'Miniflux' client_id: "{{ oidc__miniflux__client_id }}"
client_id: '{{ oidc__miniflux__client_id }}' client_secret: "{{ oidc__miniflux__client_secret }}"
client_secret: '{{ oidc__miniflux__client_secret }}'
redirect_uris: redirect_uris:
- 'https://miniflux.vakhrushev.me/oauth2/oidc/callback' - "https://miniflux.vakhrushev.me/oauth2/oidc/callback"
scopes: scopes:
- 'openid' - "openid"
- 'profile' - "profile"
- 'email' - "email"
response_types: response_types:
- 'code' - "code"
grant_types: grant_types:
- 'authorization_code' - "authorization_code"
access_token_signed_response_alg: 'none' access_token_signed_response_alg: "none"
userinfo_signed_response_alg: 'none' userinfo_signed_response_alg: "none"
token_endpoint_auth_method: 'client_secret_basic' token_endpoint_auth_method: "client_secret_basic"
- - client_name: "Wakapi"
client_name: 'Wakapi' client_id: "{{ oidc__wakapi__client_id }}"
client_id: '{{ oidc__wakapi__client_id }}' client_secret: "{{ oidc__wakapi__client_secret }}"
client_secret: '{{ oidc__wakapi__client_secret }}'
redirect_uris: redirect_uris:
- 'https://wakapi.vakhrushev.me/oidc/authelia/callback' - "https://wakapi.vakhrushev.me/oidc/authelia/callback"
scopes: scopes:
- 'openid' - "openid"
- 'profile' - "profile"
- 'email' - "email"
# response_types: # response_types:
# - 'code' # - 'code'
# grant_types: # grant_types:
@@ -1425,18 +1417,16 @@ identity_providers:
# access_token_signed_response_alg: 'none' # access_token_signed_response_alg: 'none'
# userinfo_signed_response_alg: 'none' # userinfo_signed_response_alg: 'none'
# token_endpoint_auth_method: 'client_secret_basic' # token_endpoint_auth_method: 'client_secret_basic'
- ## The description to show to users when they end up on the consent screen. Defaults to the ID above.
- client_name: "Outline"
## The description to show to users when they end up on the consent screen. Defaults to the ID above.
client_name: 'Outline'
## The Client ID is the OAuth 2.0 and OpenID Connect 1.0 Client ID which is used to link an application to a ## The Client ID is the OAuth 2.0 and OpenID Connect 1.0 Client ID which is used to link an application to a
## configuration. ## configuration.
client_id: '{{ oidc__outline__client_id }}' client_id: "{{ oidc__outline__client_id }}"
## The client secret is a shared secret between Authelia and the consumer of this client. ## The client secret is a shared secret between Authelia and the consumer of this client.
# yamllint disable-line rule:line-length # yamllint disable-line rule:line-length
client_secret: '{{ oidc__outline__client_secret }}' client_secret: "{{ oidc__outline__client_secret }}"
## Sector Identifiers are occasionally used to generate pairwise subject identifiers. In most cases this is not ## Sector Identifiers are occasionally used to generate pairwise subject identifiers. In most cases this is not
## necessary. It is critical to read the documentation for more information. ## necessary. It is critical to read the documentation for more information.
@@ -1447,7 +1437,7 @@ identity_providers:
## Redirect URI's specifies a list of valid case-sensitive callbacks for this client. ## Redirect URI's specifies a list of valid case-sensitive callbacks for this client.
redirect_uris: redirect_uris:
- 'https://outline.vakhrushev.me/auth/oidc.callback' - "https://outline.vakhrushev.me/auth/oidc.callback"
## Request URI's specifies a list of valid case-sensitive TLS-secured URIs for this client for use as ## Request URI's specifies a list of valid case-sensitive TLS-secured URIs for this client for use as
## URIs to fetch Request Objects. ## URIs to fetch Request Objects.
@@ -1459,9 +1449,9 @@ identity_providers:
## Scopes this client is allowed to request. ## Scopes this client is allowed to request.
scopes: scopes:
- 'openid' - "openid"
- 'profile' - "profile"
- 'email' - "email"
## Grant Types configures which grants this client can obtain. ## Grant Types configures which grants this client can obtain.
## It's not recommended to define this unless you know what you're doing. ## It's not recommended to define this unless you know what you're doing.
@@ -1480,7 +1470,7 @@ identity_providers:
## The policy to require for this client; one_factor or two_factor. Can also be the key names for the ## The policy to require for this client; one_factor or two_factor. Can also be the key names for the
## authorization policies section. ## authorization policies section.
authorization_policy: 'outline_policy' authorization_policy: "outline_policy"
## The custom lifespan name to use for this client. This must be configured independent of the client before ## The custom lifespan name to use for this client. This must be configured independent of the client before
## utilization. Custom lifespans are reusable similar to authorization policies. ## utilization. Custom lifespans are reusable similar to authorization policies.
@@ -1581,7 +1571,7 @@ identity_providers:
## The signing algorithm used for signing the User Info Request responses. ## The signing algorithm used for signing the User Info Request responses.
## Please read the documentation before adjusting this option. ## Please read the documentation before adjusting this option.
## See: https://www.authelia.com/c/oidc/registered-clients#userinfo_signed_response_alg ## See: https://www.authelia.com/c/oidc/registered-clients#userinfo_signed_response_alg
userinfo_signed_response_alg: 'none' userinfo_signed_response_alg: "none"
## The signing key id used for signing the User Info Request responses. ## The signing key id used for signing the User Info Request responses.
## Please read the documentation before adjusting this option. ## Please read the documentation before adjusting this option.
@@ -1645,7 +1635,7 @@ identity_providers:
## The permitted client authentication method for the Token Endpoint for this client. ## The permitted client authentication method for the Token Endpoint for this client.
## For confidential client types this value defaults to 'client_secret_basic' and for the public client types it ## For confidential client types this value defaults to 'client_secret_basic' and for the public client types it
## defaults to 'none' per the specifications. ## defaults to 'none' per the specifications.
token_endpoint_auth_method: 'client_secret_post' token_endpoint_auth_method: "client_secret_post"
## The permitted client authentication signing algorithm for the Token Endpoint for this client when using ## The permitted client authentication signing algorithm for the Token Endpoint for this client when using
## the 'client_secret_jwt' or 'private_key_jwt' token_endpoint_auth_method. ## the 'client_secret_jwt' or 'private_key_jwt' token_endpoint_auth_method.
+1 -1
View File
@@ -9,7 +9,7 @@ from invoke.context import Context
from invoke.exceptions import Exit from invoke.exceptions import Exit
from invoke.tasks import task from invoke.tasks import task
HOSTS_FILE = "production.yml" HOSTS_FILE = "timeweb.yml"
VARS_FILE = "vars/vars.yml" VARS_FILE = "vars/vars.yml"
AUTHELIA_DOCKER = "docker run --rm -v $PWD:/data authelia/authelia:4.39.4 authelia" AUTHELIA_DOCKER = "docker run --rm -v $PWD:/data authelia/authelia:4.39.4 authelia"