Komodo - инструмент для управления, развертывания и обновления Docker контейнеров и стеков

- Опубликовано
- //13 мин. чтения
Komodo - это само размещаемое веб-приложение, обеспечивающее развертывание, управление docker и docker compose, автоматического обновления docker образов, а так же мониторинг состояния с возможностью отправки уведомлений.

Репозиторий: https://github.com/moghtech/komodo
Официальный сайт: komo.do
Komodo является мощным инструментом, который может заменить вам такие сервисы как Dockge для управления стеками, Watchtower для обновления docker-образров и даже Portainer .
NOTE
Watchtower больше официально не поддерживается, а его репозиторий отправлен в публичный архив. Так же после обновления API Docker до версии 1.52 Watchtower перестал работать и не имеет обратной совместимости с более ранними версиями. В настоящий момент он поддерживает версию API Docker 1.25, и по обратной совместимости 1.44.
Архитектура и компоненты
Komodo состоит из одного ядра (Komodo Core) и любого количества подключаемых серверов, на которых работает периферийное приложение (Komodo Periphery).
Komodo Core - это сервер, на котором размещается Core API и пользовательский веб-интерфейс. Все взаимодействия пользователей с подключенными серверами происходят через ядро.
Komodo Periphery - это небольшой сервер, работающий на всех подключенных серверах. Он предоставляет API, вызываемый ядром Komodo для выполнения действий на сервере, получения информации об использовании системы и состояния/журналов контейнеров. Доступ к нему предназначен только для ядра Komodo, и существует белый список адресов, ограничивающий IP-адреса, которым разрешен вызов этого API.
Развертывание Komodo
На основном сервере мы будем разворачивать Komodo Core и Periphery, на подключаемых серверах будем развертывать только агент Komodo Periphery.
Разворачиваем Komodo на основном сервере
Cоздаем файл compose.yml по примеру из репозитория:
mkdir /home/user/docker/komodo && cd /home/user/docker/komodo && nano compose.yml
services:
postgres:
image: ghcr.io/ferretdb/postgres-documentdb
labels:
komodo.skip: # Prevent Komodo from stopping with StopAllContainers
restart: unless-stopped
volumes:
- postgres-data:/var/lib/postgresql/data
environment:
POSTGRES_USER: ${KOMODO_DB_USERNAME}
POSTGRES_PASSWORD: ${KOMODO_DB_PASSWORD}
POSTGRES_DB: postgres
ferretdb:
image: ghcr.io/ferretdb/ferretdb
labels:
komodo.skip: # Prevent Komodo from stopping with StopAllContainers
restart: unless-stopped
depends_on:
- postgres
volumes:
- ferretdb-state:/state
environment:
FERRETDB_POSTGRESQL_URL: postgres://${KOMODO_DB_USERNAME}:${KOMODO_DB_PASSWORD}@postgres:5432/postgres
core:
image: ghcr.io/moghtech/komodo-core:${COMPOSE_KOMODO_IMAGE_TAG:-latest}
container_name: komodo-core
labels:
komodo.skip: # Prevent Komodo from stopping with StopAllContainers
restart: unless-stopped
depends_on:
- ferretdb
ports:
- 9120:9120
env_file: .env
environment:
KOMODO_DATABASE_ADDRESS: ferretdb:27017
KOMODO_DATABASE_USERNAME: ${KOMODO_DB_USERNAME}
KOMODO_DATABASE_PASSWORD: ${KOMODO_DB_PASSWORD}
volumes:
- ${COMPOSE_KOMODO_BACKUPS_PATH}:/backups
periphery:
image: ghcr.io/moghtech/komodo-periphery:${COMPOSE_KOMODO_IMAGE_TAG:-latest}
labels:
komodo.skip: # Prevent Komodo from stopping with StopAllContainers
restart: unless-stopped
user: "1000:990"
env_file: .env
volumes:
## Mount external docker socket
- /var/run/docker.sock:/var/run/docker.sock
## Allow Periphery to see processes outside of container
- /proc:/proc
## Specify the Periphery agent root directory.
## Must be the same inside and outside the container,
## or docker will get confused. See https://github.com/moghtech/komodo/discussions/180.
## Default: /etc/komodo.
- /home/user/docker:/home/user/docker
- /home/user/docker/komodo/ssl:/etc/komodo/ssl
volumes:
# Postgres
postgres-data:
# FerretDB
ferretdb-state:
/home/user/docker:/home/user/docker- монтируем директорию в которой находятся ваши стеки. В моем случае это/home/user/docker, ваш путь может отличаться./home/user/docker/komodo/ssl:/etc/komodo/ssl- монтируем директорию в которой будут находится SSL сертификаты.
Создаем .env файл переменных окружения, пример которого так же можно взять из репозитория:
mkdir /home/user/docker/komodo && cd /home/user/docker/komodo && nano .env
## Stick to a specific version, or use `latest`
COMPOSE_KOMODO_IMAGE_TAG=latest
## Store dated database backups on the host - https://komo.do/docs/setup/backup
COMPOSE_KOMODO_BACKUPS_PATH=/etc/komodo/backups
## DB credentials
KOMODO_DB_USERNAME=admin
KOMODO_DB_PASSWORD=admin
## Configure a secure passkey to authenticate between Core / Periphery.
KOMODO_PASSKEY=
## Set your time zone for schedules
## https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
TZ=Europe/Moscow
## Used for Oauth / Webhook url suggestion / Caddy reverse proxy.
KOMODO_HOST=https://komodo.domain.ru
## Displayed in the browser tab.
KOMODO_TITLE=Komodo
## Create a server matching this address as the "first server".
## Use `https://host.docker.internal:8120` when using systemd-managed Periphery.
KOMODO_FIRST_SERVER=https://periphery:8120
## Give the first server a custom name.
KOMODO_FIRST_SERVER_NAME=Main
## Make all buttons just double-click, rather than the full confirmation dialog.
KOMODO_DISABLE_CONFIRM_DIALOG=false
## Rate Komodo polls your servers for
## status / container status / system stats / alerting.
## Options: 1-sec, 5-sec, 15-sec, 1-min, 5-min, 15-min
## Default: 15-sec
KOMODO_MONITORING_INTERVAL="15-sec"
## Interval at which to poll Resources for any updates / automated actions.
## Options: 15-min, 1-hr, 2-hr, 6-hr, 12-hr, 1-day
## Default: 1-hr
KOMODO_RESOURCE_POLL_INTERVAL="1-hr"
## Used to auth incoming webhooks. Alt: KOMODO_WEBHOOK_SECRET_FILE
KOMODO_WEBHOOK_SECRET=a_random_secret
## Used to generate jwt. Alt: KOMODO_JWT_SECRET_FILE
KOMODO_JWT_SECRET=a_random_jwt_secret
## Time to live for jwt tokens.
## Options: 1-hr, 12-hr, 1-day, 3-day, 1-wk, 2-wk
KOMODO_JWT_TTL="1-day"
## Enable login with username + password.
KOMODO_LOCAL_AUTH=true
## Set the initial admin username created upon first launch.
## Comment out to disable initial user creation,
## and create first user using signup button.
#KOMODO_INIT_ADMIN_USERNAME=admin
## Set the initial admin password
KOMODO_INIT_ADMIN_PASSWORD=changeme
## Disable new user signups.
KOMODO_DISABLE_USER_REGISTRATION=false
## All new logins are auto enabled
KOMODO_ENABLE_NEW_USERS=false
## Disable non-admins from creating new resources.
KOMODO_DISABLE_NON_ADMIN_CREATE=false
## Allows all users to have Read level access to all resources.
KOMODO_TRANSPARENT_MODE=false
## Prettier logging with empty lines between logs
KOMODO_LOGGING_PRETTY=false
## More human readable logging of startup config (multi-line)
KOMODO_PRETTY_STARTUP_CONFIG=false
## OIDC Login
KOMODO_OIDC_ENABLED=false
## Must reachable from Komodo Core container
KOMODO_OIDC_PROVIDER=https://authentik.domain.ru/application/o/komodo/
## Change the host to one reachable be reachable by users (optional if it is the same as above).
## DO NOT include the `path` part of the URL.
# KOMODO_OIDC_REDIRECT_HOST=https://oidc.provider.external
## Your OIDC client id
KOMODO_OIDC_CLIENT_ID= # Alt: KOMODO_OIDC_CLIENT_ID_FILE
## Your OIDC client secret.
## If your provider supports PKCE flow, this can be ommitted.
KOMODO_OIDC_CLIENT_SECRET= # Alt: KOMODO_OIDC_CLIENT_SECRET_FILE
## Make usernames the full email.
## Note. This does not work for all OIDC providers.
# KOMODO_OIDC_USE_FULL_EMAIL=true
## Add additional trusted audiences for token claims verification.
## Supports comma separated list, and passing with _FILE (for compose secrets).
# KOMODO_OIDC_ADDITIONAL_AUDIENCES=abc,123 # Alt: KOMODO_OIDC_ADDITIONAL_AUDIENCES_FILE
## Github Oauth
KOMODO_GITHUB_OAUTH_ENABLED=false
# KOMODO_GITHUB_OAUTH_ID= # Alt: KOMODO_GITHUB_OAUTH_ID_FILE
# KOMODO_GITHUB_OAUTH_SECRET= # Alt: KOMODO_GITHUB_OAUTH_SECRET_FILE
## Google Oauth
KOMODO_GOOGLE_OAUTH_ENABLED=false
# KOMODO_GOOGLE_OAUTH_ID= # Alt: KOMODO_GOOGLE_OAUTH_ID_FILE
# KOMODO_GOOGLE_OAUTH_SECRET= # Alt: KOMODO_GOOGLE_OAUTH_SECRET_FILE
## Aws - Used to launch Builder instances.
KOMODO_AWS_ACCESS_KEY_ID= # Alt: KOMODO_AWS_ACCESS_KEY_ID_FILE
KOMODO_AWS_SECRET_ACCESS_KEY= # Alt: KOMODO_AWS_SECRET_ACCESS_KEY_FILE
#=------------------------------=#
#= Komodo Periphery Environment =#
#=------------------------------=#
## Specify the root directory used by Periphery agent.
PERIPHERY_ROOT_DIRECTORY=/etc/komodo
PERIPHERY_STACK_DIR=/home/user/docker
PERIPHERY_SSL_CERT_FILE=/etc/komodo/ssl/cert.pem
PERIPHERY_SSL_KEY_FILE=/etc/komodo/ssl/key.pem
## Periphery passkeys must include KOMODO_PASSKEY to authenticate.
PERIPHERY_PASSKEYS=${KOMODO_PASSKEY}
## Specify whether to disable the terminals feature
## and disallow remote shell access (inside the Periphery container).
PERIPHERY_DISABLE_TERMINALS=false
## Enable SSL using self signed certificates.
## Connect to Periphery at https://address:8120.
PERIPHERY_SSL_ENABLED=true
## If the disk size is overreporting, can use one of these to
## whitelist / blacklist the disks to filter them, whichever is easier.
## Accepts comma separated list of paths.
## Usually whitelisting just /etc/hostname gives correct size.
PERIPHERY_INCLUDE_DISK_MOUNTS=/etc/hostname
# PERIPHERY_EXCLUDE_DISK_MOUNTS=/snap,/etc/repos
## Prettier logging with empty lines between logs
PERIPHERY_LOGGING_PRETTY=false
## More human readable logging of startup config (multi-line)
PERIPHERY_PRETTY_STARTUP_CONFIG=false
Переменные для Komodo Core:
KOMODO_PASSKEY- настройте надежный пароль для аутентификации между Core / PeripheryKOMODO_HOST- укажите URL адрес, который будет использоваться для OAuth, веб-хуков и обратного прокси-сервераKOMODO_FIRST_SERVER_NAME- укажите имя основного сервераKOMODO_INIT_ADMIN_PASSWORD- укажите пароль администратора при первом запуске
Переменные для Komodo Periphery:
PERIPHERY_STACK_DIR- укажите директорию с вашими стеками
Генерируем сертификат:
sudo mkdir -p /home/user/docker/komodo/ssl
sudo openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout /home/user/docker/komodo/ssl/key.pem \
-out /home/user/docker/komodo/ssl/cert.pem \
-subj "/CN=periphery"
sudo chown -R 1000:990 /home/user/docker/komodo/ssl
Запускаем стек:
docker compose up -d
После запуска, Komodo будет доступен на порту 9120. Перейдите в браузере по адресу http://YOUR-IP:9120 и войдите с логином admin и паролем который вы задали ранее.
Разворачиваем Komodo Periphery (агент)
Создаем файл compose.yml
mkdir /home/user/docker/komodo-periphery && cd /home/user/docker/komodo-periphery && nano compose.yml
services:
periphery:
image: ghcr.io/moghtech/komodo-periphery:${COMPOSE_KOMODO_IMAGE_TAG:-latest}
container_name: komodo-agent-${SERVER_NAME}
# user добавляем для создания файлов под конкретным пользователем
user: "${UID}:${DOCKER_GID}"
env_file: .env
labels:
komodo.skip: # Prevent Komodo from stopping with StopAllContainers
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /proc:/proc
# Точка монтирования к директории с docker compose
- /home/user/docker:/home/user/docker
# Директория хранения самовыпущенных сертификатов ssl
- /home/user/docker/komodo-periphery/ssl:/etc/komodo/ssl
ports:
- 8120:8120
WARNING
Путь точки монтирования к директории с docker compose, должен полностью соответвствать в контейнере и на хосте
WARNING
Директорию хранения самовыпущенных сертификатов ssl, необходимо создавать под пользователем из UID до первого запуска контейнера, иначе возникнет ошибка
Создаем .env файл переменных окружения:
mkdir /home/user/docker/komodo-periphery && cd /home/user/docker/komodo-periphery && nano .env
## Версия образа Komodo Periphery
COMPOSE_KOMODO_IMAGE_TAG=latest
## Имя сервера
SERVER_NAME=periphery
UID=1000
DOCKER_GID=990
## Директория, которая будет использоваться для управления репозиториями
#PERIPHERY_REPO_DIR=
## Директория, которая будет использоваться для управления стеками
PERIPHERY_STACK_DIR=/home/user/docker
## Директория, которая будет использоваться для управления билдами
#PERIPHERY_BUILD_DIR=
## Путь до SSL ключа
PERIPHERY_SSL_KEY_FILE=/etc/komodo/ssl/key.pem
## Путь до SSL сертификата
PERIPHERY_SSL_CERT_FILE=/etc/komodo/ssl/cert.pem
## Корневой каталог PERIPHERY
PERIPHERY_ROOT_DIRECTORY=/etc/komodo
## Ключ подключения из переменной KOMODO_PASSKEY komodo server
PERIPHERY_PASSKEYS=
## Включение HTTPS
PERIPHERY_SSL_ENABLED=true
## Разрешить терминалый доступ к shell
PERIPHERY_DISABLE_TERMINALS=false
## Учет точек монтирования при подсчёте дисков
PERIPHERY_INCLUDE_DISK_MOUNTS=/etc/hostname
SERVER_NAME- укажите имя сервера в среде KomodoUID- id пользователя от чьего имени будут создаваться файлы, получаем командойidDOCKER_GID- id группы docker для запуска под ограниченными правами, получаем командойgetent group dockerPERIPHERY_STACK_DIR- основная директория хранения docker compose файловPERIPHERY_PASSKEYS- ключ авторизации между сервером и агентом, смотри параметрKOMODO_PASSKEY
Генерируем сертификат:
sudo mkdir -p /home/user/docker/komodo-periphery/ssl
sudo openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout /home/user/docker/komodo-periphery/ssl/key.pem \
-out /home/user/docker/komodo-periphery/ssl/cert.pem \
-subj "/CN=periphery"
sudo chown -R 1000:990 /home/user/docker/komodo-periphery/ssl
Запускаем Komodo Periphery
docker compose up -d
Добавление серверов
После развертывания сервиса Komodo Periphery можно переходить к добавлению его в ядро. Для этого переходим в раздел Servers

В этом разделе можно увидеть нагрузку CPU, потребление RAM, а так же свободное место на диске.
WARNING
Если вы разворачиваете Komodo c помощью Docker в LXC контейнере, то мониторинг потребления RAM и нагрузки CPU работает некорректно
Нажимаем кнопку New Server, указываем имя сервера такое же как в переменной SERVER_NAME

Укажите адрес с протоколом https и включить сервер

На вкладке Docker можно управлять контейнерами на сервере.

Добавление и управление docker compose
Komodo поддерживается три вариант работы с docker compose:
UI Defined- развертывание стеков из UI и хранение в базе KomodoFiles On Server- хранение файлов на сервере в файловой системеGit Repo- хранение в репозитории
WARNING
В пределах одного экземпляра Komodo Periphery необходимо соблюдаться уникальность имен для стеков. При запуске стека будет использовано именно имя указанное как имя стека в komodo, но если стек будет перезапущен через ssh, VS Code или либо любой другой способ для имени стека будет использоваться имя папки размещения.

Существует несколько вариантоа решения этой проблемы:
- Изменить имя директории на сервере в соответствии с именем стека в Komodo
- Задать имя для стека через параметр
nameв docker compose, указав туда имя стека в Komodo - Использовать механизм Komodo -
project name
Рекомендуется использовать вариант с project name как наиболее удобный, задав имя проекта как имя папки размещения стека.
В данном примере используется вариант с хранением файлов на сервере, этот способ позволяет легко управлять стеками как через ssh подключение так и из Komodo с сохранением всего функционала.
NOTE
Важно в названии стека, указать точное название конечной директории в которой расположен стек

Далее выбираем сервер на котором развернут стек и режим работы - File On Server

Затем в поле File Paths указываем имя docker compose файла стека

Обязательными для заполнения являются:
Run Directory- путь к папке где размещается docker compose файл. Если как в данном примере смонтирована конечная директория со стеками/home/user/docker, то в данном поле можно ничего не указывать.
`-- docker
|-- nextcloud
| `-- docker-compose.yml
File Paths- имя файла docker compose, по умолчаниюcompose.yaml. Можно указать несколько файлов в том числеoverrideдля дополнения или переопределения основного файла docker compose.
WARNING
Имя файла должно полностью совпадать с реальным именем файла находящемся на сервере.
Additional Env Files- имя файла с переменными окружения, если необходимо использовать то заполнять именем.env
После добавления стека, на вкладке Info можно просматривать и изменять docker compose файлы и инициировать новые. Файлы будут созданы под именем пользователя который указан в параметрах.

Настройка тегов
TIP
Для удобного управления серверами и стеками, можно использовать теги Settings > Tags
В тегах к примеру можно указать адрес сервера. Теги можно использовать как для серверов, так и для стеков. Это может быть особенно полезно если у вас на разных серверах имеются одинаковые стеки, например nodeexporter.

Настройка обновления docker-образов
Для автоматического обновления образов переходим в раздел Procedures и настраиваем процедуру обновления по расписанию Global Auto Update

Переходим в разделе Schedule и настроиваем расписание

Настраиваем этапы задачи:

WARNING
Для каждого отдельного стека необходимо вручную указывать необходимость авто-обновления.
Переходим в настройки стека, в раздел Auto Update и включаем нужные нам переключатели.
Существуют два режима:
Poll for Updates- проверка наличия обновления, но без обновления стекаAuto update- обновление стека

Настройка очистки неиспользуемых docker-образов
TIP
Так-как автоматическое обновление по умолчанию не очищает не используемые образы. Для очистки после обновления надо включить функцию авто очистки или настроить отдельную процедуру.
Переходим в Procedures и создаем новую процедуру, добавляем отдельный Stage для каждого сервера.

Либо можно включить настройку Auto Prune Images для автоматической очистки не используемых образов на каждом сервере.

Отправка уведомлений в Telegram
По умолчание Komodo не умеет отправлять уведомления в Телеграм, но мы можем заставить его это делать при помощи небольшого сервиса - Komodo Telegram Alerter .
Создаем файл compose.yml
Чтобы переопределить шаблоны сообщений, монтируем templates.json в докер образ.
services:
komodo-telegram-alerter:
container_name: komodo-telegram-alerter
image: deniom3/komodo-telegram-alerter:latest
restart: unless-stopped
ports:
- '3000:3000'
volumes:
- ./custom-templates:/app/templates:ro
Создаем директорию custom-templates и файлом templates.json со следующим содержимым:
{
"StackAutoUpdated": {
"OK": "✅ На сервере {server_name} обновлен образ {images} в стеке {name}",
"INFO": "ℹ️ На сервере {server_name} выполняется обновление образа {images} в стеке {name}",
"ERROR": "❌ Ошибка обновления образа {images} на сервере {server_name}"
},
"ServerCpu": {
"WARNING": "⚠️ Высокая загрузка CPU на сервере {name} ({percentage}%)",
"OK": "✅ Нормальная загрузка CPU на сервере {name} ({percentage}%)",
"CRITICAL": "❌ Критическая загрузка CPU на сервере {name} ({percentage}%)"
},
"StackStateChange": {
"WARNING": "⚠️ Стек {name} на сервере {server_name} перешёл из состояния {from} в {to}",
"OK": "✅ Стек {name} на сервере {server_name} работает нормально (состояние {to})"
},
"ServerUnreachable": {
"CRITICAL": "🔴 Сервер {name} недоступен: соединение отклонено ({error})",
"OK": "🟢 Сервер {name} снова доступен"
},
"ServerDisk": {
"WARNING": "⚠️ Высокое заполнение диска на сервере {name} занято {used_gb}GB из {total_gb}GB",
"OK": "🟢 Нормальный уровень заполнения диска на сервере {name} занято {used_gb}GB из {total_gb}GB",
"CRITICAL": "🔴 Критически мало места на сервере {name} занято {used_gb}GB из {total_gb}GB"
},
"ServerMem": {
"WARNING": "⚠️ На сервере {name} большщая нагрузка RAM использовано {used_gb}GB из {total_gb}GB",
"CRITICAL": "🔴 Критическая нагрузка RAM на сервере {name} использовано {used_gb}GB из {total_gb}GB",
"OK": "🟢 Нормальная нагрузка RAM на сервере {name}"
},
"Custom": {
"OK": "✅ {message}",
"WARNING": "⚠️ {message}",
"CRITICAL": "🔴 {message}"
},
"Test": {
"OK": "✅ {message}",
"WARNING": "⚠️ {message}",
"CRITICAL": "🔴 {message}"
}
}
Запускаем Komodo Telegram Alerter:
docker compose up -d
Получение данных Telegram
- Для получения токена бота, напишите @BotFather команду
/newbot - Для получения ID чата, добавьте бота в нужный чат/канал, отправьте тестовое сообщение. Затем перейдите по ссылке
https://api.telegram.org/bot<ВАШ_ТОКЕН>/getUpdatesи найдитеchat.idв ответе. - Для отправки уведомлений в треды супергрупп, отправьте сообщение в тред. Из ответа getUpdates получите
message_thread_idи добавьте в URL:&message_thread_id=<ID_ТРЕДА>
Подключение Telegram алертера к Komodo
- Переходим в
Settings>Variablesи создаем следующие переменные:
TELEGRAM_CHAT_ID- chat.idTELEGRAM_THREADS_ID- message_thread_idTELEGRAM_TOKEN- токен бота

- Переходим в
Settings>Alertersи нажимаем кнопкуNew Alerter. Указываем название алертера. В разделеEndpointвыбираемCustomи вставляем URL:
http://<alerter-ip>:3000/alert?token=[[TELEGRAM_TOKEN]]&chat_id=[[TELEGRAM_CHAT_ID]]&message_thread_id=[[TELEGRAM_THREADS_ID]]

Интеграция с Authentik
Authentik официально поддерживает интеграцию Komodo.
Создайте соответствующее приложение и провайдера в Authentik и укажите следующие переменные в .env файле Komodo.
KOMODO_OIDC_ENABLED=true
KOMODO_OIDC_PROVIDER=https://authentik.company/application/o/<application_slug>/
KOMODO_OIDC_CLIENT_ID=<authentik_client_ID>
KOMODO_OIDC_CLIENT_SECRET=<authentik client secret>
Заключение
Мы развернули и настроили достаточно мощный инструмент для управления, обновления, мониторинга и развертывния docker контейнеров и стеков, а так же настроили алерты в Телеграм.
Содержание
- Архитектура и компоненты
- Развертывание Komodo
- Разворачиваем Komodo на основном сервере
- Разворачиваем Komodo Periphery (агент)
- Добавление серверов
- Добавление и управление docker compose
- Настройка тегов
- Настройка обновления docker-образов
- Настройка очистки неиспользуемых docker-образов
- Отправка уведомлений в Telegram
- Получение данных Telegram
- Подключение Telegram алертера к Komodo
- Интеграция с Authentik
- Заключение