Как создать портал авторизации для своих доменов с помощью Caddy
Caddy — это современный веб-сервер с автоматической поддержкой HTTPS через Let’s Encrypt. Однако стандартная сборка Caddy не включает модуль caddy-security, который необходим для создания портала авторизации и управления доступом к вашим доменам. В этой статье я расскажу, как собрать Caddy с этим модулем с помощью xcaddy, настроить портал авторизации и защитить свои веб-приложения.
Предварительные требования
Перед началом убедитесь, что у вас есть:
- Сервер с операционной системой (например, Ubuntu 22.04).
- Доступ к командной строке с правами суперпользователя (
sudo). - Базовые знания о веб-серверах и конфигурационных файлах.
- Домен или поддомен (например,
example.com), с настроенными DNS-записями, указывающими на ваш сервер. - Установленный Go (версия 1.16 или выше) для сборки Caddy.
Шаг 1: Сборка Caddy с модулем caddy-security
Поскольку модуль caddy-security не входит в стандартную сборку Caddy, нам нужно собрать кастомную версию с помощью инструмента xcaddy.
1.1. Установка xcaddy
xcaddy позволяет собирать Caddy с дополнительными модулями. Установите его следующим образом:
sudo apt update
sudo apt install -y golang
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
После выполнения этих команд xcaddy будет доступен в ~/go/bin/xcaddy. Убедитесь, что директория ~/go/bin добавлена в ваш $PATH, чтобы использовать xcaddy глобально:
export PATH=$PATH:~/go/bin
1.2. Сборка Caddy с модулем caddy-security
Теперь соберем Caddy с модулем caddy-security:
~/go/bin/xcaddy build --with github.com/greenpau/caddy-security
Эта команда создаст исполняемый файл caddy в текущей директории.
1.3. Установка собранного Caddy
Переместите скомпилированный файл в системную директорию, чтобы он был доступен глобально:
sudo mv caddy /usr/bin/
Проверьте версию Caddy, чтобы убедиться, что модуль включен:
caddy version
Вывод должен показать версию Caddy с указанием, что сборка кастомная.
Шаг 2: Настройка хранилища пользователей
Для работы портала авторизации Caddy использует JSON-файл с данными пользователей. Мы создадим файл users.json с помощью скрипта.
2.1. Создание директории для данных
Создайте директорию для хранения данных и установите правильные права доступа:
sudo mkdir -p /data/.local/caddy
sudo chown caddy:caddy /data/.local/caddy
2.2. Создание пользователя с помощью скрипта
Чтобы упростить процесс, используйте следующий скрипт. Он запрашивает данные пользователя и генерирует файл users.json.
Сохраните этот код в файл generate_users_json.sh:
#!/bin/bash
# Проверка зависимостей
if ! command -v python3 &> /dev/null; then
echo "Ошибка: Python3 не установлен. Установите: 'sudo apt install python3'."
exit 1
fi
if ! python3 -c "import bcrypt" &> /dev/null; then
echo "Ошибка: Модуль bcrypt не установлен. Установите: 'pip3 install bcrypt'."
exit 1
fi
if ! command -v uuidgen &> /dev/null; then
echo "Ошибка: uuidgen не установлен. Установите: 'sudo apt install uuid-runtime'."
exit 1
fi
# Запрос данных
read -p "Введите имя пользователя (username): " USERNAME
read -p "Введите email: " EMAIL
read -s -p "Введите пароль: " PASSWORD
echo
# Проверка данных
if [[ -z "$USERNAME" || -z "$EMAIL" || -z "$PASSWORD" ]]; then
echo "Ошибка: Все поля должны быть заполнены."
exit 1
fi
if [[ ${#USERNAME} -lt 3 || ${#USERNAME} -gt 50 || "$USERNAME" =~ [^a-z] ]]; then
echo "Ошибка: Имя пользователя — 3-50 символов, только строчные буквы (a-z)."
exit 1
fi
if [[ ${#PASSWORD} -lt 8 ]]; then
echo "Ошибка: Пароль — минимум 8 символов."
exit 1
fi
# Извлечение домена
DOMAIN=$(echo "$EMAIL" | cut -d'@' -f2)
if [[ -z "$DOMAIN" ]]; then
echo "Ошибка: Неверный формат email."
exit 1
fi
# Генерация значений
UUID=$(uuidgen)
DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
HASH=$(python3 -c "import bcrypt; print(bcrypt.hashpw('$PASSWORD'.encode(), bcrypt.gensalt(10)).decode())")
# Создание users.json
cat <<EOF > /data/.local/caddy/users.json
{
"version": "1.1.7",
"policy": {
"password": {
"min_length": 8,
"max_length": 128
},
"user": {
"min_length": 3,
"max_length": 50,
"allow_non_alpha_numeric": false,
"allow_uppercase": false
}
},
"revision": 1,
"last_modified": "$DATE",
"users": [
{
"id": "$UUID",
"username": "$USERNAME",
"email_address": {
"address": "$EMAIL",
"domain": "$DOMAIN"
},
"email_addresses": [
{
"address": "$EMAIL",
"domain": "$DOMAIN"
}
],
"passwords": [
{
"purpose": "generic",
"algorithm": "bcrypt",
"hash": "$HASH",
"cost": 10,
"expired_at": "0001-01-01T00:00:00Z",
"created_at": "$DATE",
"disabled_at": "0001-01-01T00:00:00Z"
}
],
"created": "$DATE",
"last_modified": "$DATE",
"roles": [
{
"name": "admin",
"organization": "authp"
}
]
}
]
}
EOF
# Установка прав
sudo chown caddy:caddy /data/.local/caddy/users.json
sudo chmod 640 /data/.local/caddy/users.json
echo "Файл /data/.local/caddy/users.json создан!"
echo "Перезапустите Caddy: sudo systemctl restart caddy"
Как использовать скрипт:
- Сохраните скрипт в файл
generate_users_json.sh. - Сделайте его исполняемым:
chmod +x generate_users_json.sh - Запустите:
./generate_users_json.sh - Введите данные:
- Имя пользователя (например,
john). - Email (например,
john@example.com). - Пароль (минимум 8 символов).
- Имя пользователя (например,
Скрипт создаст файл /data/.local/caddy/users.json с пользователем, которому присвоена роль authp/admin.
Шаг 3: Настройка Caddy для авторизации
Теперь настроим Caddyfile для работы с порталом авторизации.
3.1. Основная конфигурация Caddy
Откройте файл /etc/caddy/Caddyfile:
sudo nano /etc/caddy/Caddyfile
Добавьте глобальные настройки в начало файла:
{
storage file_system {
root /var/lib/caddy
}
email your-email@example.com
order authenticate before respond
order authorize before respond
security {
local identity store localdb {
realm local
path /data/.local/caddy/users.json
}
authentication portal my_portal {
crypto default token lifetime 3600
enable identity store localdb
cookie domain .example.com
ui {
links {
"Dashboard" "/dashboard" icon "las la-tachometer-alt"
"My Identity" "/auth/whoami" icon "las la-user"
}
}
transform user {
match origin local
action add role authp/admin
}
}
authorization policy my_policy {
set auth url /auth
allow roles authp/admin
acl rule {
comment "Allow authenticated admins"
match role authp/admin
allow stop log info
}
acl rule {
comment "Deny all others"
match any
deny log warn
}
}
}
}
- Замените
your-email@example.comна ваш email. - Замените
.example.comна ваш домен (например,.mydomain.com).
3.2. Настройка для домена
Добавьте блок для вашего домена:
sub.example.com {
route {
handle /auth {
rewrite * /auth
request_header +X-Forwarded-Prefix /auth
authenticate with my_portal
}
route /auth* {
authenticate with my_portal
reverse_proxy 127.0.0.1:8080 {
header_up X-Real-IP {remote}
header_up Host {host}
}
}
route /* {
authorize with my_policy
reverse_proxy 127.0.0.1:8080 {
header_up X-Real-IP {remote}
header_up Host {host}
}
}
}
log {
output file /var/log/caddy/sub.example.com-access.log {
roll_size 30mb
roll_keep 10
roll_keep_for 720h
}
level ERROR
}
}
- Замените
sub.example.comна ваш домен. - Настройте
reverse_proxyпод ваш бэкенд (адрес и порт).
Шаг 4: Проверка и перезапуск Caddy
4.1. Проверка конфигурации
Убедитесь, что Caddyfile корректен:
caddy validate --config /etc/caddy/Caddyfile
Если вы видите Valid configuration, всё в порядке.
4.2. Перезапуск Caddy
Примените изменения:
sudo systemctl restart caddy
Проверьте статус:
systemctl status caddy
Служба должна быть active (running).
Шаг 5: Тестирование портала авторизации
-
Перейдите в браузере на
https://sub.example.com/auth.
-
Введите имя пользователя и пароль из
users.json.
-
После входа проверьте доступ к защищенным ресурсам.
Если доступ не работает, проверьте:
- Данные в
users.json. - Соответствие ролей в настройках.
Шаг 6: Продвинутая настройка - OAuth аутентификация
Помимо локальной аутентификации, Caddy Security поддерживает OAuth провайдеры, такие как Google. Это позволяет пользователям входить в систему с помощью существующих аккаунтов Google.
6.1. Настройка Google Cloud Platform
Для интеграции с Google OAuth необходимо настроить проект в Google Cloud Platform:
- Перейдите в Google Cloud Console
- Создайте новый проект или выберите существующий
- Перейдите в “API и сервисы” → “Учетные данные”
- Нажмите “Настроить экран согласия”
- Выберите тип пользователя: “Внешние”
- Заполните обязательные поля: название приложения, email разработчика
- В разделе “Области” добавьте:
openid,email,profile
- Создайте OAuth 2.0 Client ID:
- Тип приложения: “Веб-приложение”
- Добавьте разрешенные URI перенаправления:
https://auth.example.com/oauth2/google/authorization-code-callback https://auth.example.com/auth/oauth2/google/authorization-code-callback
- Сохраните Client ID и Client Secret
6.2. Обновление конфигурации Caddy
Обновите ваш Caddyfile для поддержки Google OAuth:
{
storage file_system {
root /var/lib/caddy
}
email your-email@example.com
order authenticate before respond
order authorize before respond
security {
local identity store localdb {
realm local
path /data/.local/caddy/users.json
}
oauth identity provider google {
realm google
driver google
client_id {env.GOOGLE_CLIENT_ID}.apps.googleusercontent.com
client_secret {env.GOOGLE_CLIENT_SECRET}
scopes openid email profile
}
authentication portal my_portal {
crypto default token lifetime 3600
crypto key sign-verify {env.JWT_SHARED_KEY}
enable identity store localdb
enable identity provider google
cookie domain .example.com
ui {
links {
"Dashboard" "/dashboard" icon "las la-tachometer-alt"
"My Identity" "/auth/whoami" icon "las la-user"
"Portal Settings" "/settings" icon "las la-cog"
}
}
transform user {
match origin local
action add role authp/user
ui link "Portal Settings" /settings icon "las la-cog"
}
transform user {
match origin local
match email admin@example.com
action add role authp/admin
}
transform user {
match realm google
action add role authp/user
}
transform user {
match realm google
match email admin@example.com
action add role authp/admin
}
}
authorization policy my_policy {
set auth url /auth
crypto key verify {env.JWT_SHARED_KEY}
allow roles authp/admin authp/user
validate bearer header
inject headers with claims
acl rule {
comment "Allow authenticated users"
match role authp/admin authp/user
allow stop log info
}
acl rule {
comment "Deny all others"
match any
deny log warn
}
}
}
}
6.3. Настройка переменных окружения
Создайте файл /etc/caddy/env.conf с необходимыми переменными:
# JWT ключ для подписи токенов (минимум 100 символов)
JWT_SHARED_KEY=your-very-long-random-string-here-minimum-100-characters
# Google OAuth credentials
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
Убедитесь, что служба Caddy загружает переменные окружения. Добавьте в /lib/systemd/system/caddy.service в секцию [Service]:
EnvironmentFile=/etc/caddy/env.conf
6.4. Расширенные transform rules
Transform rules позволяют настраивать роли и UI элементы для пользователей в зависимости от источника аутентификации:
- match origin local - для локальных пользователей
- match realm google - для пользователей Google OAuth
- match email - для конкретного email адреса
- action add role - добавление роли пользователю
- ui link - добавление ссылки в интерфейс
6.5. Дополнительные опции authorization policy
- validate bearer header - проверка JWT токенов в заголовках
- inject headers with claims - добавление информации о пользователе в заголовки запросов к backend сервисам
- acl rule - детальные правила контроля доступа
Шаг 7: Настройка дополнительных OAuth провайдеров
Caddy Security поддерживает различные OAuth провайдеры через generic driver. Пример конфигурации для произвольного OIDC провайдера:
oauth identity provider custom {
realm custom
driver generic
client_id {env.CUSTOM_CLIENT_ID}
client_secret {env.CUSTOM_CLIENT_SECRET}
server_id {env.CUSTOM_SERVER_ID}
tenant_id {env.CUSTOM_TENANT_ID}
base_auth_url https://custom-provider.com/oauth2/authorize
metadata_url https://custom-provider.com/.well-known/openid_configuration
scopes openid email profile
}
Дополнительные советы
Улучшенный UI портала
Настройте более функциональный интерфейс портала:
ui {
links {
"Dashboard" "/dashboard" icon "las la-tachometer-alt"
"My Identity" "/whoami" icon "las la-user"
"Portal Settings" "/settings" icon "las la-cog"
"Admin Panel" "/admin" icon "las la-tools"
"Logs" "/logs" icon "las la-file-alt"
}
theme dark
custom_css_required no
custom_js_required no
}
Множественные домены
Для разных доменов создайте отдельные порталы:
authentication portal another_portal {
cookie domain .anotherdomain.com
...
}
Продвинутое логирование
Добавьте отладочные логи:
{
log {
output file /var/log/caddy/caddy.log
level DEBUG
}
}
Настройка времени жизни токенов
Различные настройки для токенов:
authentication portal my_portal {
crypto default token lifetime 3600 # 1 час
crypto key sign-verify {env.JWT_SHARED_KEY}
# Настройки для refresh токенов
token sources {
config {
token_lifetime 300 # 5 минут для access token
token_name "access_token"
}
config {
token_lifetime 86400 # 24 часа для refresh token
token_name "refresh_token"
}
}
}
Безопасность
- Обновляйте Caddy регулярно.
- Используйте сложные пароли.
- Настройте фаервол (
ufw), разрешив только 80 и 443 порты.
Заключение
Теперь у вас есть полноценный портал авторизации на Caddy с поддержкой как локальной аутентификации, так и OAuth провайдеров. Основные возможности включают:
- Локальная аутентификация с автоматическим созданием пользователей через скрипт
- OAuth интеграция с Google и другими провайдерами
- Гибкая система ролей и прав доступа
- Расширенные возможности валидации и инъекции заголовков
- Современный UI с настраиваемыми ссылками
Эта конфигурация легко масштабируется — добавляйте пользователей, домены, провайдеры аутентификации и политики авторизации в соответствии с вашими потребностями.
Для дополнительных OAuth провайдеров см. документацию по generic OIDC.
Если возникнут вопросы, загляните в документацию Caddy Security или спросите в сообществе!


