Эта страница описывает реальный продакшен-деплой с таргетом vps в versola-cli: Linux-сервер и PostgreSQL, к которому он подключается (нативный на этой же машине либо управляемый или удаленный), на котором CLI запускает сервисы Versola, их хранилище секретов (OpenBao) и реверс-прокси перед ними. Если вы просто хотите попробовать Versola, см. Установку — эта страница про то, как поднять (или передеплоить) настоящий инстанс. Все команды versola отсюда описаны в справочнике CLI.
Что CLI настраивает за вас
На vps versola-cli запускает все, кроме базы данных:
central,auth,edge— Docker-контейнеры сnetwork_mode: host, каждый привязан к127.0.0.1.centralслушает127.0.0.1:28090, а прокси стоит перед ним на127.0.0.1:8090— по этому адресу к нему обращаютсяauth,edgeи админ-консоль, благодаря чемуrolloutзаменяетcentralбез простоя.- OpenBao — хранилище, в котором лежат все секреты. CLI его запускает и при первом запуске сам инициализирует и настраивает.
- Реверс-прокси — официальный образ
nginx, вся конфигурация которого генерируется CLI. Он маршрутизирует ваш домен наauth/edge, отдает админ-консоль по/central/admin/и — если у вас еще нет своего веб-сервера — занимает порты 80/443 и сам получает сертификат Let’s Encrypt.
Что остается на вас:
- PostgreSQL — нативная установка на сервере или управляемый/удаленный сервис, не контейнер. CLI ее не создает и ей не владеет; роль, базу и схемы вы создаете один раз (SQL для роли CLI записывает в файл).
Target vps также запускает небольшой внутренний удостоверяющий центр (step-ca и одноразовый контейнер mtls-init), на котором держится mutual TLS между edge и auth; он работает только на loopback и ничего от вас не требует.
Все это работает как один Docker Compose-проект (versola-vps), поэтому versola status, down и uninstall охватывают весь деплой. По умолчанию каждый сервис работает в одном контейнере; versola replica добавляет копии auth или edge (см. Масштабирование).
Требования
- Linux VPS с Docker и плагином Docker Compose v2.
- PostgreSQL, доступный с сервера. CI Versola работает на PostgreSQL 18; более старые версии не проверялись.
- Нативный на этой же машине, с доступом суперпользователя (
sudo -u postgres psql), чтобы создать роль, базу и схемы Versola; либо - управляемый или удаленный (облачная база, отдельный сервер БД): адрес, доступный с сервера, роль, которая может создавать схемы в своей базе, и, если TLS-сертификат базы подписан CA, которому Java не доверяет по умолчанию, файл сертификата этого CA (PEM). См. Шаг 3 и Шаг 4.
- Нативный на этой же машине, с доступом суперпользователя (
- Домен для Versola (например,
id.example.com) с DNS-записьюA(иAAAA, если у сервера есть IPv6), указывающей на сервер. - Либо свободные порты 80 и 443 (их займет прокси Versola и сам займется TLS), либо ваш собственный веб-сервер на 80/443, который будет пробрасывать домен в Versola — см. Шаг 2.
versola-cli, установленный на самом VPS. Проверка памяти дляvpsчитает/proc/meminfoна той машине, где запущена, а в режимеexternalпрокси слушает только127.0.0.1сервера.- Достаточно свободной памяти:
doctorтребует 1 ГиБ доступной памяти, если Versola уже запущена (передеплой), 3 ГиБ для холодного старта и еще 256 МиБ, если OpenBao не запущен, а также около 4 ГиБ свободного места на диске. JVM каждого сервиса по умолчанию получает фиксированную кучу 512 МиБ (см. Конфигурацию).
Шаг 0 — установка или обновление versola-cli
curl -fsSL https://raw.githubusercontent.com/versolauth/versola-cli/main/install.sh | sh
export PATH="$HOME/.local/bin:$PATH" # установщик не может изменить текущий shell
CLI ставится в ~/.local/bin. Если этой папки еще нет в PATH, строка export делает versola доступной в текущем shell; добавьте ее и в стартовый файл вашего shell (~/.bashrc, или ~/.zshrc для zsh), как подсказывает установщик, чтобы CLI находился и в новых терминалах.
Если CLI уже установлен, versola upgrade проверит последний релиз и заменит бинарник на месте (сборку из исходников, dev, он трогать откажется). Установщик сверяет скачанный файл с checksums.txt релиза. О закреплении версии CLI и поддерживаемых платформах см. справочник CLI.
Шаг 1 — запустите doctor
versola doctor --target vps
Проверяет, что Docker доступен, плагин Compose v2 на месте и свободной памяти и места на диске хватает (пороги — в справочнике CLI). configure/migrate/up делают те же проверки сами, так что шаг необязательный, но показывает полную картину заранее.
Шаг 2 — выберите, как Versola доступна снаружи
Флаг --proxy у configure/bootstrap решает, где слушает прокси Versola.
--proxy nginx (по умолчанию) — Versola занимает 80/443
Для сервера, на котором больше ничего не работает на веб-портах. Прокси слушает 80 и 443; при https:// в --auth-url он сам получает и продлевает сертификат Let’s Encrypt (ACME-модуль самого nginx, без certbot) и перенаправляет HTTP на HTTPS.
- Для TLS
--auth-urlдолжен быть ровноhttps://<домен>— без порта и пути, не IP-адрес и неlocalhost. (Обычныйhttp://тоже работает, но без сертификата — только для тестов.) - DNS уже должен указывать на сервер, а порты 80/443 — быть доступны из интернета; если что-то уже занимает порт,
configureсразу упадет и назовет его. - Сертификаты хранятся в Docker-томе
versola-acme-vps, поэтому передеплой не запрашивает новый. - Для тестового деплоя добавьте
--acme-staging: сертификат придет из staging-среды Let’s Encrypt — браузеры ему не доверяют, зато нет лимитов продакшена.
--proxy external — за вашим веб-сервером
Для сервера, который уже обслуживает другие сайты на 80/443 со своим TLS. Тогда прокси Versola слушает только 127.0.0.1:2821 (обычный HTTP), а ваш веб-сервер пробрасывает на него домен и сам продолжает заниматься TLS. Он должен работать на том же хосте и передавать нужные заголовки — для nginx:
server {
server_name id.example.com;
listen 443 ssl;
# ssl_certificate ... — ваша существующая настройка TLS
client_max_body_size 8m;
location / {
proxy_pass http://127.0.0.1:2821;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
}
}
Host— передается как есть. Versola ему не доверяет: issuer, адреса редиректов иhtuдля DPoP берутся из--auth-url, а не из заголовков запроса.X-Forwarded-For— ему доверяют только от127.0.0.1; Versola восстанавливает из него реальный адрес клиента и использует его для rate limiting.X-Forwarded-Proto— схема, по которой пришел браузер; стандартный заголовок для прокси, терминирующего TLS (сама Versola берет схему из--auth-url).client_max_body_size 8m— админ-консоль загружает темы и ключи; ваш сервер должен пропускать такой же размер тела, как прокси Versola.
Вся маршрутизация Versola (какой путь идет в auth, какой в edge, админ-консоль) — внутри прокси Versola; ваш веб-сервер просто пробрасывает все по домену.
Домен должен резолвиться и с самого сервера (central обращается к auth по этому адресу): без DNS для него central пишет UnknownHostException, а на домене ничего не отвечает, пока не отвечает ваш веб-сервер.
Шаг 3 — configure
versola configure vps 0.7.2 \
--auth-url https://id.example.com \
--postgres-host 127.0.0.1:5432
# добавьте --proxy external для второго варианта из Шага 2
Для управляемой или удаленной базы укажите ее адрес, имя базы и файл CA:
versola configure vps 0.7.2 \
--auth-url https://id.example.com \
--postgres-host db.internal.example.com:5432 \
--postgres-db versola \
--postgres-ca ~/postgres-ca.pem
--postgres-host:host:portбазы. Для кластера берите адрес, который следует за failover (обычно алиас для чтения и записи), а не имя одного узла.--postgres-db: имя базы, по умолчаниюauth. Три сервиса используют ее, каждый в своей схеме.--postgres-ca: PEM-файл с CA, подписавшим сертификат базы. Базу на loopback-адресе не проверяют; все остальные проверяют, и в продакшене сервисы отказываются стартовать, если сертификат не удается проверить (PKIX path building failed). Этим флагом сервисы получают CA. CLI копирует файл в бандл и хранит свою копию рядом со своим состоянием, так что исходный файл после этого не нужен.- Исключение для loopback определяется по тому, что вы написали:
127.0.0.1(илиlocalhost,[::1]) не проверяется, а любое другое имя хоста проверяется, даже если оно указывает на эту же машину. Тогда имя должно входить в subject alternative names сертификата (самоподписанный сертификат нативного Postgres по умолчанию выдан только на имя хоста машины), а самоподписанный или частный CA нужно передать через--postgres-ca. --postgres-dbи--postgres-caтребуютversola-cli0.2.10 или новее иversola-toolsот 0.7.1. Оба флага запоминаются для следующих запусковconfigure,rolloutиsecrets plan; указывайте их снова, только чтобы изменить.
--auth-url должен в точности совпадать с origin, который видит браузер — схема и хост (порт только если он нестандартный, и никогда в режиме nginx). CLI отклоняет пути и query-строки (а хост приводит к нижнему регистру): несовпадение молча ломает редиректы и passkeys.
configure проверяет машину, тянет ghcr.io/versolauth/versola-tools:<version>, чтобы сгенерировать конфигурацию и админ-консоль этого релиза, пишет конфигурацию прокси и разрешает все секреты через OpenBao. Он не запускает ни одного сервиса Versola и не трогает базу — его можно запускать сколько угодно раз. Как и migrate и up, на vps он сначала просит подтверждение; флага --yes для этих запросов нет.
OpenBao настраивается автоматически. При первом запуске configure поднимает контейнер versola-openbao-vps и настраивает его: инициализация с одним ключом распечатки, распечатка, KV v2, аутентификация AppRole и политика, ограниченная секретами Versola. В ~/.versola/openbao/ он хранит два файла:
vps.json— учетные данные AppRole, с которыми CLI читает и пишет секреты.configureпечатает только путь к этому файлу, сами значения — никогда;vps-admin.json— root token и ключ распечатки OpenBao. После каждого перезапуска OpenBao поднимается запечатанным; перед входом (configure,rollout,secrets plan,secrets test,secrets login) CLI сам распечатывает его этим ключом и отправляет ключ только на локальный адрес, аconfigureпересоздает контейнер, если он был остановлен. Сохраните оба файла в надежном месте вне сервера — восстановить их нельзя.
Каждый секрет — ключи подписи, ключи сессий, пароль Postgres, bootstrap-пароль админа — генерируется один раз, хранится в OpenBao и переиспользуется всеми последующими configure. Список секретов приходит с каждым релизом в виде схемы: секрет, появившийся в более позднем релизе, генерируется при обновлении на него, а ключи, от которых зависят ваши данные (ключи подписи, ключи хешей паролей и refresh-токенов, …), генерируются только при первой установке — если такой ключ потом пропадет, configure остановится, ничего не записав, вместо того чтобы молча его заменить. Сами сервисы с OpenBao во время работы не общаются: configure записывает готовые значения рядом со сгенерированной конфигурацией, и OpenBao нужен только на время его запуска.
Хотите вести OpenBao сами? См. Управление OpenBao вручную.
Шаг 4 — создайте роль, базу и схемы Postgres
При первом configure пароль Postgres генерируется, поэтому роль можно создать только после этого запуска. configure пароль не печатает: он записывает SQL, который задает этот пароль роли Versola, в ~/.versola/openbao/vps-postgres-role.sql (файл читается только вами) и печатает команду для запуска:
sudo -u postgres psql < ~/.versola/openbao/vps-postgres-role.sql
Файл создает роль versola_app, если ее нет, а если она есть — задает ей пароль и разрешает вход. В нем лежит верификатор пароля SCRAM-SHA-256, а не сам пароль, поэтому пароль не попадает и в серверный лог Postgres. Нужны psql 10 или новее и POSIX-оболочка (на сервере, не PowerShell). Используйте <, а не psql -f: пользователь postgres не может открыть файл в вашем домашнем каталоге, а ваша оболочка может.
Затем от имени суперпользователя Postgres создайте базу и по одной схеме на сервис:
CREATE DATABASE auth OWNER versola_app;
\c auth
CREATE SCHEMA IF NOT EXISTS auth AUTHORIZATION versola_app;
CREATE SCHEMA IF NOT EXISTS central AUTHORIZATION versola_app;
CREATE SCHEMA IF NOT EXISTS edge AUTHORIZATION versola_app;
Выполняйте по одной команде — блок, в котором смешаны мета-команды psql (\c) и SQL, дает непонятные ошибки разбора. Это самая простая топология: одна база со схемой на каждый сервис, и именно ее генерирует таргет vps (все три URL подключения указывают на одну базу, по умолчанию auth, каждый со своим currentSchema). Чтобы использовать другое имя базы, передайте --postgres-db <name> в configure или bootstrap и подставьте это имя в строки CREATE DATABASE и \c выше. Стандартная топология для крупных установок — отдельная база на каждый сервис: у auth, central и edge своя база и своя история миграций; таргет vps ее не генерирует, URL подключения пришлось бы менять самостоятельно. В обоих случаях не используйте общую схему: каждый сервис хранит историю миграций внутри своей схемы, и два сервиса в одной схеме падают с FlywayValidateException.
Файл записывается только при этом первом запуске; дальше используется пароль, сохраненный в OpenBao.
TLS для Postgres
Каждое соединение сервисов с Postgres использует sslmode=verify-full, если в JDBC URL не указан свой sslmode: сертификат базы должен вести к доверенному CA и совпадать с именем хоста в URL. Если --postgres-host — loopback-адрес (нативный Postgres из этого руководства), сгенерированная конфигурация пишет sslmode=disable, поэтому это важно, когда вы направляете Versola на удаленную базу.
Если сертификат базы подписан CA, которому JVM еще не доверяет, передайте CA-bundle флагом --postgres-ca (Шаг 3). В файле должен быть PEM-сертификат. CLI копирует его в бандл (postgres-ca/ca.crt), монтирует только на чтение в central, auth, edge и контейнер миграций и записывает как postgres.ssl-root-cert в трех конфигурациях, так что versola migrate проверяет базу тем же CA.
URL, который не проверяет сертификат (sslmode=disable, allow, prefer, require или ssl=false), пишет предупреждение при старте, а при env = "prod" не дает сервису запуститься. Loopback-хосты (localhost, 127.0.0.1, [::1]) освобождены и от предупреждения, и от отказа. Полные правила — в разделе Конфигурация.
Управляемый или удаленный Postgres
Суперпользователя нет, поэтому роль и базу создают в консоли или CLI вашего провайдера: создайте пользователя versola_app, который владеет базой (с именем, переданным в --postgres-db). Задайте ему пароль, который сгенерировал configure: это POSTGRES_PASSWORD в auth.secrets.env самого нового бандла в ~/.versola/active/; configure его не печатает. Либо передайте SQL-файл из предыдущего шага в psql, подключенный под административной ролью кластера. Затем создайте схемы от имени этого пользователя:
BUNDLE=$(ls -dt "$HOME"/.versola/active/bundle-* | head -1)
export PGHOST=db.internal.example.com PGPORT=5432 PGDATABASE=versola PGUSER=versola_app \
PGSSLMODE=verify-full PGSSLROOTCERT="$HOME/postgres-ca.pem"
export PGPASSWORD=$(grep '^POSTGRES_PASSWORD=' "$BUNDLE/auth.secrets.env" | cut -d= -f2-)
psql -c "CREATE SCHEMA IF NOT EXISTS auth AUTHORIZATION versola_app"
psql -c "CREATE SCHEMA IF NOT EXISTS central AUTHORIZATION versola_app"
psql -c "CREATE SCHEMA IF NOT EXISTS edge AUTHORIZATION versola_app"
Переменные PG* используют команды psql, pg_dump и pg_restore ниже. Некоторые провайдеры применяют новый пароль роли с задержкой в несколько секунд, особенно за пулером соединений: password authentication failed сразу после смены стоит повторить один раз.
Пулер в transaction-режиме не может нести соединение LISTEN, которое нужно central и edge, а CLI не генерирует postgres.notifications-url. Направьте --postgres-host на прямой (не через пулер) адрес или см. Конфигурацию.
Шаг 5 — бэкап базы (при передеплое)
Миграции нельзя откатить. При первой установке бэкапить еще нечего; перед каждым следующим migrate снимайте дамп:
(umask 077; sudo -u postgres pg_dump -Fc auth > ~/versola-backup-$(date +%Y%m%d-%H%M%S).dump)
# управляемая или удаленная база, с переменными PG* из Шага 4:
(umask 077; pg_dump -Fc > ~/versola-backup-$(date +%Y%m%d-%H%M%S).dump)
pg_dump работает от postgres, но пишет в stdout, поэтому файл создает ваш собственный shell — в вашей домашней папке, от вашего имени и с доступом только для вас (umask 077: в дампе хеши паролей и зашифрованные секреты). Храните копию где-то надежно, а не только на сервере.
Шаг 6 — migrate
versola migrate
Применяет миграции каждого сервиса (auth, central и edge владеют каждый своей схемой) через один одноразовый контейнер, в котором есть миграции всех трех сервисов и который завершается по окончании. Ни один сервер не запускается. Запуск записывается в ~/.versola, и status его показывает. Сами сервисы при старте миграции не применяют — они проверяют схему и отказываются стартовать на устаревшей.
Также доступно:
versola migrate --service auth # мигрировать по одному сервису
versola migrate --dry-run # проверить без применения
С 0.7.0 миграция auth делает таблицы auth_conversations, authorization_codes и pushed_authorization_requests UNLOGGED. Она берет эксклюзивную блокировку и перезаписывает эти небольшие таблицы, поэтому входы на работающей старой версии ждут, пока она идет; запускайте migrate при низком трафике. После сбоя Postgres незавершенные входы и неиспользованные коды авторизации теряются, и пользователи входят заново; сессии и refresh-токены не затрагиваются. См. Конфигурацию.
--dry-run подключается к настоящей базе и перечисляет миграции, которые были бы применены; ничего не применяет и подтверждения не спрашивает. Dry-run выполняет образ versola-tools настроенной версии. В релизах до 0.6.2 включительно он сообщает о миграциях, которые просто еще не применены, как об ошибке проверки (Detected resolved migration not applied to database). Это ошибка тех релизов, а не вашей базы; обычный versola migrate применяет миграции нормально. Исправление вышло в 0.7.0.
Шаг 7 — up
versola up
Запускает стек и ждет, пока он реально начнет отвечать: сначала central (auth и edge синхронизируют с ним конфигурацию), затем фронт прокси перед central (по этому адресу к нему обращаются auth и edge), затем auth и edge; в конце ждет, пока заработает весь прокси, и проверяет, что запрос через него доходит до auth. Сам central стартует только после того, как step-ca и одноразовый контейнер mtls-init выпустят сертификаты, которые он читает при запуске (0.7.1 и новее); без них он завершается.
Если auth или edge все же стартуют раньше, чем central начнет слушать, они ждут его две минуты, завершаются с кодом 1, и Docker их перезапускает (restart: unless-stopped); перезапущенный процесс стартует нормально. versola up этого избегает, запуская central первым.
В режиме nginx с HTTPS, если сертификат не выпустился примерно за две минуты (DNS еще не обновился, порт 80 недоступен), up выводит предупреждение, а не падает — сервисы подняты, а nginx продолжает попытки получить сертификат; смотрите docker logs versola-proxy.
При успехе печатает адрес, логин админа и файл с ADMIN_BOOTSTRAP_PASSWORD. Этот пароль временный, действует 24 часа: при первом входе с ним система попросит задать постоянный. Если он истек до входа, перезапустите auth (docker restart versola-auth) — появится новый на 24 часа. В режиме external up также напомнит направить ваш веб-сервер на 127.0.0.1:2821.
Или все сразу: bootstrap
versola bootstrap vps <version> --auth-url … --postgres-host … [--proxy external] выполняет Шаги 3, 6 и 7 за один раз. Если при первом запуске генерируется пароль Postgres, он останавливается перед миграциями (с ненулевым кодом выхода), чтобы вы выполнили SQL из Шага 4, — затем продолжите versola migrate и versola up.
Шаг 8 — проверка
versola status
Deployed version: 0.7.2 (target: vps)
Migrations applied: 2026-10-14 17:11:51
Replicas: auth x1 (slot 1), edge x1 (slot 1)
NAME IMAGE … STATUS
versola-auth ghcr.io/versolauth/versola-auth:0.7.2 … Up 2 minutes
versola-central ghcr.io/versolauth/versola-central:0.7.2 … Up 3 minutes
versola-edge ghcr.io/versolauth/versola-edge:0.7.2 … Up 2 minutes
versola-openbao-vps openbao/openbao:2.5.4 … Up 10 minutes
versola-proxy nginx:1.30-alpine … Up 1 minute
(Таблица — это docker compose ps деплоя, здесь в сокращенном виде; в ней есть и versola-step-ca.)
Затем снаружи:
AUTH_URL=https://id.example.com # ровно тот --auth-url, что передавали в configure
curl -s -o /dev/null -w "%{http_code}\n" "$AUTH_URL/.well-known/openid-configuration" # 200
и войдите в админ-консоль по <auth-url>/central/admin/, прежде чем считать деплой завершенным.
Передеплой
Переход на другую версию — те же три шага с новым номером версии и теми же флагами, что при первом деплое: configure не запоминает --auth-url, --postgres-host, --proxy, --acme-staging и --setup-openbao (а --postgres-db и --postgres-ca хранит). В частности, не забудьте --proxy external, если использовали его: без него прокси вернется в режим nginx по умолчанию, и configure остановится на портах 80/443 вашего веб-сервера.
До 1.0: Versola не гарантирует совместимость до версии 1.0.0. Конфигурация, схема базы данных и API могут меняться между релизами 0.x без пути миграции. Перед обновлением сделайте резервную копию базы.
Руководств по обновлению между релизами 0.x нет. Прочитайте release notes версии, на которую переходите, и учтите, что база, созданная более старым релизом, может не мигрироваться: в 0.7.0 миграции схемы были объединены («сплющены»), поэтому база, созданная более ранним релизом, на месте не обновляется, а 0.7.x требует чистой базы. Считайте переход между версиями 0.x передеплоем, отменить который можно только из бэкапа.
versola upgrade # держите CLI свежим
# бэкап базы (Шаг 5)
versola secrets plan vps <new-version> # какие секреты configure оставит, создаст или на каких остановится
# уберите --proxy external, если первый деплой был в режиме nginx по умолчанию
versola configure vps <new-version> --auth-url https://id.example.com --postgres-host 127.0.0.1:5432 --proxy external
versola migrate
versola up
configure заново генерирует конфигурацию, прокси и админ-консоль из этого релиза; секреты берутся из OpenBao, а если секрет, от которого зависят сохраненные данные, выглядит потерянным, configure останавливается и ничего не записывает (см. Секреты). versola secrets plan показывает, ничего не меняя, какие секреты будут оставлены или созданы. configure и migrate не трогают работающие сервисы, поэтому старая версия продолжает обслуживать запросы, пока идут миграции, — перерыв только на время, пока up пересоздает контейнеры. Из этого же следует, что миграция должна работать со схемой, которую ожидает старая версия, пока она выполняется; Versola этого не проверяет. Если у auth или edge больше одной реплики (versola replica add), configure откажется — используйте versola rollout ниже.
Без остановки: versola rollout
С versola-cli 0.3.1 или новее versola rollout <version> --assume-compatible заменяет работающую версию по одной реплике, а не пересоздает все сразу: готовит новую версию рядом со старой, применяет миграции, переводит central через временную вторую реплику (админ-консоль остается доступной), затем заменяет каждую реплику auth и edge за временной дополнительной репликой. --dry-run показывает план и ничего не меняет; если команду прервали, запустите ее же снова; versola rollout --abort возвращает предыдущую версию, не пересоздавая реплики, которые с нее не уходили. --assume-compatible — ваше подтверждение, что миграции аддитивные и работающая версия справляется с новой схемой: релизы до 1.0 этого не обещают, поэтому сначала прочитайте release notes. Секреты новой версии он проверяет так же, как configure, а перед запуском временной реплики проверяет свободную память (около 1,13 ГиБ) и запас соединений Postgres. --no-surge обходится без дополнительной реплики; central тогда перезапускается на месте — так же, как при первом rollout развертывания, сделанного до того, как прокси встал перед central, — и админ-консоль недоступна, пока он не будет готов. Пока rollout не завершен, configure, up и replica отказываются работать. Перед запуском сделайте бэкап базы (Шаг 5) и скопируйте ~/.versola/active/state.json. Подробности, проверки и короткие перерывы, которые у него остаются, — в README versola-cli.
Откат
Пока versola rollout не завершен, versola rollout --abort возвращает предыдущую версию (миграции и секреты остаются). Остальная часть раздела — про завершенный rollout и про схему, на которой предыдущая версия работать не может.
Миграции необратимы: down-миграций нет, и отменить миграцию можно только восстановлением дампа из Шага 5. Сможет ли старая версия работать на новой схеме, в 0.x не гарантируется; не рассчитывайте на это.
Чтобы вернуться, восстановите базу до запуска предыдущей версии — никогда не запускайте ее на схеме, которую понимает только новый релиз:
versola down # во время восстановления ничего не должно писать в базу
sudo -u postgres psql -c "DROP DATABASE auth;"
sudo -u postgres psql -c "CREATE DATABASE auth OWNER versola_app;"
sudo -u postgres pg_restore -d auth < ~/versola-backup-<timestamp>.dump # файл открывает ваш shell, а не postgres
# уберите --proxy external, если первый деплой был в режиме nginx по умолчанию
versola configure vps <previous-version> --auth-url https://id.example.com --postgres-host 127.0.0.1:5432 --proxy external
versola migrate # ничего не сделает: в дампе уже предыдущая схема
versola up
versola down останавливает и OpenBao, который работает в том же Compose-проекте; следующий configure запустит и распечатает его снова. Если нужен предыдущий CLI, поставьте его со страницы релизов. В управляемой или удаленной базе нельзя удалить базу, к которой вы подключены, а суперпользователя нет. Вместо этого удалите три схемы Versola (остальные схемы этой базы останутся) и восстановите дамп: он пересоздает схемы.
versola down
psql -c "DROP SCHEMA auth CASCADE; DROP SCHEMA central CASCADE; DROP SCHEMA edge CASCADE;"
pg_restore --no-owner -d "$PGDATABASE" < ~/versola-backup-<timestamp>.dump
versola configure vps <previous-version> --auth-url https://id.example.com --postgres-host db.internal.example.com:5432
versola migrate
versola up
Если вы добавляли реплики auth или edge, сначала уберите их (versola replica remove auth|edge <n>) — пока у сервиса больше одной реплики, configure откажется. Все, что было записано между дампом (Шаг 5) и откатом, теряется — поэтому дамп снимают прямо перед migrate.
Масштабирование
versola replica add <auth|edge> [count] запускает дополнительные копии auth или edge за реверс-прокси Versola, который распределяет между ними запросы; versola replica remove останавливает их. central не реплицируется, у сервиса может быть не больше 9 реплик. Деплой должен быть уже запущен (versola up); число реплик запоминается, поэтому versola up поднимет те же реплики. Подробности и флаги — в справочнике CLI.
Управление OpenBao вручную
Если у вас своя схема работы с OpenBao, передайте --setup-openbao в configure/bootstrap: тогда CLI никогда не обращается к admin API OpenBao, а настройку и сохранение учетных данных AppRole вы делаете сами. Распечатка после перезапуска тогда тоже на вас.
Порядок такой: один раз выполните versola configure vps … --setup-openbao — он запустит контейнер versola-openbao-vps и остановится с ошибкой «no OpenBao credentials stored», так и должно быть, — выполните шаги ниже, сохраните учетные данные через versola secrets login и снова запустите тот же configure. TLS на этом OpenBao выключен (он слушает только 127.0.0.1:8200), но CLI bao по умолчанию ходит по https, поэтому каждой команде нужен BAO_ADDR:
# 1. Инициализация — сохраните ОБА напечатанных значения; восстановить их нельзя.
docker exec -it -e BAO_ADDR=http://127.0.0.1:8200 versola-openbao-vps \
bao operator init -key-shares=1 -key-threshold=1
# 2. Распечатка — снова после каждого перезапуска контейнера.
docker exec -it -e BAO_ADDR=http://127.0.0.1:8200 versola-openbao-vps \
bao operator unseal <ключ распечатки>
# 3–4. KV v2 и AppRole.
docker exec -it -e BAO_ADDR=http://127.0.0.1:8200 -e BAO_TOKEN=<root token> versola-openbao-vps \
bao secrets enable -path=secret kv-v2
docker exec -it -e BAO_ADDR=http://127.0.0.1:8200 -e BAO_TOKEN=<root token> versola-openbao-vps \
bao auth enable approle
# 5. Политика, ограниченная секретами Versola.
docker exec -i -e BAO_ADDR=http://127.0.0.1:8200 -e BAO_TOKEN=<root token> versola-openbao-vps \
bao policy write versola-vps - <<'EOF'
path "secret/data/versola/vps/*" {
capabilities = ["create", "read", "update"]
}
EOF
# 6. Роль AppRole, привязанная к ней (долгоживущие учетные данные для автоматического инструмента).
docker exec -it -e BAO_ADDR=http://127.0.0.1:8200 -e BAO_TOKEN=<root token> versola-openbao-vps \
bao write auth/approle/role/versola-vps \
token_policies="versola-vps" token_ttl=1h token_max_ttl=4h \
secret_id_ttl=0 token_num_uses=0
# 7. Учетные данные, которые нужны CLI.
docker exec -it -e BAO_ADDR=http://127.0.0.1:8200 -e BAO_TOKEN=<root token> versola-openbao-vps \
bao read auth/approle/role/versola-vps/role-id
docker exec -it -e BAO_ADDR=http://127.0.0.1:8200 -e BAO_TOKEN=<root token> versola-openbao-vps \
bao write -f auth/approle/role/versola-vps/secret-id
Затем сохраните их — secret ID запрашивается скрытым вводом, поэтому не попадает в историю shell:
versola secrets login vps http://127.0.0.1:8200 <role-id>
Пишете политику на Windows? Сохраните HCL-файл в кодировке ASCII, а не в UTF-8 по умолчанию — BOM ломает парсер OpenBao с ошибкой
illegal char at 1:1. Создайте файл локально, скопируйте его черезdocker cpи выполнитеbao policy write versola-vps /путь/внутри/контейнера.hcl.
Изменение сохраненного секрета
Секреты лежат в secret/versola/vps/{auth,central,edge}; ключ клиента utils хранится отдельно, в secret/versola/vps/utils. Что защищает каждый секрет, какие из них нельзя ротировать и как configure обращается с сохраненными значениями — см. Секреты. Используйте bao kv patch — kv put заменяет весь путь и сотрет остальные ключи — с root token из ~/.versola/openbao/vps-admin.json:
docker exec -it -e BAO_ADDR=http://127.0.0.1:8200 -e BAO_TOKEN=<root token> versola-openbao-vps \
bao kv patch -mount=secret versola/vps/auth SOME_KEY='<значение>'
Существующее значение в OpenBao всегда побеждает, так что именно так его и заменяют. Затем выполните versola configure vps <текущая-версия> с вашими обычными флагами и versola up. POSTGRES_PASSWORD общий для всех трех сервисов и должен совпадать в auth, central и edge — если значения расходятся, configure откажется продолжать.
Не каждый секрет можно так сменить. Пары ключей подписи и ключи, защищающие сохраненные данные, — PASSWORDS_SECRET (хеши паролей), REFRESH_TOKENS_SECRET и EDGE_TOKEN_ENC_KEY (refresh-токены), CLIENT_SECRETS_SECRET (секреты клиентов), CENTRAL_RESOURCE_SECRET — при замене делают эти данные нечитаемыми: пользователи не смогут войти, токены и сессии будут отклонены. Меняйте их только там, где данные не жалко потерять. Закрытый ключ клиента utils лежит отдельно, в secret/versola/vps/utils.
Решение проблем
configure падает, потому что порт 80 или 443 занят. Там уже что-то слушает (обычно веб-сервер). Либо остановите его, либо используйте --proxy external за ним.
OpenBao не поднимается после перезагрузки или запечатан. Работающие сервисы это не затрагивает — OpenBao им во время работы не нужен. Следующая команда, которая входит в него (configure, rollout, secrets plan, secrets test, secrets login), распечатает его сохраненным ключом, а configure пересоздаст контейнер, если он был остановлен. С --setup-openbao сохраненного ключа нет: распечатайте его сами (bao operator unseal).
«container name already in use». Контейнер с одним из фиксированных имен Versola существует в другом Compose-проекте. Проверьте через docker ps и docker compose ls, остановите и удалите эти контейнеры по имени и повторите запуск.
502 через ваш веб-сервер (режим external). Проверьте, что прокси отвечает локально: curl -H 'Host: id.example.com' http://127.0.0.1:2821/.well-known/openid-configuration. Если отвечает — проблема в пробросе вашего веб-сервера; если нет — смотрите versola status и docker logs versola-proxy.
Админ-консоль отдает 404 сразу после up. Обновите страницу — первый запрос сразу после старта может попасть на еще прогревающийся сервис.
Сервис уходит в crash-loop с PKIX path building failed (или certificate_unknown). Сертификат базы подписан CA, которому Java не доверяет, а сервисы его проверяют. Передайте CA флагом --postgres-ca <файл> в configure (см. Шаг 3) и снова запустите versola up. Не правьте сгенерированные файлы вручную: следующий configure их заменит.
password authentication failed сразу после смены пароля роли. В управляемом Postgres новый пароль может применяться несколько секунд; повторите один раз. Если не проходит, пароль в базе не совпадает с POSTGRES_PASSWORD в OpenBao: задайте в базе именно это значение.
up предупреждает, что сертификат не выпущен (режим nginx). Let’s Encrypt должен достучаться до сервера по порту 80 под вашим доменом. Проверьте, что DNS-запись указывает на публичный IP сервера, что CDN или прокси перед записью (например, «проксируемая» запись Cloudflare) выключен на время выпуска сертификата и что файрвол пропускает 80 и 443. Сначала попробуйте --acme-staging, чтобы не упереться в лимиты продакшена.
configure останавливается с the secrets plan has N problem(s). Ничего не записано. Запустите versola secrets plan vps <version>, чтобы увидеть, какой секрет и почему: lost — в OpenBao нет ключа, от которого зависят ваши данные (восстановите из бэкапа); unknown-state — в OpenBao есть секреты, о которых у этой машины нет записи (обычно uninstall оставил том OpenBao или деплоили с другой машины), и среди них не хватает ключа, от которого зависят данные (для действительно чистой установки удалите том или перечислите недостающие секреты в --generate-missing, если новые значения допустимы); vault-empty-with-state — с этой машины уже деплоили, но OpenBao пуст (тот ли это OpenBao?). --generate-missing NAME,... разрешает сгенерировать названные секреты — только если старое значение потеряно навсегда.
image not found. Проверьте формат версии — у тегов нет v в начале: <version>, а не v<version>. Опубликованные версии — на странице пакета versola-tools.
Дальше
- Справочник CLI — все команды и флаги с этой страницы.
- Секреты — что лежит в OpenBao и как это ротировать.
- Наблюдаемость — health-эндпоинты, метрики и логи работающего стека.