Руководство администратора. Комплект работает без интернета: образы лежат в архиве, продукт не пытается выйти наружу, пока вы явно это не разрешите.
Требования
| Что | Минимум |
|---|---|
| ОС | Linux x86_64 |
| Docker | Engine 24+, Compose v2.24+ |
| Процессор, память | 4 ядра, 16 ГБ |
| Диск | 60 ГБ свободно под Docker (данные растут) |
| Сеть | одно имя в DNS заказчика; порты 80 и 443 |
Интернет не нужен ни для установки, ни для работы.
Подлинность комплекта
Комплект подписан ключом выпуска поставщика (ECDSA P-256). Открытый ключ и его отпечаток опубликованы на странице abmpersona.ru/security/bundle и указаны в документах поставки. Отпечаток берите оттуда, а не из комплекта: кто подменил комплект, подменил бы и ключ в нём.
До переноса архива в контур (нужны только openssl и sha256sum; файл <ключ>.pem — действующий открытый ключ со страницы выше, его номер там же; номер подписавшего ключа записан в файле SIGNED_BY комплекта):
``bash openssl pkey -pubin -in <ключ>.pem -outform DER | sha256sum # сверить с опубликованным openssl dgst -sha256 -verify <ключ>.pem \ -signature abm-persona-onprem-<версия>.tar.sha256.sig abm-persona-onprem-<версия>.tar.sha256 sha256sum -c abm-persona-onprem-<версия>.tar.sha256 ``
Обе команды должны ответить Verified OK и OK. Эта проверка — главная для первой установки: install.sh повторяет её, но сам является частью комплекта. При обновлениях проверяет уже установленная система — ключами, закреплёнными при установке.
Что в образах и как это проверено
Образы собирает сборочный сервер поставщика, подписывает — машина правообладателя, и она не верит серверу на слово (images/PROVENANCE.json в комплекте, под подписью):
ClickHouse, Valkey, Caddy) закреплены по digest; их слои в каждом образе сверяются со списком, а digest вы можете сверить с hub.docker.com;
app, training; web: public, static) машина правообладателя собирает заново из того же коммита и сравнивает по хэшу слоя — расхождение означает, что комплект не подписывается;
Next.js (server.js, .next/server) собираются только на сборочном сервере и такой проверкой не покрыты — в PROVENANCE.json у них verified: false. Это честная граница текущей версии.
- базовые образы (
node:20-alpine,python:3.11-slim, PostgreSQL, - слои с кодом приложения (
api: dist, prompts, миграции, shared;ml: - слои зависимостей (
node_modulesиз pnpm,pip,apt) и серверный код
images.lock хранит digest конфига и хэши слоёв каждого образа; установщик сверяет digest конфига из архива до docker load и слои после — это не зависит от типа хранилища Docker на вашем сервере. Сверить самим: docker image inspect -f '{{json .RootFS.Layers}}' accellum-onprem/api:<версия> ↔ images.lock.
Подпись по ГОСТ
Комплект может нести вторую подпись — по ГОСТ Р 34.10-2012 квалифицированным сертификатом поставщика: SHA256SUMS.sgn внутри комплекта и <имя>.tar.sha256.sgn рядом с архивом (CMS, CAdES-BES, DER). Сертификат подписанта лежит в trust/gost/ комплекта и опубликован на той же странице abmpersona.ru/security/bundle.
Проверка до переноса — любым из двух средств:
```bash
КриптоПро CSP: сертифицированное средство, проверяет и цепочку до аккредитованного УЦ;
<отпечаток>.cer — сертификат подписанта со страницы (ставить в хранилище не нужно)
cryptcp -vsignf -detached -dir . -f <отпечаток>.cer abm-persona-onprem-<версия>.tar.sha256
openssl с gost-engine: несертифицированное; подлинность сертификата — по отпечатку с сайта
openssl cms -verify -binary -inform DER -engine gost \ -in abm-persona-onprem-<версия>.tar.sha256.sgn -content abm-persona-onprem-<версия>.tar.sha256 \ -noverify -signer signer.pem -out /dev/null && openssl x509 -in signer.pem -noout -fingerprint -sha1 ```
Установщик проверяет ГОСТ-подпись, если на сервере есть КриптоПро CSP или gost-engine для openssl (openssl engine gost), и называет, чем проверил. Сертификат подписанта он берёт из закреплённого trust/gost/ — ставить его в хранилище КриптоПро не нужно. С КриптоПро он сначала проверяет подпись с цепочкой до УЦ без проверки отзыва (список отозванных сертификатов в закрытом контуре недоступен); если корневой сертификат УЦ не установлен в хранилище (certmgr -inst -store mRoot), проверяет подпись без цепочки и говорит об этом. Если проверить нечем — говорит об этом и продолжает: подпись ECDSA проверяется всегда. Подпись, которая есть, но не сходится, — отказ. Пока квалифицированный сертификат поставщика не оформлен, комплекты выходят без ГОСТ-подписи, и установщик сообщает «ГОСТ-подписи в комплекте нет».
Установка
``bash tar -xf abm-persona-onprem-<версия>.tar cd abm-persona-onprem-<версия> sudo ./install.sh --address abm.example.ru --admin-email it@example.ru \ --key-fingerprint "<отпечаток со страницы или из документов поставки>" \ --org-name "Компания" --org-slug company --tls internal ``
Прежде чем что-либо менять, установщик проверяет, что ключ комплекта совпадает с указанным отпечатком, подпись над списком контрольных сумм верна, а состав комплекта равен подписанному списку (лишний файл — отказ). Затем ключи выпуска закрепляются в /opt/abm-persona/trust/.
Режимы TLS (--tls):
сертификат — /opt/abm-persona/root-ca.crt: раздайте его браузерам сотрудников (групповой политикой или вручную).
/opt/abm-persona/certs/.
адреса укажите в --trusted-proxy (раздел «Адрес клиента и прокси перед установкой»).
internal— сертификат выпускает встроенный центр сертификации. Корневойfiles— ваш сертификат: до запуска положитеtls.crtиtls.keyвoff— обычный HTTP на порту 80, если TLS завершает ваш прокси; его
Порты меняются --http-port и --https-port.
Установщик проверяет подпись и требования, загружает образы, создаёт /opt/abm-persona/.env с новыми ключами (root, 600), применяет миграции, лишает роль приложения прав суперпользователя (иначе изоляция организаций в базе не действует), запускает службы и создаёт первую организацию и её владельца.
Первый вход
``bash sudo cat /opt/abm-persona/owner.txt ``
Там адрес, код организации, почта и пароль владельца. Пароль временный: при первом входе установка требует задать свой (форма «Задайте свой пароль»), и пока он не задан, кабинет и API закрыты; после этого пароль из owner.txt не действует — файл удалите. Установка, обновлённая с версии до 0.9.7, этого не требует (признака «пароль временный» у прежних учётных записей нет) — смените пароль владельца сами. Владелец — администратор установки: ему открыт экран «ИИ-провайдеры». Открытой регистрации в установке нет, и новую организацию в кабинете не создать: организация одна — её создаёт установщик, и лимиты лицензии считаются по всей установке; сотрудников заводит владелец там же — «Добавить участника» (почта, имя, роль); система выдаёт временный пароль и показывает его один раз, передайте его сотруднику — при первом входе система потребует заменить его своим. Забытый пароль сотрудника владелец сбрасывает в списке участников («Сбросить пароль»); число сотрудников ограничено лицензией. Восстановления пароля по почте нет; забытый пароль, в том числе единственного владельца, сбрасывает администратор сервера — см. «Забытый пароль».
Забытый пароль
Пароль сотрудника сбрасывает владелец в кабинете (список участников → «Сбросить пароль»). Если пароль забыл единственный владелец, пароль любой учётной записи установки сбрасывает администратор сервера (с версии 0.9.9):
``bash sudo /opt/abm-persona/reset-password.sh --email owner@example.ru sudo cat /opt/abm-persona/password-reset.txt ``
Команда задаёт новый временный пароль и кладёт его в /opt/abm-persona/password-reset.txt (доступен только root; на экран пароль не выводится) — передайте его человеку лично. При входе система потребует задать свой пароль. Все сессии учётной записи в этой организации завершаются сразу; блокировки входа после неудачных попыток снимаются — учётной записи и всех адресов, сбрасывается и ограничение частоты входа. Если у учётной записи есть другие организации установки, команда предупредит: после входа в них можно переключиться, и сессии там сброс не завершает. В журнале аудита организации («Настройки → Журнал аудита») остаётся запись с действием auth.password.reset_by_server от имени системы. Организаций в установке несколько — укажите код: --org <код>. Отключённой учётной записи пароль не сбрасывается: сначала включите её в кабинете. После входа удалите файл: sudo rm /opt/abm-persona/password-reset.txt.
Адрес клиента и прокси перед установкой
Блокировка входа после неудачных попыток (десять подряд — адрес закрыт на сутки, учётная запись на час), ограничения частоты запросов и журнал аудита считают адрес компьютера пользователя. Его передаёт вход установки (Caddy): api доверяет заголовку X-Forwarded-For только от него (TRUST_PROXY_HOPS: "1" в docker-compose.onprem.yml), а такой заголовок, присланный браузером или скриптом, Caddy заменяет настоящим адресом.
В версиях до 0.9.11 включительно адрес был общим на установку: api видел адрес Caddy, и десять неудачных входов с любого компьютера закрывали вход всем на сутки. До обновления установке 0.9.11 поможет строка в .env:
``bash echo 'TRUST_PROXY_HOPS=1' | sudo tee -a /opt/abm-persona/.env cd /opt/abm-persona && sudo docker compose -f docker-compose.onprem.yml --env-file .env up -d --force-recreate api ``
С версии 0.9.12 значение задаёт сам комплект; строку в .env можно оставить, на результат она не влияет.
Ваш прокси перед установкой (например, TLS завершает ваш балансировщик — --tls off): Caddy видит адрес прокси, и без доверия к нему все, кто за прокси, снова делят один адрес. Назовите адреса своих прокси установщику — от них Caddy примет адрес клиента:
``bash sudo ./install.sh <те же параметры, что при установке> --tls off --trusted-proxy 10.0.0.5 ``
Несколько прокси — через запятую. Повторный запуск без флага сохраняет прежний список, --trusted-proxy none снимает его; вход пересоздаётся сразу, а Caddyfile меняется только после того, как его принял сам Caddy. Указывайте адреса самих прокси, а не подсети рабочих мест: любой компьютер в доверенной подсети может назваться чужим адресом — снять свою блокировку входа или навесить чужую. /0 установщик не принимает, о подсетях шире /24 (IPv6 — /64) предупреждает. Прокси должен передавать адрес клиента в X-Forwarded-For (nginx: proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for). Caddy читает цепочку справа налево и пропускает только перечисленные прокси, поэтому адрес, который клиент сам вписал в начало цепочки, не принимается.
Если в сети Docker нет IPv6, клиенты по IPv6 и запросы с самого сервера приходят к Caddy через прокси Docker — с адреса шлюза Docker, общего для всех них. Шлюз Docker в --trusted-proxy не добавляйте: тогда любой такой клиент сможет назваться чужим адресом.
Снять блокировки входа — reset-password.sh (раздел «Забытый пароль»).
Выход в интернет
Закрыт. Продукт свободно ходит только к своим службам и в вашу сеть (частные адреса: почтовый ящик IMAP, модель ИИ в вашем контуре). Попытка выйти в интернет отклоняется ответом outbound_blocked с названием адреса.
CRM по частному адресу пока не подключается: Bitrix24 проверяет адрес вебхука и отклоняет частные и служебные адреса (защита от подмены адреса, ssrf-guard.ts), а amoCRM работает только с облачным amocrm.ru. См. «Чего пока нет».
Разрешить конкретный адрес:
``bash sudo sed -i 's|^EGRESS_ALLOW_HOSTS=.|EGRESS_ALLOW_HOSTS=api.example.ru,.example.org|' /opt/abm-persona/.env cd /opt/abm-persona && sudo docker compose -f docker-compose.onprem.yml --env-file .env up -d --force-recreate api worker ``
Адрес облачной модели ИИ отдельно разрешать не нужно: администратор включает её на экране «ИИ-провайдеры» с отметкой «данные уйдут за пределы контура», и это отметка и есть разрешение.
Задачи, которым нужен интернет (внешние сигналы и их дайджест, перепроверка по реестрам ФНС, Яндекс Метрика), в установке не запускаются.
Ключи шифрования — на вашей стороне
Ключи, которыми зашифрованы персональные данные, и секреты входа (JWT) могут лежать на диске только запечатанными — главным ключом в вашем хранилище или паролем. При запуске службы распечатывают их в память; в .env и в резервных копиях открытых ключей нет. Вход (Caddy) переменных окружения не получает вовсе, а служба ml файл .env целиком не получает — только свои настройки, перечисленные по именам в docker-compose.onprem.yml; ключи данных и секреты входа до них не доходят.
Режим (--keys) | Где главный ключ | Что нужно при запуске |
|---|---|---|
env | в .env открытым текстом (по умолчанию) | ничего |
vault | Transit в HashiCorp Vault или OpenBao | доступ к Vault (токен или AppRole) |
passphrase | пароль администратора | файл пароля в памяти сервера (/run) |
Vault / OpenBao:
``bash sudo ./install.sh … --keys vault --vault-addr https://vault.example.ru:8200 \ --vault-transit-key abm-persona --vault-role-id <role> --vault-secret-id-file ./secret-id \ [--vault-cacert ./vault-ca.pem] [--vault-namespace ns] ``
Политика в Vault — update на transit/encrypt/<ключ>, transit/decrypt/<ключ>, transit/rewrap/<ключ>. Рекомендуем AppRole с привязкой к адресу сервера (secret_id_bound_cidrs) и коротким сроком токена. Отзыв доступа в Vault — и при следующем запуске службы не распечатают ключи (данные станут нечитаемыми, пока доступ не вернут). После ротации ключа в Vault: sudo /opt/abm-persona/keys.sh rewrap.
Пароль:
```bash sudo ./install.sh … --keys passphrase --passphrase-file ./pass.txt
после каждой перезагрузки сервера:
sudo /opt/abm-persona/keys.sh unlock ```
Потеря пароля — потеря данных. Храните пароль отдельно от сервера. Сменить: keys.sh change-passphrase --new-passphrase-file F. Заменить секреты входа (JWT и защита от перебора) свежими, не трогая ключи ПДн: keys.sh rotate --names JWT_ACCESS_SECRET,JWT_REFRESH_SECRET,BRUTE_FORCE_SECRET — все сотрудники войдут заново.
Перевести уже работающую установку: sudo /opt/abm-persona/keys.sh migrate --to vault … (или --to passphrase). Ключи запечатываются, запечатанное распечатывается и сверяется по отпечатку — и только после этого открытые ключи удаляются из .env. Проверить: sudo /opt/abm-persona/keys.sh check (источник, отпечаток, имена — без значений).
Что это даёт и чего не даёт: защищает от кражи диска, образа сервера и резервных копий; даёт отзыв доступа и журнал обращений (Vault). От полного захвата работающего сервера не защищает — ключи в его памяти.
Модели ИИ
Экран «ИИ-провайдеры» (меню → ИИ-провайдеры): любая модель с OpenAI-совместимым API — vLLM, Ollama, llama.cpp, LM Studio в вашей сети. Зарубежные облачные сервисы ИИ в этой редакции не подключаются; российские облачные — по вашему решению. Почта и телефоны в запросы к модели не попадают.
Лицензия
Лицензия привязана к коду установки и выпускается без интернета, обменом файлами:
``bash sudo /opt/abm-persona/license.sh show # код установки — пришлите его поставщику sudo /opt/abm-persona/license.sh install license.txt ``
То же — на экране «Лицензия» в кабинете администратора. До установки лицензии действует ознакомление 30 дней. За 30 дней до конца срока в кабинете появится предупреждение; после срока — 14 дней льготы, всё работает. Затем отправки лидам, ИИ и добавление нового (компании, импорт, сценарии, сегменты, интеграции) останавливаются; просмотр, выгрузка и правка существующего работают всегда — данные не запираются. Лицензия с чужим кодом установки не устанавливается. Если часы сервера переведены назад больше чем на сутки, лицензия считается недействительной, пока время не исправят (NTP).
Резервные копии
``bash sudo /opt/abm-persona/backup.sh ``
Копия — в /opt/abm-persona/backups/<время>/: PostgreSQL и ClickHouse. .env в копию не входит: храните его отдельно и надёжно — без его ключей персональные данные в копии не расшифровать. Настройте запуск по расписанию (cron) и вынос копий на отдельное хранилище по вашим правилам.
Обновление и откат
``bash tar -xf abm-persona-onprem-<новая-версия>.tar sudo /opt/abm-persona/upgrade.sh "$PWD/abm-persona-onprem-<новая-версия>" ``
Обновление запускает установленная копия: она проверяет подпись нового комплекта ключами, закреплёнными при установке, и только затем передаёт управление его скриптам. Подделанный комплект отклоняется до резервной копии — установка не меняется. Новый ключ выпуска приходит либо в комплекте, подписанном уже доверенным ключом (закрепляется сам), либо — после отзыва прежнего — по отпечатку со страницы, который вы указываете один раз (ниже).
Установке, поставленной до подписи комплектов, отпечаток нужен один раз: sudo ./upgrade.sh --key-fingerprint "<отпечаток>" из каталога нового комплекта.
Перед обновлением делается резервная копия; если что-то пойдёт не так, прежняя версия и базы возвращаются автоматически. Вернуть прежнюю версию вручную:
``bash sudo /opt/abm-persona/upgrade.sh --rollback ``
Вход (Caddy) при обновлении
Обновление переводит на образ Caddy из комплекта и вход установки. Свой Caddyfile установка сохраняет — обновление его не переписывает, поэтому до каких-либо изменений его проверяет Caddy нового комплекта. Если не принимает, обновление останавливается: службы, базы и файлы установки остаются прежними, вход работает как работал, на экране — причина и команда проверки. Исправьте Caddyfile и повторите обновление.
Вход, который до обновления не работал (установка не завершена или вход отключён намеренно), обновление не поднимает. Откат возвращает вход на прежний образ Caddy, если тот принимает нынешний Caddyfile; иначе вход остаётся на новом.
Переход на Valkey при обновлении
С версии 0.9.5 вместо Redis в комплекте Valkey (совместимая замена под открытой лицензией). Данные Redis 7.4 в бинарном виде Valkey не читает, поэтому upgrade.sh при первом обновлении переносит ключи логической копией (очереди, отложенные задачи, сессии, TTL) в новый том valkey_data до пересоздания служб; том redis_data остаётся нетронутым, и --rollback возвращает прежний Redis вместе с прежним описанием служб. Перенос занимает секунды на тысячи ключей; на это время api, worker и ml остановлены.
Сотрудники с версии 0.9.6
До 0.9.6 установка была рассчитана на одного пользователя: регистрация в ней закрыта, а приглашение могла принять только уже существующая учётная запись. С 0.9.6 сотрудников заводит владелец в кабинете (см. «Первый вход»); имеющиеся учётные записи обновление не меняет. Откат на 0.9.5 (--rollback) возвращает базы из копии, снятой перед обновлением: сотрудники, заведённые после обновления, пропадут вместе с остальными изменениями после него.
Отзыв ключа выпуска
Если закрытый ключ выпуска у поставщика утёк, поставщик отзывает его: список отозванных ключей trust/REVOKED приходит внутри следующего комплекта под подписью действующего ключа, а отпечатки отозванных публикуются на странице abmpersona.ru/security/bundle. Установщик при обновлении применяет список: маркер /opt/abm-persona/trust/revoked/<ключ> остаётся навсегда (его не снимают ни обновление, ни откат), и комплект с подписью отозванного ключа отклоняется до резервной копии и до любых изменений — даже если подпись сходится и даже с явным отпечатком.
Если у установки закреплён только отозванный ключ (новый ещё не приходил), действующий ключ принимается по отпечатку со страницы — один раз:
``bash cd abm-persona-onprem-<версия> && sudo ./upgrade.sh \ --key-fingerprint "<отпечаток действующего ключа со страницы>" ``
Это единственный случай, когда upgrade.sh запускается прямо из комплекта: установленная копия новый ключ проверить не может, доверие — по отпечатку, как при первой установке; маркеры отзыва установки при этом действуют. Так же принимает новый ключ и установка версии до 0.9.4.
Отзыв действует и по отпечатку ключа: тот же ключ под другим именем всё равно отклоняется, а указанный вами отпечаток отозванного ключа установка не принимает.
Честные ограничения. Первую установку с комплекта, подписанного утёкшим ключом, отзыв не остановит — у сервера ещё нет ни маркеров, ни списка; единственная защита — отпечаток со страницы, сверенный и со списком отозванных. До прихода отзыва утёкший ключ для установки ещё доверенный: комплект с его подписью, объявляющий отозванным действующий ключ поставщика, установка примет — поэтому поставщик сообщает об отзыве сразу, а вы не ставите комплекты, которых не ждали. Отзыв исполняют скрипты установленной копии, поэтому не откатывайтесь на комплекты старше того, что принёс отзыв.
Отчёт для поддержки
``bash sudo /opt/abm-persona/diag.sh ``
Архив abm-persona-diag-<время>.tar.gz — версии, состояние служб, миграции, очереди, число блокировок выхода наружу, диск, закреплённые и отозванные ключи выпуска, ГОСТ-сертификаты (отпечатки) и чем сервер проверяет ГОСТ-подпись. Персональных данных, ключей и журналов с содержимым запросов в нём нет.
Чего пока нет
Vault — keys.sh rewrap — работает).
адресу.
- Аппаратные модули и ГОСТ (PKCS#11: КриптоПро HSM, Рутокен).
- Ротация ключа персональных данных в запечатанном режиме (ротация ключа
- Прямой SMTP вашего почтового сервера и коробочные Bitrix24/amoCRM по вашему