Authelia на сервере: частые ошибки и решения
Authelia — лёгкий forward-auth сервер: он не проксирует трафик сам, а только отвечает "да/нет" на вопрос "пускать ли этого пользователя дальше", который ему задаёт Nginx или Traefik. Именно поэтому большинство проблем с ней — не баги самой Authelia, а нестыковки в связке с реверс-прокси: не тот cookie domain, не те заголовки, не синхронизированное время. Разберём конкретные симптомы и что с ними делать.
Содержание
- Как Authelia работает с Nginx и Traefik
- Бесконечный редирект на страницу логина после успешного входа
- 401/403 при интеграции с Traefik: ошибки в middleware и labels
- Nginx: auth_request отдаёт 500/502 вместо перенаправления на логин
- Сессии слетают: Redis, session secret и перезапуски
- TOTP не проходит проверку, хотя код точно верный
- Access control rules: правило не срабатывает, хотя оно есть в конфиге
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Как Authelia работает с Nginx и Traefik
Прежде чем чинить, держите в голове схему. Клиент стучится в защищённый сервис (app.example.com), реверс-прокси перед ответом спрашивает у Authelia внутренним запросом: "у пользователя есть валидная сессия?". Authelia смотрит на cookie, сверяет её с хранилищем сессий и возвращает либо 200 OK с заголовками (Remote-User, Remote-Groups, Remote-Email), либо 401, из-за которого прокси делает редирект на страницу логина.
Три вещи должны совпадать между собой, иначе всё разваливается: domain в session.domain (родительский для всех защищённых поддоменов), access control rules (какой поддомен под какой политикой) и заголовки/middleware на стороне прокси (как именно он спрашивает Authelia и что делает с ответом).
Если реверс-прокси ещё не поднят, сначала разберитесь с ним отдельно, а потом накладывайте Authelia сверху.
Бесконечный редирект на страницу логина после успешного входа
Самая частая жалоба: вы вводите логин и пароль, проходите TOTP, а браузер снова кидает на /. Причина почти всегда одна — cookie от Authelia не видна защищаемому сервису.
Authelia ставит cookie сессии на домен, указанный в session.domain. Он обязан быть родительским для *всех* доменов, которые вы защищаете, и не может совпадать один в один с доменом самой Authelia:
session:
name: authelia_session
domain: example.com # не auth.example.com!
same_site: lax
expiration: 1h
inactivity: 5m
remember_me: 1M
Если Authelia висит на auth.example.com, а защищённый сервис на app.example.com, cookie с domain: auth.example.com в запросах к app.example.com просто не отправится. Ставьте example.com — тогда cookie валидна для всех поддоменов.
Второй вариант той же болезни — разные схемы (http/https) на пути редиректа. Cookie с флагом Secure (Authelia ставит его автоматически при https) не уйдёт по обычному http, поэтому если часть трафика внутри docker-сети ходит по http, а снаружи https, петля почти гарантирована. Проверяйте на реальном внешнем домене, а не через curl -k на localhost — там симптом не воспроизведётся.
Третья причина, которую легко упустить — рассинхрон времени сервера влияет и на TTL cookie: если часы убежали вперёд, Authelia может считать свежую сессию уже истёкшей. Подробнее — в разделе про TOTP ниже.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать сервер401/403 при интеграции с Traefik: ошибки в middleware и labels
С Traefik типичная ошибка — middleware forwardAuth описан, но не подключён к нужному роутеру, либо не проброшены заголовки ответа обратно клиенту.
Рабочий минимальный набор labels для сервиса за Traefik:
services:
authelia:
image: authelia/authelia:4.38
networks: [proxy]
volumes: ["./config:/config"]
labels:
- "traefik.http.routers.authelia.rule=Host(`auth.example.com`)"
- "traefik.http.services.authelia.loadbalancer.server.port=9091"
- "traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/verify?rd=https://auth.example.com"
- "traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true"
- "traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email"
app:
image: your/app
networks: [proxy]
labels:
- "traefik.http.routers.app.rule=Host(`app.example.com`)"
- "traefik.http.routers.app.middlewares=authelia@docker"
Что обычно упускают:
trustForwardHeader=true— без него Traefik не передаёт исходные заголовки вX-Forwarded-*, и Authelia не может понять, к какому домену идёт запрос, поэтому решает не в вашу пользу.authResponseHeaders— без явного списка Traefik не пробрасываетRemote-Userдальше в приложение, из-за чего сервисы, которые сами читают эти заголовки для SSO (например, Grafana сauth.proxy), видят анонимного пользователя, даже если Authelia пропустила запрос.- Middleware не привязан к роутеру приложения — легко забыть строку
traefik.http.routers.app.middlewares=authelia@docker, тогда Traefik вообще не спрашивает Authelia, и сервис открыт всем. Проверяйте через dashboard Traefik (/api/http/routers), привязан ли middleware к нужному роутеру.
Если 401 приходит сразу на попытку логина — проверьте, что роутер самой Authelia не защищён этим же middleware (частая опечатка copy-paste). Общие проблемы конфигурации Traefik отдельно от Authelia разобраны в статье про частые ошибки Traefik на сервере.
Nginx: auth_request отдаёт 500/502 вместо перенаправления на логин
С Nginx вместо labels используется модуль auth_request (в nginx из репозиториев Ubuntu и в nginx:alpine он собран по умолчанию, но в кастомных минимальных сборках его иногда вырезают — проверьте nginx -V 2>&1 | grep -o with-http_auth_request_module).
Рабочая связка — два конфиг-сниппета, подключаемые в каждый защищённый server:
# snippets/authelia-location.conf
location /authelia {
internal;
proxy_pass http://authelia:9091/api/verify;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# snippets/authelia-authrequest.conf
auth_request /authelia;
auth_request_set $target_url $scheme://$http_host$request_uri;
error_page 401 =302 https://auth.example.com/?rd=$target_url;
auth_request_set $user $upstream_http_remote_user;
proxy_set_header Remote-User $user;
Подключение в server приложения: include snippets/authelia-location.conf;, а в защищённой location / { include snippets/authelia-authrequest.conf; proxy_pass http://app-backend; }.
Типичные причины 500/502 именно на этом узле:
- Authelia недоступна изнутри docker-сети — если Nginx не в той же сети, что и контейнер Authelia,
proxy_pass http://authelia:9091резолвится в никуда. Проверяйтеdocker exec nginx getent hosts authelia. - Тело запроса передаётся в /authelia — без
proxy_pass_request_body offи обнулённогоContent-Lengthбольшие POST-запросы (загрузка файлов) иногда рвут внутренний auth-запрос с 502, потому что Authelia не ожидает тело на/api/verify. - error_page 401 без
=302— если написать простоerror_page 401 https://auth.example.com/;, Nginx отдаст статус 401 с телом страницы логина вместо редиректа, и браузер это не подхватит как переход.
Общие проблемы auth_request и reverse proxy на Nginx (504, не видит правки конфига) разобраны отдельно в материале про частые ошибки Nginx как reverse proxy — свериться стоит, если проблема не специфична для Authelia.
Сессии слетают: Redis, session secret и перезапуски
По умолчанию Authelia хранит сессии в памяти процесса. Это работает, пока контейнер не перезапускается — а он перезапускается при обновлении образа, docker compose restart, рестарте сервера. Каждый такой рестарт разлогинивает всех пользователей разом.
Для продакшена сессии нужно выносить в Redis:
session:
redis:
host: redis
port: 6379
# password: опционально, если Redis защищён паролем
Отдельная и более коварная проблема — secret для сессий и JWT должен быть зафиксирован явно и не меняться между перезапусками. Если он генерируется на лету или задан через переменную окружения, которая пересоздаётся при каждом деплое (например, случайное значение в CI), Authelia при рестарте будет считать все существующие cookie невалидными — те же симптомы, что при отсутствии Redis, только маскируются под "иногда работает, иногда нет".
Храните такие секреты в файле, подключаемом через session.secret_file, storage.encryption_key_file, identity_validation.reset_password.jwt_secret_file, а не генерируйте заново при каждом билде — это касается и storage.encryption_key, потеря которого делает нечитаемой всю базу пользовательских данных (включая секреты TOTP).
Если параллельно с Authelia на сервере крутится ещё несколько сервисов в Docker Compose, свериться со списком типовых граблей продакшен-конфигурации можно в статье про частые ошибки Docker Compose для продакшена — там как раз про секреты, volumes и порядок запуска зависимостей вроде Redis.
TOTP не проходит проверку, хотя код точно верный
Если пользователь вводит код из приложения-аутентификатора (Google Authenticator, Aegis, 1Password) и стабильно получает "неверный код" — в 9 случаях из 10 дело не в Authelia, а в рассинхронизации системного времени сервера. TOTP-коды валидны короткое окно (обычно 30 секунд ± допуск), и если часы сервера убежали хотя бы на минуту, все коды будут отклоняться, независимо от того, насколько верно они введены.
Проверка и фикс на Ubuntu/Debian:
timedatectl status # смотрите "System clock synchronized: yes"
sudo apt install systemd-timesyncd -y
sudo timedatectl set-ntp true && sudo systemctl restart systemd-timesyncd
На серверах с виртуализацией (особенно после миграции VM) часы иногда уезжают заметно — проверяйте это в первую очередь, прежде чем разбираться в конфигурации самой Authelia.
Вторая причина — пересоздание базы пользователей (storage) без миграции: секреты TOTP теряются, и пользователям нужно заново сканировать QR-код в Settings → Security → One-Time Password.
Третья, менее очевидная — повторная попытка с тем же кодом. Authelia защищается от replay-атак и не даёт использовать тот же TOTP-код дважды в пределах его окна действия. Если пользователь два раза быстро нажал "войти", вторая попытка закономерно отклонится — нужно дождаться следующего кода.
Access control rules: правило не срабатывает, хотя оно есть в конфиге
Правила в access_control.rules применяются сверху вниз, первое совпадение побеждает. Это главный источник путаницы: люди дописывают конкретное правило в конец списка, а общее правило выше него уже успело перехватить запрос.
Неправильно — общее правило стоит раньше частного и всегда срабатывает первым:
access_control:
default_policy: deny
rules:
- domain: "*.example.com"
policy: one_factor
- domain: "admin.example.com" # никогда не сработает,
policy: two_factor # правило выше уже отдало one_factor
Правильно — от частного к общему:
access_control:
default_policy: deny
rules:
- domain: "admin.example.com"
policy: two_factor
subject:
- "group:admins"
- domain: "*.example.com"
policy: one_factor
Ещё одна частая ошибка — забытый default_policy: deny в самом низу. Без него действует bypass, и любой домен, не попавший под явное правило, оказывается открытым без авторизации вообще — тихая дыра в безопасности, которую не видно, пока не проверишь вручную.
Если задача — не просто закрыть один сервис логином, а построить полноценный SSO с ролями и группами, стоит посмотреть в сторону Keycloak — установка описана в статье про настройку Keycloak на VPS. Authelia часто используют как лёгкий guard перед внутренними дашбордами, а Keycloak — как полноценный identity provider с OIDC/SAML.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Authelia обязательно нужен Redis?
Нет, для одного инстанса можно жить с сессиями в памяти, но каждый рестарт контейнера тогда разлогинивает всех. Redis обязателен, если реплик Authelia несколько — иначе сессии одной реплики не увидит другая.
Можно ли использовать Authelia без Docker?
Да, есть standalone-бинарник и systemd unit с той же самой configuration.yml. Docker просто самый популярный способ из-за простоты подключения к сети с Nginx/Traefik.
Authelia защищает сам трафик приложения или только логин?
Только проверку доступа на входе. Дальше трафик идёт напрямую от прокси к приложению — это не VPN и не шифрование канала, а контроль "пускать/не пускать".
Забыл сбросить 2FA, а доступа через веб нет — что делать?
Зайдите по SSH и удалите привязанный TOTP-секрет пользователя прямо в базе (SQLite/PostgreSQL/MySQL), либо используйте команду authelia storage user identity generate-reset-password для ссылки на сброс через notifier.
Нужен ли отдельный сервер под Authelia?
Нет, это лёгкий Go-бинарник на десятки мегабайт памяти в простое — он прекрасно живёт в том же docker-compose стеке, что и остальные сервисы.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →