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