Appearance
Authority Doc / Public V1 Environments
The Environment Runbook defines how CoachMe environments are configured, promoted, recovered, and operated.
This page is the Public V1 authority for local, test/CI, staging, and production environment rules across the CoachMe app stack: API, workers, coach web, coach mobile, client mobile, PostgreSQL, Redis/BullMQ, object storage, Keycloak, reverse proxy, configuration, secrets, migrations, deployment gates, backup, restore, and rollback.
AuthorityEnvironmentsDockerSecretsRelease GatesPublic V1
Note
This page does not re-explain the architecture. technical-architecture-plan explains the stack choices; this runbook defines how those choices are configured and operated by environment.
Scope
This runbook owns the environment contract for the future CoachMe application stack and hands off adjacent concerns to the authority pages that define them in detail.
This Runbook Owns
- Local, test/CI, staging, and production environment tiers.
- Service topology for the CoachMe app stack.
- Environment-specific URLs, ports, domains, mobile schemes, and deep-link rules.
- Public client config, backend runtime config, and secrets.
- Local bootstrap and reset expectations.
- Fixture provisioning, reset mechanics, and environment validation.
- Staging and production provisioning, configuration, deployment, and health mechanics.
- Migrations, seed data, backup, restore, rollback, and health checks.
- A small appendix documenting the current static docs-site deployment.
This Runbook Does Not Own
- Architecture rationale owned by technical-architecture-plan.
- REST route shape, DTOs, errors, OpenAPI compatibility, and generated clients owned by api-contract-standard.
- Backend events, transactional outbox, publisher behavior, consumer idempotency, and dead letters owned by event-and-outbox-standard.
- Mobile local outbox, SQLite protocol, receipts, replay, and conflict handling owned by offline-sync-protocol.
- Roles and permission policy owned by roles-and-permissions.
- Workflow lifecycle states owned by workflow-state-map.
- Privacy classification and retention owned by privacy-and-retention.
- Signal semantics, dashboards, alerts, objectives, and diagnosis playbooks owned by observability-plan.
- Provider/component approval owned by integration-register; package/build/source-map lifecycle owned by toolchain-contract.
- Release admission, required-check cadence, fixture eligibility, blocking policy, and final approval owned by test-and-release-gate; evidence classification and retention owned by privacy-and-retention.
Note
Feature pages may declare that they need storage, queues, workers, or provider config, but this runbook decides the shared environment contract those features depend on.
Environment Model
Public V1 uses four environment tiers with distinct ownership, promotion posture, and data safety rules.
| Environment | Owner | Purpose | Data posture |
|---|---|---|---|
local | Developer | Disposable development stack and app bootstrap. | Sample data only; easy reset; no production secrets. |
test | Automation | Test and CI validation for contracts, migrations, workers, and protocol gates. | Deterministic fixtures; isolated services per run. |
staging | Release owner | Production-like release candidate environment. | Versioned synthetic fixtures only; persistent dependencies; restore drills. |
production | Operations owner | Customer-facing runtime. | Customer data; audited changes; least-privilege access. |
Environment Invariants
- staging and production are configured through environment files, secrets, and deployment manifests;
- Public V1 does not use product-admin UI to mutate secrets or core environment behavior;
- promotion moves the same immutable application artifact where the surface supports promotion, plus reviewed environment-specific configuration;
- where app-store or native configuration requires a separate production binary, the production candidate is built reproducibly from the same accepted commit, assigned its own digest, and verified before store release without a second source change;
- production-only secrets never run in local or CI;
- staging proves migrations, TLS, domains, auth providers, storage, queues, workers, backup, restore, rollback, and smoke tests before production.
Service Topology
The environment contract names the deployable runtime surfaces and dependency services without re-explaining the architecture rationale.
| Service | Role |
|---|---|
api | NestJS HTTP API, OpenAPI generation, guards, domain application services. |
worker | NestJS/BullMQ worker for outbox publishing, reminders, media jobs, push jobs, imports, scheduled materialization, and retryable background work. |
web | Next.js coach/admin web app. |
mobile-coach | Expo coach mobile app with generated API clients and environment-specific config. |
mobile-client | Expo client/personal mobile app with generated API clients and environment-specific config. |
postgres | canonical relational store. |
redis | BullMQ coordination, short-lived locks, rate-limit counters, and approved cache. |
minio or compatible object storage | media and document bytes. |
keycloak | identity provider, external federation, sessions, realm config, and token issuer. |
reverse-proxy | TLS termination, host routing, request limits, and future WebSocket/SSE allowance if needed. |
alloy | Docker-managed collector for approved backend logs, application/runtime metrics, and collector self-signals. |
Note
Bounded-context structure and stack rationale remain in technical-architecture-plan; this runbook owns the environment-facing contract those components follow.
Local
Local is disposable and optimized for developer bootstrap, inspection, and safe reset.
Local Expectations
- app dependency services run through Docker Compose: PostgreSQL, Redis, MinIO, and Keycloak;
- API, worker, and web run natively through
pnpm devfor fast reload, and are not containers in the default local stack; - a
fullCompose profile additionally runs API, worker, and web as containers for full-stack and end-to-end runs, so parity is available on demand without slowing daily iteration; - Expo coach and client apps point at a local or LAN-accessible API base URL;
- local uses safe sample credentials and sample data;
- local can import a development Keycloak realm;
- local object storage creates required buckets automatically or through an explicit bootstrap command;
- local reset drops disposable data, queues, and buckets without affecting shared environments;
- local exposes health checks for API, worker dependencies, database, Redis, object storage, and Keycloak.
Local Must Not
- local does not use production secrets, production services, or sample data as migration evidence.
Test And CI
Test and CI prove repeatable environment correctness before release-candidate promotion.
- dependency install with approved package manager and lockfile;
- lint, typecheck, and unit tests;
- migrations against empty and upgraded seeded PostgreSQL databases;
- OpenAPI client generation or validation;
- REST contract tests;
- event/outbox retry and idempotency tests;
- offline-sync replay and conflict protocol tests;
- worker tests with Redis/BullMQ available;
- object-storage integration tests for upload intent, metadata, and cleanup;
- Keycloak test realm/config import or validation;
- required env validation for missing values and unsafe dummy-secret values.
Staging
Staging is the production-like release-candidate environment that proves operational readiness before production.
- real TLS and production-shaped hostnames;
- production-style secrets in the chosen secret mechanism;
- persistent PostgreSQL, Redis, object storage, and Keycloak;
- release-candidate config, migrations, workers, scheduled jobs, and OpenAPI clients;
- mobile deep links and app schemes for staging builds;
- push-provider sandbox or production-equivalent validation where available;
- object-storage buckets, upload limits, lifecycle policies, and media worker checks;
- backup creation and restore drill evidence before production launch;
- smoke tests for coach web, coach mobile, client mobile, auth, API, queues, media upload, and worker processing;
- no copied, anonymized, exported, or snapshotted production data; staging uses versioned synthetic fixtures only. This rule is load-bearing for the staging region decision below: synthetic fixtures are not personal data, which is what permits staging to run outside the production data region. Copying a production dump, export, or snapshot onto staging would place regulated client data in an unapproved region and is prohibited.
Staging Topology
Public V1 staging runs on a single operator-controlled VPS rather than a managed platform, matching one-engineer operations and reusing the deployment pattern already proven by the docs site.
| Concern | Decision |
|---|---|
| Host | One Hostinger KVM 4 VPS: 4 vCPU, 16 GB RAM, 200 GB NVMe. |
| Region | Outside UAE/GCC. Permitted for staging only, and only while the synthetic-fixture rule above holds. |
| Runtime | Docker Compose running the app-repo stack: PostgreSQL, Redis, Keycloak, API, web, and workers as they exist. |
| Object storage | Not settled by this row. The integration-register approves MinIO for local development only and explicitly withholds staging use, and its staging/production S3-compatible selection is still conditional. Staging object storage needs a register decision before media features are exercised there. |
| Ingress | Traefik with the Let's Encrypt cert resolver, following the existing docs-site label pattern. |
| Hostnames | grow-pro.cloud subdomains for staging surfaces, giving the real TLS and production-shaped hostnames required above. |
| Capacity posture | The stack fits the host with headroom. ClamAV is the largest incremental consumer once media scanning lands and must be sized before it is enabled. |
| Production | Production topology and data region remain undecided. This staging choice does not imply or constrain them. |
Production
Production protects customer data and requires auditable promotion, recovery, and incident access posture.
- immutable release artifacts;
- reviewed deployment manifests and environment config;
- least-privilege secrets and service credentials;
- TLS and correct public domains;
- explicit database backup before risky migrations;
- migration approval and post-migration smoke checks;
- health endpoints, Pino logs, OpenTelemetry metrics, Sentry errors/crashes, safe client diagnostics, request ids, whole-workflow correlation ids, and alert destinations; distributed tracing remains Maturity;
- incident access rules for production secrets, health/nutrition records, media, and support diagnostics;
- backup retention and restore evidence;
- rollback or forward-fix plan for every release;
- no unaudited manual shell edits as the deploy mechanism.
Production Smoke Identities
- Dedicated synthetic coach and client identities are provisioned only through a reviewed bootstrap script.
- They remain isolated in a clearly named synthetic workspace and relationship.
- They cannot discover, select, invite, message, or access real users or real workspaces.
- Smoke-created records are labeled, bounded, and cleaned through the approved Privacy lifecycle.
- Credentials remain production secrets and are never stored in release artifacts or test output.
Configuration
Environment behavior is expressed through explicit configuration classes so public client values, backend runtime settings, and secrets stay separate.
| Class | Examples | Rule |
|---|---|---|
| Public client config | API base URL, app scheme, deep-link domains, supported locales, safe feature flags. | May be exposed to web/mobile clients. Must not contain secrets. |
| Backend runtime config | Database URL, Redis URL, object-storage endpoint, queue names, CORS origins, token issuer/audience, rate limits, retention windows. | Backend-only. May reference secret names but should not leak secret values. |
| Secrets | Database passwords, Keycloak admin credentials, OAuth client secrets, signing keys, object-storage credentials, push provider credentials, webhook secrets. | Secret manager or deployment secret mechanism only. Never committed. Never bundled into clients. |
Secrets
Secret handling is environment-owned and non-negotiable for Public V1.
- no secrets in Git;
- no raw secrets in docs examples;
- no secrets in frontend bundles;
- no production secrets in local or CI;
- secret rotation requires a reviewed deployment change and audit evidence;
- provider credentials live in Keycloak, the deployment secret store, or another approved backend-only secret mechanism;
- product-admin UI does not mutate Public V1 secrets;
- support/admin diagnostics redact secret values.
Data State
Runtime state ownership is explicit so supporting systems never become alternate product authorities.
Durable Authorities
- PostgreSQL owns aggregates, audit, outbox, auth mapping, object metadata, and durable business facts.
- Keycloak owns credentials, identity federation, token/session mechanics, and realm-level identity configuration.
Supporting Runtime State
- Redis owns queue coordination and short-lived operational state only.
- MinIO/S3 owns bytes; PostgreSQL owns metadata, permissions, and lifecycle.
- Mobile SQLite owns offline drafts and cached slices until server acceptance.
Migrations And Seeds
Schema change, rollback posture, and data seeding rules differ by environment and must be declared up front.
Migration Rules
- every schema change ships with a forward migration;
- every migration states its rollback, forward-fix, or restore posture;
- CI runs migrations against an empty database and an upgraded seeded database;
- staging runs release-candidate migrations before production;
- production migrations require backup evidence, operator approval, and smoke-test checkpoints.
Seed Tiers
- local gets rich demo data;
- test/CI gets deterministic fixtures only;
- staging gets release-candidate fixtures and synthetic accounts;
- production gets bootstrap data only through reviewed scripts or admin runbooks.
Storage And Queues
Object storage and background work are shared environment contracts, not feature-local implementation details.
Object Storage Rules
- required buckets are declared by environment;
- Public V1 uses two buckets, one for media and one for documents, so lifecycle, retention, and access policy can differ per class rather than being forced to share one policy; the local bootstrap creates both;
- the documents-bucket environment variable is added when document handling lands, rather than shipping a required variable no code reads yet;
- service and region selection is gated on the residency review named in the integration-register; if UAE/GCC residency is required for health-adjacent media, the selected service must expose an in-region endpoint;
- signed URL TTLs and upload limits are configured per environment;
- PostgreSQL stores metadata and permissions;
- media workers handle validation, normalization, scanning, thumbnails, and cleanup where feature pages require them;
- production bucket permissions follow least privilege;
- lifecycle and retention rules align with the Privacy And Retention authority.
Queue Rules
- Redis/BullMQ queues are named consistently by bounded context or operational purpose;
- workers are separately health-checked from the API;
- retry, backoff, and dead-letter behavior follows the event/outbox authority where events are involved;
- failed jobs retain diagnostic context without leaking secrets or unnecessary private data;
- staging proves scheduled jobs and retry behavior before production.
Mobile Domains
Environment ownership for mobile surfaces covers hostnames, schemes, redirects, and safe bundled config only.
- API base URLs per environment;
- app schemes for coach and client apps;
- universal/app link domains for invitation, login, onboarding, and media flows;
- OAuth redirect URLs and Keycloak client settings;
- push notification environment identifiers;
- build profile names for local, staging, and production;
- public client config that is safe to bundle;
- cache purge and app reinstall behavior only at the environment level;
- offline operation envelopes, SQLite schemas, receipts, and conflict behavior are defined in offline-sync-protocol.
Observability Runtime And Health
This runbook owns the approved collection path, environment isolation, configuration, hardening, and health semantics.
V1 Provider Layout
- Use one conditional Grafana Cloud stack for staging and production to keep one-engineer operations small.
- Every production query and alert filters
deployment.environment.name=production. - Staging and production use separate write credentials. Local and test do not export externally.
- Sentry uses separate projects for backend API/workers, coach web, coach mobile, and client mobile; environment and release distinguish staging/production.
Collector And Access Hardening
- Alloy uses the protected restricted Docker API proxy. A direct Docker socket mount, including a read-only mount, is prohibited.
- Run non-root where supported, drop unused capabilities, use a read-only filesystem, bound memory, and expose no public receiver/UI ports.
- Use scoped write-only ingestion credentials, named admin accounts, MFA, least privilege, separate admin/ingestion credentials, and provider activity logging.
- Client Sentry DSNs may be public config only after approval; Grafana credentials, backend tokens, and source-map upload tokens remain secrets.
Environment-owned health semantics
| Check | Required semantics |
|---|---|
/health/live | API process only; no downstream dependency check. |
/health/ready | PostgreSQL plus only dependencies required to accept requests safely. |
| Worker readiness | PostgreSQL and Redis/BullMQ through the approved process/container check. |
| Component/degraded checks | Keycloak, object storage, processors, and external providers are reported separately and do not make the API blanket-unready unless the request-acceptance contract requires them. |
| Exposure and cadence | Public response is minimal; protected detail names dependencies. Internal checks run every 60 seconds. Public synthetics remain Observability-owned. |
Container Log Rotation And Disk
Every Docker environment uses the local logging driver with max-size=10m and max-file=3. A reviewed json-file fallback must use the same bounds. Export filesystem use, rotation evidence, Alloy heartbeat, and exporter failures/drops.
Failure Boundary
Collector/provider failure never blocks accepted requests or jobs. Local stdout remains available. Observability owns the 85%/10-minute disk alert and telemetry-pipeline alert; this runbook owns configuration and recovery.
Deployment Gates
Promotion is gated by environment evidence rather than ad hoc confidence.
Configuration validation
Required values, safe URLs, origins, and non-placeholder secrets are present.
Database validation
Migrations apply cleanly and risky changes have backup evidence.
Contract validation
OpenAPI clients are current and REST contract checks pass.
Event validation
Outbox, retry, idempotency, and dead-letter expectations are proven.
Offline validation
Replay, conflict, upload refresh, and mobile smoke checks pass.
Auth validation
Keycloak realm/config import and login flows work for the target environment.
Storage/queue validation
Buckets, limits, queues, workers, and scheduled jobs are healthy.
Observability validation
Launch health, Pino logs, OpenTelemetry metrics, Sentry errors/crashes, safe client diagnostics, identifiers, dashboards, synthetics, and alert destinations are present. Distributed tracing is Maturity.
Note
Detailed release evidence and final promotion approval are defined by the Test And Release Gate; these environment categories already bind Public V1 promotion.
Backup And Restore
Recovery evidence is environment-specific and must account for both relational metadata and stored bytes.
- backup cadence and retention are defined per environment;
- local backups are optional and developer-owned;
- CI state is disposable;
- staging requires a restore drill before production launch and after material storage or backup changes;
- production requires at least one successful scheduled backup every 24 hours, a 6-hour grace period, monitored success/failure, and documented restore steps; the stale threshold is 30 hours;
- object storage and database restore plans account for metadata/byte consistency.
Rollback
Rollback posture is declared before release approval and stays separate from production data repair.
- app image rollback and config rollback are documented separately;
- migration rollback is not assumed safe;
- irreversible or risky migrations require a forward-fix or restore plan before release approval;
- failed worker/outbox deployments require queue-drain, retry, or pause/resume instructions;
- rollback is separate from data repair;
- production data repair requires an audited runbook.
Docs-Site Appendix
This appendix records the current repo deployment reality without treating it as the product application stack.
- current
docker-compose.ymlserves the static docs site only; - current route is
docs.grow-pro.cloudthrough Traefik labels; - current docs service exposes Nginx port
80inside the container; scripts/deploy-coach-me-docs.shis a docs-site operational convenience;- the docs-site deployment is not the application deployment process;
- the
coach-meapp repo now provides its own local applicationdocker-compose.yml(PostgreSQL, Redis, MinIO with bucket bootstrap, and Keycloak with realm import); the docs-site deployment stays separate from it.
Related Docs
This runbook hands off product scope, architecture rationale, protocol detail, privacy policy, observability, and release proof to adjacent docs.
Product OS Home
Entry point for the CoachMe planning set and status summary.
Development Readiness Review
Tracks readiness gaps and cross-system implementation evidence.
Public V1 Scope Contract
Defines the approved Public V1 scope that this environment contract supports.
Technical Architecture Plan
Owns architecture rationale and stack choice explanation.
Workflow State Map
Lifecycle states that environment gates and automation must respect.
Roles And Permissions
Authorization boundaries for runtime access, diagnostics, and support workflows.
API Contract Standard
REST, DTO, OpenAPI, and generated client rules referenced by CI and release gates.
Event And Outbox Standard
Event publisher, consumer, retry, and dead-letter behavior for background work.
Offline Sync Protocol
Mobile SQLite, replay, receipt, and conflict behavior that stays outside this runbook.
Privacy And Retention
Owns retention, legal posture, telemetry classes, and storage lifecycle policy.
Observability Plan
Owns signal semantics, dashboards, alerts, synthetics, objectives, and developer diagnosis playbooks.
Test And Release Gate
Defines executable release evidence, required-check cadence, and final promotion approval.