Перейти к содержимому

Self-Hosting

Запустите Moira на своей машине через Docker Compose. Основной путь скачивает готовый образ из реестра — клонировать исходники и собирать локально не нужно.

Требования

  • Docker с плагином Compose (docker compose)
  • Публичные docker-compose.yml и .env.example; для обычного пути не нужны сборка исходников, private-репозиторий, CLI SQLite на хосте или отдельный upgrade-скрипт

Быстрый старт

Скачайте актуальные публичные self-host файлы:

Terminal window
MOIRA_FILES=https://raw.githubusercontent.com/moira-mcp/moira/master
curl -fLO "$MOIRA_FILES/docker-compose.yml"
curl -fLo .env.example "$MOIRA_FILES/.env.example"
  1. Создайте конфиг

    Terminal window
    cp .env.example .env

    Для запуска на localhost значения по умолчанию работают без изменений.

  2. Запустите контейнер

    Terminal window
    docker compose up -d

    Compose скачивает ghcr.io/moira-mcp/moira:latest, актуальный публичный релиз, и запускает контейнер.

  3. Откройте веб-интерфейс

    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 и перезапустите контейнер:

Terminal window
EMAIL_PROVIDER=smtp
EMAIL_FROM=moira@example.com
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_REQUIRE_TLS=true
SMTP_USER=your-smtp-user
SMTP_PASSWORD=your-smtp-password

SMTP-аутентификация необязательна, но 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:

Terminal window
read -s ADMIN_PASSWORD
export ADMIN_PASSWORD
docker compose exec -e ADMIN_PASSWORD moira npx tsx scripts/create-admin-user.ts
unset ADMIN_PASSWORD

ADMIN_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. Перед закреплением такого образа остановите внешний трафик, создайте резервную копию базы и выполните преобразование на текущем образе:

Terminal window
docker compose exec moira npm run prepare:account-approval-downgrade -- \
--confirm-block-pending-users

Без аргумента подтверждения команда отказывается работать. В одной транзакции она блокирует каждого ожидающего пользователя через старое поле blocked и отзывает его сессии, API-токены, OAuth-токены и OAuth-согласия. Проверьте выведенные счётчики до остановки текущего контейнера. Не выполняйте откат раньше преобразования: старый образ не умеет его делать. При возврате на версию с подтверждением сначала проверьте каждую преобразованную учётную запись, а затем подтвердите и явно разблокируйте её.

Переменные, зависящие от хоста

Эти три должны указывать на ваш хост и иметь согласованные порты. Значения по умолчанию нацелены на localhost:8080, поэтому для запуска на localhost правки не нужны.

ПеременнаяПо умолчаниюНазначение
MOIRA_HOSTlocalhost:8080Публичный хост (протокол определяется автоматически)
MOIRA_PORT8080Порт хоста, проброшенный в контейнер
STATIC_ARTIFACTS_DOMAINstatic.localhost:8080Домен для размещаемых HTML-артефактов

Для реального хоста или другого порта меняйте все три вместе:

Terminal window
MOIRA_HOST=moira.example.com
MOIRA_PORT=8080
STATIC_ARTIFACTS_DOMAIN=static.example.com

STATIC_ARTIFACTS_DOMAIN обязателен — при пустом значении запуск прерывается.

Автогенерируемые секреты

В режиме self-host они генерируются при первом запуске и сохраняются в <data-dir>/.secrets.env. Оставьте их пустыми в .env:

ПеременнаяСгенерированное значение
BETTER_AUTH_SECRETКлюч шифрования сессий
TELEGRAM_ENCRYPTION_KEYКлюч шифрования учётных данных Telegram
ADMIN_PASSWORDПароль администратора, выводится в логи один раз

Данные для входа администратора выводятся в логи контейнера один раз при первом запуске:

Terminal window
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 приложения:

Terminal window
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/callback
WORKSPACE_GITHUB_APP_INSTALL_URL=https://github.com/apps/<github-app-slug>/installations/new
WORKSPACE_CREDENTIAL_VAULT_KEY=<случайный-64-значный-hex-ключ>
WORKSPACE_CREDENTIAL_VAULT_KEY_VERSION=v1

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

Terminal window
openssl rand -hex 32
docker compose up -d

Origin 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:

Terminal window
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-аутентификацию. Настройку клиента смотрите в Быстром старте.

Обновление и восстановление

Для обычного обновления не требуется искать версию или запускать скрипт из репозитория:

Terminal window
docker compose pull
docker compose up -d
docker compose ps

Если существующий .env создан из старого сломанного шаблона и всё ещё содержит удалённый тег 0.3.5, один раз замените строку перед обновлением:

Terminal window
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-копия сохраняется. После исправления конфигурации или каталога проверьте состояние и повторите запуск:

Terminal window
docker compose logs moira
docker 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 moira
docker compose ps

latest намеренно следует за текущим публичным релизом. Автоматическое восстановление защищает постоянные данные, но не может заменить сам 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 запускает остановленный контейнер обычным способом.

Terminal window
docker compose run --rm moira npm run reconcile -- status
docker 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 -- apply
docker 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-варианта.

Terminal window
RELEASE_VERSION=x.y.z
TARGET_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 остаётся без изменений. Из корня репозитория выполните:

Terminal window
cp .env.example .env
mkdir -p extensions
cp -R examples/extensions/webhook-notify extensions/

В скопированном манифесте замените зарезервированный example.com и в верхнеуровневом permissions.network, и в permissions.network канала коммуникации на точный хост своего эндпоинта. Разрешения ноды и канала независимы. Адрес, получателя уведомлений по умолчанию и остальные значения каждый пользователь заполняет на странице настроек Moira. Затем добавьте адрес runner в .env и включите профиль:

Terminal window
printf '\nMOIRA_EXTENSION_RUNNER_URL=http://moira-extension-runner:9110\n' >> .env
docker compose --profile extensions up -d --build

Профиль собирает runner, монтирует ./extensions в его контейнер только для чтения, ждёт готовности runner и затем запускает Moira. Обычный docker compose up -d runner не запускает.

Runner и Moira загружают каталог расширений при старте. После изменения установленных бандлов:

Terminal window
docker compose --profile extensions up -d --force-recreate --wait moira-extension-runner
docker compose --profile extensions restart moira

Причины отказа и живой каталог можно проверить, не публикуя порт runner:

Terminal window
docker compose --profile extensions logs moira-extension-runner
docker 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):

Terminal window
WORKFLOWS_DIRS=./workflows/production:./my-private-workflows/production

Каталоги объединяются и дедуплицируются по (owner, slug). Поздний каталог переопределяет ранний при коллизии, поэтому каталог, указанный последним, может расширять или перекрывать встроенный. Не задан → только встроенный ./workflows/production. Смонтируйте дополнительный каталог в контейнер (например, через volume в compose), чтобы путь существовал во время выполнения.

Сборка из исходников

Локальная сборка — альтернатива для контрибьюторов, которым нужно изменить образ. В docker-compose.yml закомментируйте строку image: и раскомментируйте блок build:, затем:

Terminal window
docker compose up -d --build

Связанное