feat: update setup
This commit is contained in:
parent
eb11db753e
commit
dd48d4e1a1
|
|
@ -13,12 +13,11 @@ apps/*/dist/
|
|||
apps/*/.next/
|
||||
.next/
|
||||
|
||||
# Environment files
|
||||
.env
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
# Environment files - KEEP .env FILES FOR TRACKING
|
||||
# We commit .env but ignore local overrides and secrets
|
||||
.env*.local
|
||||
secrets.env
|
||||
.env.production
|
||||
|
||||
# IDE files
|
||||
.vscode/
|
||||
|
|
@ -73,7 +72,7 @@ jspm_packages/
|
|||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
# .env
|
||||
|
||||
# Generated images and uploads
|
||||
data/storage/
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
"--access-mode=unrestricted"
|
||||
],
|
||||
"env": {
|
||||
"DATABASE_URI": "postgresql://banatie_user:banatie_secure_password@localhost:5434/banatie_db"
|
||||
"DATABASE_URI": "postgresql://banatie_user:banatie_secure_password@localhost:5460/banatie_db"
|
||||
}
|
||||
},
|
||||
"mastra": {
|
||||
|
|
|
|||
109
CLAUDE.md
109
CLAUDE.md
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
**IMPORTANT**: Always refer to [docs/environment.md](docs/environment.md) for detailed environment configuration, runtime modes, and known issues. Keep that document updated when making infrastructure or configuration changes.
|
||||
|
||||
## Project Overview
|
||||
|
||||
Banatie is a comprehensive monorepo for AI-powered image generation platform featuring multiple applications:
|
||||
|
|
@ -15,34 +17,37 @@ The project uses MinIO for object storage and PostgreSQL for data persistence, a
|
|||
|
||||
## Development Commands
|
||||
|
||||
Use `docker compose` command for Docker services (v3 version).
|
||||
The project has **two separate environments**:
|
||||
|
||||
### Infrastructure
|
||||
### Development Mode (Local API + Docker Infrastructure)
|
||||
|
||||
- `docker compose up -d postgres minio storage-init` - Start database and storage services
|
||||
- `docker compose up -d` - Start all services including the API app container
|
||||
- `docker compose down` - Stop all services
|
||||
From `apps/api-service/`:
|
||||
|
||||
```bash
|
||||
pnpm dev # Start infrastructure + API with hot reload
|
||||
pnpm infra:up # Start only infrastructure (postgres, minio)
|
||||
pnpm infra:down # Stop infrastructure
|
||||
pnpm infra:logs # View infrastructure logs
|
||||
```
|
||||
|
||||
### Production Mode (All Services in Docker)
|
||||
|
||||
From `prod-env/`:
|
||||
|
||||
```bash
|
||||
docker compose up -d # Start all services
|
||||
docker compose up -d --build # Rebuild and start
|
||||
docker compose down # Stop all services
|
||||
docker compose logs -f app # API logs
|
||||
docker compose logs -f landing # Landing logs
|
||||
```
|
||||
|
||||
### Monorepo Commands (from root)
|
||||
|
||||
- `pnpm dev` - Start all applications in development mode
|
||||
- `pnpm dev:api` - Start API service only (`apps/api-service`)
|
||||
- `pnpm dev:landing` - Start landing page only (`apps/landing`)
|
||||
- `pnpm dev:studio` - Start studio platform only (`apps/studio`)
|
||||
- `pnpm dev:admin` - Start admin dashboard only (`apps/admin`)
|
||||
|
||||
### Build & Production
|
||||
|
||||
- `pnpm build` - Build all applications
|
||||
- `pnpm build:api` - Build API service only
|
||||
- `pnpm start:api` - Start API service in production mode
|
||||
- `pnpm start:landing` - Start landing page in production mode
|
||||
|
||||
### Code Quality (runs across all apps)
|
||||
|
||||
- `pnpm lint` - Run ESLint on all applications
|
||||
- `pnpm typecheck` - Run TypeScript checking on all applications
|
||||
- `pnpm test` - Run tests (currently API service only)
|
||||
- `pnpm test` - Run tests
|
||||
- `pnpm clean` - Clean all build outputs and dependencies
|
||||
|
||||
## Architecture
|
||||
|
|
@ -52,16 +57,25 @@ Use `docker compose` command for Docker services (v3 version).
|
|||
```
|
||||
banatie-service/
|
||||
├── apps/
|
||||
│ ├── api-service/ # Express.js REST API (TypeScript)
|
||||
│ ├── landing/ # Next.js landing page
|
||||
│ ├── studio/ # Next.js SaaS platform
|
||||
│ └── admin/ # Next.js admin dashboard
|
||||
│ ├── api-service/ # Express.js REST API (TypeScript)
|
||||
│ │ ├── docker-compose.yml # Dev infrastructure only
|
||||
│ │ ├── .env # Dev config (localhost)
|
||||
│ │ └── Dockerfile # Production build
|
||||
│ ├── landing/ # Next.js landing page
|
||||
│ │ └── Dockerfile # Production build
|
||||
│ ├── studio/ # Next.js SaaS platform
|
||||
│ └── admin/ # Next.js admin dashboard
|
||||
├── packages/
|
||||
│ └── database/ # Shared database package (Drizzle ORM)
|
||||
├── data/ # Docker volume data (postgres, minio)
|
||||
├── docker-compose.yml # Infrastructure services
|
||||
├── pnpm-workspace.yaml # Workspace configuration
|
||||
└── package.json # Root workspace scripts
|
||||
│ └── database/ # Shared database package (Drizzle ORM)
|
||||
├── prod-env/ # Production environment
|
||||
│ ├── docker-compose.yml # All services (api, landing, infra)
|
||||
│ ├── .env # Prod config (Docker hostnames)
|
||||
│ └── README.md # Deployment instructions
|
||||
├── data/ # Docker volume data (postgres, minio)
|
||||
├── docs/
|
||||
│ └── environment.md # Environment configuration guide
|
||||
├── pnpm-workspace.yaml # Workspace configuration
|
||||
└── package.json # Root workspace scripts
|
||||
```
|
||||
|
||||
### API Service Architecture (`apps/api-service/`)
|
||||
|
|
@ -101,7 +115,7 @@ banatie-service/
|
|||
### Storage & Data
|
||||
|
||||
- **MinIO**: Object storage for generated images and uploads (port 9000)
|
||||
- **PostgreSQL**: Database for API keys, user data, and metadata (port 5434)
|
||||
- **PostgreSQL**: Database for API keys, user data, and metadata (port 5460)
|
||||
- Database name: `banatie_db`
|
||||
- User: `banatie_user`
|
||||
- Tables: `api_keys`, `organizations`, `projects`, `users`, `images`, `upload_sessions`
|
||||
|
|
@ -125,6 +139,8 @@ Key table: `api_keys`
|
|||
|
||||
## Environment Configuration
|
||||
|
||||
**CRITICAL**: See [docs/environment.md](docs/environment.md) for complete configuration details, known issues, and solutions.
|
||||
|
||||
**Important**: We use TWO `.env` files with different purposes:
|
||||
|
||||
### Root `.env` (Docker Compose Infrastructure)
|
||||
|
|
@ -136,13 +152,30 @@ Used by Docker Compose services (MinIO, Postgres, API container). Key difference
|
|||
- `MINIO_ROOT_USER` and `MINIO_ROOT_PASSWORD` - MinIO admin credentials
|
||||
- All variables are passed to the app container via docker-compose.yml environment section
|
||||
|
||||
### API Service `.env` (Local Development Only)
|
||||
### Development `.env` (`apps/api-service/.env`)
|
||||
|
||||
Located at `apps/api-service/.env` - used ONLY when running `pnpm dev:api` locally:
|
||||
Used when running `pnpm dev` locally (connects to Docker via port forwarding):
|
||||
|
||||
- `DATABASE_URL=postgresql://banatie_user:banatie_secure_password@localhost:5434/banatie_db` (port-forwarded)
|
||||
- `MINIO_ENDPOINT=localhost:9000` (port-forwarded)
|
||||
- **NOTE**: This file is excluded from Docker builds (see Dockerfile.mono)
|
||||
- `DATABASE_URL=postgresql://banatie_user:banatie_secure_password@localhost:5460/banatie_db`
|
||||
- `MINIO_ENDPOINT=localhost:9000`
|
||||
- **NOTE**: This file is excluded from Docker builds
|
||||
|
||||
### Production `.env` (`prod-env/.env`)
|
||||
|
||||
Used when running `docker compose` in prod-env (internal Docker hostnames):
|
||||
|
||||
- `DATABASE_URL=postgresql://banatie_user:banatie_secure_password@postgres:5432/banatie_db`
|
||||
- `MINIO_ENDPOINT=minio:9000`
|
||||
- `IS_DOCKER=true` environment variable is set
|
||||
|
||||
### Secrets (`secrets.env`)
|
||||
|
||||
Sensitive values stored separately (NOT in git):
|
||||
|
||||
- `GEMINI_API_KEY` - Required for image generation
|
||||
- `MASTER_KEY`, `API_KEY` - Optional testing keys
|
||||
|
||||
See `secrets.env.example` in each directory for template.
|
||||
|
||||
### Required Environment Variables
|
||||
|
||||
|
|
@ -195,7 +228,7 @@ Located at `apps/api-service/.env` - used ONLY when running `pnpm dev:api` local
|
|||
| Landing Page | 3001 | Public website |
|
||||
| Studio Platform | 3002 | SaaS application |
|
||||
| Admin Dashboard | 3003 | Administration |
|
||||
| PostgreSQL | 5434 | Database |
|
||||
| PostgreSQL | 5460 | Database |
|
||||
| MinIO API | 9000 | Object storage |
|
||||
| MinIO Console | 9001 | Storage management |
|
||||
|
||||
|
|
@ -275,4 +308,6 @@ curl -X POST http://localhost:3000/api/upload \
|
|||
- ESLint configured with TypeScript and Prettier integration
|
||||
- Jest for testing with ts-jest preset (API service)
|
||||
- Each app can be developed and deployed independently
|
||||
- **Docker**: Uses monorepo-aware Dockerfile (`Dockerfile.mono`) that includes workspace packages
|
||||
- **Docker**: Uses monorepo-aware Dockerfiles in each app directory
|
||||
- **Environment**: Two separate configs (dev: `apps/api-service/`, prod: `prod-env/`)
|
||||
- **Secrets**: Stored in `secrets.env` (not tracked in git)
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ See individual app README files for specific environment variables.
|
|||
| Landing Page | 3001 | Public website |
|
||||
| Studio Platform | 3002 | SaaS application |
|
||||
| Admin Dashboard | 3003 | Administration |
|
||||
| PostgreSQL | 5434 | Database |
|
||||
| PostgreSQL | 5460 | Database |
|
||||
| MinIO API | 9000 | Object storage |
|
||||
| MinIO Console | 9001 | Storage admin |
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
BANATIE_API_URL=http://localhost:3000
|
||||
|
||||
# Database Configuration (Direct admin access)
|
||||
POSTGRES_URL=postgresql://banatie_user:banatie_secure_password@localhost:5434/banatie
|
||||
POSTGRES_URL=postgresql://banatie_user:banatie_secure_password@localhost:5460/banatie
|
||||
|
||||
# MinIO Storage Configuration
|
||||
MINIO_ENDPOINT=http://localhost:9000
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ pnpm dev
|
|||
BANATIE_API_URL=http://localhost:3000
|
||||
|
||||
# Database (Direct admin access)
|
||||
POSTGRES_URL=postgresql://user:password@localhost:5434/banatie
|
||||
POSTGRES_URL=postgresql://user:password@localhost:5460/banatie
|
||||
|
||||
# Storage
|
||||
MINIO_ENDPOINT=http://localhost:9000
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
# Server Configuration
|
||||
PORT=3000
|
||||
NODE_ENV=development
|
||||
|
||||
# CORS Configuration
|
||||
CORS_ORIGIN=*
|
||||
|
||||
# Database Configuration (connects to Docker via port forwarding)
|
||||
DATABASE_URL=postgresql://banatie_user:banatie_secure_password@localhost:5460/banatie_db
|
||||
|
||||
# IMPORTANT: Sensitive values should be in secrets.env (not tracked in git)
|
||||
# See secrets.env.example for required variables like GEMINI_API_KEY
|
||||
|
||||
# MinIO Storage Configuration
|
||||
STORAGE_TYPE=minio
|
||||
MINIO_ENDPOINT=localhost:9000
|
||||
MINIO_ACCESS_KEY=banatie_service
|
||||
MINIO_SECRET_KEY=banatie_service_key_2024
|
||||
MINIO_USE_SSL=false
|
||||
MINIO_BUCKET_NAME=banatie
|
||||
MINIO_PUBLIC_URL=http://localhost:9000
|
||||
|
||||
# MinIO Admin Configuration (for initialization)
|
||||
MINIO_ROOT_USER=banatie_admin
|
||||
MINIO_ROOT_PASSWORD=banatie_storage_secure_key_2024
|
||||
|
||||
# Multi-tenancy Configuration
|
||||
DEFAULT_ORG_ID=default
|
||||
DEFAULT_PROJECT_ID=main
|
||||
DEFAULT_USER_ID=system
|
||||
|
||||
# API Configuration
|
||||
API_BASE_URL=http://localhost:3000
|
||||
PRESIGNED_URL_EXPIRY=86400
|
||||
|
||||
# File Upload Configuration
|
||||
MAX_FILE_SIZE=5242880
|
||||
MAX_FILES=3
|
||||
|
||||
# Directory Configuration
|
||||
RESULTS_DIR=./results
|
||||
UPLOADS_DIR=./uploads/temp
|
||||
|
||||
# Logging Configuration
|
||||
LOG_LEVEL=info
|
||||
TTI_LOG=logs/tti-log.md
|
||||
ENH_LOG=logs/enhancing.md
|
||||
|
||||
# REMOVED: Sensitive keys moved to secrets.env
|
||||
# MASTER_KEY, API_KEY, and GEMINI_API_KEY should be in secrets.env
|
||||
|
|
@ -1,76 +1,90 @@
|
|||
# Development stage - for docker-compose development with hot reload
|
||||
FROM node:20-alpine AS development
|
||||
# Multi-stage Dockerfile for API Service
|
||||
|
||||
# Stage 1: Dependencies
|
||||
FROM node:20-alpine AS deps
|
||||
WORKDIR /app
|
||||
|
||||
# Install pnpm globally
|
||||
RUN npm install -g pnpm
|
||||
# Install pnpm
|
||||
RUN npm install -g pnpm@10.11.0
|
||||
|
||||
# Copy package files for dependency installation
|
||||
COPY package*.json pnpm-lock.yaml ./
|
||||
# Copy workspace configuration
|
||||
COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./
|
||||
|
||||
# Copy package.json files
|
||||
COPY apps/api-service/package.json ./apps/api-service/
|
||||
COPY packages/database/package.json ./packages/database/
|
||||
|
||||
# Install dependencies
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
|
||||
# Expose port
|
||||
EXPOSE 3000
|
||||
|
||||
# Use development command with hot reload
|
||||
CMD ["pnpm", "dev"]
|
||||
|
||||
# Builder stage - for production build
|
||||
# Stage 2: Builder
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
|
||||
# Install pnpm globally
|
||||
RUN npm install -g pnpm
|
||||
# Install pnpm
|
||||
RUN npm install -g pnpm@10.11.0
|
||||
|
||||
# Copy package files
|
||||
COPY package*.json pnpm-lock.yaml ./
|
||||
# Copy dependencies from deps stage
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY --from=deps /app/apps/api-service/node_modules ./apps/api-service/node_modules
|
||||
COPY --from=deps /app/packages/database/node_modules ./packages/database/node_modules
|
||||
|
||||
# Install all dependencies (including dev dependencies for build)
|
||||
RUN pnpm install --frozen-lockfile
|
||||
# Copy workspace files
|
||||
COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
# Copy database package
|
||||
COPY packages/database ./packages/database
|
||||
|
||||
# Build TypeScript to JavaScript
|
||||
# Copy API service source (exclude .env - it's for local dev only)
|
||||
COPY apps/api-service/package.json ./apps/api-service/
|
||||
COPY apps/api-service/tsconfig.json ./apps/api-service/
|
||||
COPY apps/api-service/src ./apps/api-service/src
|
||||
|
||||
# Set working directory to API service
|
||||
WORKDIR /app/apps/api-service
|
||||
|
||||
# Build TypeScript
|
||||
RUN pnpm build
|
||||
|
||||
# Production stage - optimized final image
|
||||
# Stage 3: Production Runner
|
||||
FROM node:20-alpine AS production
|
||||
WORKDIR /app
|
||||
|
||||
# Create non-root user for security
|
||||
RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001
|
||||
# Install pnpm
|
||||
RUN npm install -g pnpm@10.11.0
|
||||
|
||||
# Install pnpm globally
|
||||
RUN npm install -g pnpm
|
||||
ENV NODE_ENV=production
|
||||
|
||||
# Copy package files
|
||||
COPY --from=builder /app/package*.json ./
|
||||
# Create non-root user
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 apiuser
|
||||
|
||||
# Copy workspace configuration
|
||||
COPY --from=builder /app/pnpm-workspace.yaml ./
|
||||
COPY --from=builder /app/package.json ./
|
||||
COPY --from=builder /app/pnpm-lock.yaml ./
|
||||
|
||||
# Install only production dependencies
|
||||
RUN pnpm install --prod --frozen-lockfile
|
||||
# Copy database package
|
||||
COPY --from=builder /app/packages/database ./packages/database
|
||||
|
||||
# Copy built application
|
||||
COPY --from=builder /app/dist ./dist
|
||||
# Copy built API service
|
||||
COPY --from=builder --chown=apiuser:nodejs /app/apps/api-service/dist ./apps/api-service/dist
|
||||
COPY --from=builder /app/apps/api-service/package.json ./apps/api-service/
|
||||
|
||||
# Create required directories and set ownership
|
||||
RUN mkdir -p logs && chown -R nodejs:nodejs /app
|
||||
# Copy node_modules for runtime
|
||||
COPY --from=builder /app/node_modules ./node_modules
|
||||
COPY --from=builder /app/apps/api-service/node_modules ./apps/api-service/node_modules
|
||||
COPY --from=builder /app/packages/database/node_modules ./packages/database/node_modules
|
||||
|
||||
# Switch to non-root user
|
||||
USER nodejs
|
||||
# Create directories for logs and data
|
||||
RUN mkdir -p /app/apps/api-service/logs /app/results /app/uploads/temp
|
||||
RUN chown -R apiuser:nodejs /app/apps/api-service/logs /app/results /app/uploads
|
||||
|
||||
USER apiuser
|
||||
|
||||
# Expose port
|
||||
EXPOSE 3000
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
||||
CMD node -e "require('http').request('http://localhost:3000/health', (res) => { \
|
||||
process.exit(res.statusCode === 200 ? 0 : 1) \
|
||||
}).on('error', () => process.exit(1)).end()"
|
||||
WORKDIR /app/apps/api-service
|
||||
|
||||
# Start the application
|
||||
# Run production build
|
||||
CMD ["node", "dist/server.js"]
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
# Monorepo-aware Dockerfile for API Service
|
||||
# Development stage - for docker-compose development with hot reload
|
||||
FROM node:20-alpine AS development
|
||||
WORKDIR /app
|
||||
|
||||
# Install pnpm globally
|
||||
RUN npm install -g pnpm@10.11.0
|
||||
|
||||
# Copy workspace configuration from root
|
||||
COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./
|
||||
|
||||
# Copy all workspace packages
|
||||
COPY packages/ ./packages/
|
||||
|
||||
# Copy API service (exclude .env file - it's for local dev only)
|
||||
COPY apps/api-service/package.json ./apps/api-service/
|
||||
COPY apps/api-service/tsconfig.json ./apps/api-service/
|
||||
COPY apps/api-service/src/ ./apps/api-service/src/
|
||||
|
||||
# Install all dependencies (workspace-aware)
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# Set working directory to API service
|
||||
WORKDIR /app/apps/api-service
|
||||
|
||||
# Expose port
|
||||
EXPOSE 3000
|
||||
|
||||
# Use development command with hot reload
|
||||
CMD ["pnpm", "dev"]
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
# Development Infrastructure
|
||||
# This docker-compose.yml starts only infrastructure services (postgres, minio)
|
||||
# The API service runs locally via `pnpm dev` for hot reload
|
||||
|
||||
services:
|
||||
# PostgreSQL Database
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
container_name: banatie-postgres-dev
|
||||
ports:
|
||||
- "5460:5432"
|
||||
volumes:
|
||||
- ../../data/postgres:/var/lib/postgresql/data
|
||||
- ../../scripts/init-db.sql:/docker-entrypoint-initdb.d/01-init.sql
|
||||
networks:
|
||||
- banatie-dev-network
|
||||
environment:
|
||||
POSTGRES_DB: banatie_db
|
||||
POSTGRES_USER: banatie_user
|
||||
POSTGRES_PASSWORD: banatie_secure_password
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U banatie_user -d banatie_db"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
restart: unless-stopped
|
||||
|
||||
# MinIO Object Storage - SNMD Mode
|
||||
minio:
|
||||
image: quay.io/minio/minio:latest
|
||||
container_name: banatie-storage-dev
|
||||
ports:
|
||||
- "9000:9000" # S3 API
|
||||
- "9001:9001" # Web Console
|
||||
volumes:
|
||||
# SNMD: 4 drives for full S3 compatibility
|
||||
- ../../data/storage/drive1:/data1
|
||||
- ../../data/storage/drive2:/data2
|
||||
- ../../data/storage/drive3:/data3
|
||||
- ../../data/storage/drive4:/data4
|
||||
networks:
|
||||
- banatie-dev-network
|
||||
environment:
|
||||
MINIO_ROOT_USER: banatie_admin
|
||||
MINIO_ROOT_PASSWORD: banatie_storage_secure_key_2024
|
||||
MINIO_BROWSER_REDIRECT_URL: http://localhost:9001
|
||||
MINIO_SERVER_URL: http://localhost:9000
|
||||
MINIO_DOMAIN: localhost
|
||||
command: server /data{1...4} --console-address ":9001"
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
restart: unless-stopped
|
||||
|
||||
# MinIO Storage Initialization
|
||||
storage-init:
|
||||
image: minio/mc:latest
|
||||
container_name: banatie-storage-init-dev
|
||||
networks:
|
||||
- banatie-dev-network
|
||||
depends_on:
|
||||
minio:
|
||||
condition: service_healthy
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
echo 'Setting up MinIO alias...'
|
||||
mc alias set storage http://minio:9000 banatie_admin banatie_storage_secure_key_2024
|
||||
|
||||
echo 'Creating main bucket...'
|
||||
mc mb --ignore-existing storage/banatie
|
||||
|
||||
echo 'Creating service user...'
|
||||
mc admin user add storage banatie_service banatie_service_key_2024
|
||||
|
||||
echo 'Attaching readwrite policy to service user...'
|
||||
mc admin policy attach storage readwrite --user=banatie_service
|
||||
|
||||
echo 'Setting up lifecycle policy...'
|
||||
cat > /tmp/lifecycle.json <<'LIFECYCLE'
|
||||
{
|
||||
"Rules": [
|
||||
{
|
||||
"ID": "temp-cleanup",
|
||||
"Status": "Enabled",
|
||||
"Filter": {
|
||||
"Prefix": "temp/"
|
||||
},
|
||||
"Expiration": {
|
||||
"Days": 7
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
LIFECYCLE
|
||||
mc ilm import storage/banatie < /tmp/lifecycle.json
|
||||
|
||||
echo 'Storage initialization completed!'
|
||||
echo 'Bucket: banatie'
|
||||
echo 'Dev mode: API service will connect via localhost:9000'
|
||||
exit 0
|
||||
restart: "no"
|
||||
|
||||
networks:
|
||||
banatie-dev-network:
|
||||
driver: bridge
|
||||
|
|
@ -4,7 +4,9 @@
|
|||
"description": "Nano Banana Image Generation Service - REST API for AI-powered image generation using Gemini Flash Image model",
|
||||
"main": "dist/server.js",
|
||||
"scripts": {
|
||||
"infra:up": "cd ../.. && docker compose up -d postgres minio storage-init",
|
||||
"infra:up": "docker compose up -d postgres minio storage-init",
|
||||
"infra:down": "docker compose down",
|
||||
"infra:logs": "docker compose logs -f",
|
||||
"dev": "npm run infra:up && echo 'Logs will be saved to api-dev.log' && tsx --watch src/server.ts 2>&1 | tee api-dev.log",
|
||||
"start": "node dist/server.js",
|
||||
"build": "tsc",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
# secrets.env.example
|
||||
# Copy this file to secrets.env and fill with real values
|
||||
# secrets.env is NOT tracked in git for security
|
||||
|
||||
# REQUIRED: Google Gemini API Key for image generation
|
||||
GEMINI_API_KEY=your_gemini_api_key_here
|
||||
|
||||
# OPTIONAL: For testing purposes (usually generated via API bootstrap)
|
||||
# These keys will be generated when you first run the API
|
||||
# MASTER_KEY=will_be_generated_on_bootstrap
|
||||
# API_KEY=will_be_generated_by_admin_endpoint
|
||||
|
|
@ -1,14 +1,24 @@
|
|||
import { createDbClient } from '@banatie/database';
|
||||
import { config } from 'dotenv';
|
||||
import path from 'path';
|
||||
import { existsSync } from 'fs';
|
||||
|
||||
// Load .env from api-service directory and OVERRIDE shell env vars
|
||||
// This is needed because docker-compose sets DATABASE_URL for Docker network
|
||||
config({ path: path.join(__dirname, '../.env'), override: true });
|
||||
// Load .env from api-service directory only if exists and not in Docker
|
||||
// In Docker (IS_DOCKER=true), environment variables are injected via docker-compose
|
||||
const envPath = path.join(__dirname, '../.env');
|
||||
if (existsSync(envPath) && !process.env['IS_DOCKER']) {
|
||||
config({ path: envPath });
|
||||
}
|
||||
|
||||
// Also load secrets.env if exists (for both dev and docker)
|
||||
const secretsPath = path.join(__dirname, '../secrets.env');
|
||||
if (existsSync(secretsPath)) {
|
||||
config({ path: secretsPath });
|
||||
}
|
||||
|
||||
const DATABASE_URL =
|
||||
process.env['DATABASE_URL'] ||
|
||||
'postgresql://banatie_user:banatie_secure_password@localhost:5434/banatie_db';
|
||||
'postgresql://banatie_user:banatie_secure_password@localhost:5460/banatie_db';
|
||||
|
||||
export const db = createDbClient(DATABASE_URL);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
# Multi-stage Dockerfile for Next.js Landing Page
|
||||
|
||||
# Stage 1: Dependencies
|
||||
FROM node:20-alpine AS deps
|
||||
WORKDIR /app
|
||||
|
||||
# Install pnpm
|
||||
RUN npm install -g pnpm@10.11.0
|
||||
|
||||
# Copy workspace configuration
|
||||
COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./
|
||||
|
||||
# Copy landing package.json
|
||||
COPY apps/landing/package.json ./apps/landing/
|
||||
|
||||
# Copy database package (workspace dependency)
|
||||
COPY packages/database/package.json ./packages/database/
|
||||
|
||||
# Install dependencies
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# Stage 2: Builder
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
|
||||
# Install pnpm
|
||||
RUN npm install -g pnpm@10.11.0
|
||||
|
||||
# Copy dependencies from deps stage
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY --from=deps /app/apps/landing/node_modules ./apps/landing/node_modules
|
||||
COPY --from=deps /app/packages/database/node_modules ./packages/database/node_modules
|
||||
|
||||
# Copy workspace files
|
||||
COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./
|
||||
|
||||
# Copy database package
|
||||
COPY packages/database ./packages/database
|
||||
|
||||
# Copy landing app
|
||||
COPY apps/landing ./apps/landing
|
||||
|
||||
# Set working directory to landing
|
||||
WORKDIR /app/apps/landing
|
||||
|
||||
# Build Next.js application
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
RUN pnpm build
|
||||
|
||||
# Stage 3: Production Runner
|
||||
FROM node:20-alpine AS runner
|
||||
WORKDIR /app
|
||||
|
||||
# Install pnpm
|
||||
RUN npm install -g pnpm@10.11.0
|
||||
|
||||
ENV NODE_ENV=production
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
|
||||
# Create non-root user
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
|
||||
# Copy workspace configuration
|
||||
COPY --from=builder /app/pnpm-workspace.yaml ./
|
||||
COPY --from=builder /app/package.json ./
|
||||
COPY --from=builder /app/pnpm-lock.yaml ./
|
||||
|
||||
# Copy database package
|
||||
COPY --from=builder /app/packages/database ./packages/database
|
||||
|
||||
# Copy built Next.js application
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/apps/landing/.next ./apps/landing/.next
|
||||
COPY --from=builder /app/apps/landing/package.json ./apps/landing/
|
||||
COPY --from=builder /app/apps/landing/public ./apps/landing/public
|
||||
|
||||
# Copy node_modules for runtime
|
||||
COPY --from=builder /app/node_modules ./node_modules
|
||||
COPY --from=builder /app/apps/landing/node_modules ./apps/landing/node_modules
|
||||
COPY --from=builder /app/packages/database/node_modules ./packages/database/node_modules
|
||||
|
||||
USER nextjs
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENV PORT=3000
|
||||
|
||||
WORKDIR /app/apps/landing
|
||||
|
||||
CMD ["pnpm", "start"]
|
||||
|
|
@ -4,7 +4,7 @@ import * as schema from '@banatie/database';
|
|||
|
||||
const connectionString =
|
||||
process.env.DATABASE_URL ||
|
||||
'postgresql://banatie_user:banatie_secure_password@localhost:5434/banatie_db';
|
||||
'postgresql://banatie_user:banatie_secure_password@localhost:5460/banatie_db';
|
||||
|
||||
// Create postgres client
|
||||
const client = postgres(connectionString);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,398 @@
|
|||
# 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)
|
||||
25
package.json
25
package.json
|
|
@ -10,39 +10,16 @@
|
|||
"pnpm": ">=8.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "pnpm --parallel run dev",
|
||||
"dev:api": "pnpm --filter @banatie/api-service dev",
|
||||
"dev:landing": "pnpm --filter @banatie/landing dev",
|
||||
"dev:studio": "pnpm --filter @banatie/studio dev",
|
||||
"dev:admin": "pnpm --filter @banatie/admin dev",
|
||||
"build": "pnpm -r build",
|
||||
"build:api": "pnpm --filter @banatie/api-service build",
|
||||
"build:landing": "pnpm --filter @banatie/landing build",
|
||||
"build:studio": "pnpm --filter @banatie/studio build",
|
||||
"build:admin": "pnpm --filter @banatie/admin build",
|
||||
"start:api": "pnpm --filter @banatie/api-service start",
|
||||
"start:landing": "pnpm --filter @banatie/landing start",
|
||||
"start:studio": "pnpm --filter @banatie/studio start",
|
||||
"start:admin": "pnpm --filter @banatie/admin start",
|
||||
"lint": "pnpm -r lint",
|
||||
"lint:api": "pnpm --filter @banatie/api-service lint",
|
||||
"lint:landing": "pnpm --filter @banatie/landing lint",
|
||||
"lint:studio": "pnpm --filter @banatie/studio lint",
|
||||
"lint:admin": "pnpm --filter @banatie/admin lint",
|
||||
"typecheck": "pnpm -r typecheck",
|
||||
"typecheck:api": "pnpm --filter @banatie/api-service typecheck",
|
||||
"typecheck:landing": "pnpm --filter @banatie/landing typecheck",
|
||||
"typecheck:studio": "pnpm --filter @banatie/studio typecheck",
|
||||
"typecheck:admin": "pnpm --filter @banatie/admin typecheck",
|
||||
"test": "vitest",
|
||||
"test:ui": "vitest --ui",
|
||||
"test:run": "vitest run",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
"test:api": "pnpm --filter @banatie/api-service test",
|
||||
"format": "prettier --write \"apps/**/*.{ts,tsx,js,jsx,json,css,md}\" \"packages/**/*.{ts,tsx,js,jsx,json,css,md}\" \"*.{ts,tsx,js,jsx,json,css,md}\" --ignore-unknown",
|
||||
"format:check": "prettier --check \"apps/**/*.{ts,tsx,js,jsx,json,css,md}\" \"packages/**/*.{ts,tsx,js,jsx,json,css,md}\" \"*.{ts,tsx,js,jsx,json,css,md}\" --ignore-unknown",
|
||||
"clean": "pnpm -r clean && rm -rf node_modules",
|
||||
"install:all": "pnpm install"
|
||||
"clean": "pnpm -r clean && rm -rf node_modules"
|
||||
},
|
||||
"keywords": [
|
||||
"monorepo",
|
||||
|
|
|
|||
|
|
@ -7,6 +7,6 @@ export default {
|
|||
dbCredentials: {
|
||||
url:
|
||||
process.env.DATABASE_URL ||
|
||||
'postgresql://banatie_user:banatie_secure_password@localhost:5434/banatie_db',
|
||||
'postgresql://banatie_user:banatie_secure_password@localhost:5460/banatie_db',
|
||||
},
|
||||
} satisfies Config;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
# Production Environment Configuration
|
||||
# This file is used when running docker compose in prod-env/
|
||||
|
||||
# Application Configuration
|
||||
NODE_ENV=production
|
||||
PORT=3000
|
||||
LOG_LEVEL=info
|
||||
API_BASE_URL=http://localhost:3000
|
||||
|
||||
# CORS Configuration
|
||||
CORS_ORIGIN=*
|
||||
|
||||
# Database Configuration (Docker internal network)
|
||||
DB_HOST=postgres
|
||||
DB_PORT=5432
|
||||
DB_NAME=banatie_db
|
||||
DB_USER=banatie_user
|
||||
DB_PASSWORD=banatie_secure_password
|
||||
DATABASE_URL=postgresql://banatie_user:banatie_secure_password@postgres:5432/banatie_db
|
||||
|
||||
# MinIO Storage Configuration (Docker internal network)
|
||||
MINIO_ROOT_USER=banatie_admin
|
||||
MINIO_ROOT_PASSWORD=banatie_storage_secure_key_2024
|
||||
STORAGE_TYPE=minio
|
||||
MINIO_ENDPOINT=minio:9000
|
||||
MINIO_ACCESS_KEY=banatie_service
|
||||
MINIO_SECRET_KEY=banatie_service_key_2024
|
||||
MINIO_USE_SSL=false
|
||||
MINIO_BUCKET_NAME=banatie
|
||||
MINIO_PUBLIC_URL=http://localhost:9000
|
||||
|
||||
# Multi-tenancy Configuration
|
||||
DEFAULT_ORG_ID=default
|
||||
DEFAULT_PROJECT_ID=main
|
||||
DEFAULT_USER_ID=system
|
||||
|
||||
# Presigned URL Configuration
|
||||
PRESIGNED_URL_EXPIRY=86400 # 24 hours
|
||||
|
||||
# File Upload Configuration
|
||||
MAX_FILE_SIZE=5242880 # 5MB
|
||||
MAX_FILES=3
|
||||
|
||||
# Directory Configuration (Docker paths)
|
||||
RESULTS_DIR=/app/results
|
||||
UPLOADS_DIR=/app/uploads/temp
|
||||
|
||||
# Logging Configuration
|
||||
TTI_LOG=logs/tti-log.md
|
||||
ENH_LOG=logs/enhancing.md
|
||||
|
||||
# IMPORTANT: Sensitive values should be in secrets.env (not tracked in git)
|
||||
# See secrets.env.example for required variables
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
# Production Environment
|
||||
|
||||
This directory contains the production Docker Compose configuration for running all Banatie services in containers.
|
||||
|
||||
## Services
|
||||
|
||||
- **API Service** (port 3000) - REST API for image generation
|
||||
- **Landing Page** (port 3001) - Public website
|
||||
- **PostgreSQL** (port 5460→5432) - Database
|
||||
- **MinIO** (ports 9000-9001) - Object storage with S3 compatibility
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Setup Secrets
|
||||
|
||||
```bash
|
||||
cp secrets.env.example secrets.env
|
||||
# Edit secrets.env with real values
|
||||
```
|
||||
|
||||
Required secrets:
|
||||
- `GEMINI_API_KEY` - Your Google Gemini API key
|
||||
|
||||
### 2. Start Services
|
||||
|
||||
```bash
|
||||
# From prod-env directory
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### 3. Check Status
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
docker compose logs -f app # API logs
|
||||
docker compose logs -f landing # Landing logs
|
||||
```
|
||||
|
||||
### 4. Stop Services
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
## Deployment to VPS
|
||||
|
||||
### Initial Setup
|
||||
|
||||
```bash
|
||||
# On VPS
|
||||
cd /path/to/banatie-service
|
||||
git pull
|
||||
cd prod-env
|
||||
cp secrets.env.example secrets.env
|
||||
# Edit secrets.env with production values
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
### Updates
|
||||
|
||||
```bash
|
||||
# On VPS
|
||||
cd /path/to/banatie-service/prod-env
|
||||
git pull
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Configuration is split into two files:
|
||||
|
||||
- **`.env`** - Base configuration (committed to git)
|
||||
- Service endpoints (Docker internal: `postgres:5432`, `minio:9000`)
|
||||
- Database credentials (development values)
|
||||
- Storage configuration
|
||||
- Application settings
|
||||
|
||||
- **`secrets.env`** - Sensitive secrets (NOT committed)
|
||||
- API keys (Gemini)
|
||||
- Production passwords (if different)
|
||||
- Testing keys (optional)
|
||||
|
||||
## Port Mappings
|
||||
|
||||
| Service | Host Port | Container Port | Description |
|
||||
|------------|-----------|----------------|-----------------------|
|
||||
| API | 3000 | 3000 | REST API |
|
||||
| Landing | 3001 | 3000 | Landing page |
|
||||
| PostgreSQL | 5460 | 5432 | Database |
|
||||
| MinIO API | 9000 | 9000 | S3-compatible storage |
|
||||
| MinIO UI | 9001 | 9001 | Web console |
|
||||
|
||||
## Data Persistence
|
||||
|
||||
All data is stored in the parent `data/` directory:
|
||||
|
||||
```
|
||||
../data/
|
||||
├── postgres/ # Database files
|
||||
├── storage/ # MinIO storage (4 drives for SNMD)
|
||||
├── results/ # Generated images
|
||||
└── uploads/ # Uploaded files
|
||||
```
|
||||
|
||||
## Accessing Services
|
||||
|
||||
- **API**: http://localhost:3000
|
||||
- **Landing**: http://localhost:3001
|
||||
- **MinIO Console**: http://localhost:9001
|
||||
- Username: `banatie_admin`
|
||||
- Password: (from MINIO_ROOT_PASSWORD in .env)
|
||||
|
||||
## Database Access
|
||||
|
||||
Connect to PostgreSQL from host:
|
||||
|
||||
```bash
|
||||
psql -h localhost -p 5460 -U banatie_user -d banatie_db
|
||||
```
|
||||
|
||||
From another Docker container (same network):
|
||||
|
||||
```bash
|
||||
psql -h postgres -p 5432 -U banatie_user -d banatie_db
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Check service health
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
### View logs
|
||||
|
||||
```bash
|
||||
docker compose logs -f # All services
|
||||
docker compose logs -f app # API only
|
||||
docker compose logs -f postgres # Database only
|
||||
```
|
||||
|
||||
### Restart specific service
|
||||
|
||||
```bash
|
||||
docker compose restart app
|
||||
```
|
||||
|
||||
### Rebuild after code changes
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
### Reset everything
|
||||
|
||||
```bash
|
||||
docker compose down -v # ⚠️ This deletes volumes!
|
||||
```
|
||||
|
||||
## Production Considerations
|
||||
|
||||
1. **Secrets Management**
|
||||
- Never commit `secrets.env`
|
||||
- Use strong passwords in production
|
||||
- Rotate API keys regularly
|
||||
|
||||
2. **Database Backups**
|
||||
- Set up automated backups of `data/postgres/`
|
||||
- Test restore procedures
|
||||
|
||||
3. **Resource Limits**
|
||||
- Add memory/CPU limits to docker-compose.yml if needed
|
||||
- Monitor with `docker stats`
|
||||
|
||||
4. **SSL/TLS**
|
||||
- Use reverse proxy (nginx/traefik) for HTTPS
|
||||
- Enable MinIO SSL for production
|
||||
|
||||
5. **Monitoring**
|
||||
- Set up health check endpoints
|
||||
- Configure alerts for service failures
|
||||
|
||||
## Development vs Production
|
||||
|
||||
This configuration is for **production** (all services in Docker).
|
||||
|
||||
For **development** (local API, Docker infrastructure):
|
||||
- Use `apps/api-service/docker-compose.yml`
|
||||
- Run `pnpm dev` from api-service directory
|
||||
- Connects to Docker services via `localhost:5460` and `localhost:9000`
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
|
||||
services:
|
||||
# API Service
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./apps/api-service/Dockerfile.mono
|
||||
target: development
|
||||
context: ..
|
||||
dockerfile: apps/api-service/Dockerfile
|
||||
target: production
|
||||
container_name: banatie-app
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- ./apps/api-service/src:/app/apps/api-service/src
|
||||
- ./apps/api-service/logs:/app/apps/api-service/logs
|
||||
- ./packages:/app/packages
|
||||
- ../apps/api-service/logs:/app/apps/api-service/logs
|
||||
- ../data/results:/app/results
|
||||
- ../data/uploads:/app/uploads
|
||||
networks:
|
||||
- banatie-network
|
||||
depends_on:
|
||||
|
|
@ -19,40 +19,43 @@ services:
|
|||
condition: service_healthy
|
||||
minio:
|
||||
condition: service_healthy
|
||||
env_file:
|
||||
- .env
|
||||
- secrets.env
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
- DATABASE_URL=${DATABASE_URL}
|
||||
- GEMINI_API_KEY=${GEMINI_API_KEY}
|
||||
- STORAGE_TYPE=${STORAGE_TYPE}
|
||||
- MINIO_ENDPOINT=${MINIO_ENDPOINT}
|
||||
- MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY}
|
||||
- MINIO_SECRET_KEY=${MINIO_SECRET_KEY}
|
||||
- MINIO_USE_SSL=${MINIO_USE_SSL}
|
||||
- MINIO_BUCKET_NAME=${MINIO_BUCKET_NAME}
|
||||
- MINIO_PUBLIC_URL=${MINIO_PUBLIC_URL}
|
||||
- API_BASE_URL=${API_BASE_URL}
|
||||
- DEFAULT_ORG_ID=${DEFAULT_ORG_ID}
|
||||
- DEFAULT_PROJECT_ID=${DEFAULT_PROJECT_ID}
|
||||
- DEFAULT_USER_ID=${DEFAULT_USER_ID}
|
||||
- PRESIGNED_URL_EXPIRY=${PRESIGNED_URL_EXPIRY}
|
||||
- MAX_FILE_SIZE=${MAX_FILE_SIZE}
|
||||
- MAX_FILES=${MAX_FILES}
|
||||
- RESULTS_DIR=${RESULTS_DIR}
|
||||
- UPLOADS_DIR=${UPLOADS_DIR}
|
||||
- LOG_LEVEL=${LOG_LEVEL}
|
||||
- PORT=${PORT}
|
||||
- CORS_ORIGIN=${CORS_ORIGIN}
|
||||
- TTI_LOG=${TTI_LOG}
|
||||
- IS_DOCKER=true
|
||||
- NODE_ENV=production
|
||||
restart: unless-stopped
|
||||
|
||||
# Landing Page
|
||||
landing:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: apps/landing/Dockerfile
|
||||
container_name: banatie-landing
|
||||
ports:
|
||||
- "3001:3000"
|
||||
networks:
|
||||
- banatie-network
|
||||
depends_on:
|
||||
- postgres
|
||||
env_file:
|
||||
- .env
|
||||
- secrets.env
|
||||
environment:
|
||||
- IS_DOCKER=true
|
||||
- NODE_ENV=production
|
||||
restart: unless-stopped
|
||||
|
||||
# PostgreSQL Database
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
container_name: banatie-postgres
|
||||
ports:
|
||||
- "5434:5432"
|
||||
- "5460:5432"
|
||||
volumes:
|
||||
- ./data/postgres:/var/lib/postgresql/data
|
||||
- ./scripts/init-db.sql:/docker-entrypoint-initdb.d/01-init.sql
|
||||
- ../data/postgres:/var/lib/postgresql/data
|
||||
- ../scripts/init-db.sql:/docker-entrypoint-initdb.d/01-init.sql
|
||||
networks:
|
||||
- banatie-network
|
||||
environment:
|
||||
|
|
@ -67,19 +70,19 @@ services:
|
|||
start_period: 40s
|
||||
restart: unless-stopped
|
||||
|
||||
# SNMD MinIO Setup - Production Ready
|
||||
# MinIO Object Storage - Production Ready with SNMD
|
||||
minio:
|
||||
image: quay.io/minio/minio:latest
|
||||
container_name: banatie-storage
|
||||
ports:
|
||||
- "9000:9000" # S3 API
|
||||
- "9001:9001" # Console
|
||||
- "9001:9001" # Web Console
|
||||
volumes:
|
||||
# SNMD: 4 drives for full S3 compatibility and erasure coding
|
||||
- ./data/storage/drive1:/data1
|
||||
- ./data/storage/drive2:/data2
|
||||
- ./data/storage/drive3:/data3
|
||||
- ./data/storage/drive4:/data4
|
||||
- ../data/storage/drive1:/data1
|
||||
- ../data/storage/drive2:/data2
|
||||
- ../data/storage/drive3:/data3
|
||||
- ../data/storage/drive4:/data4
|
||||
networks:
|
||||
- banatie-network
|
||||
environment:
|
||||
|
|
@ -98,6 +101,7 @@ services:
|
|||
start_period: 40s
|
||||
restart: unless-stopped
|
||||
|
||||
# MinIO Storage Initialization
|
||||
storage-init:
|
||||
image: minio/mc:latest
|
||||
container_name: banatie-storage-init
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
# secrets.env.example
|
||||
# Copy this file to secrets.env and fill with real values
|
||||
# secrets.env is NOT tracked in git for security
|
||||
|
||||
# REQUIRED: Google Gemini API Key for image generation
|
||||
GEMINI_API_KEY=your_gemini_api_key_here
|
||||
|
||||
# OPTIONAL: For testing purposes (usually generated via API)
|
||||
# MASTER_KEY=will_be_generated_on_bootstrap
|
||||
# API_KEY=will_be_generated_by_admin_endpoint
|
||||
Loading…
Reference in New Issue