MAATRIX / Блог / Authentik в Docker Compose: готовый файл

Authentik в Docker Compose: готовый файл

MAATRIX

Когда у вас накопилось десяток внутренних сервисов и в каждом свой логин, единый вход перестаёт быть роскошью — это способ не потерять контроль над доступами. Authentik решает эту задачу без java-тяжеловесности Keycloak: современный UI, визуальный редактор flow-процессов входа и разумные требования к ресурсам. Ниже — рабочий docker-compose.yml, с которым Authentik поднимается на чистом VPS без плясок с бубном, и разбор мест, где обычно спотыкаются на первом запуске.

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

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

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

Что такое Authentik и чем он отличается от Keycloak

Authentik — open-source identity provider: SSO, OAuth2/OIDC, SAML, LDAP-outpost, forward-auth для reverse proxy. По функциональности он закрывает те же задачи, что и Keycloak, но устроен иначе.

Ключевое отличие — flow-редактор. В Keycloak процесс входа (логин, MFA, восстановление пароля) зашит в готовые «реалмы» с ограниченной кастомизацией через темы и SPI-расширения на Java. В Authentik каждый этап входа — это отдельный "stage" (ввод логина, проверка пароля, MFA, согласие, редирект), и вы собираете из них flow визуально, как блок-схему. Хотите добавить капчу перед вводом пароля или отдельный флоу для внешних подрядчиков с другим набором проверок — просто пересобираете граф в UI, без кода.

Второе отличие — стек. Authentik написан на Python (Django) + Go для отдельных компонентов, поэтому память ест заметно скромнее: сервер и worker вместе обычно укладываются в 500-700 МБ на небольшой инсталляции, тогда как JVM у Keycloak часто просит гигабайт и больше уже на старте. Для VPS с 2 ГБ RAM это существенно.

Из минусов: экосистема моложе, готовых интеграций и статей меньше, а часть enterprise-функций (расширенный аудит, некоторые SSO-коннекторы) доступна только в платной версии. Для типичного self-hosted сценария — SSO для Grafana, Nextcloud, Gitea, внутренних дашбордов — бесплатной версии хватает с запасом.

Если вы уже смотрели Keycloak в Docker Compose и он показался тяжеловесным для вашей задачи — Authentik стоит попробовать первым.

Что нужно подготовить перед установкой

Минимальные требования: VPS с 2 ядрами и 2 ГБ RAM (комфортно — 4 ГБ, если параллельно крутите ещё сервисы за тем же прокси), Docker и Docker Compose plugin, домен или поддомен (например, auth.example.com) с A-записью на IP сервера — Authentik нужен собственный HTTPS-адрес, на который будут ходить все защищённые сервисы для проверки логина.

Проверьте версии перед стартом:

docker --version
docker compose version

Если Docker ещё не стоит, разверните его так же, как для любого compose-стека — процесс не отличается от установки для production-окружения на Ubuntu 24.04.

Создайте рабочую директорию и сгенерируйте секреты заранее — Authentik требует непустой AUTHENTIK_SECRET_KEY (используется для подписи cookie сессий и токенов) и пароль для PostgreSQL:

mkdir -p /opt/authentik && cd /opt/authentik
mkdir -p media custom-templates certs

echo "PG_PASS=$(openssl rand -base64 36 | tr -d '\n')" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')" >> .env

.env с секретами не коммитьте в git и держите права 600:

chmod 600 .env

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

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

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

Готовый docker-compose.yml

Authentik всегда состоит минимум из четырёх компонентов: PostgreSQL (хранит конфигурацию, пользователей, flow), Redis (кэш и очередь задач), server (веб-интерфейс и API) и worker (фоновые задачи — отправка почты, синхронизация LDAP, генерация сертификатов). Экономить на любом из них не получится — без worker, например, не отправляются письма подтверждения и не обновляются сертификаты outpost'ов.

services:
  postgresql:
    image: postgres:16-alpine
    container_name: authentik-db
    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}
      POSTGRES_USER: authentik
      POSTGRES_DB: authentik
    env_file:
      - .env

  redis:
    image: redis:alpine
    container_name: authentik-redis
    restart: unless-stopped
    command: --save 60 1 --loglevel warning
    healthcheck:
      test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
      start_period: 20s
      interval: 30s
      retries: 5
      timeout: 3s
    volumes:
      - redis:/data

  server:
    image: ghcr.io/goauthentik/server:2025.6
    container_name: authentik-server
    restart: unless-stopped
    command: server
    environment:
      AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
      AUTHENTIK_REDIS__HOST: redis
      AUTHENTIK_POSTGRESQL__HOST: postgresql
      AUTHENTIK_POSTGRESQL__USER: authentik
      AUTHENTIK_POSTGRESQL__NAME: authentik
      AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
      AUTHENTIK_ERROR_REPORTING__ENABLED: "false"
    volumes:
      - ./media:/media
      - ./custom-templates:/templates
    env_file:
      - .env
    ports:
      - "127.0.0.1:9000:9000"
      - "127.0.0.1:9443:9443"
    depends_on:
      postgresql:
        condition: service_healthy
      redis:
        condition: service_healthy

  worker:
    image: ghcr.io/goauthentik/server:2025.6
    container_name: authentik-worker
    restart: unless-stopped
    command: worker
    environment:
      AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
      AUTHENTIK_REDIS__HOST: redis
      AUTHENTIK_POSTGRESQL__HOST: postgresql
      AUTHENTIK_POSTGRESQL__USER: authentik
      AUTHENTIK_POSTGRESQL__NAME: authentik
      AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
    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:
  redis:

Тег образа 2025.6 зафиксирован намеренно — не берите latest: релизы Authentik иногда несут миграции схемы БД, и внезапное обновление контейнера при перезапуске может уронить сервис посреди рабочего дня. Смотрите актуальный стабильный тег в релизах на GitHub (goauthentik/authentik) и обновляйтесь осознанно, читая changelog.

Порты сервера намеренно смотрят только на 127.0.0.1 — наружу Authentik отдаёт reverse proxy с TLS, сам сервис в интернет напрямую не публикуется. Сокет Docker в volume у worker нужен только если вы планируете использовать Docker-based outposts (proxy-outpost для forward-auth к сервисам, которые сами не умеют OIDC) — если такого сценария нет, эту строку можно убрать.

Первый запуск и настройка администратора

Поднимаем стек:

docker compose up -d
docker compose logs -f server

Дождитесь строки вида Startup complete — на слабом VPS первая инициализация БД и миграции могут занять минуту-две. После этого откройте http://127.0.0.1:9000/if/flow/initial-setup/ (через SSH-туннель, если у вас нет ещё reverse proxy: ssh -L 9000:127.0.0.1:9000 user@ваш-сервер) — это одноразовый мастер создания первого администратора. Ссылка перестаёт работать после того, как аккаунт создан.

Задайте логин, e-mail и пароль администратора. Дальше вход идёт уже через обычный /if/flow/default-authentication-flow/ на вашем домене.

Если мастер уже "сгорел" (например, вы случайно зашли туда раньше), создать администратора можно из shell контейнера:

docker compose exec server ak create_recovery_key 10 akadmin

Команда выведет одноразовую ссылку восстановления доступа, действующую 10 дней.

Reverse proxy и HTTPS перед Authentik

Authentik должен быть доступен только по HTTPS — через него проходят пароли и токены сессий других сервисов. Самый простой вариант — Traefik с автоматическим TLS через Let's Encrypt: добавьте лейблы прямо к сервису server из compose-файла выше, если Traefik уже развёрнут в той же docker-сети (см. Traefik как reverse proxy для Docker):

  server:
    # ...остальные настройки как выше...
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.authentik.rule=Host(`auth.example.com`)"
      - "traefik.http.routers.authentik.entrypoints=websecure"
      - "traefik.http.routers.authentik.tls.certresolver=letsencrypt"
      - "traefik.http.services.authentik.loadbalancer.server.port=9000"
    networks:
      - traefik-net
      - default

Если предпочитаете более простой конфиг без отдельного докер-лейбла, подойдёт и Caddy с автоматическим TLS. Для Caddy конфиг сведётся к трём строкам:

auth.example.com {
    reverse_proxy 127.0.0.1:9000
}

Важный нюанс: если сервисы, которые вы защищаете через Authentik (forward-auth), находятся на других поддоменах, cookie сессии должен работать между ними — задайте единый корневой домен (example.com) и настройте cookie-domain в Authentik через AUTHENTIK_COOKIE_DOMAIN=example.com, иначе пользователю придётся логиниться заново в каждом сервисе.

Обновления, бэкапы и типичные проблемы

Обновление. Смените тег образа на новый релиз в обоих сервисах (тег должен совпадать), затем:

docker compose pull
docker compose up -d

Миграции БД сервер применяет автоматически при старте. Перед мажорным обновлением (например, между годовыми релизными ветками) обязательно прочитайте раздел "Breaking changes" в release notes — иногда меняются переменные окружения.

Бэкап. Всё состояние живёт в PostgreSQL и в примонтированной media (загруженные логотипы, кастомные шаблоны писем). Бэкапить нужно оба:

docker compose exec postgresql pg_dump -U authentik authentik | gzip > authentik-$(date +%F).sql.gz
tar czf authentik-media-$(date +%F).tar.gz media/

Автоматизировать это разумнее через готовый инструмент, а не голый cron-скрипт с забытым логом ошибок — подход с ротацией и проверкой целостности разобран в статье про бэкап и восстановление BorgBackup: тот же паттерн, только вместо произвольных файлов в архив кладёте дамп PostgreSQL и папку media.

Частые проблемы:

  • Сервер не стартует, в логах django.db.utils.OperationalError. PostgreSQL ещё не готов принять соединения — проверьте, что healthcheck у postgresql реально зелёный (docker compose ps), а не просто "started". В compose-файле выше это уже учтено через condition: service_healthy, но если вы меняли структуру — легко потерять эту зависимость.
  • Письма не уходят (подтверждение регистрации, восстановление пароля). Проверьте, что запущен именно worker, а не только server — рассылкой занимается он. Дальше — переменные AUTHENTIK_EMAIL__HOST, AUTHENTIK_EMAIL__PORT, AUTHENTIK_EMAIL__USE_TLS в .env.
  • После логина в защищённом сервисе бросает обратно на страницу входа по кругу. Почти всегда — рассинхрон cookie-домена между Authentik и forward-auth outpost'ом, см. раздел про reverse proxy выше.
  • Контейнер worker падает по OOM на слабом VPS. Первичная индексация и миграции при апгрейде временно повышают потребление памяти. На 2 ГБ RAM добавьте своп-файл на 1-2 ГБ, чтобы пережить пиковые моменты без падения процесса.

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

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

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

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

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

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

Authentik заменяет Keycloak один в один?

Функционально — да, для 90% задач SSO/OIDC/SAML/LDAP. Отличия в философии конфигурации (flow-граф вместо реалмов) и в весе — Authentik легче для небольшого VPS.

Нужен ли отдельный сервер под Authentik или можно на том же VPS, что и защищаемые сервисы?

Можно на том же — стек компактный. Отдельный сервер имеет смысл только если через Authentik проходит критичная инфраструктура и вы хотите изолировать её отказоустойчивость от остального.

Можно ли обойтись без Redis?

Нет, Redis обязателен — на нём построены кэш сессий и очередь задач между server и worker, без него сервис не запустится.

Как защитить сервис, который вообще не умеет OIDC/SAML (например, старую внутреннюю панель)?

Через Proxy Provider и forward-auth outpost — Authentik встаёт перед сервисом и требует логин до того, как запрос дойдёт до самого приложения. Настраивается в разделе Applications → Providers, тип Proxy.

Обязательно ли открывать Authentik в интернет, или можно только во внутренней сети?

Если все защищаемые сервисы доступны только через VPN, Authentik можно держать без публичного домена вовсе, обвязав его тем же VPN-туннелем. Публичный домен нужен только если снаружи логинятся реальные внешние пользователи.

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

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

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