# Deployment This document describes how to deploy the Happy backend (`packages/happy-server`) and the infrastructure it expects. ## Runtime overview - **App server:** Node.js running `tsx ./sources/main.ts` (Fastify + Socket.IO). - **Database:** Postgres via Prisma. - **Cache:** Redis (currently used for connectivity and future expansion). - **Object storage:** S3-compatible storage for user-uploaded assets (MinIO works). - **Metrics:** Optional Prometheus `/metrics` server on a separate port. ## Required services 1. **Postgres** - Required for all persisted data. - Configure via `DATABASE_URL`. 2. **Redis** - Required by startup (`redis.ping()` is called). - Configure via `REDIS_URL`. - Managed by this repo: `packages/happy-server/deploy/happy-redis.yaml` (StatefulSet + redis-exporter sidecar). 3. **S3-compatible storage** - Used for avatars and other uploaded assets. - Configure via `S3_HOST`, `S3_PORT`, `S3_ACCESS_KEY`, `S3_SECRET_KEY`, `S3_BUCKET`, `S3_PUBLIC_URL`, `S3_USE_SSL`. - **Deployed separately** — not managed by this repo's Kubernetes manifests. In prod, the S3-compatible service (MinIO or similar) behind `S3_PUBLIC_URL` is provisioned and managed by external infrastructure. The app only consumes it via env vars: `S3_PUBLIC_URL` is set in the Deployment, and credentials come from Vault via ExternalSecret (`/handy-files`). - If `S3_HOST` is unset, the server falls back to local filesystem storage (`./data/files/`). - For local k8s dev, a MinIO pod is deployed via `deploy/overlays/local/minio.yaml`. ## Environment variables **Required** - `DATABASE_URL`: Postgres connection string. - `HANDY_MASTER_SECRET`: master key for auth tokens and server-side encryption. - `REDIS_URL`: Redis connection string. - `S3_HOST`, `S3_ACCESS_KEY`, `S3_SECRET_KEY`, `S3_BUCKET`, `S3_PUBLIC_URL`: object storage config. **Common** - `PORT`: API server port (default `3005`). - `METRICS_ENABLED`: set to `false` to disable metrics server. - `METRICS_PORT`: metrics server port (default `9090`). - `S3_PORT`: optional S3 port. - `S3_USE_SSL`: `true`/`false` (default `true`). **Optional integrations** - GitHub OAuth/App: `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET`, `GITHUB_APP_ID`, `GITHUB_PRIVATE_KEY`, `GITHUB_WEBHOOK_SECRET`, plus redirect URL/URI. - `GITHUB_REDIRECT_URL` is used by the OAuth callback handler. - `GITHUB_REDIRECT_URI` is used by the GitHub App initializer. - Voice: `ELEVENLABS_API_KEY` (required for `/v1/voice/conversations` in production). - Subscriptions: `REVENUECAT_API_KEY` (server-side RevenueCat key, required for voice subscription checks). - Debug logging: `DANGEROUSLY_LOG_TO_SERVER_FOR_AI_AUTO_DEBUGGING` (enables file logging + dev log endpoint). ## Docker image A production Dockerfile is provided at `Dockerfile.server`. Key notes: - The server defaults to port `3005` (set `PORT` explicitly in container environments). - The image includes FFmpeg and Python for media processing. ## Kubernetes manifests Example manifests live in `packages/happy-server/deploy`: - `handy.yaml`: Deployment + Service + ExternalSecrets for the server. - `happy-redis.yaml`: Redis StatefulSet + Service + ConfigMap. The deployment config expects: - Prometheus scraping annotations on port `9090`. - A secret named `handy-secrets` populated by ExternalSecrets. - A service mapping port `3000` to container port `3005`. ## Local dev helpers The server package includes scripts for local infrastructure: - `pnpm --filter happy-server db` (Postgres in Docker) - `pnpm --filter happy-server redis` - `pnpm --filter happy-server s3` + `s3:init` Use `.env`/`.env.dev` to load local settings when running `pnpm --filter happy-server dev`. ## Implementation references - Entrypoint: `packages/happy-server/sources/main.ts` - Dockerfile: `Dockerfile.server` - Kubernetes manifests: `packages/happy-server/deploy` - Env usage: `packages/happy-server/sources` (`rg -n "process.env"`)