Установка¶
Alatyr состоит из двух независимо устанавливаемых частей:
- Сервер — Go API + PostgreSQL + PKI-бэкенд (Vault и/или внешний SCEP CA)
- React Admin UI. Разворачивается один раз на инфраструктуре организации.
- Агент — исполняемый файл для macOS/Windows/Linux, ставится на каждое устройство сотрудника отдельно и сам обращается к серверу за сертификатом.
Эта страница покрывает установку обеих частей. Полный список переменных окружения сервера — на странице Конфигурация. Прежде чем разворачивать сервер в продакшене, прочитайте Отказоустойчивость (HA) и Расчёт ресурсов — ни один из манифестов ниже не разворачивает БД или Vault в отказоустойчивой конфигурации из коробки.
Что нужно перед началом¶
| Компонент | Обязательность | Назначение |
|---|---|---|
| PostgreSQL | обязательно | основная БД сервера |
| Vault (или внешний SCEP CA) | обязательно | PKI-бэкенд, выпуск сертификатов |
| Keycloak | опционально | SSO для Admin UI; альтернатива — встроенная локальная email+password аутентификация |
Порты, встречающиеся на этой странице:
| Порт | Что на нём слушает |
|---|---|
8090 |
API сервера (docker-compose.yml) |
13000 / 18090 |
turnkey-демо (docker-compose.demo.yml): UI / API |
8200 |
Vault |
8080 |
Keycloak (dev-стек docker-compose.dev.yml) |
Сервер¶
Есть два независимых пути установки сервера: Docker Compose (самостоятельный хостинг, три готовых файла под разные сценарии) и Helm-чарт alatyr-demo для Kubernetes. Оба варианта описаны ниже.
Вариант 1 — Docker Compose¶
| Файл | Назначение |
|---|---|
docker-compose.yml |
«Production-shaped» стек: PostgreSQL + сервер + UI. Ожидает уже настроенный внешний Vault (и, опционально, Keycloak) — сам их не поднимает. |
docker-compose.demo.yml |
Turnkey-демо: одна команда, ничего настраивать не нужно. Поднимает PostgreSQL, Vault (dev-режим), сервер, UI и наполняет БД тестовыми данными. |
docker-compose.dev.yml |
Только dev-инфраструктура (PostgreSQL + Vault dev + Keycloak) — сервер и фронтенд предполагается запускать локально, либо в Docker через --profile app. |
docker-compose.yml — самостоятельный хостинг¶
Поднимает postgres, alatyr-server (порт 8090) и alatyr-ui (порт
3000, проксирует на внутренний 8080). Требует до запуска:
DB_PASSWORD— пароль PostgreSQL (host-only переменная, подставляется вALATYR_DB_URL, самим сервером напрямую не читается);- доступ к Vault: либо
VAULT_ADDR+VAULT_ROLE_ID/VAULT_SECRET_ID(AppRole, рекомендуется для продакшена), либоVAULT_ADDR+VAULT_TOKEN(статический токен, приоритет ниже AppRole); - если используете Keycloak SSO —
KEYCLOAK_URL,KEYCLOAK_REALM,KEYCLOAK_CLIENT_ID,KEYCLOAK_CLIENT_SECRET. Альтернатива без Keycloak — встроенная локальная email+password аутентификация (ALATYR_LOCAL_AUTH_ENABLEDи связанные переменные, см. Конфигурация).
export DB_PASSWORD="<сильный пароль>"
export VAULT_ADDR="https://vault.internal.example.com:8200"
export VAULT_ROLE_ID="..." VAULT_SECRET_ID="..."
export KEYCLOAK_URL="https://keycloak.internal.example.com" \
KEYCLOAK_REALM="alatyr" KEYCLOAK_CLIENT_ID="alatyr-portal" \
KEYCLOAK_CLIENT_SECRET="..."
docker compose -f docker-compose.yml up --build -d
Базовые образы для сборки
Dockerfile сервера и Dockerfile фронтенда (используются этим файлом по
умолчанию) параметризованы через build-args (GOLANG_BASE,
ALPINE_BASE и т.п.) под внутренний registry-mirror конкретного
окружения сборки. Если у вас нет аналогичного зеркала, соберите с
override на публичные образы (--build-arg GOLANG_BASE=golang:1.25.8-alpine
--build-arg ALPINE_BASE=alpine:3.21.6 для сервера). Либо, для
быстрого локального теста без правки build-args, ориентируйтесь на
Dockerfile.demo/docker-compose.demo.yml ниже: он использует ровно те
же публичные docker.io-образы и специально существует для сборки без
внутренней инфраструктуры.
docker-compose.demo.yml — turnkey-демо (быстрее всего попробовать)¶
Одна команда — и ничего настраивать не нужно. Собирается на публичных
docker.io-образах (Dockerfile.demo), поднимает Vault в dev-режиме и
конфигурирует его PKI-движок автоматически (vault-init), включает
локальную аутентификацию и вебхуки, наполняет базу тестовыми данными:
docker compose -f docker-compose.demo.yml up --build
Затем откройте http://localhost:13000 и войдите как admin@wifi.local /
Admin1234!. API — http://localhost:18090.
Только для демо/локального теста
Секреты (ALATYR_LOCAL_JWT_SECRET, ALATYR_WEBHOOK_ENC_KEY,
Vault dev-root-token, пароль администратора) захардкожены в самом файле
ради воспроизводимости с нуля. Никогда не переиспользуйте их в
продакшен-развёртывании.
docker-compose.dev.yml — только dev-инфраструктура¶
Поднимает PostgreSQL (host-порт 5433), Vault dev-режим (8200) и Keycloak
(8080) — без самого сервера/UI, которые предполагается запускать локально
для разработки. Чтобы поднять сервер и UI тоже в Docker:
docker compose -f docker-compose.dev.yml --profile app up.
Вариант 2 — Helm chart (Kubernetes)¶
Доступен Helm-чарт alatyr-demo.
Это демонстрационный/референсный чарт, не подготовленный к продакшену
Как и docker-compose.demo.yml, этот чарт по умолчанию запускает Vault
в dev-режиме (hashicorp/vault:1.17, vault server -dev — in-memory,
без persistent storage backend, без auto/manual unseal), одну реплику
PostgreSQL без задачи резервного копирования и без реплики, и держит
демо-секреты прямо в values.yaml открытым текстом. Он также по
умолчанию включает demoReseed — CronJob, который каждые 4 часа
полностью очищает все таблицы приложения и заново наполняет их
тестовыми данными (reseed/truncate.sql + reseed/seed-dev-data.sql,
по расписанию demoReseed.schedule). Используйте этот чарт как
отправную точку/шаблон для собственного production-чарта, а не как
есть — как минимум, переопределите все значения под secrets: и
поставьте demoReseed.enabled: false, иначе периодическая задача
уничтожит любые реальные данные. См. также Отказоустойчивость и
Расчёт ресурсов — там подробно, что именно в текущей
топологии не готово к продакшен-нагрузке нескольких реплик.
Что разворачивает чарт:
| Компонент | Файл | Примечание |
|---|---|---|
| PostgreSQL | postgres-deployment.yaml, postgres-service.yaml, pvc.yaml |
Один под, PVC по умолчанию 5Gi (values.yaml: postgres.storage.size) |
| Vault | vault-deployment.yaml, vault-service.yaml, vault-init-job.yaml |
Dev-режим; vault-init-job идемпотентно конфигурирует PKI engine + роль alatyr (post-install/post-upgrade Helm hook) |
| Сервер | server-deployment.yaml, server-service.yaml |
1 реплика, читает секреты из Secret (см. ниже), readinessProbe/livenessProbe на /api/v1/version |
| Frontend | frontend-deployment.yaml, frontend-service.yaml, frontend-nginx-configmap.yaml |
nginx + статика Vite |
| Ingress | ingress.yaml |
опционально (ingress.enabled), маршрутизирует /api и /swagger на сервер, остальное — на frontend; ожидает cert-manager (ingress.clusterIssuer) |
| Секреты | secrets.yaml |
Secret из values.yaml: secrets.* (postgres-password, local-jwt-secret, webhook-enc-key, vault-token, local-admin-email, local-admin-password) — обязательно переопределить для не-демо использования |
| Демо-reseed | reseed-configmap.yaml, reseed-cronjob.yaml, reseed-rbac.yaml |
CronJob, включён по умолчанию (demoReseed.enabled: true) — см. предупреждение выше |
Ключевые значения values.yaml: namespace, image.server/image.frontend
(образы <ваш-registry>/alatyr-server/<ваш-registry>/alatyr-frontend —
соберите и загрузите их в свой registry перед деплоем)
+ image.tag, postgres.*, vault.pkiMount/vault.pkiRole/vault.certTTLHours,
server.env.logLevel/server.env.corsOrigins, ingress.*, demoReseed.*,
secrets.*.
helm install alatyr ./alatyr-demo \
--namespace alatyr --create-namespace \
--set demoReseed.enabled=false \
--set server.env.corsOrigins="https://alatyr.your-domain.example" \
--set ingress.host="alatyr.your-domain.example" \
--set secrets.postgresPassword="<сильный пароль>" \
--set secrets.localJWTSecret="$(openssl rand -hex 32)" \
--set secrets.webhookEncKey="$(openssl rand -hex 32)" \
--set secrets.vaultToken="<production Vault token/AppRole>" \
--set secrets.localAdminEmail="admin@your-domain.example" \
--set secrets.localAdminPassword="<сильный пароль>"
Агент¶
Агент — кросс-платформенный CLI-бинарь (Go), который выполняется на
устройстве сотрудника: генерирует ключевой материал в доступном
аппаратном хранилище (TPM 2.0 на Windows/Linux, Secure Enclave на macOS,
либо программный fallback-ключ на Linux при отсутствии TPM), отправляет
CSR на сервер (/enroll), ждёт одобрения администратором в Admin UI и
устанавливает выданный сертификат + Wi-Fi/802.1X-профиль локально.
Собственной привязки к учётной записи сервера агент не требует — он
аутентифицируется enrollment_token устройства, полученным при первом
enroll. Флаги команды alatyr-agent run (--server, --ca-cert,
--poll-interval и т.д.) одинаковы на всех трёх платформах — таблица
приведена в разделе Linux ниже, отличаются только пути
по умолчанию для конфига и state-файла.
Linux¶
Устанавливает исполняемый файл /usr/local/bin/alatyr-agent (или через
deb/rpm), systemd-юниты alatyr-agent.timer/alatyr-agent.service,
alatyr-agent-secretd.service, per-user alatyr-agent-user.service и
конфигурационный файл /etc/alatyr-agent/config.env.
Статически слинкованный бинарь (кроме опционального модуля tpm2-pkcs11),
поддерживает amd64/arm64. Два способа установки:
deb/rpm (тянут TPM/PKCS#11-зависимости автоматически через
recommends):
sudo apt install ./alatyr-agent_<version>_amd64.deb # Debian/Ubuntu
sudo dnf install ./alatyr-agent-<version>-1.x86_64.rpm # Fedora/RHEL
deb/rpm не принимают install-time флаги — параметры задаются после установки
через /etc/alatyr-agent/config.env (0600, KEY=VALUE), до первого
запуска таймера (запускается сразу после установки, далее каждые
10 минут):
sudo tee /etc/alatyr-agent/config.env >/dev/null <<'EOF'
WIFI_CERT_SERVER="https://alatyr.your-domain.example"
CORP_DOMAIN="your-domain.example"
CORP_EMAIL="user@your-domain.example"
EOF
sudo chmod 0600 /etc/alatyr-agent/config.env
sudo systemctl restart alatyr-agent.timer
tgz (install.sh сам определяет и ставит TPM/pkcs11-пакеты через
apt/dnf/yum, --skip-tpm-deps — пропустить):
tar xzf alatyr-agent-linux-<version>.tar.gz -C alatyr-agent
cd alatyr-agent
sha256sum -c SHA256SUMS.txt
sudo ./install.sh \
--server "https://alatyr.your-domain.example" \
--corp-domain "your-domain.example" \
--corp-email "user@your-domain.example"
install.sh ставит бинарь в /usr/local/bin/alatyr-agent, регистрирует
systemd alatyr-agent.timer (загрузка + каждые 10 мин) и
alatyr-agent-secretd.service (постоянный D-Bus secret-agent, отдаёт PIN
для TPM PKCS#11-ключа NetworkManager'у при подключении).
Дополнительно install.sh устанавливает и включает per-user systemd
--user-юнит alatyr-agent-user.service (для корпоративного пользователя,
через loginctl enable-linger + systemctl --user enable --now). Это
постоянный процесс, работающий от имени интерактивного пользователя (не
root/SYSTEM), который выпускает и устанавливает ключ user_mtls и
поднимает аппаратный ssh-agent — подробнее в «Агенты».
Параметры alatyr-agent run (CLI-флаг > env var > config.env):
| Флаг | Env var | По умолчанию | Описание |
|---|---|---|---|
--server/-s |
WIFI_CERT_SERVER |
— | URL сервера Alatyr (обязателен) |
--corp-email/-u |
CORP_EMAIL |
— | Email/UPN пользователя, на который выпускается сертификат (обязателен) |
--state-file |
WIFI_CERT_STATE_FILE |
/var/lib/alatyr-agent/state.json |
Путь к state.json |
--config |
WIFI_CERT_CONFIG |
/etc/alatyr-agent/config.env |
Путь к config-файлу |
--ca-cert |
WIFI_CERT_CA_CERT |
системный CA pool | Custom CA bundle для TLS-проверки сервера |
--poll-interval |
— | 30s |
Частота опроса статуса approval |
TPM 2.0 — soft dependency: без пакета tpm2-pkcs11/libtpm2-pkcs11-1 агент
использует программный fallback-ключ в /var/lib/alatyr-agent/wifi-cert.<serial>.pem
(0600). При production-развёртывании с реальным TPM обязательны все 5
пакетов: tpm2-tools, libtpm2-pkcs11-1, libtpm2-pkcs11-tools, p11-kit,
libengine-pkcs11-openssl (Debian/Ubuntu, аналоги для Fedora/RHEL).
Без libengine-pkcs11-openssl реальный Wi-Fi не заработает
Enroll и выпуск сертификата пройдут нормально даже без этого пакета — ошибка проявится позже и не сразу: реальное Wi-Fi-подключение завершится ошибкой на этапе EAP-TLS. Устанавливайте все 5 пакетов из списка выше, а не только первые четыре.
Диагностика:
systemctl status alatyr-agent.timer alatyr-agent.service alatyr-agent-secretd.service
journalctl -u alatyr-agent.service -f
sudo /usr/local/bin/alatyr-agent status --state-file /var/lib/alatyr-agent/state.json
Деинсталляция: sudo ./uninstall.sh (оставляет state/сертификаты для
аудита) или sudo ./uninstall.sh --purge (полная очистка).
macOS¶
Агент на macOS работает per-user как LaunchAgent, не per-machine
LaunchDaemon — ключ подписи создаётся в Secure Enclave и держится secd
залогиненного пользователя, которого под root-демоном не существует. Каждый
пользователь на одной машине проходит enroll отдельно и получает свой
сертификат.
В отличие от Linux/Windows, готового бинарного пакета «как есть» не
поставляется — организация обязана собрать и подписать .pkg
самостоятельно под свой Apple Developer аккаунт. Идентичность
привязывается к CryptoTokenKit Secure Enclave token extension внутри .app,
который должен быть подписан вашим собственным Developer ID и
нотаризован Apple. Кратко процесс:
- Разово создать в Apple Developer аккаунте организации сертификаты
Developer ID Application (подпись
.app) и Developer ID Installer (подпись.pkg), сгенерировать app-specific password дляnotarytool(нотаризация — обязательная проверка Apple перед распространением вне App Store). - Собрать релиз: скрипт
sign-agent-release.shсWIFI_CERT_SERVER(URL сервера) иCORP_DOMAIN(домен для email-fallback) — компилирует.app, подписывает, нотаризует, упаковывает в.pkg(dist/alatyr-agent-<version>.pkg).SKIP_NOTARIZE=1— для локального теста на собственной машине без отправки на серверы Apple. - Развернуть
.pkgчерез MDM (например, FleetDM — Software → Add Software → выбрать устройства → Install) либо установить вручную.
Ручная установка с параметрами конкретного устройства — через
install-pkg.sh (preseed-файл, читаемый postinstall-скриптом). Сам агент
после установки запускается с теми же флагами alatyr-agent run, что и на
остальных платформах — см. таблицу в разделе Linux:
sudo bash install-pkg.sh \
--pkg dist/alatyr-agent-<version>.pkg \
--server https://alatyr.your-domain.example \
--corp-domain your-domain.example \
--corp-email user@your-domain.example
Email нельзя передать через переменные окружения installer'а
macOS installer не пробрасывает env vars в postinstall-скрипт —
sudo CORP_EMAIL=x installer -pkg ... не работает и молча
откатится на auto-detect (<shortname>@<CORP_DOMAIN> или
LDAP/AD-атрибут, если Mac включён в домен). Задавайте email только
через install-pkg.sh --corp-email или ручной preseed-файл.
Headless-машины без активной GUI-сессии не получат сертификат
.pkg ставится нормально и без активного логина, но сертификат не
выпустится, пока кто-то не залогинится в графическую сессию —
SE-ключ живёт в per-user data-protection keychain, который держит
secd, а secd есть только в GUI-сессии. Это осознанное ограничение
архитектуры, не баг.
Windows¶
Ключ подписи создаётся в TPM 2.0 (per-machine, не per-user, в отличие от
macOS). Готового MSI-инсталлятора нет — пакет для распространения
собирается скриптом build-windows-pkg.sh и представляет собой
подписанный Authenticode zip-архив с PowerShell-скриптами установки
(не MSI/WiX):
alatyr-agent-windows-<version>.zip
├── alatyr-agent-windows-amd64.exe / -arm64.exe
├── install.ps1 / launcher.ps1 / uninstall.ps1
├── alatyr-agent-codesign-cert.crt (публичный сертификат для Trusted Publishers)
└── SHA256SUMS.txt
Сборка требует собственного code-signing сертификата организации
(osslsigncode + RFC 3161 timestamp-сервер) — без него install.ps1
всё равно отработает, но Windows может блокировать неподписанный .exe
политиками AppLocker/WDAC. Ручная установка на целевой машине (от имени
Administrator):
Expand-Archive .\alatyr-agent-windows-<version>.zip -DestinationPath .\wca -Force
Import-Certificate -FilePath .\wca\alatyr-agent-codesign-cert.crt `
-CertStoreLocation Cert:\LocalMachine\TrustedPublisher
.\wca\install.ps1 -Server "https://alatyr.your-domain.example" `
-CorpDomain "your-domain.example" -CorpEmail "user@your-domain.example"
install.ps1:
- Копирует бинарь в
C:\Program Files\AlatyrAgent\alatyr-agent.exeс restrictive NTFS ACL (запись — толькоSYSTEM/Administrators, обычным пользователям — только чтение/исполнение; без этого подмена бинаря пользователем без прав дала бы RCE отSYSTEMна очередном запуске задачи). - Пишет конфиг в
C:\ProgramData\AlatyrAgent\config.env(ACL: толькоSYSTEM+Administrators). - Регистрирует Scheduled Task
AlatyrAgent— запуск отSYSTEMсHighestAvailable(обязательно для доступа к TPM), триггеры: при загрузке + каждые 10 минут, лимит выполнения 10 минут на итерацию. Задача запускается сразу после установки. - Дополнительно регистрирует второй Scheduled Task,
AlatyrAgentUser— logon-triggered, запускается от имени интерактивного пользователя (неSYSTEM), по одному экземпляру на каждого вошедшего пользователя. Выполняет DPAPI token handoff от SYSTEM-процесса и выпуск/установку per-user CNG-ключа (user_mtls) — подробнее в «Агенты».
Флаги alatyr-agent.exe run (--server, --ca-cert, --poll-interval и
т.д.) те же, что и на остальных платформах — см. таблицу в разделе
Linux; отличаются только пути по умолчанию (config.env и
state.json — в C:\ProgramData\AlatyrAgent\).
Развёртывание через FleetDM (или аналогичный MDM с поддержкой скриптов) —
загрузить zip как software package и настроить install-команду,
разворачивающую архив и запускающую install.ps1 с нужными параметрами;
подробности и пример команды — в README.md внутри пакета.
Логи и статус: C:\ProgramData\AlatyrAgent\agent.log,
C:\ProgramData\AlatyrAgent\state.json, история задачи — Task Scheduler →
Library → AlatyrAgent. Деинсталляция — .\uninstall.ps1 (останавливает
и удаляет Scheduled Task и C:\Program Files\AlatyrAgent\; логи/state в
ProgramData остаются для аудита).