9.0 KiB
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:
cd apps/api-service
pnpm dev
What happens:
- Starts infrastructure: postgres, minio (Docker)
- API runs locally with
tsx --watch(hot reload) - 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:
cd prod-env
docker compose up -d
What happens:
- All services run in Docker containers
- Internal Docker network:
postgres:5432,minio:9000 - Host access via port forwarding
- 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
# 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
# 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
# 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:
// 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
localhostwith 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
# Start dev environment
cd apps/api-service
pnpm dev
# Stop infrastructure
pnpm infra:down
# View logs
pnpm infra:logs
Production
# 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
# 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:
lsof -i :5460 # PostgreSQL
lsof -i :9000 # MinIO
lsof -i :3000 # API
Database Connection Refused
-
Check containers are running:
docker ps | grep banatie -
Check health status:
docker compose ps # In respective directory -
Verify port in
.envmatches mode:- Dev:
localhost:5460 - Prod:
postgres:5432
- Dev:
MinIO Connection Refused
-
Check MinIO is healthy:
docker logs banatie-storage(-dev) -
Verify endpoint in
.env:- Dev:
localhost:9000 - Prod:
minio:9000
- Dev:
-
Check storage-init completed:
docker logs banatie-storage-init(-dev)
"No such file or directory" for secrets.env
Create from template:
# 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:
- Port:
5434→5460(everywhere) - Secrets: Moved to
secrets.env(not in git) db.ts: Removedoverride: true, addedIS_DOCKERcheck- Dockerfile:
Dockerfile.mono→Dockerfile
Best Practices
- Never commit
secrets.env- Use templates - Use correct config for mode - Dev vs Prod
.env - Test locally before deploy - Use
prod-envlocally - Monitor health checks - Ensure services are healthy
- 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)