# Environment Configuration Guide ## Overview Banatie uses a monorepo structure with **two separate environment configurations**: - **Development** (`apps/api-service/`) - Infrastructure in Docker, API runs locally - **Production** (`prod-env/`) - All services run in Docker containers --- ## Services & Ports | Service | Port(s) | Description | Container Name | |-----------------|--------------|------------------------------|----------------------------| | PostgreSQL | 5460 → 5432 | Database | banatie-postgres(-dev) | | MinIO API | 9000 → 9000 | Object storage (S3) | banatie-storage(-dev) | | MinIO Console | 9001 → 9001 | Storage management UI | banatie-storage(-dev) | | API Service | 3000 → 3000 | REST API (prod only) | banatie-app | | Landing Page | 3001 → 3000 | Public website (prod only) | banatie-landing | | Studio Platform | 3002 | SaaS (future) | - | | Admin Dashboard | 3003 | Administration (future) | - | **Port Format**: `host:container` (e.g., `5460:5432` means host port 5460 maps to container port 5432) --- ## Runtime Modes ### Development Mode (`apps/api-service/`) **Use Case**: Active development with hot reload **Structure**: ``` apps/api-service/ ├── docker-compose.yml # Infrastructure only (postgres, minio) ├── .env # Dev config (localhost endpoints) └── secrets.env # API keys (not in git) ``` **Launch**: ```bash cd apps/api-service pnpm dev ``` **What happens**: 1. Starts infrastructure: postgres, minio (Docker) 2. API runs locally with `tsx --watch` (hot reload) 3. Connects via port forwarding: `localhost:5460`, `localhost:9000` **Configuration**: - Database: `localhost:5460` - MinIO: `localhost:9000` - Hot reload enabled - Uses local `.env` + `secrets.env` --- ### Production Mode (`prod-env/`) **Use Case**: Production deployment, local testing **Structure**: ``` prod-env/ ├── docker-compose.yml # All services (postgres, minio, api, landing) ├── .env # Prod config (Docker hostnames) ├── secrets.env # API keys (not in git) └── README.md # Deployment instructions ``` **Launch**: ```bash cd prod-env docker compose up -d ``` **What happens**: 1. All services run in Docker containers 2. Internal Docker network: `postgres:5432`, `minio:9000` 3. Host access via port forwarding 4. Production-optimized builds **Configuration**: - Database: `postgres:5432` (internal) - MinIO: `minio:9000` (internal) - Production build (TypeScript compiled) - Uses prod `.env` + `secrets.env` --- ## Environment Files ### Development `.env` (`apps/api-service/.env`) **Purpose**: Local development configuration ```env # Connects to Docker via port forwarding DATABASE_URL=postgresql://banatie_user:banatie_secure_password@localhost:5460/banatie_db MINIO_ENDPOINT=localhost:9000 ``` ✅ **Committed to git** (no secrets) --- ### Production `.env` (`prod-env/.env`) **Purpose**: Production Docker configuration ```env # Internal Docker network hostnames DATABASE_URL=postgresql://banatie_user:banatie_secure_password@postgres:5432/banatie_db MINIO_ENDPOINT=minio:9000 ``` ✅ **Committed to git** (no secrets) --- ### Secrets (`secrets.env`) **Purpose**: Sensitive API keys and credentials ```env # Required GEMINI_API_KEY=your_key_here # Optional (generated by API) MASTER_KEY=will_be_generated API_KEY=will_be_generated ``` ❌ **NOT committed to git** ✅ Template available: `secrets.env.example` --- ## Key Configuration Differences | Variable | Dev (`apps/api-service/.env`) | Prod (`prod-env/.env`) | |----------|-------------------------------|------------------------| | `DATABASE_URL` | `localhost:5460` | `postgres:5432` | | `MINIO_ENDPOINT` | `localhost:9000` | `minio:9000` | | `RESULTS_DIR` | `./results` | `/app/results` | | `UPLOADS_DIR` | `./uploads/temp` | `/app/uploads/temp` | | `IS_DOCKER` | not set | `true` | --- ## How db.ts Loads Config The `apps/api-service/src/db.ts` file has smart loading: ```typescript // 1. Load .env only if NOT in Docker if (existsSync(envPath) && !process.env['IS_DOCKER']) { config({ path: envPath }); } // 2. Always load secrets.env if exists if (existsSync(secretsPath)) { config({ path: secretsPath }); } ``` - **Dev mode**: Loads `apps/api-service/.env` + `secrets.env` - **Prod mode**: Uses Docker env vars + `secrets.env` --- ## Docker Network - **Network Name**: `banatie-network` (prod), `banatie-dev-network` (dev) - **Internal DNS**: Containers reach each other by service name - **Host Access**: Use `localhost` with mapped ports --- ## Database Credentials **PostgreSQL**: - Host (dev): `localhost:5460` - Host (prod): `postgres:5432` - Database: `banatie_db` - User: `banatie_user` - Password: `banatie_secure_password` **MinIO**: - Endpoint (dev): `http://localhost:9000` - Endpoint (prod): `http://minio:9000` - Console: `http://localhost:9001` - Root User: `banatie_admin` - Root Password: `banatie_storage_secure_key_2024` - Service Account: `banatie_service` / `banatie_service_key_2024` - Bucket: `banatie` --- ## Storage Layout **MinIO Structure**: ``` banatie/ ├── {orgSlug}/ │ └── {projectSlug}/ │ ├── generated/ │ │ └── {year-month}/ │ │ └── {filename}.{ext} │ └── uploads/ │ └── {year-month}/ │ └── {filename}.{ext} ``` **Local Volumes** (both modes): - Database: `data/postgres/` - MinIO: `data/storage/drive{1-4}/` (SNMD mode) - Results: `data/results/` - Uploads: `data/uploads/` --- ## Quick Commands ### Development ```bash # Start dev environment cd apps/api-service pnpm dev # Stop infrastructure pnpm infra:down # View logs pnpm infra:logs ``` ### Production ```bash # Start all services cd prod-env docker compose up -d # View logs docker compose logs -f app # API docker compose logs -f landing # Landing docker compose logs -f postgres # DB # Stop all docker compose down # Rebuild after code changes docker compose up -d --build ``` ### Database Access ```bash # From host (both modes) psql -h localhost -p 5460 -U banatie_user -d banatie_db # From Docker container (prod only) docker exec -it banatie-postgres psql -U banatie_user -d banatie_db ``` --- ## Health Checks All services have health checks: - **PostgreSQL**: `pg_isready -U banatie_user -d banatie_db` - **MinIO**: `curl -f http://localhost:9000/minio/health/live` Intervals: 30s, timeout: 10s, retries: 3, start period: 40s --- ## Troubleshooting ### Port Already in Use Check what's using the port: ```bash lsof -i :5460 # PostgreSQL lsof -i :9000 # MinIO lsof -i :3000 # API ``` ### Database Connection Refused 1. Check containers are running: ```bash docker ps | grep banatie ``` 2. Check health status: ```bash docker compose ps # In respective directory ``` 3. Verify port in `.env` matches mode: - Dev: `localhost:5460` - Prod: `postgres:5432` ### MinIO Connection Refused 1. Check MinIO is healthy: ```bash docker logs banatie-storage(-dev) ``` 2. Verify endpoint in `.env`: - Dev: `localhost:9000` - Prod: `minio:9000` 3. Check storage-init completed: ```bash docker logs banatie-storage-init(-dev) ``` ### "No such file or directory" for secrets.env Create from template: ```bash # Dev cd apps/api-service cp secrets.env.example secrets.env # Edit with your GEMINI_API_KEY # Prod cd prod-env cp secrets.env.example secrets.env # Edit with your GEMINI_API_KEY ``` --- ## Migration Guide ### From Old Structure to New The project was reorganized to separate dev/prod configs: **Before**: ``` /.env # Confusing mix of localhost/docker /docker-compose.yml # Unclear if dev or prod ``` **After**: ``` /apps/api-service/ ├── docker-compose.yml # Dev infrastructure └── .env # Dev config (localhost) /prod-env/ ├── docker-compose.yml # Prod all services └── .env # Prod config (docker hostnames) ``` **Changes**: 1. Port: `5434` → `5460` (everywhere) 2. Secrets: Moved to `secrets.env` (not in git) 3. `db.ts`: Removed `override: true`, added `IS_DOCKER` check 4. Dockerfile: `Dockerfile.mono` → `Dockerfile` --- ## Best Practices 1. **Never commit `secrets.env`** - Use templates 2. **Use correct config for mode** - Dev vs Prod `.env` 3. **Test locally before deploy** - Use `prod-env` locally 4. **Monitor health checks** - Ensure services are healthy 5. **Backup data directory** - Especially `data/postgres/` --- ## Next Steps - ✅ Document environment configuration - ✅ Separate dev/prod configurations - ✅ Update port from 5434 to 5460 - ✅ Move secrets to separate file - 🔜 Test dev mode - 🔜 Test prod mode locally - 🔜 Deploy to VPS --- **Last Updated**: 2025-01-12 **Author**: Claude Code **Version**: 2.0 (Post-reorganization)