Self-Hosting
Запустите Moira на своей машине через Docker Compose. Основной путь скачивает готовый образ из реестра — клонировать исходники и собирать локально не нужно.
Требования
- Docker с плагином Compose (
docker compose) - Публичные
docker-compose.ymlи.env.example; для обычного пути не нужны сборка исходников, private-репозиторий, CLI SQLite на хосте или отдельный upgrade-скрипт
Быстрый старт
Скачайте актуальные публичные self-host файлы:
MOIRA_FILES=https://raw.githubusercontent.com/moira-mcp/moira/mastercurl -fLO "$MOIRA_FILES/docker-compose.yml"curl -fLo .env.example "$MOIRA_FILES/.env.example"-
Создайте конфиг
Terminal window cp .env.example .envДля запуска на
localhostзначения по умолчанию работают без изменений. -
Запустите контейнер
Terminal window docker compose up -dCompose скачивает
ghcr.io/moira-mcp/moira:latest, актуальный публичный релиз, и запускает контейнер. -
Откройте веб-интерфейс
http://localhost:8080Ваш экземпляр также раздаёт эту документацию по адресу
http://localhost:8080/docs/(и/ru/docs/), а MCP-эндпоинт — поhttp://localhost:8080/mcp.
При первом запуске Moira генерирует недостающие секреты и одноразовый пароль администратора.
Конфигурация
DEPLOYMENT_MODE=self-host (по умолчанию) — установка для приватной команды с
открытой регистрацией и подтверждением администратором. Новый пользователь может
посмотреть статус подтверждения и выйти, но до подтверждения не получает доступ к
workflow, API-токенам, OAuth и MCP. Верификация email остаётся отдельной проверкой и
в self-host не обязательна. Недостающие секреты генерируются при первом запуске.
Администратору self-host остаётся доступна страница Пользователи для подтверждения, блокировки и восстановления учётных записей. Сквозное администрирование чужих workflow, исполнений и артефактов, облачная аналитика, операционная панель и инструменты намеренной проверки мониторинга отключены на сервере и не показываются в навигации. Это возможности режима установки, а не только скрытые элементы интерфейса. Политика SaaS включает их через тот же resolver, который используют API и веб-интерфейс. Панель self-host по-прежнему показывает состояние базы данных, определений настроек и сверки управляемых workflow, но не запрашивает и не отображает общие показатели workflow и исполнений всей установки.
Подтверждение новых пользователей
В веб-интерфейсе войдите как администратор, откройте Панель администратора → Пользователи и выберите учётную запись со статусом Ожидает подтверждения. Нажмите Подтвердить учётную запись и подтвердите действие в диалоге. Во время запроса кнопка показывает процесс, после завершения статус меняется на Подтверждён администратором, а страница ожидания пользователя автоматически открывает Moira без повторного входа. На узком экране сначала откройте навигацию Панели администратора кнопкой меню.
Эквивалентная операция API — POST /api/admin/users/:id/approve, а
GET /api/admin/users возвращает время подтверждения. Операция идемпотентна: повтор запроса
после неопределённого ответа не меняет первоначальное время и не создаёт второй переход.
Миграция помечает существующих пользователей подтверждёнными, а начальный администратор
всегда создаётся подтверждённым. Блокировка и верификация email независимы от подтверждения:
заблокированная учётная запись не получает доступ даже после подтверждения.
Настройка почты и восстановление без неё
По умолчанию доставка писем отключена. Чтобы включить письма для сброса пароля и верификации,
настройте стандартный SMTP-сервер в .env и перезапустите контейнер:
EMAIL_PROVIDER=smtpEMAIL_FROM=moira@example.comSMTP_HOST=smtp.example.comSMTP_PORT=587SMTP_SECURE=falseSMTP_REQUIRE_TLS=trueSMTP_USER=your-smtp-userSMTP_PASSWORD=your-smtp-passwordSMTP-аутентификация необязательна, но SMTP_USER и SMTP_PASSWORD задаются только вместе.
Для неявного TLS (обычно порт 465) используйте SMTP_SECURE=true; в остальных случаях
SMTP_REQUIRE_TLS=true требует STARTTLS. Brevo по-прежнему доступен с
EMAIL_PROVIDER=brevo, BREVO_API_KEY и EMAIL_FROM. При неполной или некорректной
конфигурации запуск прерывается. Режим SaaS также не запускается без реального провайдера.
С EMAIL_PROVIDER=none (значение по умолчанию) Moira запускается, а веб-интерфейс честно
сообщает, что восстановление пароля и почтовые действия недоступны. Администратор может
открыть карточку обычного пользователя, выбрать Установить временный пароль и передать
его по отдельному защищённому каналу. Действие отзывает все сессии пользователя, API-токены,
OAuth-учётные данные и согласия. Пользователь входит с временным паролем и обязан сразу его
заменить. Для учётных записей администраторов используйте описанную ниже CLI-процедуру.
EMAIL_PROVIDER=test предназначен только для записи писем в лог в автоматических тестах.
Он не означает настроенную доставку и не сообщает о записанном письме как об отправленном.
Восстановление доступа администратора
В каталоге с docker-compose.yml задайте новый пароль так, чтобы он не попал в историю shell:
read -s ADMIN_PASSWORDexport ADMIN_PASSWORDdocker compose exec -e ADMIN_PASSWORD moira npx tsx scripts/create-admin-user.tsunset ADMIN_PASSWORDADMIN_PASSWORD обязателен. Значения ADMIN_EMAIL и ADMIN_ID по умолчанию —
admin@moira.local и system-admin, а DB_PATH — ./data/moira.db. Для переопределения
добавьте к docker compose exec аргументы -e ADMIN_EMAIL, -e ADMIN_ID или -e DB_PATH.
Команда создаёт или восстанавливает администратора, помечает email и учётную запись
подтверждёнными, снимает блокировку и заменяет credential. Пароль в вывод не попадает.
Откат на версию без подтверждения учётных записей
Старый образ не учитывает approvedAt. Перед закреплением такого образа остановите внешний
трафик, создайте резервную копию базы и выполните преобразование на текущем образе:
docker compose exec moira npm run prepare:account-approval-downgrade -- \ --confirm-block-pending-usersБез аргумента подтверждения команда отказывается работать. В одной транзакции она блокирует
каждого ожидающего пользователя через старое поле blocked и отзывает его сессии, API-токены,
OAuth-токены и OAuth-согласия. Проверьте выведенные счётчики до остановки текущего контейнера.
Не выполняйте откат раньше преобразования: старый образ не умеет его делать. При возврате на
версию с подтверждением сначала проверьте каждую преобразованную учётную запись, а затем
подтвердите и явно разблокируйте её.
Переменные, зависящие от хоста
Эти три должны указывать на ваш хост и иметь согласованные порты. Значения по умолчанию
нацелены на localhost:8080, поэтому для запуска на localhost правки не нужны.
| Переменная | По умолчанию | Назначение |
|---|---|---|
MOIRA_HOST | localhost:8080 | Публичный хост (протокол определяется автоматически) |
MOIRA_PORT | 8080 | Порт хоста, проброшенный в контейнер |
STATIC_ARTIFACTS_DOMAIN | static.localhost:8080 | Домен для размещаемых HTML-артефактов |
Для реального хоста или другого порта меняйте все три вместе:
MOIRA_HOST=moira.example.comMOIRA_PORT=8080STATIC_ARTIFACTS_DOMAIN=static.example.comSTATIC_ARTIFACTS_DOMAIN обязателен — при пустом значении запуск прерывается.
Автогенерируемые секреты
В режиме self-host они генерируются при первом запуске и сохраняются в
<data-dir>/.secrets.env. Оставьте их пустыми в .env:
| Переменная | Сгенерированное значение |
|---|---|
BETTER_AUTH_SECRET | Ключ шифрования сессий |
TELEGRAM_ENCRYPTION_KEY | Ключ шифрования учётных данных Telegram |
ADMIN_PASSWORD | Пароль администратора, выводится в логи один раз |
Данные для входа администратора выводятся в логи контейнера один раз при первом запуске:
docker compose logs | grep -A3 "ADMIN LOGIN"Войдите с ADMIN_EMAIL (по умолчанию admin@moira.local) и выведенным паролем.
Включение подключения GitHub для рабочих пространств
Подключение GitHub для рабочих пространств не связано с социальным входом через GitHub. Оно остаётся отключённым, пока не заданы все корректные значения GitHub App и хранилища учётных данных. Создайте GitHub App, включите истекающие user authorization tokens и «Request user authorization (OAuth) during installation», выдайте ему права на репозитории Codespaces (write), Codespaces lifecycle admin (write), Codespaces metadata (read), Contents (read) и Metadata (read), укажите точный API-путь Moira для callback и URL установки с GitHub slug приложения:
WORKSPACE_GITHUB_APP_CLIENT_ID=<github-app-client-id>WORKSPACE_GITHUB_APP_CLIENT_SECRET=<github-app-client-secret>WORKSPACE_GITHUB_APP_CALLBACK_URL=https://moira.example.com/api/integrations/github/callbackWORKSPACE_GITHUB_APP_INSTALL_URL=https://github.com/apps/<github-app-slug>/installations/newWORKSPACE_CREDENTIAL_VAULT_KEY=<случайный-64-значный-hex-ключ>WORKSPACE_CREDENTIAL_VAULT_KEY_VERSION=v1Создайте отдельный ключ хранилища вне репозитория и поместите результат в незатреканное окружение деплоя:
openssl rand -hex 32docker compose up -dOrigin callback должен совпадать с публичным origin Moira. Публичный callback использует HTTPS и не содержит query или fragment. Используйте client secret, созданный GitHub: placeholder, повторяющиеся символы и другие значения с низким разнообразием отклоняются. Ключ хранилища не генерируется автоматически и должен оставаться неизменным между перезапусками контейнера; после его замены существующие credentials подключения нельзя прочитать.
Если ключ или ciphertext потерян, обычные переподключение и отключение не могут подтвердить удалённый отзыв. Сначала удалите grant приложения Moira GitHub App в настройках GitHub. Затем вернитесь в Настройки → Интеграции → GitHub и выберите Удалить после внешнего отзыва. Подтверждение удаляет нечитаемый локальный ciphertext; не подтверждайте, пока grant виден в GitHub. Если исходные ключ и версия восстановлены, Moira больше не предлагает восстановление для нечитаемого credential. Обычные Переподключить GitHub и Отключить снова доступны; оба действия точно отзывают читаемый предыдущий credential.
Такое же подтверждение внешнего отзыва появляется, если обновление могло вернуть новый credential, который Moira не смогла сохранить или отозвать. Перед подтверждением отзовите весь grant GitHub App; в этом состоянии переподключение и обычное отключение намеренно недоступны.
После выхода контейнера в healthy каждый пользователь открывает Настройки → Интеграции → GitHub, нажимает Подключить GitHub, завершает браузерную авторизацию и устанавливает приложение для нужных личных репозиториев. Авторизация никогда не выполняется через MCP-инструмент или агента. Если настройка отсутствует или credential нужно обновить, пользователь возвращается на этот сайт.
Для создания рабочих пространств и операций агента дополнительно требуются
WORKSPACE_CODESPACES_ENABLED=true и пара коннектора из отключённого по умолчанию профиля Compose:
docker compose --profile workspaces up -dПосле настройки подключения и коннектора аутентифицированный MCP-клиент использует один инструмент
workspace, выбирая операцию полем action: list показывает одобренные репозитории и существующие
пространства, create создаёт постоянный Codespace с личным биллингом для одобренного репозитория, а
exec, stat, search, read, write, apply_patch, upload и download работают внутри него по
workspace_id. stop сохраняет данные репозитория; delete удаляет Codespace
и требует явного подтверждения. Разные чаты и клиенты могут использовать одно пространство; ничего
не удаляется при завершении команды или отключении клиента.
Агент в рабочем пространстве действует как обычный пользователь Codespace: он может читать репозиторий, использовать сеть и читать секреты, настроенные для этого Codespace. Изоляция Moira защищает сервер Moira и других пользователей, а не пространство от агента, которого авторизовал его владелец. Если настройка не завершена, инструменты возвращают безопасную ошибку со ссылкой на эту страницу настроек и не запускают никакой процесс авторизации.
Теми же пространствами пользователи управляют в Настройки → Интеграции → Облачные рабочие пространства: создают пространство для одобренного репозитория, запускают или останавливают его (остановка сохраняет данные репозитория) и удаляют после явного подтверждения. Администраторы открывают Админ → Настройки → Рабочие пространства, чтобы увидеть готовность инстанса (конфигурация, коннектор, очередь согласования, активные пространства и операции относительно лимитов) и приостановить работу глобальным или провайдерским аварийным контролем; приостановка отклоняет новые пространства, запуски и операции агентов и останавливает работающие пространства, ничего не удаляя.
Для мониторинга GET /api/health и эндпоинт MCP /health сообщают состояние готовности
(disabled, misconfigured, control_disabled, connector_unavailable или ready); отключённая
функция считается здоровой, а неверная конфигурация или недоступный коннектор помечают инстанс как
degraded. Health отвечает из кэшированного решения, обновляемого с интервалом согласования, а
проверка коннектора ограничена двумя секундами, поэтому зависший коннектор не подвешивает health. Внутренний порт метрик отдаёт gauge и счётчики moira_workspace_*. Оповещайте, когда
moira_workspace_ready остаётся 0 при WORKSPACE_CODESPACES_ENABLED=true, когда
moira_workspace_connector_available равен 0, когда
moira_workspace_reconciliation_oldest_due_age_seconds превышает несколько интервалов согласования
или когда moira_workspace_rejections_total растёт по кодам квот или занятости.
Отключение запрещает локальное использование до отзыва доступа в GitHub. Если GitHub временно недоступен, страница показывает незавершённый отзыв, а кнопка Отключить повторяет операцию по точной зашифрованной capability; credential не возвращается в браузер или модели.
Подключение MCP-клиента
MCP-эндпоинт — это ваш хост плюс /mcp:
http://localhost:8080/mcpДобавьте его как MCP-сервер в ваш AI-клиент и пройдите OAuth-аутентификацию. Настройку клиента смотрите в Быстром старте.
Обновление и восстановление
Для обычного обновления не требуется искать версию или запускать скрипт из репозитория:
docker compose pulldocker compose up -ddocker compose psЕсли существующий .env создан из старого сломанного шаблона и всё ещё содержит удалённый тег
0.3.5, один раз замените строку перед обновлением:
MOIRA_IMAGE=ghcr.io/moira-mcp/moira:latestДо запуска миграций нового self-host образа startup guard создаёт online backup существующей SQLite
БД и проверяет PRAGMA integrity_check. База вместе с соответствующим prompt-manifest.json
сохраняется в data/.moira-startup-backups/current/, а предыдущие состояния ротируются в
previous-1/ и previous-2/. При настоящем первом запуске БД ещё нет, поэтому backup не создаётся.
В current-слоте хранится persistent-маркер незавершённой инициализации. Если контейнер или хост прерывается до фиксации результата, следующий запуск сначала восстанавливает проверенный slot и только затем создаёт новый backup, поэтому частично мигрированная БД не становится новым baseline. На первом запуске отдельный marker без фиктивной backup-БД фиксирует, что базы раньше не было. После прерывания повторный запуск удаляет только незавершённые новую БД, WAL/SHM и prompt manifest и начинает с чистого состояния; успешная инициализация удаляет marker.
Если инициализация схемы, промптов или workflow завершается ошибкой после записи данных, guard
удаляет WAL/SHM, восстанавливает проверенные БД и manifest, пишет /tmp/init-failed и не запускает
MCP, API и nginx. Recovery-копия сохраняется. После исправления конфигурации или каталога проверьте
состояние и повторите запуск:
docker compose logs moiradocker compose exec -T moira sqlite3 /app/data/moira.db 'PRAGMA integrity_check;'docker compose exec -T moira sqlite3 /app/data/.moira-startup-backups/current/moira.db 'PRAGMA integrity_check;'docker compose restart moiradocker compose pslatest намеренно следует за текущим публичным релизом. Автоматическое восстановление защищает
постоянные данные, но не может заменить сам Docker-образ. Если образ не доходит до startup guard,
БД не мигрировалась. Временно укажите в MOIRA_IMAGE предыдущую версию из
GitHub Releases, выполните docker compose up -d,
а после исправленного релиза вернитесь на latest.
Обновление, изменяющее встроенный workflow, может оставить приостановленное внутри него выполнение
без возможности продолжиться. Старт называет такие выполнения до применения обновления — workflow,
выполнение и ноду, на которой каждое стоит, — поэтому они видны в docker compose logs moira, пока
прежние определения ещё на месте. Предупреждение никогда не останавливает обновление. Выполнение,
ставшее непригодным из-за изменения workflow, можно затем восстановить через
session({ action: 'diagnose', ... }) и session({ action: 'recover', ... }); выполнение, чей
workflow обновление удаляет, восстановить нельзя — возобновляться не на чем, — и строка сообщает,
какой это случай. Отсутствие предупреждения означает, что ни одно приостановленное выполнение не
пострадает.
Когда обнаружение конфликта создало локальный bundle в data/.moira-reconciliation/pending,
выполните его AGENT INSTRUCTIONS через одноразовые Compose CLI-контейнеры. Сам CLI не останавливает
и не перезапускает сервисы и не подменяет snapshot базы. Он использует только локальные файлы — без
--force, MCP, HTTP API и UI-транспорта. Инициализация завершается fail-closed: после восстановления
БД контейнер останавливается, а MCP, API и nginx остаются недоступны. После применения bundle
финальная команда docker compose up -d запускает остановленный контейнер обычным способом.
docker compose run --rm moira npm run reconcile -- statusdocker compose run --rm moira npm run reconcile -- diff --reference owner/slug# Прочитайте previous.json, current.json и incoming.json по выведенным путям.# Запишите revision-bound решение current, incoming или merged для каждого конфликта:docker compose run --rm moira npm run reconcile -- choose \ --reference owner/slug --selection incoming --revision REVISION \ --rationale "Incoming заменяет локальный эксперимент"docker compose run --rm moira npm run reconcile -- applydocker compose up -dДля слияния возьмите incoming.json за основу, перенесите только всё ещё нужное локальное намерение
из previous.json → current.json, проверьте полный merged state через reconcile validate и передайте
его в choose --selection merged --file .... choose меняет только локальный decisions manifest.
Только apply изменяет базу и отказывается работать с неполным или устаревшим manifest.
Необязательный preflight до остановки
Оператор может заранее проверить точный образ на изолированной копии БД, скачав advanced helper из
этого релиза. Это необязательный путь; обычное обновление использует две Compose-команды выше. CLI
sqlite3 на хосте нужен только для advanced-варианта.
RELEASE_VERSION=x.y.zTARGET_IMAGE=ghcr.io/moira-mcp/moira:${RELEASE_VERSION}curl -fLo self-host-upgrade.sh "https://raw.githubusercontent.com/moira-mcp/moira/v${RELEASE_VERSION}/scripts/self-host-upgrade.sh"chmod +x self-host-upgrade.sh./self-host-upgrade.sh preflight "$TARGET_IMAGE"./self-host-upgrade.sh upgrade "$TARGET_IMAGE"Helper сохраняет проверенный snapshot и диагностическую копию в .moira-upgrade/; если замена или
health check завершились ошибкой, используйте ./self-host-upgrade.sh rollback. Advanced-путь
записывает точный образ в .env; чтобы вернуться в обычный release channel, после проверки задайте
MOIRA_IMAGE=ghcr.io/moira-mcp/moira:latest.
Включение расширений
Для расширений нужен checkout исходников: образ сопутствующего runner собирается локально, а опубликованный образ приложения Moira остаётся без изменений. Из корня репозитория выполните:
cp .env.example .envmkdir -p extensionscp -R examples/extensions/webhook-notify extensions/В скопированном манифесте замените зарезервированный example.com и в верхнеуровневом
permissions.network, и в permissions.network канала коммуникации на точный хост своего
эндпоинта. Разрешения ноды и канала независимы. Адрес, получателя уведомлений по умолчанию и
остальные значения каждый пользователь заполняет на странице настроек Moira. Затем добавьте адрес
runner в .env и включите профиль:
printf '\nMOIRA_EXTENSION_RUNNER_URL=http://moira-extension-runner:9110\n' >> .envdocker compose --profile extensions up -d --buildПрофиль собирает runner, монтирует ./extensions в его контейнер только для чтения, ждёт готовности
runner и затем запускает Moira. Обычный docker compose up -d runner не запускает.
Runner и Moira загружают каталог расширений при старте. После изменения установленных бандлов:
docker compose --profile extensions up -d --force-recreate --wait moira-extension-runnerdocker compose --profile extensions restart moiraПричины отказа и живой каталог можно проверить, не публикуя порт runner:
docker compose --profile extensions logs moira-extension-runnerdocker compose --profile extensions exec moira-extension-runner curl -fsS http://127.0.0.1:9110/healthПустой каталог допустим. Health-ответ перечисляет загруженные типы нод и ID каналов коммуникации. Если Moira сообщает о недоступном реестре, проверьте URL, health и логи, затем перезапустите обе службы в показанном порядке. Если отсутствует отдельный вклад расширения, найдите причину отказа его манифеста. Полный контракт манифеста, SDK, разрешений, настроек, редактора, доставки, результатов, ошибок и безопасности описан в Написании расширения.
Добавление собственных workflow-флоу
В образе есть встроенный каталог workflow в ./workflows/production. Чтобы дополнительно
загрузить свои флоу, задайте WORKFLOWS_DIRS — список базовых каталогов каталога через
двоеточие (каждый со структурой flows/<uuid>.json):
WORKFLOWS_DIRS=./workflows/production:./my-private-workflows/productionКаталоги объединяются и дедуплицируются по (owner, slug). Поздний каталог
переопределяет ранний при коллизии, поэтому каталог, указанный последним, может
расширять или перекрывать встроенный. Не задан → только встроенный
./workflows/production. Смонтируйте дополнительный каталог в контейнер (например, через
volume в compose), чтобы путь существовал во время выполнения.
Сборка из исходников
Локальная сборка — альтернатива для контрибьюторов, которым нужно изменить образ.
В docker-compose.yml закомментируйте строку image: и раскомментируйте блок build:,
затем:
docker compose up -d --buildСвязанное
- Быстрый старт - Подключение AI-клиента
- MCP-клиенты - Интеграции с клиентами