Когда у компании или домашней лаборатории появляется несколько собственных сервисов — вики, панель мониторинга, Git-сервер, внутренний портал, — пароли начинают дублироваться, а учётные записи приходится удалять вручную. Keycloak решает эту задачу: он выступает поставщиком идентичности по OpenID Connect и SAML, хранит пользователей, группы и роли, а приложения получают от него подписанные токены. Ниже — практическая настройка с нуля на своём сервере.
Зачем нужен единый вход
Единый вход (SSO) означает, что человек один раз вводит логин и пароль на странице Keycloak, а дальше получает доступ к подключённым приложениям без повторной аутентификации. Для администратора это единая точка отключения доступа: блокировка учётной записи сразу закрывает все сервисы.
Keycloak не требует встраивать свою базу пользователей в каждый проект. Приложение перенаправляет браузер на сервер идентичности, получает код авторизации и обменивает его на токен. Такой поток называется Authorization Code Flow; для публичных клиентов добавляют PKCE.
Установка: PostgreSQL и контейнер
Для небольшой инсталляции достаточно одного узла и PostgreSQL. Встроенная база dev-file годится только для экспериментов: она не рассчитана на параллельную нагрузку. Создадим отдельную сеть, том и контейнер базы.
podman network create kc-net
podman volume create kc-db
podman run -d --name kc-db --network kc-net \
-e POSTGRES_DB=keycloak -e POSTGRES_USER=keycloak \
-e POSTGRES_PASSWORD='S3curePass' \
-v kc-db:/var/lib/postgresql/data postgres:17
Тег образа лучше зафиксировать по номеру версии из официальных release notes, а не использовать latest в production.
Первый запуск и realm
Keycloak 26.x использует переменные KC_BOOTSTRAP_ADMIN_USERNAME и KC_BOOTSTRAP_ADMIN_PASSWORD: они создают временного администратора только при первом старте, когда база ещё пуста. После входа пароль нужно сменить.
podman run -d --name keycloak --network kc-net \
-p 127.0.0.1:8080:8080 -p 127.0.0.1:9000:9000 \
-e KC_DB=postgres -e KC_DB_URL=jdbc:postgresql://kc-db:5432/keycloak \
-e KC_DB_USERNAME=keycloak -e KC_DB_PASSWORD='S3curePass' \
-e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
-e KC_BOOTSTRAP_ADMIN_PASSWORD='Adm1nPass' \
quay.io/keycloak/keycloak:latest start-dev
Режим start-dev отключает часть проверок и включает HTTP — он допустим лишь для локальной отладки. Рабочий запуск выполняют командой start с заранее заданными KC_HOSTNAME и параметрами TLS. Настройки realm хранятся в базе, поэтому контейнер можно пересоздавать без потери данных.
Создадим отдельный realm corp: в нём будут жить пользователи и клиенты организации. Realm master оставим только для администрирования.
podman exec -it keycloak /opt/keycloak/bin/kcadm.sh \
config credentials --server http://localhost:8080 \
--realm master --user admin --password 'Adm1nPass'
podman exec -it keycloak /opt/keycloak/bin/kcadm.sh \
create realms -s realm=corp -s enabled=true
Подключаем сервис по OIDC
Клиент описывает приложение, которому разрешено получать токены. Для серверного приложения с секретом выбирают confidential client, для одностраничного JavaScript-приложения — public client с PKCE. В поле redirectUris перечисляют точные адреса возврата: слишком широкий шаблон создаёт риск утечки кода авторизации.
podman exec keycloak /opt/keycloak/bin/kcadm.sh create clients -r corp \
-s clientId=wiki -s enabled=true -s protocol=openid-connect \
-s publicClient=false -s standardFlowEnabled=true \
-s 'redirectUris=["https://wiki.example.ru/*"]' \
-s secret='wiki-secret'
Проверить конфигурацию можно через discovery-документ: он содержит issuer, адреса авторизации и токенов, список поддерживаемых алгоритмов.
Роли, группы и мапперы
Роли бывают realm- и client-уровня. Первые удобны для общих прав вроде editor или viewer, вторые — для полномочий внутри конкретного приложения. Группы позволяют выдать набор ролей одним действием и упрощают управление, когда сотрудников много.
Приложению нужен не только access token, но и понятная структура прав. Маппер audience добавляет в токен идентификатор клиента, а маппер групп переносит членство в группе в claim groups. Без audience некоторые библиотеки отклоняют токен, даже если подпись верна.
Пользователей можно завести вручную, импортировать из CSV или подключить LDAP и Active Directory через User Federation. Keycloak не копирует пароли, а проверяет их в каталоге, поэтому смена пароля происходит в привычном месте.
HTTPS и обратный прокси
Публиковать Keycloak в интернет не стоит. Обычно TLS завершается на Nginx или другом прокси, а контейнер слушает localhost. Важно передать исходную схему и хост, иначе Keycloak сформирует ссылки с http и вход завершится ошибкой.
server {
listen 443 ssl;
http2 on;
server_name sso.example.ru;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
}
}
В окружении контейнера задают KC_HOSTNAME=https://sso.example.ru, KC_PROXY_HEADERS=xforwarded и KC_HTTP_ENABLED=true. Порт управления 9000 оставляют доступным только с localhost: на нём публикуются health-проверки.
Диагностика
Большинство проблем связано с неверным redirect URI, рассинхронизацией часов или отсутствием claim. Начинают с логов контейнера и discovery-документа, затем проверяют настройки клиента.
podman logs --tail 100 keycloak | grep -i error
curl -s http://127.0.0.1:9000/health/ready
Ошибка invalid_redirect_uri означает, что адрес не совпал по схеме или завершающему слешу. Ответ 401 после прокси часто указывает на потерянный заголовок X-Forwarded-Proto. Если токен принимается, но ролей нет, смотрят мапперы и scope: client scope должен быть назначен клиенту.
Полезно включить аудит: Keycloak пишет входы, ошибки и административные операции в журнал, при необходимости — во внешнюю систему мониторинга. Это помогает разбирать инциденты без раскопок в базе.
Чек-лист перед публикацией
- PostgreSQL вместо dev-file, регулярный дамп базы и экспорт realm.
- Сильный пароль администратора, смена временного пароля, ограничение доступа к /admin по сети.
- HTTPS, корректные KC_HOSTNAME и KC_PROXY_HEADERS, порт управления закрыт снаружи.
- Для каждого клиента — точные redirect URI, PKCE для публичных клиентов, короткий срок жизни токенов.
- Резервный администратор или доступ к базе на случай блокировки основной учётной записи.
Итог
Keycloak закрывает задачу аутентификации для собственных сервисов без привязки к одному языку или фреймворку. Разумный минимум — PostgreSQL, отдельный realm, OIDC-клиенты с точными адресами возврата и TLS на прокси. Дальше можно добавить LDAP, второй фактор, тонкую настройку ролей и мониторинг. Главное — не оставлять админку открытой и проверять конфигурацию после каждого обновления.