MAATRIX / Блог / Authentik на сервере: частые ошибки и решения

Authentik на сервере: частые ошибки и решения

MAATRIX

Authentik — удобная замена Keycloak для тех, кому не нужна вся тяжесть Java-стека, а нужен рабочий SSO с гибким редактором flow и адекватным UI. Но именно гибкость flow — источник половины проблем: одна неправильно настроенная стадия, и пользователи либо не могут войти вообще, либо застревают в бесконечном редиректе. Разберём типовые ошибки установки Authentik на сервере — от неверных переменных окружения до конфликтов с reverse proxy — и как их чинить, не пересобирая всё с нуля.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Контейнеры стартуют, но UI недоступен

Самая частая ситуация после docker compose up -d: контейнеры в статусе running, а https://auth.example.com не открывается или отдаёт 502.

Первым делом проверьте логи обоих ключевых сервисов — сервера и воркера:

docker compose logs -f server
docker compose logs -f worker

Типичная причина — Authentik ещё выполняет миграции базы данных при первом запуске, это может занять от 30 секунд до пары минут в зависимости от диска. Если в логах воркера видно Applying migration..., просто подождите. Если миграции зависли — почти всегда дело в PostgreSQL, который ещё не готов принимать соединения, а depends_on в docker-compose без condition: service_healthy эту гонку не ловит:

services:
  postgresql:
    image: docker.io/library/postgres:16-alpine
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
      interval: 5s
      timeout: 5s
      retries: 10
  server:
    image: ghcr.io/goauthentik/server:2026.6
    depends_on:
      postgresql:
        condition: service_healthy
      redis:
        condition: service_healthy

Второй частый вариант — reverse proxy проксирует не тот порт. Контейнер server слушает 9000 (HTTP) и 9443 (HTTPS) внутри сети, а не 80/443 наружу. Если у вас Traefik, убедитесь, что лейбл указывает именно на 9000:

labels:
  - "traefik.http.services.authentik.loadbalancer.server.port=9000"

Если прокси настроен верно, а всё равно 502 — проверьте, не съел ли контейнер память при старте: server + worker комфортно чувствуют себя от 2 ГБ RAM, на 1 ГБ воркер может падать по OOM при компиляции flow-шаблонов, и в dmesg или journalctl -k будет Out of memory: Killed process.

Ошибка "Invalid state" или бесконечный редирект на login

Пользователь вводит логин, форма мигает и снова показывает форму входа — либо браузер уходит в цикл редиректов между /if/flow/ и приложением. Причина в 95% случаев — рассинхронизация cookie-домена и AUTHENTIK_COOKIE_DOMAIN.

Если Authentik и защищаемое приложение находятся на разных поддоменах (auth.example.com и app.example.com), сессионная cookie должна быть выставлена на родительский домен, иначе браузер её просто не пришлёт при обращении к приложению:

# .env
AUTHENTIK_COOKIE_DOMAIN=example.com

После смены переменной обязательно перезапустите оба сервиса — server и worker — и попросите пользователей заново залогиниться, старые cookie с прежним доменом останутся невалидными:

docker compose up -d server worker

Вторая причина того же симптома — часы на сервере "уехали". Authentik подписывает и валидирует JWT-токены с ограниченным сроком жизни, и если системное время расходится больше чем на минуту-две (частая история на VPS без корректного NTP), токен считается просроченным ещё до того, как дошёл до получателя:

timedatectl status
# при рассинхроне:
apt install -y chrony && systemctl enable --now chrony

Третий вариант — вы используете HTTP за прокси, который терминирует TLS, но не пробрасывает заголовок X-Forwarded-Proto. Authentik решает, ставить ли Secure-флаг на cookie, по этому заголовку, и без него cookie может не сохраняться в браузере вовсе.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Forward-auth не пускает даже с валидной сессией

Схема forward-auth (или ForwardAuth в Traefik / auth_request в nginx) — самый частый способ прикрутить Authentik перед приложением, у которого нет своего OIDC-клиента. И самый частый баг — 403 на защищённом ресурсе, хотя в самом Authentik сессия активна.

Для nginx конфигурация должна прокидывать оригинальный URI и хост через заголовки, иначе Authentik не сможет сопоставить запрос с нужным provider:

location /outpost.goauthentik.io {
    proxy_pass              http://authentik-proxy:9000;
    proxy_set_header        Host $host;
    proxy_set_header        X-Original-URL $scheme://$http_host$request_uri;
    proxy_set_header        X-Forwarded-Proto $scheme;
    add_header               Set-Cookie $auth_cookie;
    auth_request_set         $auth_cookie $upstream_http_set_cookie;
}

location / {
    auth_request /outpost.goauthentik.io/auth/nginx;
    error_page 401 = @goauthentik_proxy_signin;
    auth_request_set $auth_status $upstream_status;
}

location @goauthentik_proxy_signin {
    internal;
    add_header Set-Cookie $auth_cookie;
    return 302 https://auth.example.com/outpost.goauthentik.io/start?rd=$scheme://$http_host$request_uri;
}

Если после этого всё равно 403 — проверьте в Applications → Outposts, что нужный outpost привязан к провайдеру этого приложения и что у него healthy-статус (зелёная точка). Outpost нужно создать и назначить явно, он не появляется автоматически.

Ещё одна классика — вы поменяли домен приложения в Authentik (External Host у Proxy Provider), но не дождались синхронизации embedded outpost. Конфигурация подтягивается не мгновенно (до минуты), либо форсируйте синхронизацию кнопкой в UI outpost'а.

LDAP или внешний источник пользователей не синхронизируется

Если вы подключили Authentik к LDAP (Active Directory, FreeIPA) как Federation & Social login → LDAP Source, а пользователи не появляются, начните с логов worker'а — синхронизация идёт там, а не в server:

docker compose logs worker | grep -i ldap

Частые причины:

  • Неверный Bind DN. Authentik использует его для чтения дерева каталога, а не логина конкретного пользователя — это должна быть служебная учётная запись с правом чтения (cn=svc-authentik,ou=service,dc=example,dc=com).
  • Base DN указывает не туда. Если он сужен до одной OU, а нужные пользователи лежат в другой — синхронизация пройдёт "успешно", но с нулём импортированных объектов.
  • TLS без валидного сертификата. При ldaps:// с самоподписанным сертификатом нужно загрузить корневой сертификат в Authentik (Server Certificate Validation), а не отключать проверку насовсем.
  • Синхронизация не запущена вручную после первой настройки. По умолчанию она идёт по расписанию, для теста жмите Sync прямо в карточке источника.

Если синхронизация идёт, но пароли не работают — это ожидаемо: LDAP source по умолчанию только импортирует пользователей и группы, а не проксирует аутентификацию. Для проверки пароля через LDAP нужен отдельный LDAP Password stage в flow логина, который делает bind-попытку к тому же каталогу.

Email не отправляется: verification и password reset не доходят

Flow с подтверждением почты или восстановлением пароля молча "проглатывает" письмо — пользователь не получает ссылку, а в UI никакой ошибки не видно, потому что отправка идёт асинхронно через worker.

Проверьте переменные SMTP в .env — там легко перепутать AUTHENTIK_EMAIL__USE_TLS (STARTTLS на 587) и AUTHENTIK_EMAIL__USE_SSL (implicit TLS на 465), включёнными вместе они конфликтуют:

AUTHENTIK_EMAIL__HOST=smtp.example.com
AUTHENTIK_EMAIL__PORT=587
AUTHENTIK_EMAIL__USERNAME=noreply@example.com
AUTHENTIK_EMAIL__PASSWORD=app-specific-password
AUTHENTIK_EMAIL__USE_TLS=true
AUTHENTIK_EMAIL__USE_SSL=false
AUTHENTIK_EMAIL__FROM=noreply@example.com

Реальную ошибку SMTP смотрите в логах worker'а, не server'а:

docker compose logs worker | grep -i -E "smtp|email"

Если ошибка про TLS handshake или authentication — почти всегда дело либо в неверном пароле приложения (у Gmail/Yandex это отдельный пароль приложения, не основной), либо провайдер требует явного разрешения на "менее защищённые" SMTP-клиенты. Если писем нет, а ошибок тоже нет — проверьте, что stage типа Email реально подключён к нужному flow: частая ошибка — stage создан, но не добавлен в цепочку binding'ов.

Отдельно учитывайте надёжность самой отправки: даже верно настроенный SMTP может улетать в спам без корректных SPF/DKIM записей на домене — это уже вопрос DNS, а не Authentik.

Flow зацикливается или падает на конкретной стадии

Кастомный flow — самая гибкая, но и самая ломкая часть Authentik. Если пользователь застревает на конкретном экране (например, MFA setup) и flow не двигается дальше — причина почти всегда в неправильном порядке или условиях привязки stage.

Откройте Flows → нужный flow → Stage Bindings и проверьте:

  • Order — стадии выполняются строго по возрастанию этого числа, дублирующийся order даёт непредсказуемое поведение.
  • Policies — если у binding'а стадии MFA стоит политика "только для группы Admins", а тестируете вы не под админом, стадия молча пропускается.
  • Re-evaluate policies — если включено, политика проверяется на каждой попытке, что иногда приводит к неожиданным пропускам стадии при изменении контекста запроса.

Для отладки есть встроенный инструмент: страница /if/flow/<flow-slug>/?query=debug показывает JSON с контекстом на каждом шаге прямо в интерфейсе — быстрее, чем гадать по докер-логам.

Если flow вообще не запускается — проверьте designation (Authentication, Authorization, Invalidation и т.д.): Authentik ищет flow по его роли, и если вы создали новый flow для логина, но не назначили его Default в Tenants → System settings, система продолжит использовать старый.

Бэкап и обновление без потери настроек

Authentik хранит всю конфигурацию — flow, providers, политики, пользователей — в PostgreSQL, а не в файлах, поэтому бэкапить нужно именно базу. Media (загруженные иконки, брендинг) лежит отдельно в volume.

# бэкап базы
docker compose exec -T postgresql pg_dump -U authentik authentik | gzip > authentik_$(date +%F).sql.gz

# бэкап media-volume
docker run --rm -v authentik_media:/data -v $(pwd):/backup alpine \
  tar czf /backup/authentik_media_$(date +%F).tar.gz -C /data .

Перед обновлением на новую минорную версию читайте release notes в репозитории — Authentik иногда требует ручного шага миграции, и правило "просто поднять новый тег" не всегда безопасно. Общая последовательность:

docker compose pull
docker compose down
# правим тег версии в docker-compose.yml или .env (AUTHENTIK_TAG)
docker compose up -d
docker compose logs -f worker  # следим за миграциями

Если после обновления сервер не стартует — откат на предыдущий тег образа и восстановление бэкапа базы обычно решает проблему быстрее, чем разбор конфликта миграции на лету. Держите 2-3 последних дампа отдельно от сервера — единственная копия на том же диске бесполезна, если диск откажет.

Общая логика конфигурации reverse proxy и forward-auth во многом пересекается с Traefik как reverse proxy для докера — если вы ещё выбираете между Traefik и nginx proxy manager перед Authentik, сравнение вариантов есть в статье Traefik или Nginx Proxy Manager: что выбрать для сервера. А раз Authentik целиком держится на PostgreSQL, стоит заранее прочитать про типовые проблемы этой базы — PostgreSQL на сервере: частые ошибки и решения — многие "странности" Authentik на деле оказываются проблемами именно СУБД под капотом.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Сколько ресурсов реально нужно Authentik для 50-100 пользователей?

Комфортно работает от 2 ГБ RAM и 2 vCPU для связки server + worker + PostgreSQL + Redis на одной машине. На 1 ГБ RAM возможны OOM-килы воркера при компиляции сложных flow, особенно если параллельно запущены другие сервисы.

Можно ли использовать SQLite вместо PostgreSQL?

Нет, начиная с текущих релизов Authentik официально поддерживает только PostgreSQL — это осознанное архитектурное решение проекта, а не временное ограничение.

Почему после смены пароля админа через веб-UI старая сессия остаётся активной на других устройствах?

Смена пароля сама по себе не инвалидирует уже выданные сессии — если нужно принудительно разлогинить пользователя везде, используйте кнопку "Impersonate" → "Log out" или удалите активные сессии пользователя вручную в разделе Directory → Sessions.

Outpost показывает "unhealthy", хотя контейнер работает — что проверить?

Чаще всего это неверный AUTHENTIK_HOST во внешнем outpost-контейнере (должен указывать на публично доступный адрес server, включая протокол) либо истёкший токен outpost'а — перевыпустите токен в UI и обновите переменную окружения контейнера.

Нужен ли отдельный Redis, если он уже используется другим приложением на сервере?

Лучше держать для Authentik отдельный инстанс или хотя бы отдельный DB index в Redis — Authentik использует его и для кэша, и для очереди задач worker'а, и делить его "как есть" с чужим приложением рискованно при флаше кэша.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →