Deployment Blueprints
Техническое руководство из исходного проекта Notty. Примеры, параметры и эксплуатационные ограничения.
Цель документа — дать команде готовый набор паттернов развёртывания Notty CMS, чтобы внедрение не зависело от знания конкретного разработчика. Все блюпринты рассчитаны на stateless-сервер: всё состояние живёт в Postgres/MySQL и в объектном хранилище.
TL;DR
| Сценарий | Шаблон |
|---|---|
| Pet-проект / staging | deployment/docker-compose.minimal.yml |
| On-prem / single VPS production | deployment/docker-compose.yml + Nginx |
| Cloud Kubernetes (managed PG + S3) | deployment/kubernetes/ (kustomize) |
| Готовый artefact из CI | deployment/Dockerfile.runtime |
Базовые принципы
- Stateless app. Все pods/контейнеры Notty взаимозаменяемы. Локальный диск
используется только для эфемерных артефактов (например, обработка изображений
через
/tmp). Источник правды — БД + объектное хранилище. - Externalized state. Postgres/MySQL — managed (RDS, Cloud SQL, Neon,
Supabase) либо statefull-сервис в кластере с собственными бэкапами. Media —
S3, R2, GCS. Локальный
STORAGE_TYPE=localдопустим только для одного pod'а. - Configuration via env.
nitro.config.tsчитает переменные окружения, настройки админки лочатся, если задан соответствующий env (см. config-model.md). - Secrets out of band. Секреты не лежат в Git и не в
Deployment.spec.envкак plain text — только через Secret/External Secrets/Vault и т.п. См. secrets-management.md. - Health и readiness. Оркестратор должен использовать
/api/healthz(liveness) и/api/readyz(readiness). Последний возвращает 503, когда БД недоступна.
Топология 1 — Single instance
Client ──▶ Caddy/Nginx (TLS) ──▶ notty:2102 ──▶ Postgres (managed)
│
└──▶ local volume или S3
Когда подходит:
- команды до сотен тысяч записей, ~100 RPS;
- staging/preview-окружения;
- on-prem без оркестратора.
Шаблон:
cp deployment/.env.example .env
./deployment/scripts/secret-rotate-jwt.sh --init
docker compose -f deployment/docker-compose.minimal.yml up -d
Ограничения: один pod = SPOF; локальный media-volume не реплицируется.
Топология 2 — Reference production stack
deployment/docker-compose.yml поднимает app + Postgres + Redis + MinIO. Nginx
лежит в профиле edge, потому что для него нужны реальные TLS-файлы.
Используется как:
- референс для on-prem развёртывания;
- стенд для отработки runbook'ов (rollback, restore, secret rotation);
- основа для адаптации под VM/Compute Engine + managed PG.
Слой за слоем:
| Компонент | Зачем | В prod заменяется на |
|---|---|---|
| Nginx | TLS termination, статика, лимит body size | Cloudflare / managed LB / Caddy |
| notty | application | то же |
| Postgres | OLTP storage | managed PG (рекомендация) |
| Redis | shared cache (через плагин) | managed Redis |
| MinIO | S3-совместимое объектное хранилище | AWS S3 / Cloudflare R2 / GCS |
docker compose -f deployment/docker-compose.yml up -d
docker compose -f deployment/docker-compose.yml --profile edge up -d nginx
Топология 3 — Kubernetes blueprint
Директория deployment/kubernetes/ готова к применению через kustomize:
kubectl apply -k deployment/kubernetes/
Что внутри:
Deploymentс rolling update (maxUnavailable: 0), startup/readiness/ liveness probes на/api/healthzи/api/readyz,preStopsleep для graceful shutdown;ServiceClusterIP + headlessnotty-metricsдля Prometheus operator;Ingress(nginx-ingress + cert-manager) с явным запретом/api/metricsнаружу;HorizontalPodAutoscalerпо CPU/memory;PodDisruptionBudgetсminAvailable: 1;CronJobежедневного бэкапа через API Notty.
Что приносите со своей стороны:
- managed Postgres → URL в
notty-secrets.DATABASE_URL; - объектное хранилище → ключи в
notty-secrets.STORAGE_*; - ваш ingress controller / cert-manager / cluster-issuer.
STORAGE_TYPE=local в k8s имеет смысл только если вы готовы пожертвовать
горизонтальным масштабированием и привязать pod к конкретному PVC. Для prod —
всегда S3-совместимое хранилище.
CI → Image
Рекомендуемая последовательность:
pnpm install --frozen-lockfile
pnpm build:libs
pnpm --filter @notty/admin build
pnpm --filter @notty/server build
docker build -f deployment/Dockerfile.runtime \
--build-arg OUTPUT_DIR=packages/server/.output \
-t registry.example.com/notty:${GIT_SHA} .
docker push registry.example.com/notty:${GIT_SHA}
Dockerfile (multi-stage из монорепо) удобнее, когда сборку нужно делать
строго внутри образа (reproducible builds). Dockerfile.runtime — когда CI
артефакт вы и так уже делаете.
Что точно нужно проверять перед prod-деплоем
JWT_SECRETсгенерирован (openssl rand -base64 64) и хранится в Secret-механизме.NITRO_JWT_SECRETсовпадает сJWT_SECRET, если запускаетеnode .output/server/index.mjsнапрямую безnotty-serverCLI.DATABASE_URLуказывает на managed PG/MySQL с автобэкапами.NOTTY_CORS_ORIGINSявно перечисляет домены клиента.- Включено rate limiting (
NOTTY_RATE_LIMIT_ENABLED=true). /api/metricsзакрыт от внешнего трафика (см. nginx/ingress sample).STORAGE_TYPE=s3|cloudflare-r2|google-cloud(или single-instance со осмысленным local).- Настроен Prometheus scrape на
/api/metricsи алёрты поdocs/scaling.md. - Запланированы бэкапы (см.
backup-automation.md). - Проверена процедура rollback (см.
runbooks/rollback.md).
Источник: docs/operations/deployment-blueprints.md. Снимок документации исходного проекта. Технический справочник сохраняет язык оригинала.