Справочник по конфигурации — Versola Docs
VersolaVersola/docs
До 1.00.7.1versola.kzGitHub

Справочник по конфигурации

Как auth и central загружают HOCON-конфигурацию, какие переменные окружения читают, все блоки конфигурации с ключами и значениями по умолчанию, правила TLS для Postgres и настройки JVM.

auth (data plane) и central (control plane) при старте читают по одному HOCON-файлу и несколько переменных окружения. Эта страница перечисляет и то и другое по блокам и говорит, какие блоки нужны в продакшене. У edge свой список блоков — см. Конфигурацию edge.

Обычно эти файлы вручную не пишут. versola configure (и Helm chart) генерирует их с помощью versola-tools для разворачиваемого релиза, а секреты оставляет плейсхолдерами ${VAR}. Файлы пересоздаются при каждом configure, поэтому на таргете vps ручная правка теряется; поддерживаемого способа менять отдельные настройки там пока нет. Считайте эту страницу справочником по содержимому сгенерированных файлов.

Как загружается конфигурация

  • Сервис читает HOCON-файл по пути из CONFIG_PATH (в контейнере по умолчанию /app/config/env.conf; образ передаёт его в JVM как -Denv.path). Вместо файла всю конфигурацию можно передать строкой в переменной окружения ENV_CONFIG.
  • Ключи пишутся в kebab-case (maximum-pool-size). Длительности — HOCON-длительности ("60 seconds", 5 minutes).
  • Работает стандартная подстановка HOCON, поэтому ${VAR} и ${?VAR} берут значения из переменных окружения. Сгенерированные файлы используют это для секретов: versola configure разрешает каждый секрет из OpenBao в файлы <service>.secrets.env, которые Compose передаёт контейнеру как окружение, а в файле конфигурации остаётся только плейсхолдер. В Kubernetes те же ключи приходят из Secret (Kubernetes).
  • Синтаксическая ошибка останавливает сервис при старте. HOCON не читает UTF-16: правьте файлы в UTF-8.
  • env обязателен. Значение prod означает продакшен; любое другое считается тестовой средой. Продакшен местами строже (например, TLS для Postgres) — об этом ниже.

Переменные окружения

ПеременнаяПо умолчаниюЗначение
PORT8080Порт приложения.
DPORT8081Порт диагностики: /metrics, /liveness, /readiness. См. Наблюдаемость.
APORT8082Дополнительный внутренний порт приложения. Его использует auth для Account Settings; публичной поверхностью он не является.
MPORT8083mutual-TLS-listener auth. Работает, только если есть блок mutual-tls.
BIND_HOST0.0.0.0Адрес, на котором слушают listener’ы. В Compose-файле vps задан 127.0.0.1.
CONFIG_PATH/app/config/env.confПуть к HOCON-файлу (образы).
ENV_CONFIGнетHOCON строкой; если задана, используется вместо файла.
RUN_MIGRATIONSfalsetrue: применять миграции Flyway при старте. false или не задана: проверить схему и отказаться стартовать на устаревшей. Любое значение, кроме точного true/false, останавливает сервис. Деплои используют versola migrate.
JAVA_OPTSсм. настройки JVMФлаги JVM. Если задать, значения по умолчанию заменяются целиком.
WARMUP_ENABLEDtrueВыполнять прогрев до того, как сервис сообщит о готовности. Строго true или false.
WARMUP_BUDGET_SECONDS20Верхняя граница прогрева; после неё готовность объявляется в любом случае.
HTTP_CLIENT_POOL_KINDfixedПул исходящего HTTP-клиента, общего для всех трёх сервисов: fixed или dynamic. См. Пул исходящего HTTP-клиента. Неверное значение заменяется значением по умолчанию.
HTTP_CLIENT_POOL_SIZE128Соединений на цель. Для dynamic — максимум.
HTTP_CLIENT_POOL_MIN0Только dynamic: сколько соединений держать открытыми в простое.
HTTP_CLIENT_POOL_TTL30sТолько dynamic: как долго пул должен простоять без использования, чтобы сжаться до минимума, например 30s или 2m.
ARGON2_MAX_CONCURRENCYнетТолько auth: переопределяет argon2.max-concurrent в сгенерированном файле.
POSTGRES_POOL_METRICS_INTERVALнетПереопределяет postgres.pool-metrics-interval в сгенерированном файле.

Сгенерированная конфигурация читает и несколько переменных, которые за вас задаёт chart или Compose-файл (например, издателя сертификатов в Kubernetes). Всё остальное, включая секреты, лежит в HOCON-файле и хранилище секретов.

Блоки, общие для всех сервисов

Верхний уровень

КлючОбязателенЗначение
envдаИмя среды; prod включает продакшен-проверки.
configuration-cache-refresh-intervalauth, centralКак часто обновляется кеш конфигурации из central. В сгенерированных файлах: 5 minutes для vps и Kubernetes, 1 minute локально.
otel-exporterнетOTLP gRPC-эндпоинт для трейсов, например http://otel-collector:4317. Если ключа нет, трейсинг выключен. В сгенерированных файлах он закомментирован.

postgres

Все ключи, кроме notifications-url, ssl-root-cert и pool-metrics-interval, обязательны и значений по умолчанию не имеют: так бюджет соединений всех экземпляров можно спланировать относительно max_connections Postgres. Ниже — значения, которые генерирует versola-tools.

КлючГенерируетсяЗначение
urlдля каждого сервисаJDBC URL. Стандартная топология: отдельная база на каждый сервис, то есть у каждого сервиса свои URL, пользователь и пароль. Таргеты vps и local генерируют простейший вариант — одну базу auth со схемой на каждый сервис: ...?currentSchema=auth (или central, edge). Никогда не направляйте два сервиса в одну схему.
userимя ролиРоль базы данных.
password${POSTGRES_PASSWORD}Пароль.
maximum-pool-sizeauth 10, central 15Максимум пула HikariCP.
minimum-idleравен максимумуСколько соединений держать в простое; не больше maximum-pool-size.
connection-timeout30 secondsСколько ждать соединение из пула до ошибки.
max-lifetime30 minutesВремя жизни соединения; держите его меньше любого таймаута сервера или прокси.
leak-detection-threshold60 secondsСоединение, удерживаемое дольше, пишет предупреждение. 0 seconds отключает.
notifications-urlнетПрямой (не через пулер) JDBC URL, только для соединения LISTEN. Если не задан, берётся url.
ssl-root-certнетПуть к CA-bundle для проверки сертификата базы. Если нет — хранилище доверия JVM.
pool-metrics-intervalнетПубликовать метрики пула (db_client_connection_*) с этим интервалом, например 10 seconds. Если нет — не публикуются.

TLS для Postgres

Каждое соединение с Postgres открывается с sslmode=verify-full, если в URL не задан свой sslmode: сертификат должен вести к доверенному CA и совпадать с именем хоста. Это относится и к пулу, и к соединению notifications-url.

  • Чтобы доверять приватному CA, смонтируйте его bundle в контейнер и задайте ssl-root-cert; на таргете vps передайте --postgres-ca <file> в versola configure, и CLI сделает и то и другое. Уже заданный в URL sslrootcert имеет приоритет.
  • URL, который не проверяет сертификат (sslmode=disable, allow, prefer или require, либо ssl=false), пишет предупреждение при старте. При env = "prod" сервис отказывается запускаться.
  • Хосты localhost, 127.0.0.1 и [::1] освобождены от обоих правил. versola-tools пишет sslmode=disable для встроенного локального Postgres и для vps, у которого --postgres-host — loopback; удалённый хост vps остаётся на проверяющем режиме по умолчанию.
  • sslfactory в URL, который может пропускать проверку, считается слабостью так же.

За пулером соединений

central и edge держат соединение, припаркованное на LISTEN: так изменение конфигурации доходит до каждой реплики, а отозванный токен перестаёт приниматься до истечения срока. Пулер в transaction-режиме LISTEN пронести не может. Если url указывает на пулер, задайте notifications-url прямым URL Postgres:

postgres {
  url               = "jdbc:postgresql://pgbouncer:6432/auth?currentSchema=edge"
  notifications-url = "jdbc:postgresql://postgres:5432/auth?currentSchema=edge"
}

При старте сервис проверяет, что получает собственное уведомление, и если нет — отказывается запускаться, называя эту настройку.

auth

Обязательны в продакшене: env, configuration-cache-refresh-interval, security, jwt, central, postgres. Необязательны: bootstrap, par, dpop, argon2, mutual-tls, otp-provider, smtp, cleanup. Сгенерированный файл включает bootstrap, par, argon2, mutual-tls и cleanup.

security

Одиннадцать секретов, все обязательны. Каждый — значение в base64url; сгенерированные плейсхолдеры и длина после декодирования:

КлючПеременная секретаБайт
access-tokens-secretACCESS_TOKENS_SECRET32
client-secrets-secretCLIENT_SECRETS_SECRET16
refresh-tokens-secretREFRESH_TOKENS_SECRET32
auth-codes-secretAUTH_CODES_SECRET32
sessions-secretSESSIONS_SECRET32
passwords-secretPASSWORDS_SECRET16
conversation-cookie-secretCONVERSATION_COOKIE_SECRET32
session-cookie-secretSESSION_COOKIE_SECRET32
user-agent-cookie-secretUSER_AGENT_COOKIE_SECRET32
par-requests-secretPAR_REQUESTS_SECRET32
dpop-nonces-secretDPOP_NONCES_SECRET32

Часть из них защищает хранимые данные и ни в коем случае не должна пересоздаваться; см. Секреты.

jwt

КлючЗначение
issuerСтрока issuer и публичный origin. Генерируется из --auth-url. Токены, discovery-метаданные и проверка DPoP htu используют его, а не заголовок Host.
private-keyПриватный RSA-ключ (PKCS#8 DER, стандартный base64), ${JWT_PRIVATE_KEY}.

central

КлючЗначение
urlАдрес central. auth синхронизирует с ним конфигурацию и ждёт (до двух минут), пока он станет доступен.
secret-keyКлюч, общий для auth и central, ${CENTRAL_SECRET_KEY}.

par

Необязателен. Pushed authorization requests (RFC 9126).

КлючПо умолчаниюЗначение
request-uri-ttl60 secondsВремя жизни request_uri.
max-request-size8192Максимальный размер отправленного запроса в байтах.

dpop

Необязателен. Если блока нет, действуют значения по умолчанию.

КлючПо умолчаниюЗначение
iat-leeway60 secondsДопустимое расстояние между iat proof и текущим временем в обе стороны. Это же окно, в течение которого proof помнится для обнаружения повторов.
nonce-ttl300 secondsСколько принимается выданный сервером DPoP-Nonce.

Нужен ли nonce — настройка тенанта в админ-консоли, а не конфигурации. См. токены с привязкой к отправителю.

mutual-tls

Необязателен. Запускает второй listener на MPORT, который требует клиентский сертификат и обслуживает /token, /introspect, /revoke, /par и /userinfo, а discovery начинает объявлять mtls_endpoint_aliases (RFC 8705 §5). Без блока клиентский сертификат доходит до auth только заголовком, который пробрасывает прокси тенанта.

КлючОбязателенЗначение
certificateдаPEM-путь к сертификату, который предъявляет listener.
private-keyдаPEM-путь к его ключу, незашифрованный PKCS#8.
trusted-certificatesдаPEM-путь к сертификатам CA, по которым проверяются цепочки клиентов. Значения по умолчанию нет намеренно: откат к хранилищу доверия JDK позволил бы любому публичному CA ручаться за клиентов.
external-urlдаАдрес, который клиентам сообщается для этого listener’а (алиас в discovery). Может отличаться от того, где он привязан.

Таргеты vps и Kubernetes генерируют этот блок и стоящие за ним сертификаты (сервис mtls-init на базе step-ca или cert-manager). См. клиентские сертификаты edge.

argon2

Необязателен. Хеширование паролей Argon2id.

КлючПо умолчаниюЗначение
max-concurrent12Максимум одновременных хешей паролей. Каждый на время работы занимает около 19 МиБ кучи, так что худший случай — примерно max-concurrent × 19 МиБ (около 228 МиБ при 12), рассчитано на кучу 512 МиБ по умолчанию. Увеличивайте только вместе с памятью контейнера.

otp-provider

Необязателен, в сгенерированном файле закомментирован. HTTP-эндпоинт, доставляющий OTP-коды (например, SMS).

КлючЗначение
methodHTTP-метод, например POST.
urlЭндпоинт провайдера.
username, passwordНеобязательные учётные данные Basic.
bodyСловарь полей тела запроса; значения могут содержать плейсхолдеры {{phone}} и {{message}}.

smtp

Необязателен, в сгенерированном файле закомментирован. Используется для e-mail OTP и доставки паролей.

КлючЗначение
host, portSMTP-сервер, порт обычно 587.
username, passwordУчётные данные.
fromАдрес отправителя.
subjectТема письма.
start-tlstrue — перевести соединение на STARTTLS.

Без SMTP и OTP-провайдера у продакшен-деплоя нет канала доставки временного пароля; в prod пароль можно только доставить, но не показать на экране.

bootstrap

Необязателен. При первом старте создаёт пользователя-администратора.

КлючЗначение
loginЛогин администратора, по умолчанию admin.
passwordВременный пароль, на vps и в Kubernetes — ${ADMIN_BOOTSTRAP_PASSWORD}. Действует 24 часа; первый вход с ним требует задать новый. Перезапуск auth после истечения устанавливает новый.
admin-user-idUUID администратора. Должен совпадать с bootstrap.admin-user-id у central.

cleanup

Периодическое удаление просроченных строк. Сгенерированный файл перечисляет эти таблицы с размером пачки и интервалом:

Таблицаbatch-sizeintervalkey-column
auth_conversations10005 minutesнет
authorization_codes10005 minutescode
pushed_authorization_requests10005 minutesrequest_uri
refresh_tokens100010 minutesнет
sso_sessions100010 minutesнет
challenge_throttle10005 minutesctid
user_passwords100012 hoursнет
user_agents100010 minutesнет

Неудавшаяся пачка больше не останавливает очистку этой таблицы до перезапуска (исправлено в 0.7.0). Сервис публикует метрики cleanup_*, по которым видно, успевает ли удаление; см. Наблюдаемость.

КлючЗначение
max-threadsРабочих потоков очистки (2).
tables[].table-nameОчищаемая таблица.
tables[].batch-sizeСтрок в пачке (1000).
tables[].intervalКак часто выполняется.
tables[].key-columnНеобязательный столбец для выбора пачек (code, request_uri или ctid у некоторых таблиц).

central

Обязательны в продакшене: env, configuration-cache-refresh-interval, secret-key, client-secrets-secret, auth, user-outbox, postgres. Необязательны: bootstrap, client-certificates, client-certificate-authority.

КлючЗначение
secret-keyКлюч, общий с auth, ${CENTRAL_SECRET_KEY}.
client-secrets-secretAES-ключ, которым central шифрует секреты клиентов, ключи подписи, ключи edge и секреты ресурсов, ${CLIENT_SECRETS_SECRET}. Тот же, что у auth. Никогда не пересоздавайте его.
auth.urlВнутренний адрес auth для его административных вызовов. В сгенерированном файле по умолчанию — публичный URL.
user-outboxКак изменения пользователей передаются в auth: poll-interval (1 second), batch-size (32), lease (1 minute), max-backoff (5 minutes), max-attempts (5). После max-attempts неудач событие переезжает в central.user_outbox_dead и больше не повторяется.

bootstrap

В коде необязателен; сгенерированный файл всегда его включает. Он заполняет базу central один раз, при первом старте на пустой базе. Последующие изменения конфигурации ничего не меняют: правьте объекты в админ-консоли.

КлючОбязателенЗначение
loginдаЛогин администратора.
admin-user-idдаUUID администратора; тот же, что у auth.
redirect-urisдаRedirect URI клиента central-admin. Сгенерированный список содержит <auth-url>/central/admin/ и URL /complete edge.
edgesнетРегистрируемые edge: [{ id, public-key-jwk }].
jwksнетПубличный набор JWK, парный jwt.private-key у auth, ${JWKS_JSON}.
metadataнетНачальный документ метаданных сервера авторизации (эндпоинты, поддерживаемые алгоритмы). Некоторые поля auth вычисляет сам при выдаче документа; request_uri_parameter_supported всегда true (с 0.7.0).
presetsнетПресеты авторизации для входа в админ-консоль: id, description, redirect-uri, post-login-redirect-uri, post-logout-redirect-uri, cookie-domain, cookie-path.
central-urlнетАдрес central.
resource-secretнетСекрет ресурса central, ${CENTRAL_RESOURCE_SECRET}. Если не задан, генерируется.
front-channel-logout-uriнетПублично доступный front-channel logout эндпоинт, обычно <auth-url>/logout/frontchannel.
passkeyдаrp-id и origins[] для passkeys.
auth-additional-urlдаВнутренний адрес listener’а auth на APORT.
auth-resource-secretдаСекрет, общий с этим listener’ом, ${ACCOUNT_RESOURCE_SECRET}. central его сам не генерирует.
utility-clientнетКлиент utils: client-id и либо public-key-jwk (private_key_jwt с DPoP), либо secret. Нужно одно из двух; если заданы оба, побеждает ключ. Заполняется один раз. См. Секреты.
central-admin-mtlsнетcertificate-header и certificate-encoding (urlEncodedPem или base64Der) говорят, где TLS-терминатор пробрасывает сертификат, который edge предъявляет как central-admin (RFC 8705 tls_client_auth). certificate (один PEM с сертификатом и его ключом PKCS#8) необязателен: без него сертификат выпускает сам central через client-certificates (или client-certificate-authority) и отказывается стартовать, если CA не настроен. Таргеты vps и local генерируют блок с заголовком ssl-client-cert и без сертификата. Без блока целиком central-admin создаётся с client_secret, а тенант FAPI 2.0 по умолчанию такое не допускает, и bootstrap пишет предупреждение.

client-certificates

Необязателен. Как central выпускает и продлевает сертификаты клиентов, стоящих за edge. В этом режиме ключа CA у central нет. Настраивается ровно один бэкенд; пока бэкенд не назван, блок считается отсутствующим.

КлючПо умолчаниюЗначение
validity14 daysЗапрашиваемый срок жизни каждого сертификата.
renew-before4 daysСертификат с меньшим остатком продлевается.
check-interval1 hourКак часто проверяются сохранённые сертификаты.
step-caнетБэкенд step-ca: url, root-certificate (PEM-путь), provisioner (имя JWK-провижионера), provisioner-key (путь к JWK-файлу). Генерируется для vps и local.
cert-managerнетБэкенд cert-manager: issuer-name, issuer-kind (ClusterIssuer), issuer-group (cert-manager.io), namespace (собственный namespace пода), api-url, token-path, ca-path, namespace-path. Генерируется для Kubernetes.

client-certificate-authority

Необязателен, только для локальной разработки: ключ CA хранит сам central. certificate и private-key — PEM-пути (ключ — незашифрованный PKCS#8); validity-days при необходимости ограничивает срок. Без него регистрация клиента, которая просит central выпустить сертификат, отклоняется. Везде, кроме локальной разработки, используйте client-certificates.

Порядок запуска

auth и edge при старте синхронизируют конфигурацию с central. Если central ещё не слушает, они ждут до двух минут. Само по себе ожидание заканчивается успехом только с HTTP_CLIENT_POOL_KIND=dynamic. С пулом fixed по умолчанию первый запрос открывает все соединения пула, central их отклоняет, и пул хранит по одному неудавшемуся соединению на слот (по умолчанию 128), так что каждая повторная попытка тратит одно из них, и ожидание не может завершиться успехом, даже когда central уже поднялся. Через две минуты сервис завершается с кодом 1 и полагается на политику перезапуска (restart: unless-stopped в Compose-бандлах, restartPolicy: Always в Kubernetes); перезапущенный процесс строит новый пул и стартует нормально. Ожидайте один перезапуск при холодной установке, где central стартует не первым. versola up запускает central первым и этого избегает. Пока сервис ждёт, /liveness отвечает 200, а /readiness — 503. central, который отвечает и отклоняет запрос (неверный URL, неверный ключ), приводит к ошибке старта за секунды.

Пул исходящего HTTP-клиента

auth, central и edge используют один исходящий HTTP-клиент: вызовы между сервисами и вызовы edge к бэкендам, которые он проксирует. Пул ведётся на цель (схема, хост и порт), поэтому у каждого бэкенда свой пул заданного размера. Выбранный пул один раз логируется при старте (outbound HTTP client pool: ...).

ПеременнаяПо умолчаниюЗначение
HTTP_CLIENT_POOL_KINDfixedfixed: ровно SIZE соединений на цель, все открываются при первом использовании цели и сохраняются. dynamic: от MIN до SIZE, остальные по требованию.
HTTP_CLIENT_POOL_SIZE128Соединений на цель; для dynamic — максимум.
HTTP_CLIENT_POOL_MIN0Только dynamic; не больше максимума.
HTTP_CLIENT_POOL_TTL30sТолько dynamic: пул сжимается обратно до MIN, только если за это время не было ни одной выдачи и возврата соединения. Это время простоя всего пула, поэтому при стабильном трафике лишние соединения остаются открытыми.

HTTP/1.1-соединение обслуживает один запрос за раз, поэтому пул ограничивает пропускную способность пода к одному бэкенду примерно величиной size / задержка бэкенда. Ни один вид пула не падает при исчерпании: запрос ждёт свободное соединение без собственного таймаута, поэтому слишком маленький пул проявляется задержкой, а не ошибками. http_client_active_requests считает исходящие запросы в работе, включая стоящие в очереди, и растёт первым. Размер выбирайте как пиковые запросы в секунду на под, умноженные на p99 задержки бэкенда, с запасом. Пул fixed на 128 открывает 128 соединений к каждому бэкенду, с которым работает под; при многих бэкендах dynamic с малым MIN занимает меньше сокетов, но платит установкой соединения, когда приходит всплеск.

Таблицы состояния входа UNLOGGED

Это один из осознанных компромиссов Versola; полный список таблиц UNLOGGED, цену сбоя и способ вернуть журналирование см. в Компромиссах.

С 0.7.0 таблицы auth_conversations, authorization_codes и pushed_authorization_requests — UNLOGGED: они не пишутся в журнал предзаписи (WAL). В них лежит только состояние входа возрастом в минуты, а их журналирование заставляло базу ждать фиксации WAL. Что за это платится:

  • Штатный перезапуск Postgres сохраняет их строки.
  • Сбой Postgres (kill -9, отказ хоста, потеря питания) их опустошает. Standby их никогда не получает, поэтому после failover они пусты, а восстановление из бэкапа возвращает их пустыми.
  • Теряется только состояние в процессе: пользователи посреди многошагового входа начинают заново, а ещё не использованный код авторизации или отправленный запрос отклоняется, и клиент повторяет попытку. Сессии, токены, согласия и пользователи не затрагиваются.
  • Миграция выполняет ALTER TABLE ... SET UNLOGGED, берёт эксклюзивную блокировку и перезаписывает каждую таблицу. Таблицы небольшие, но запускайте versola migrate при низком трафике: входы на ещё работающей старой версии ждут, пока она идёт.

Время жизни refresh-токена

Время жизни refresh-токена фиксируется при выдаче и больше не продлевается использованием (с 0.7.0). Это не настройка файла конфигурации: у каждого клиента своё refreshTokenTtl в секундах, оно задаётся при регистрации клиента через Central API или админ-консоль. Если не указано, по умолчанию 15552000 (180 дней); релизы до 0.7.0 брали 90 дней и продлевали при каждом использовании.

Заголовки безопасности

Все прикладные listener’ы auth, central и edge (основной, дополнительный, mutual-TLS; но не порт диагностики) добавляют эти заголовки ответа, если обработчик не выставил их сам:

ЗаголовокЗначениеКогда
X-Content-Type-Optionsnosniffвсегда
Referrer-Policyno-referrerвсегда
Permissions-Policycamera=(), microphone=(), geolocation=(), payment=()всегда
Content-Security-Policyframe-ancestors 'none'; base-uri 'none'; object-src 'none'HTML-ответы
X-Frame-OptionsDENYHTML-ответы
Strict-Transport-Securitymax-age=31536000; includeSubDomainsзапросы, пришедшие по https: схема URL, X-Forwarded-Proto: https или mutual-TLS listener

Политики default-src в Content-Security-Policy и form-action нет: они сломали бы логотипы и шрифты тенантов и редиректы на redirect_uri клиента. Ваш прокси, терминирующий TLS, должен пробрасывать X-Forwarded-Proto, иначе HSTS не будет отправляться; includeSubDomains предполагает, что все хосты под доменом работают только по https.

Настройки JVM по умолчанию

Образы auth, central и edge задают JAVA_OPTS с профилем фиксированного размера на Temurin 25, поэтому расход памяти не зависит от того, сколько её у хоста:

-XX:+UseG1GC -Xms512m -Xmx512m -XX:MaxDirectMemorySize=64m -XX:MaxMetaspaceSize=128m
-XX:ReservedCodeCacheSize=64m -Xss512k -XX:NativeMemoryTracking=summary
-XX:+UseCompactObjectHeaders -XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/diagnostics/heap.hprof -XX:+ExitOnOutOfMemoryError
-Xlog:gc*:file=/diagnostics/gc.log:time,uptime,level,tags:filecount=5,filesize=20M
--enable-native-access=ALL-UNNAMED

У edge MaxDirectMemorySize=96m; у auth и central — 64m. Куча — 512 МиБ, фиксированная (-Xms равен -Xmx). Закладывайте около 850 МиБ резидентной памяти на сервис: из этого рассчитан лимит памяти 1 ГиБ в chart. При OutOfMemoryError JVM пишет один дамп кучи (при каждом падении он перезаписывается), завершается, чтобы супервизор её перезапустил, и оставляет ротируемый GC-лог в /diagnostics; оба деплоя монтируют туда том. См. Наблюдаемость.

JAVA_OPTS заменяет строку целиком, поэтому повторите все флаги, которые хотите сохранить. Прежнего значения -XX:MaxRAMPercentage=75.0 больше нет: на таргете vps память контейнеров ничем не ограничена, и процент считался бы от всего сервера для каждой из трёх JVM.

Дальше