====== Реализация SSO с помощью Authentik ======
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/banner.png?nolink&}}
===== Введение =====
[[https://goauthentik.io/|Authentik]] - это провайдер аутентификации с [[https://github.com/goauthentik/authentik?tab=readme-ov-file|открытым исходным кодом]], который отличается гибкостью и универсальностью, поддерживая широкий набор протоколов.
При развертывании приложений в домашней лаборатории вы можете столкнуться с тем, что некоторые из них вовсе не поддерживают аутентификацию либо поддерживают базовую в которой могут иметься уязвимости. Так же малое количество сервисов из коробки поддерживает 2FA (двухфакторная аутентификация). Помимо этого для каждого сервиса вам приходится придумывать отдельно логин и пароль, что может запутать когда этих сервисов у вас много. Выход из всего этого есть и это - **Authentik**.
Технология единого входа (Single sign-on SSO) — метод аутентификации, который позволяет пользователям безопасно аутентифицироваться сразу в нескольких приложениях и сайтах, используя один набор учетных данных.
===== Развертывание Authentik =====
Развертывать Authentik будем при помощи Docker Compose и использовать в связке с обратным прокси сервером [[https://doc.traefik.io/traefik/user-guides/docker-compose/basic-example/|Traefik]]. Для этого переходим на [[https://docs.goauthentik.io/docs/install-config/install/docker-compose|страницу документации]] Authentik с использованием Docker Compose и внимательно изучаем ее. Нам предлагается сразу загрузить готовый ''docker-compose'' файл при помощи команды:
wget https://goauthentik.io/docker-compose.yml
\\
Так как Authentik не поддерживает тег latest после каждого обновления на сайте публикуется новый docker-compose файл с изменения версий docker образов.\\
\\
\\
Возьмем за основу шаблон с сайта актуальной на момент написания заметки 2025 года.
''docker-compose.yaml''
services:
postgresql:
image: docker.io/library/postgres:16-alpine
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
start_period: 20s
interval: 30s
retries: 5
timeout: 5s
volumes:
- database:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${PG_PASS:?database password required}
POSTGRES_USER: ${PG_USER:-authentik}
POSTGRES_DB: ${PG_DB:-authentik}
env_file:
- .env
redis:
image: docker.io/library/redis:alpine
command: --save 60 1 --loglevel warning
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
start_period: 20s
interval: 30s
retries: 5
timeout: 3s
volumes:
- redis:/data
server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.1}
restart: unless-stopped
command: server
environment:
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?secret key required}
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
volumes:
- ./media:/media
- ./custom-templates:/templates
env_file:
- .env
ports:
- "${COMPOSE_PORT_HTTP:-9000}:9000"
- "${COMPOSE_PORT_HTTPS:-9443}:9443"
depends_on:
postgresql:
condition: service_healthy
redis:
condition: service_healthy
worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.1}
restart: unless-stopped
command: worker
environment:
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?secret key required}
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
# `user: root` and the docker socket volume are optional.
# See more for the docker socket integration here:
# https://goauthentik.io/docs/outposts/integrations/docker
# Removing `user: root` also prevents the worker from fixing the permissions
# on the mounted folders, so when removing this make sure the folders have the correct UID/GID
# (1000:1000 by default)
user: root
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./media:/media
- ./certs:/certs
- ./custom-templates:/templates
env_file:
- .env
depends_on:
postgresql:
condition: service_healthy
redis:
condition: service_healthy
volumes:
database:
driver: local
redis:
driver: local
Далее согласно документации нужно сгенерировать пароль и секретный ключ в файл с переменными ''.env''
echo "PG_PASS=$(openssl rand -base64 36 | tr -d '\n')">> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')">> .env
Так же можно настроить порты, т.к. по умолчанию authentik прослушивает внутренний порт 9000 для HTTP и 9443 для HTTPS. Поэтому чтобы пробросить порты 80 и 443, вы можете задать переменные ''COMPOSE_PORT''. Но нам это не нужно так как на этих портах уже работает Traefik.
''.env''
PG_PASS= AUTHENTIK_SECRET_KEY=
#COMPOSE_PORT_HTTPS=80
#COMPOSE_PORT_HTTP=433
# SMTP Host Emails are sent to AUTHENTIK_EMAIL__HOST=localhost
AUTHENTIK_EMAIL__PORT=25
# Optionally authenticate (don't add quotation marks to your password)
AUTHENTIK_EMAIL__USERNAME=
AUTHENTIK_EMAIL__PASSWORD=
# Use StartTLS AUTHENTIK_EMAIL__USE_TLS=false
# Use SSL AUTHENTIK_EMAIL__USE_SSL=false
AUTHENTIK_EMAIL__TIMEOUT=10
# Email address authentik will send from, should have a correct @domain
AUTHENTIK_EMAIL__FROM=authentik@localhost
Перед запуском контейнера обязательно проверьте локальное время на сервере, чтобы избежать проблем с аутентификацией.
timedatectl
Local time: Sat 2024-10-19 23:59:41 MSK
Universal time: Sat 2024-10-19 20:59:41 UTC
RTC time: Sat 2024-10-19 20:59:41 ''
Time zone: Europe/Moscow (MSK, +0300)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
Если время не совпадает то найдите и установите ваш часовой пояс:
timedatectl list-timezones
sudo timedatectl set-timezone Europe/Moscow
Запускаем контейнер:
docker compose pull
docker compose up -d
После запуска переходим по адресу [[http://:9000/if/flow/initial-setup/]] для первоначальной настройки. Там вам будет предложено установить пароль для пользователя по умолчанию ''akadmin''.
После того как создали пароль и авторизовались создайте субдомен для Authentik, например ''authentik.domain.ru''
===== Конфигурирование Traefik =====
Создаем файл динамической конфигурации для Authentik:
''ext_authentik.yml''
http:
routers:
authentik:
rule: "Host(`authentik.domain.ru`)"
entrypoints:
- http
middlewares:
- authentik-https-redirect
service: authentik
authentik-secure:
rule: "Host(`authentik.domain.ru`)"
entrypoints:
- https
middlewares:
tls: true
service: authentik
middlewares:
authentik-https-redirect:
redirectScheme:
scheme: https
services:
authentik:
loadBalancer:
servers:
- url: "http://192.168.78.110:9000"
И сразу создадим промежуточный слой, который будет использоваться для включения авторизации в наших сервисах.
''authentik.yml''
http:
middlewares:
authentik:
forwardAuth:
address: "http://192.168.78.110:9000/outpost.goauthentik.io/auth/traefik"
trustForwardHeader: true
authResponseHeaders:
- X-authentik-username
- X-authentik-groups
- X-authentik-email
- X-authentik-name
- X-authentik-uid
- X-authentik-jwt
- X-authentik-meta-jwks
- X-authentik-meta-outpost
- X-authentik-meta-provider
- X-authentik-meta-app
- X-authentik-meta-version
И еще один промежуточный слой для arr-стека, если вы планируете использовать Sonarr, Radarr, Prowlarr и т.д.
''media-authentik.yml''
http:
middlewares:
authentik-media:
forwardAuth:
address: "http://192.168.78.110:9000/outpost.goauthentik.io/auth/traefik"
trustForwardHeader: true
authResponseHeaders:
- X-authentik-username
- X-authentik-groups
- X-authentik-email
- X-authentik-name
- X-authentik-uid
- X-authentik-jwt
- X-authentik-meta-jwks
- X-authentik-meta-outpost
- X-authentik-meta-provider
- X-authentik-meta-app
- X-authentik-meta-version
- Authorization
Теперь переходим по вашему адресу ''authentik.domain.ru'' и логинимся.
===== Настройка Authentik =====
==== Создание пользователя ====
Переходим в интерфейс администратора.
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/1.jpg?nolink&}}
Затем в левом меню переходим в ''Каталог > Пользователи'' и нажимаем **Создать**.
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/2.jpg?nolink&}}
Указываем username, отображаемое имя и почту.
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/3.jpg?nolink&}}
Теперь нам нужно установить пароль, для этого переходим в созданного пользователя и нажимаем **Установить пароль**
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/4.jpg?nolink&}}
Затем переходим в группы, выбираем ''authentik Admins'', переходим на вкладку пользователи и нажимаем **Добавить существующего пользователя**, выбираем нашего пользователя **User** из списка и нажимаем добавить.
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/5.jpg?nolink&}}
Наш пользователь добавлен в группу суперпользователей. Теперь разлогинимся из аккаунта ''akadmin'' и авторизуемся под новым пользователем. После чего снова перейдем в раздел Пользователи, проваливаемся в пользователя ''akadmin'' и отключаем его нажав кнопку **Деактивировать**
==== Подключаем двухфакторную аутентификацию (2FA) ====
Нажимаем шестеренку в правом верхнем углу экрана или на иконку пользователя в нижнем левом если вы находитесь в панели администратора. Выбираем MFA-устройства и зарегистрировать **TOTP Device**
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/6.jpg?nolink&}}
После этого вас перекинет на страницу привязки устройства.
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/7.jpg?nolink&}}
После этого перелогиниваемся и проверяем что после ввода пароля у вас запросят еще и OTP-код.
==== Создание провайдера и подключение приложения ====
Переходим в раздел провайдеры и создаем провайдера:
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/8.jpg?nolink&}}
Выбираем тип провайдера Proxy Provider:
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/9.jpg?nolink&}}
Поток провайдера выбираем ''explicit'' и Прямая аутентификация (уровень домена):
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/10.jpg?nolink&}}
Прописываем наш субдомен на котором работает Authentik и домен для cookie:
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/11.jpg?nolink&}}
После создания провайдера видим предупреждение что к нему не привязано ни одно приложение
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/12.jpg?nolink&}}
Переходим в раздел приложения и приступаем к созданию, обязательно выбираем ранее созданный провайдер.
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/13.jpg?nolink&}}
После создания приложения, предупреждение должно исчезнуть.
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/14.jpg?nolink&}}
Теперь переходим в раздел внешние компоненты и перемещаем наше приложение из **Доступные приложения** в **Выбранные приложения**:
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/15.jpg?nolink&}}
В конфигурации обязательно проверяем что имя домена для ''authentik_host'' указано верно.
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/16.jpg?nolink&}}
На этом конфигурация окончена.
==== Подключаем Authentik к Traefik и проксируемым через него приложениям ====
Теперь перейдем к файлу динамической конфигурации самого Traefik и подключим аутентификацию, добавив промежуточный слой ''authentik''
''ext_traefik.yml''
http:
routers:
traefik:
rule: "Host(`traefik.domain.ru`)"
entrypoints:
- http
middlewares:
- traefik-https-redirect
- authentik
service: api@internal
traefik-secure:
rule: "Host(`traefik.domain.ru`)"
entrypoints:
- https
middlewares:
- authentik
tls: true
service: api@internal
middlewares:
traefik-https-redirect:
redirectScheme:
scheme: https
Теперь при входе в дашборд Traefik необходимо будет авторизоваться.
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/17.jpg?nolink&}}
После этого можно подключить аутентификацию на любом вашем сервисе, просто добавив промежуточный слой. Но при подключении к другим приложениям, экран входа меняться не будет. Всегда будет написано ''Войдите чтобы перейти на traefik''.
Чтобы этого избежать нужно как и ранее создать еще одного Proxy-провайдера но выбрать **Переадресация аутентификации (одно приложение)** и указать домен на котором развернуто приложение.
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/18.jpg?nolink&}}
==== Подключение OIDC-аутентификации ====
OpenID Connect (OIDC) — протокол аутентификации и получения информации о пользователе из внешней системы. Протокол обратно совместим с OAuth, разница заключается в том, что OpenID Connect используется для аутентификации, а OAuth для авторизации.
На [[https://docs.goauthentik.io/integrations/|странице документации]] есть множество примеров интеграции со многими популярными приложениями, но некоторых в этом списке нет. Например разберем пример включения OIDC аутентификации на примере дашборда [[https://homarr.dev/|Homarr]]. Из документации - [[https://homarr.dev/docs/advanced/sso/|Single Sign On | Homarr documentation]] мы видим что само приложение это поддерживает, но нужно изменить ''docker-compose'' файл добавив туда некоторые переменные.
''docker-compose.yaml''
version: "3"
services:
homarr:
container_name: homarr
image: ghcr.io/ajnart/homarr:fix-oidc-wrong-redirect
restart: unless-stopped
volumes:
# - /var/run/docker.sock:/var/run/docker.sock # Optional, only if you want docker integration
- ./homarr/configs:/app/data/configs
- ./homarr/icons:/app/public/icons
- ./homarr/data:/data
environment:
AUTH_PROVIDER: oidc
AUTH_OIDC_URI: https://authentik.domain.ru/application/o/homarr
AUTH_LOGOUT_REDIRECT_URL: https://authentik.domain.ru/application/o/homarr/end-session/
AUTH_OIDC_CLIENT_SECRET: ${AUTH_OIDC_CLIENT_SECRET}
AUTH_OIDC_CLIENT_ID: ${AUTH_OIDC_CLIENT_ID}
AUTH_OIDC_CLIENT_NAME: Authentik
AUTH_OIDC_ADMIN_GROUP: authentik Admins
AUTH_OIDC_OWNER_GROUP: admin
AUTH_OIDC_TIMEOUT: 3500
AUTH_OIDC_AUTO_LOGIN: false
ports:
- 7575:7575
networks: {}
Создаем файл для хранения переменных ''.env'':
nano .env
Вместо **your_client_secret** и **your_client_id** вставляем соответствующие данные полученные из **Authentik**:
''.env''
AUTH_OIDC_CLIENT_SECRET='your_client_secret'
AUTH_OIDC_CLIENT_ID='your_client_id'
\\
NOTE На момент написания заметки, в образе latest были проблемы с редиректом после включения OIDC, поэтому использовался тег fix-oidc-wrong-redirect.\\
После этого нужно перейти в Authentik и создать новое приложение и провайдера.
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/19.jpg?nolink&}}
В **Перенаправляющие URI/Источники (RegEx)** указываем имя домена Homarr, например [[https://homarr.domain.ru|https://homarr.domain.ru]]
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/20.jpg?nolink&}}
Копируем ID Клиента и Секрет клиента, вставляем в соответствующие переменные ''docker-compose'' файла. Создаем приложение и подключаем к нему ранее созданного провайдера.
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/21.jpg?nolink&}}
Разворачиваем настройки пользовательского интерфейса и указываем имя домена на котором развернут Homarr.
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/22.jpg?nolink&}}
После этого переходим в раздел Провайдеры, нажимаем на наш провайдер и справа вы увидите ссылки для редиректа. Нам понадобится **Эмитент конфигурации OpenID** для переменной ''AUTH_OIDC_URI'' и **URL-адрес выхода из системы** для ''AUTH_LOGOUT_REDIRECT_URL''
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/23.jpg?nolink&}}
После этого запускаем контейнер и видим что теперь мы можем войти с помощью Authentik
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/24.jpg?nolink&}}
Возьмем еще один пример - [[https://www.portainer.io/|Portainer]]. Здесь все немного проще, во первых есть [[https://docs.goauthentik.io/integrations/services/portainer/|документация по интеграции]] а во вторых все переменные можно задать прям в панели управления.
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/25.jpg?nolink&}}
Cохраните настройки выйдите из аккаунта и убедитесь что теперь доступна аутентификация через OAuth.
{{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/26.jpg?nolink&}}