Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/stevenrq/sgivu/llms.txt

Use this file to discover all available pages before exploring further.

Overview

SGIVU uses Docker Compose to orchestrate all microservices, databases, and supporting infrastructure. The compose setup is located in infra/compose/sgivu-docker-compose/ and provides both development and production configurations.

Compose Files

docker-compose.dev.yml

Development configuration with:
  • All services with exposed ports for direct access
  • Native profile for Config Server (loads from local filesystem)
  • Volume mount for config repository: ../../../../sgivu-config-repo:/config-repo
  • Uses .env.dev environment file

docker-compose.yml

Production configuration with:
  • Minimal port exposure (only Gateway:8080 and Auth:9000)
  • Git profile for Config Server (loads from GitHub repository)
  • Uses .env environment file
  • extra_hosts configuration to resolve EC2 hostname internally

Quick Start

Development Stack

cd infra/compose/sgivu-docker-compose
cp .env.dev.example .env.dev
# Edit .env.dev with your values
./run.bash --dev

Production Stack

cd infra/compose/sgivu-docker-compose
cp .env.example .env
# Edit .env with production values
./run.bash --prod

Stop Stack

docker compose down

# Remove volumes (WARNING: deletes all data)
docker compose down -v

Service Definitions

Infrastructure Services

sgivu-postgres

sgivu-postgres:
  container_name: sgivu-postgres
  image: postgres:16
  ports:
    - "5432:5432"  # Dev only
  restart: always
  env_file: .env
  networks:
    - sgivu-network
  volumes:
    - postgres-data:/var/lib/postgresql/data
Purpose: Shared PostgreSQL instance hosting all service databases Databases:
  • sgivu_auth_db: OAuth2 clients, authorizations, consent
  • sgivu_user_db: Users, roles, permissions
  • sgivu_client_db: Customer/client management
  • sgivu_vehicle_db: Vehicle inventory
  • sgivu_purchase_sale_db: Transaction records
  • sgivu_ml_db: ML model artifacts and predictions
Environment Variables:
  • POSTGRES_HOST=sgivu-postgres
  • POSTGRES_DB=postgres
  • POSTGRES_USER=postgres
  • POSTGRES_PASSWORD=<your-password>

sgivu-mysql

sgivu-mysql:
  container_name: sgivu-mysql
  image: mysql:8
  command: --mysql-native-password=ON
  ports:
    - "3306:3306"  # Dev only
  restart: always
  env_file: .env
  networks:
    - sgivu-network
  volumes:
    - mysql-data:/var/lib/mysql
    - ./mysql-init:/docker-entrypoint-initdb.d
Purpose: MySQL instance used exclusively by Zipkin for trace storage Environment Variables:
  • MYSQL_HOST=sgivu-mysql
  • MYSQL_ROOT_PASSWORD=<your-password>
  • MYSQL_DATABASE=sgivu_zipkin_db
  • MYSQL_USER=zipkin
  • MYSQL_PASSWORD=<your-password>
MySQL is not used by any business services. All application data is stored in PostgreSQL.

sgivu-redis

sgivu-redis:
  container_name: sgivu-redis
  image: redis:7
  ports:
    - "6379:6379"  # Dev only
  command: >
    sh -c "redis-server --requirepass \"$REDIS_PASSWORD\""
  env_file: .env
  restart: always
  networks:
    - sgivu-network
  volumes:
    - redis-data:/data
Purpose: Session storage for Gateway’s BFF pattern Usage: sgivu-gateway stores HTTP sessions containing OAuth2 tokens in Redis, enabling horizontal scaling while maintaining session state. Configuration:
  • Session namespace: spring:session:sgivu-gateway
  • Store type: spring.session.store-type=redis
  • Dependencies: spring-session-data-redis, spring-boot-starter-data-redis-reactive
Environment Variables:
  • REDIS_HOST=sgivu-redis
  • REDIS_PORT=6379
  • REDIS_PASSWORD=<your-password> (must match in both container and Gateway config)
Redis is used only by sgivu-gateway for session persistence. It is not used for rate limiting, caching, or direct RedisTemplate operations.

Core Services

sgivu-config

sgivu-config:
  container_name: sgivu-config
  image: stevenrq/sgivu-config:v1
  ports:
    - "8888:8888"  # Dev only
  restart: always
  networks:
    - sgivu-network
  environment:
    - SPRING_PROFILES_ACTIVE=git  # or 'native' for dev
    - SPRING_CLOUD_CONFIG_SERVER_GIT_URI=https://github.com/stevenrq/sgivu-config-repo.git
    - SPRING_CLOUD_CONFIG_SERVER_GIT_DEFAULT_LABEL=main
Purpose: Centralized configuration server for all microservices Profiles:
  • native: Loads configuration from local filesystem (development)
  • git: Loads configuration from GitHub repository (production)
Endpoints:
  • GET /{service}/{profile}: Retrieve configuration for a service
  • Example: http://sgivu-config:8888/sgivu-gateway/dev
Configuration Repository: sgivu-config-repo

sgivu-discovery

sgivu-discovery:
  container_name: sgivu-discovery
  image: stevenrq/sgivu-discovery:v1
  ports:
    - "8761:8761"
  restart: always
  networks:
    - sgivu-network
  env_file: .env
Purpose: Eureka service registry for service discovery Endpoints:
  • GET /eureka/apps: List all registered services
  • Web UI: http://sgivu-discovery:8761
Configuration:
  • All services configure eureka.client.service-url.defaultZone=http://sgivu-discovery:8761/eureka
  • Gateway uses lb://service-name for load-balanced routing

sgivu-zipkin

sgivu-zipkin:
  container_name: sgivu-zipkin
  image: openzipkin/zipkin
  ports:
    - "9411:9411"
  restart: always
  networks:
    - sgivu-network
  env_file: .env
  depends_on:
    - sgivu-mysql
Purpose: Distributed tracing system for request correlation Storage: MySQL (sgivu_zipkin_db) Environment Variables:
  • STORAGE_TYPE=mysql
  • MYSQL_HOST=sgivu-mysql
  • MYSQL_DB=sgivu_zipkin_db
  • MYSQL_USER=zipkin
  • MYSQL_PASS=<your-password>
Web UI: http://localhost:9411
Zipkin UI is exposed without authentication. In production, restrict access via IP whitelist or VPN.

Business Services

sgivu-auth

sgivu-auth:
  container_name: sgivu-auth
  image: stevenrq/sgivu-auth:v1
  ports:
    - "9000:9000"
  restart: always
  networks:
    - sgivu-network
  env_file: .env
  depends_on:
    - sgivu-postgres
    - sgivu-config
    - sgivu-discovery
Purpose: OAuth 2.1 / OpenID Connect Authorization Server Key Features:
  • JWT issuance with RSA signing (keystore.jks)
  • OAuth2 client registration
  • User authentication via sgivu-user service
  • Spring Session JDBC for authorization consent
Endpoints:
  • /.well-known/openid-configuration: OIDC discovery
  • /oauth2/authorize: Authorization endpoint
  • /oauth2/token: Token endpoint
  • /oauth2/jwks: JSON Web Key Set
  • /login: Login page
  • /actuator/health: Health check
Database: sgivu_auth_db (PostgreSQL) Critical Environment Variables:
  • ISSUER_URL: Must match JWT iss claim
  • JWT_KEYSTORE_LOCATION=classpath:keystore.jks
  • JWT_KEYSTORE_PASSWORD
  • JWT_KEY_ALIAS=sgivu-jwt
  • JWT_KEY_PASSWORD
  • SGIVU_GATEWAY_SECRET: OAuth2 client secret (BCrypt hashed in DB)

sgivu-gateway

sgivu-gateway:
  container_name: sgivu-gateway
  image: stevenrq/sgivu-gateway:v1
  ports:
    - "8080:8080"
  restart: always
  networks:
    - sgivu-network
  env_file: .env
  extra_hosts:  # Production only
    - "ec2-98-86-100-220.compute-1.amazonaws.com:host-gateway"
  depends_on:
    - sgivu-config
    - sgivu-discovery
    - sgivu-auth
    - sgivu-redis
Purpose: API Gateway and Backend For Frontend (BFF) Key Features:
  • OAuth2 Client (authorization_code + PKCE)
  • Token relay to downstream services
  • Circuit breaker with Resilience4j
  • Session management (Redis-backed)
  • Route rewriting for Swagger UI
Endpoints:
  • /auth/session: Session info for SPA
  • /v1/*: Business APIs (routes to microservices)
  • /docs/{service}/*: Swagger UI proxy
  • /actuator/health: Health check
Routes (see GatewayRoutesConfig.java):
  • /v1/users/** → lb://sgivu-user
  • /v1/persons/** → lb://sgivu-user
  • /v1/clients/** → lb://sgivu-client
  • /v1/vehicles/** → lb://sgivu-vehicle
  • /v1/purchase-sales/** → lb://sgivu-purchase-sale
  • /v1/ml/** → http://sgivu-ml:8000
Extra Hosts: In production, maps EC2 hostname to host gateway so Gateway can reach Auth Server via Nginx

sgivu-user

sgivu-user:
  container_name: sgivu-user
  image: stevenrq/sgivu-user:v1
  ports:
    - "8081:8081"  # Dev only
  restart: always
  networks:
    - sgivu-network
  env_file: .env
  extra_hosts:  # Production only
    - "ec2-98-86-100-220.compute-1.amazonaws.com:host-gateway"
  depends_on:
    - sgivu-postgres
    - sgivu-config
    - sgivu-discovery
    - sgivu-auth
Purpose: User, role, and permission management Features:
  • User CRUD with person associations
  • Role and permission management
  • Internal endpoint for Auth Server credential validation
Endpoints:
  • GET /api/v1/users: List users
  • POST /api/v1/users: Create user
  • GET /api/v1/internal/users/by-username/{username}: Internal (requires X-Internal-Service-Key)
  • /actuator/health: Health check
Database: sgivu_user_db (PostgreSQL) Migrations: V1__initial_schema.sql, seed data in R__seed_data.sql (creates steven admin user)

sgivu-client

sgivu-client:
  container_name: sgivu-client
  image: stevenrq/sgivu-client:v1
  ports:
    - "8082:8082"  # Dev only
  restart: always
  networks:
    - sgivu-network
  env_file: .env
  extra_hosts:  # Production only
    - "ec2-98-86-100-220.compute-1.amazonaws.com:host-gateway"
  depends_on:
    - sgivu-postgres
    - sgivu-config
    - sgivu-discovery
    - sgivu-auth
Purpose: Customer/client management (persons and companies) Features:
  • Person and company CRUD
  • Address management
  • Multi-criteria search
Endpoints:
  • GET /api/v1/clients/persons: List person clients
  • GET /api/v1/clients/companies: List company clients
  • /actuator/health: Health check
Database: sgivu_client_db (PostgreSQL)

sgivu-vehicle

sgivu-vehicle:
  container_name: sgivu-vehicle
  image: stevenrq/sgivu-vehicle:v1
  ports:
    - "8083:8083"  # Dev only
  restart: always
  networks:
    - sgivu-network
  env_file: .env
  extra_hosts:  # Production only
    - "ec2-98-86-100-220.compute-1.amazonaws.com:host-gateway"
  depends_on:
    - sgivu-postgres
    - sgivu-config
    - sgivu-discovery
    - sgivu-auth
Purpose: Vehicle inventory management Features:
  • Vehicle CRUD (make, model, year, VIN, etc.)
  • Image upload to S3
  • Pre-signed URL generation for image access
  • Vehicle status tracking
Endpoints:
  • GET /api/v1/vehicles: List vehicles
  • POST /api/v1/vehicles: Create vehicle
  • POST /api/v1/vehicles/{id}/images: Upload images
  • /actuator/health: Health check
Database: sgivu_vehicle_db (PostgreSQL) AWS Integration:
  • S3 bucket: AWS_VEHICLES_BUCKET=sgivu-vehicle-images
  • Region: AWS_REGION=us-east-1
  • CORS: AWS_S3_ALLOWED_ORIGINS

sgivu-purchase-sale

sgivu-purchase-sale:
  container_name: sgivu-purchase-sale
  image: stevenrq/sgivu-purchase-sale:v1
  ports:
    - "8084:8084"  # Dev only
  restart: always
  networks:
    - sgivu-network
  env_file: .env
  extra_hosts:  # Production only
    - "ec2-98-86-100-220.compute-1.amazonaws.com:host-gateway"
  depends_on:
    - sgivu-postgres
    - sgivu-config
    - sgivu-discovery
    - sgivu-auth
Purpose: Vehicle purchase and sale transaction management Features:
  • Purchase contract creation
  • Sale contract creation
  • Transaction history
  • Integration with vehicle and client services
Endpoints:
  • GET /api/v1/purchase-sales: List transactions
  • POST /api/v1/purchase-sales/purchases: Create purchase
  • POST /api/v1/purchase-sales/sales: Create sale
  • /actuator/health: Health check
Database: sgivu_purchase_sale_db (PostgreSQL)

sgivu-ml

sgivu-ml:
  container_name: sgivu-ml
  image: stevenrq/sgivu-ml:v1
  ports:
    - "8000:8000"  # Dev only
  restart: always
  networks:
    - sgivu-network
  env_file: .env
  extra_hosts:  # Production only
    - "ec2-98-86-100-220.compute-1.amazonaws.com:host-gateway"
  depends_on:
    - sgivu-postgres
    - sgivu-auth
    - sgivu-client
    - sgivu-gateway
    - sgivu-user
    - sgivu-vehicle
    - sgivu-purchase-sale
Purpose: Machine learning service for demand forecasting Technology: FastAPI + Uvicorn, scikit-learn, pandas Features:
  • Demand prediction by vehicle segment
  • Model retraining with historical data
  • Model metadata and versioning
  • JWT validation via OIDC
Endpoints:
  • POST /v1/ml/predict: Generate prediction
  • POST /v1/ml/predict-with-history: Prediction with historical context
  • POST /v1/ml/retrain: Trigger model retraining
  • GET /v1/ml/models/latest: Model metadata
  • GET /health or /actuator/health: Health check
  • GET /docs: FastAPI OpenAPI docs
Database: sgivu_ml_db (PostgreSQL) Configuration (Pydantic Settings):
  • ENVIRONMENT=prod
  • SGIVU_AUTH_DISCOVERY_URL=http://sgivu-auth:9000/.well-known/openid-configuration
  • MODEL_DIR=models
  • MODEL_NAME=demand_forecaster
  • REQUEST_TIMEOUT_SECONDS=15

Environment Variables

Master Reference

See infra/compose/sgivu-docker-compose/ENV-REFERENCE.md for complete documentation.

Critical Variables

Profile Selection

SPRING_PROFILES_ACTIVE=prod  # or 'dev'
Selects {service}-prod.yml or {service}-dev.yml from Config Server.

JWT Configuration

# MUST BE IDENTICAL
ISSUER_URL=http://your-ec2-hostname
SGIVU_AUTH_URL=http://your-ec2-hostname

# JWT Signing
JWT_KEYSTORE_LOCATION=classpath:keystore.jks
JWT_KEYSTORE_PASSWORD=<your-keystore-password>
JWT_KEY_ALIAS=sgivu-jwt
JWT_KEY_PASSWORD=<your-key-password>
If ISSUER_URL and SGIVU_AUTH_URL differ, all JWT validation fails → complete authentication failure.

OAuth2 Client Secret

SGIVU_GATEWAY_SECRET=<your-gateway-secret>
Stored BCrypt-hashed in sgivu_auth_db. Changing after initial setup requires deleting client registration.

Internal Service Communication

SERVICE_INTERNAL_SECRET_KEY=<your-internal-secret>
Must be identical across all 7 backend services + sgivu-ml. Used for X-Internal-Service-Key header.

Redis Configuration

REDIS_HOST=sgivu-redis
REDIS_PORT=6379
REDIS_PASSWORD=<your-redis-password>
REDIS_PASSWORD must match in both:
  1. Redis container --requirepass command
  2. Gateway spring.data.redis.password

Frontend URLs

# Development
DEV_ANGULAR_APP_URL=http://localhost:4200

# Production
PROD_ANGULAR_APP_URL=http://your-ec2-hostname
Controls:
  • CORS configuration in Auth and Gateway
  • OAuth2 redirect URIs
  • Post-logout redirect URIs

AWS Configuration

AWS_ACCESS_KEY=<your-access-key>
AWS_SECRET_KEY=<your-secret-key>
AWS_REGION=us-east-1
AWS_VEHICLES_BUCKET=sgivu-vehicle-images
AWS_S3_ALLOWED_ORIGINS=http://your-ec2-hostname

Database Configuration

PostgreSQL (shared instance):
POSTGRES_HOST=sgivu-postgres
POSTGRES_DB=postgres
POSTGRES_USER=postgres
POSTGRES_PASSWORD=<your-postgres-password>
Per-service databases (example for Auth):
PROD_AUTH_DB_HOST=sgivu-postgres
PROD_AUTH_DB_PORT=5432
PROD_AUTH_DB_NAME=sgivu_auth_db
PROD_AUTH_DB_USERNAME=postgres
PROD_AUTH_DB_PASSWORD=<your-postgres-password>

Management Scripts

run.bash

Unified script to launch the stack:
# Development
./run.bash --dev

# Production
./run.bash --prod
Automatically selects the appropriate compose file and environment.

rebuild-service.bash

Rebuild and restart a single service without affecting others:
# Development
./rebuild-service.bash --dev sgivu-auth

# Production
./rebuild-service.bash --prod sgivu-gateway
Actions:
  1. Builds/pulls latest image
  2. Publishes image (if applicable)
  3. Recreates only that container

build-and-push-images.bash

Build and publish all service images:
./build-and-push-images.bash
Actions:
  • Traverses all services in apps/backend/, apps/frontend/, apps/ml/
  • Invokes build-image.bash for each service
  • Pushes to Docker Hub (stevenrq/* namespace)

Networking

Bridge Network

networks:
  sgivu-network:
    driver: bridge
All services communicate through sgivu-network. Services reference each other by container name (e.g., http://sgivu-auth:9000).

Extra Hosts (Production)

In production, services need to reach the EC2 hostname (for OAuth2 flows through Nginx):
extra_hosts:
  - "ec2-98-86-100-220.compute-1.amazonaws.com:host-gateway"
Maps EC2 hostname to Docker host gateway, allowing containers to reach Nginx.
In development, this is not needed. Services communicate directly via Docker network.

Volume Management

Persistent Volumes

volumes:
  mysql-data:      # Zipkin traces
  postgres-data:   # All service databases
  redis-data:      # Gateway sessions

Backup Volumes

# Backup PostgreSQL
docker compose exec sgivu-postgres pg_dumpall -U postgres > backup.sql

# Restore PostgreSQL
cat backup.sql | docker compose exec -T sgivu-postgres psql -U postgres

# Backup Redis
docker compose exec sgivu-redis redis-cli -a "$REDIS_PASSWORD" SAVE
cp /var/lib/docker/volumes/sgivu-docker-compose_redis-data/_data/dump.rdb ./backup/

Clean Volumes

This deletes all data permanently. Use with caution.
docker compose down -v

Troubleshooting

Service Dependency Issues

Problem: Services fail to start due to missing dependencies Solution: Verify startup order with depends_on. Wait for Config and Discovery before starting other services:
# Check service status
docker compose ps

# View logs for dependency
docker compose logs sgivu-config

Config Validation

# Validate compose file
docker compose config

# Check which environment file is loaded
docker compose config | grep env_file

Port Already Allocated

# Find conflicting process
lsof -i :8080

# Or adjust port mapping in compose file
ports:
  - "8090:8080"  # Map to different host port

Variable Substitution

Problem: Variables not replaced (show as ${VAR_NAME}) Solution: Ensure .env file is in same directory as docker-compose.yml and contains all required variables:
# Verify variable resolution
docker compose config | grep ISSUER_URL

# Check for missing variables
docker compose config 2>&1 | grep -i "warn"

Next Steps

Build docs developers (and LLMs) love