11 KiB
Deployment
1. Назначение документа
Этот документ фиксирует platform-agnostic модель деплоя проекта.
Он отвечает на вопросы:
- какие deployment artifacts должны быть в репозитории;
- как проект должен запускаться в production-like окружении;
- как routing должен работать через reverse proxy;
- что должен делать CD pipeline.
Документ не привязан к конкретному hypervisor, cloud provider, типу VM или домашней инфраструктуре.
Практический post-deploy smoke checklist вынесен отдельно в deploy-and-staging-smoke.md.
Отдельный release checklist именно для открытой редакции вынесен в community-release-checklist.md.
2. Базовая модель деплоя
Для MVP принимается контейнерная модель:
admin-api,mcp-serverиuiупаковываются в контейнеры;PostgreSQLзапускается как отдельный контейнер;- сервисы запускаются через
docker-compose; - перед приложением находится reverse proxy;
- CI проверяет качество, CD доставляет и перезапускает сервисы.
3. Что должно быть в репозитории
В проекте должны существовать:
Dockerfileдляapps/admin-api;Dockerfileдляapps/mcp-server;Dockerfileдляapps/uiили отдельный production build flow для UI;deploy/community/docker-compose.ymlкак canonical Community deployment manifest;deploy/community/.env.exampleкак canonical Community runtime env template;docker-compose.ymlи root.env.exampleтолько как local development convenience layers, а не как future private delivery boundary;.gitea/workflows/ci.yml;.gitea/workflows/deploy.yml;- примеры reverse proxy конфигураций.
Рекомендуемое стартовое распределение портов:
ui->3000admin-api->3001mcp-server->3002
4. Production-like runtime состав
Минимальный набор сервисов:
uiadmin-apimcp-serverpostgres- optional
valkeyчерез compose profilecache
Persistent data:
- volume для
postgres; - volume или bind mount для
artifact storage.
5. Рекомендуемая routing model
Под одним доменом:
/->ui/api/admin/->admin-api/mcp/->mcp-server
Это позволяет:
- централизовать TLS;
- не плодить поддомены без необходимости;
- держать demo URL простым;
- использовать один reverse proxy для UI, API и MCP.
6. Требования к reverse proxy
Reverse proxy должен обеспечивать:
- TLS termination;
- редирект
HTTP -> HTTPS; X-Forwarded-*headers;- отключение buffering для MCP endpoint;
- увеличенные таймауты для долгих runtime-запросов;
- корректную маршрутизацию UI, admin API и MCP.
Особенно для mcp-server важно:
proxy_buffering off;proxy_request_buffering off;- длинный
proxy_read_timeout.
7. Пример nginx
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
client_max_body_size 25m;
proxy_set_header Host $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_http_version 1.1;
location / {
proxy_pass http://ui:3000;
}
location /api/admin/ {
proxy_pass http://admin-api:3001/;
}
location /mcp/ {
proxy_pass http://mcp-server:3002/;
proxy_buffering off;
proxy_request_buffering off;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
}
8. Пример Traefik
services:
ui:
labels:
- traefik.enable=true
- traefik.http.routers.ui.rule=Host(`example.com`) && PathPrefix(`/`)
- traefik.http.services.ui.loadbalancer.server.port=3000
admin-api:
labels:
- traefik.enable=true
- traefik.http.routers.admin.rule=Host(`example.com`) && PathPrefix(`/api/admin`)
- traefik.http.services.admin.loadbalancer.server.port=3001
mcp-server:
labels:
- traefik.enable=true
- traefik.http.routers.mcp.rule=Host(`example.com`) && PathPrefix(`/mcp`)
- traefik.http.services.mcp.loadbalancer.server.port=3002
Для production нужно отдельно проверить timeout behavior на MCP маршруте.
9. Требования к docker-compose
deploy/community/docker-compose.yml должен:
- поднимать
postgres,admin-api,mcp-server,ui; - использовать env vars вместо hardcoded config;
- иметь persistent storage для БД и artifacts;
- публиковать
ui,admin-apiиmcp-serverна loopback по умолчанию; - позволять переопределить publish bind одним env для случаев, когда reverse proxy вынесен на отдельный хост;
- не публиковать внутренние сервисы наружу без необходимости;
- содержать healthchecks;
- поддерживать optional cache profile без превращения
Valkeyв обязательную runtime dependency.
Для Community optional cache layer включается отдельно:
- profile:
cache - service:
valkey - базовый запуск без profile должен оставаться полностью рабочим
Пример:
docker compose \
-f deploy/community/docker-compose.yml \
--env-file deploy/community/.env.example \
--profile cache up -d
10. Healthchecks
Нужны как минимум:
GET /healthдляadmin-apiGET /healthдляmcp-server
CD не должен считать deployment успешным, пока эти endpoints не начали возвращать 200 OK.
11. CI и CD
11.1. CI
CI должен выполнять:
cargo fmt --all --checkcargo check --workspacecargo clippy --workspace --all-targets --all-features -- -D warningscargo test --workspace --all-targets
11.2. CD
CD для MVP должен:
- запускаться только после успешного
CIнаmainили вручную; - собирать versioned container images;
- пушить их в container registry с cache;
- доставлять deployment files на целевой Linux host;
- выполнять controlled restart через
pull, без сборки на сервере; - проверять health endpoints после запуска.
Минимальный flow:
- push в
main - успешный
CI - build and push images в registry
- upload runtime env и deployment files
docker loginна registry на целевом хостеdocker compose config -qdocker compose pulldocker compose up -d- healthcheck verification для
ui,admin-api,mcp-server
Для текущего проекта базовая рекомендуемая схема:
- registry на том же Gitea instance;
- versioned tags по
git sha; - self-hosted Gitea Actions runner;
- на сервере только
pull + restart, безdocker compose up --build.
Для private registry на сервере нужны отдельные deployment secrets:
DEPLOY_REGISTRY_USERDEPLOY_REGISTRY_TOKEN
Они используются только для docker login на целевом Linux host перед docker compose pull.
Монолитный DEPLOY_ENV_FILE больше не используется.
Workflow доставляет именно deploy/community/docker-compose.yml как public Community deployment manifest
и собирает .env на сервере из отдельных Gitea secrets. Для runtime-переменных нужно
создавать secrets с теми же именами, что и у приложений:
POSTGRES_HOSTPOSTGRES_PORTPOSTGRES_DBPOSTGRES_USERPOSTGRES_PASSWORDCRANK_STORAGE_ROOTCRANK_PUBLISH_BINDCRANK_ADMIN_BINDCRANK_MCP_BINDCRANK_MCP_REFRESH_MSCRANK_LOG_LEVELCRANK_MASTER_KEYCRANK_BASE_URLCRANK_CACHE_BACKENDCRANK_CACHE_URLCRANK_CACHE_DEFAULT_TTL_MSCRANK_SESSION_SECRETCRANK_PASSWORD_PEPPERCRANK_SESSION_TTL_HOURSCRANK_BOOTSTRAP_ADMIN_EMAILCRANK_BOOTSTRAP_ADMIN_PASSWORDCRANK_BOOTSTRAP_ADMIN_DISPLAY_NAMECRANK_DEMO_SEED
Практически это означает:
- одна runtime-переменная = один GitHub secret;
- ротация одного секрета не требует переписывать весь набор env;
.envна сервере каждый deploy собирается заново из актуальных secrets.
11. Граница Community против future commercial delivery
Community delivery path должен оставаться отдельным и воспроизводимым сам по себе.
Это означает:
deploy/community/*— public source of truth для открытой поставки;- future
EnterpriseиCloudне должны появляться как еще один.envна том же compose-файле; - commercial manifests и pipelines должны жить отдельно после создания private repositories.
12. Что нельзя забыть
- TLS и renewal сертификатов;
- backup для
postgresи artifact storage; - секреты вне репозитория;
- app-level auth для
admin-apiи bootstrap admin credentials в env; - rollback на предыдущий image tag или предыдущую compose revision.