Разделы документации
ОбзорБыстрый стартРедакции и возможностиМодели и поляРедактор контентаМедиатекаЛокализацияПубликация и работа командыAPI, SDK и генерация типовРасширения и инструментыРабочие проектыЗадания, вебхуки и наблюдаемостьАудит и управление даннымиСоветники и доверие к плагинамКорпоративный входПространства, квоты и масштабированиеCommerce и PortalПрава и безопасностьРазвёртывание и обновленияЛицензии и установка пакетовТекущие ограниченияПомощь и диагностикаДанные в кабинетеCore CMSDeveloper PlatformProduction UseWorkflowOperationsComplianceAI AssistantsPlugin TrustEnterprise IdentityEnterprise ScaleEnterprise DeploymentCommerce BundlePortal BundleNotty CMS DocumentationAuth & SecurityContent ModelingDeploymentEcosystem & Packaging ConventionsEditions and First-party ModulesExtensibilityGetting StartedMedia ManagementModule Extraction PathDraft & PublishUpgrade GuideWebhooks & IntegrationsCookbook: Blog with Next.jsCookbook: Custom PluginCookbook: Multilingual SiteOperations DocsBackup AutomationDeployment BlueprintsRunbook — Восстановление БД из бэкапаRunbook — Плановый деплойRunbook — Реакция на инцидентRunbook — Откат релизаRunbook — Горизонтальное масштабированиеRunbook — Ротация секретовRunbook — Major upgradeSecrets ManagementNotty CMS — Capability MapNotty Configuration ModelGenerated App ContractComponents and Dynamic ZonesMiddleware SystemPerformance & Scaling ToolkitDisaster Recovery PlaybookDistribution Model
Документация / Технический справочник

Secrets Management

Техническое руководство из исходного проекта Notty. Примеры, параметры и эксплуатационные ограничения.

По функциям модуляОбновлено 2026-09-30

Документ описывает «секретный контур» Notty CMS: где какие секреты живут, как они доставляются в runtime и как их ротировать без простоя.

Реестр секретов

Имя Что это Где используется Критичность
JWT_SECRET Подпись JWT для admin сессий и API token nitro.config.ts → JWT, auth-middleware high
NITRO_JWT_SECRET Runtime override для прямого Nitro output useRuntimeConfig().jwt.secret high
DATABASE_URL Креды primary БД lib/database.ts high
NITRO_DATABASE_URL Runtime override для прямого Nitro output useRuntimeConfig().database.url high
DATABASE_REPLICA_URLS Креды read replicas lib/db-query.ts medium
STORAGE_ACCESS_KEY_ID S3/R2 access key lib/storage/S3StorageProvider.ts high
STORAGE_SECRET_ACCESS_KEY S3/R2 secret key то же high
NITRO_STORAGE_ACCESS_KEY_ID Runtime override для прямого Nitro output useRuntimeConfig().storage.accessKeyId high
NITRO_STORAGE_SECRET_ACCESS_KEY Runtime override для прямого Nitro output useRuntimeConfig().storage.secretAccessKey high
STORAGE_CREDENTIALS_JSON GCS service account JSON lib/storage/GCSStorageProvider.ts high
GOOGLE_/GITHUB_/VK_/FACEBOOK_* OAuth client_id + secret lib/oauth.ts medium
API tokens (в БД) Внешний доступ к Content/Admin API lib/api-tokens.ts depends
Webhook signing keys (в БД) HMAC-подпись webhook payload lib/webhooks.ts medium

«В БД» означает, что секрет хранится в Postgres (хешируется или шифруется на прикладном уровне) — он автоматически попадает в бэкап, поэтому бэкап БД тоже должен быть зашифрован при покое.

Принципы

  1. Никогда в Git. .env.* (кроме .env.example) — в .gitignore. Любой k8s Secret — в виде шаблона (secret.example.yaml); реальные значения приходят из External Secrets / sealed-secrets / vault-injector.
  2. Один источник правды. Выберите один backend (Vault, AWS Secrets Manager, GCP Secret Manager, 1Password Connect) и ходите всегда туда. Ручные копии в нескольких местах — путь к рассинхрону.
  3. Запись только через pipeline. Менять секреты ручкой в проде запрещено; все изменения — через CI или утвержденный admin-runbook.
  4. Read-only для приложения. Notty не должен иметь прав менять секреты в backend'е. Только читать на старте/при reload.
  5. Шифрование at rest. Бэкапы БД и объектное хранилище — с шифрованием. Доступ — по короткоживущим IAM-токенам, а не по статическим ключам.

Контуры

docker-compose / VM

  • .env-файл с правами 600 (chmod 600 .env), владелец — пользователь, под которым запущен Docker.
  • JWT_SECRET и POSTGRES_PASSWORD генерируются один раз через deployment/scripts/secret-rotate-jwt.sh --init и openssl rand -base64 32.
  • Резервная копия .env хранится в защищённом месте (например, password-менеджер команды), не в repo.
  • Опционально подключите docker secret (Swarm) или --env-file /run/secrets/... с tmpfs-mount.

Kubernetes

Рекомендуемый паттерн — External Secrets Operator (ESO) с источником в Vault / AWS Secrets Manager / GCP Secret Manager:

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: notty-secrets
  namespace: notty
spec:
  refreshInterval: 5m
  secretStoreRef:
    name: cluster-secret-store
    kind: ClusterSecretStore
  target:
    name: notty-secrets
    creationPolicy: Owner
  data:
    - secretKey: JWT_SECRET
      remoteRef: { key: notty/prod/jwt }
    - secretKey: NITRO_JWT_SECRET
      remoteRef: { key: notty/prod/jwt }
    - secretKey: DATABASE_URL
      remoteRef: { key: notty/prod/db_url }
    - secretKey: NITRO_DATABASE_URL
      remoteRef: { key: notty/prod/db_url }
    - secretKey: STORAGE_ACCESS_KEY_ID
      remoteRef: { key: notty/prod/storage_access_key }
    - secretKey: NITRO_STORAGE_ACCESS_KEY_ID
      remoteRef: { key: notty/prod/storage_access_key }
    - secretKey: STORAGE_SECRET_ACCESS_KEY
      remoteRef: { key: notty/prod/storage_secret_key }
    - secretKey: NITRO_STORAGE_SECRET_ACCESS_KEY
      remoteRef: { key: notty/prod/storage_secret_key }

Альтернативы:

  • Sealed Secrets — секреты лежат в Git зашифрованными; меняются через kubeseal. Проще, но без centralised audit.
  • Vault Agent Injector — sidecar вкатывает секреты в файл, приложение их читает. Notty не умеет читать секреты из файла, поэтому потребуется маленький init-скрипт, который превратит файл в env (или запишет значения в .env).

Cloud-managed

Платформа Где хранить Как достать в runtime
AWS ECS / EKS AWS Secrets Manager ECS task secrets:, EKS — ESO + IRSA
GCP Cloud Run Secret Manager --update-secrets=ENV=name:latest
Fly.io / Railway platform secrets flagged как secret, доступны как env

Ротация

Общий принцип: секрет считается скомпрометированным, если хоть кто-то прочёл его в обход pipeline. Ротация — рутина, не ЧП.

Секрет Cadence Как
JWT_SECRET 90 дней См. runbooks/secret-rotation.md. После ротации все сессии сбрасываются.
DATABASE_URL (пароль) 90 дней Сменить пароль в managed PG → обновить secret backend → rolling update Notty.
STORAGE_* ключи 180 дней / по политике cloud Сначала добавить новый ключ → раскатать → удалить старый.
OAuth client secret при компрометации Сгенерировать новый в OAuth-провайдере → обновить env → redeploy.
API tokens (в БД) при инциденте Через UI/API revoke + создать новый.
Webhook signing keys при компрометации Через UI/API regenerate; сообщите получателям.

Что нельзя делать:

  • Менять JWT_SECRET в .env без перезапуска сервера — старый секрет останется в памяти процесса.
  • Делать ротацию в час пик: rolling restart возможен, но клиенты с активными сессиями получат 401 после истечения cache в gateway.
  • Хранить «прошлый» JWT_SECRET в env как dual-key: Notty не поддерживает multi-key верификацию. Любая ротация = принудительный re-login.

Boundary checks

Каждый квартал прогоняйте:

  • git ls-files + сканер (gitleaks/trufflehog) на repo и tags.
  • Проверьте, что docker image не содержит .env (см. .dockerignore).
  • Audit who can read для secret backend — список не растёт без ревью.
  • Бэкапы БД зашифрованы; ключ шифрования в KMS, а не в коде.
  • Сверка реестра секретов с тем, что реально читается в runtime (/api/health + kubectl describe pod).

Источник: docs/operations/secrets-management.md. Снимок документации исходного проекта. Технический справочник сохраняет язык оригинала.