banatie-service/docs/environment.md

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:

  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:

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

# 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 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

# 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

  1. Check containers are running:

    docker ps | grep banatie
    
  2. Check health status:

    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:

    docker logs banatie-storage(-dev)
    
  2. Verify endpoint in .env:

    • Dev: localhost:9000
    • Prod: minio:9000
  3. 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:

  1. Port: 54345460 (everywhere)
  2. Secrets: Moved to secrets.env (not in git)
  3. db.ts: Removed override: true, added IS_DOCKER check
  4. Dockerfile: Dockerfile.monoDockerfile

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)