Skip to main content
SGIVU uses environment variables to configure all microservices. This guide explains each configuration option, its purpose, and critical dependencies between variables.

Configuration Flow

SGIVU’s configuration follows this hierarchy:
.env / .env.dev (environment files)

docker-compose.yml (container environment)

Config Server (centralized YAML configs with ${VAR} placeholders)

Spring Boot @Value / Pydantic Settings (application runtime)
The SPRING_PROFILES_ACTIVE variable is the master switch that selects between dev and prod configuration overlays.

Environment Files

SGIVU provides two environment templates:
  • .env.example - Production template with placeholders
  • .env.dev.example - Development template with working defaults
Never commit actual .env or .env.dev files with real secrets to version control. Always use .example templates and replace placeholders.

Core Configuration

Spring Profile

VariableDefaultDescription
SPRING_PROFILES_ACTIVEdevSelects configuration overlay: dev or prod. Determines which YAML files are loaded from Config Server.
Development:
SPRING_PROFILES_ACTIVE=dev
Production:
SPRING_PROFILES_ACTIVE=prod

Service Discovery (Eureka)

VariableDefaultDescription
EUREKA_URLhttp://sgivu-discovery:8761/eurekaEureka service registry URL. All services must register here.
If EUREKA_URL is incorrect, services cannot register and the gateway will return 503 errors for all API routes.
# Development (Docker network)
EUREKA_URL=http://sgivu-discovery:8761/eureka

# Production
EUREKA_URL=http://your-ec2-host:8761/eureka

Critical Configuration Dependencies

Some variables have hidden dependencies that will break authentication if misconfigured:

SGIVU_AUTH_URL ↔ ISSUER_URL

These two variables must match exactly or all JWT validation will fail.
VariableUsed ByPurpose
ISSUER_URLsgivu-authWritten into the iss claim of every JWT token
SGIVU_AUTH_URLAll resource serversUsed as issuer-uri to validate the iss claim
Development:
# Only SGIVU_AUTH_URL needed (ISSUER_URL uses default)
SGIVU_AUTH_URL=http://sgivu-auth:9000
Production:
# Both must point to public hostname
SGIVU_AUTH_URL=http://your-ec2-public-hostname
ISSUER_URL=http://your-ec2-public-hostname

REDIS_PASSWORD

This password must be identical in two places:
  1. Redis container --requirepass flag
  2. Gateway’s spring.data.redis.password configuration
REDIS_PASSWORD=your-secure-redis-password
If these don’t match, the gateway cannot connect to Redis and all HTTP sessions will fail, preventing authentication.

SGIVU_GATEWAY_SECRET

sgivu-auth stores this secret hashed with BCrypt on first startup. Changing it later requires deleting the OAuth2 client registration from the database.
SGIVU_GATEWAY_SECRET=your-gateway-oauth2-secret
This is the OAuth2 client secret used for the authorization code flow between sgivu-auth and sgivu-gateway.

SERVICE_INTERNAL_SECRET_KEY

This secret must be identical in all 7 backend services + sgivu-ml. If it differs in even one service, internal service-to-service calls will fail with 401/403.
SERVICE_INTERNAL_SECRET_KEY=your-internal-service-secret
Used in the X-Internal-Service-Key header for service-to-service communication without JWT tokens. Examples of flows using this key:
  • sgivu-authsgivu-user: Validate credentials during login
  • sgivu-mlsgivu-purchase-sale: Fetch contracts for training
  • sgivu-mlsgivu-vehicle: Fetch vehicle data

Service URLs

Internal Service URLs

These are used for direct service-to-service HTTP calls:
# Auth service (must match ISSUER_URL in production)
SGIVU_AUTH_URL=http://sgivu-auth:9000

# Gateway (for OAuth2 redirect URI registration)
SGIVU_GATEWAY_URL=http://sgivu-gateway:8080

# Business services
SGIVU_USER_URL=http://sgivu-user:8081
SGIVU_CLIENT_URL=http://sgivu-client:8082
SGIVU_VEHICLE_URL=http://sgivu-vehicle:8083
SGIVU_PURCHASE_SALE_URL=http://sgivu-purchase-sale:8084
The gateway uses Eureka service discovery (lb://service-name) and does not use these URL variables. These are only for direct service-to-service calls.

Frontend URL

Controls CORS, OAuth2 redirects, and post-logout behavior:
# Development
DEV_ANGULAR_APP_URL=http://localhost:4200

# Production
PROD_ANGULAR_APP_URL=http://your-ec2-public-hostname
PROD_ANGULAR_APP_URL must match the domains in AWS_S3_ALLOWED_ORIGINS for the browser to load vehicle images from S3 without CORS errors.

JWT Configuration

Keystore Settings

SGIVU uses RSA keys stored in a JKS keystore for 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 any of these values are incorrect, sgivu-auth will fail to start.

Generate a keystore:

keytool -genkeypair -alias sgivu-jwt \
  -keyalg RSA -keysize 2048 \
  -storetype JKS -keystore keystore.jks \
  -validity 3650 \
  -storepass YOUR_KEYSTORE_PASSWORD \
  -keypass YOUR_KEY_PASSWORD \
  -dname "CN=SGIVU Auth, OU=Security, O=SGIVU, L=City, ST=State, C=US"

Database Configuration

PostgreSQL (Shared Instance)

All services share one PostgreSQL container but use separate databases:
# Container initialization
POSTGRES_HOST=sgivu-postgres
POSTGRES_DB=postgres
POSTGRES_USER=postgres
POSTGRES_PASSWORD=your-postgres-password

Per-Service Database Configuration

Each microservice has its own database:
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
For development, use DEV_ prefix instead of PROD_.

Flyway Migration

# Development: allows baseline on existing databases
FLYWAY_BASELINE_ON_MIGRATE=true

# Production: requires clean migration history
FLYWAY_BASELINE_ON_MIGRATE=false
In production, FLYWAY_BASELINE_ON_MIGRATE=false ensures you don’t accidentally hide pending migrations.

Redis Configuration

Redis is used exclusively by sgivu-gateway for HTTP session storage (BFF pattern):
REDIS_HOST=sgivu-redis
REDIS_PORT=6379
REDIS_PASSWORD=your-redis-password
Redis is not used for:
  • Rate limiting
  • Caching
  • Direct RedisTemplate operations
It only stores Spring Session data for the gateway.

AWS / S3 Configuration

Required for vehicle image storage:
# AWS credentials
AWS_ACCESS_KEY=your-aws-access-key
AWS_SECRET_KEY=your-aws-secret-key
AWS_REGION=us-east-1

# S3 bucket
AWS_VEHICLES_BUCKET=sgivu-vehicle-images

# CORS origins (must match frontend URL)
AWS_S3_ALLOWED_ORIGINS=http://your-frontend-url,http://your-s3-bucket-url
AWS_S3_ALLOWED_ORIGINS must include the same domains as PROD_ANGULAR_APP_URL to prevent CORS errors when loading images.

MySQL / Zipkin Configuration

MySQL is used exclusively as storage for Zipkin distributed tracing:
# MySQL container
MYSQL_HOST=sgivu-mysql
MYSQL_ROOT_PASSWORD=your-mysql-root-password
MYSQL_DATABASE=sgivu_zipkin_db
MYSQL_USER=zipkin
MYSQL_PASSWORD=your-mysql-password

# Zipkin storage (uses different variable names)
STORAGE_TYPE=mysql
MYSQL_DB=sgivu_zipkin_db
MYSQL_PASS=your-mysql-password
The Zipkin Docker image uses different variable names (MYSQL_DB vs MYSQL_DATABASE, MYSQL_PASS vs MYSQL_PASSWORD) for the same values.

ML Service Configuration (FastAPI)

The ML service uses Pydantic Settings and consumes environment variables directly (not through Config Server):
# Environment
ENVIRONMENT=prod
APP_NAME=sgivu-ml
APP_VERSION=0.1.0

# Auth discovery
SGIVU_AUTH_DISCOVERY_URL=http://sgivu-auth:9000/.well-known/openid-configuration

# Model settings
MODEL_DIR=models
MODEL_NAME=demand_forecaster
REQUEST_TIMEOUT_SECONDS=15
DEFAULT_HORIZON_MONTHS=6
MIN_HISTORY_MONTHS=1
TARGET_COLUMN=sales_count

# Retraining schedule
RETRAIN_CRON="0 3 1 * *"
RETRAIN_TIMEZONE=UTC

# Permissions (leave empty to only require valid JWT)
PERMISSIONS_PREDICT=ml:predict
PERMISSIONS_RETRAIN=ml:retrain
PERMISSIONS_MODELS=ml:models

# Database
DATABASE_ENV=prod
PROD_ML_DB_HOST=sgivu-postgres
PROD_ML_DB_PORT=5432
PROD_ML_DB_NAME=sgivu_ml_db
PROD_ML_DB_USERNAME=postgres
PROD_ML_DB_PASSWORD=your-postgres-password
DATABASE_AUTO_CREATE=false
DATABASE_ECHO=false
SGIVU_AUTH_DISCOVERY_URL must return an issuer field that matches ISSUER_URL, or JWT validation will fail.

OpenAPI / Swagger Configuration

# Production only
OPENAPI_SERVER_URL=http://your-ec2-public-hostname
This ensures “Try it out” in Swagger UI uses the correct hostname. In development, Swagger defaults to localhost.

Configuration Validation

Validate your configuration before starting services:
# Check environment file syntax
docker compose -f docker-compose.dev.yml --env-file .env.dev config

# Verify all required variables are set
grep -v '^#' .env.dev | grep '=.*your-.*-here'
Common validation issues:
  • Missing required variables
  • Mismatched paired variables (ISSUER_URL vs SGIVU_AUTH_URL)
  • Incorrect database credentials
  • Wrong CORS origins

Environment File Templates

Complete working templates are available in the repository:

Development Template

.env.dev.example with working local defaults

Production Template

.env.example with placeholders for production

Variable Reference

Detailed explanation of every variable

Config Repository

Centralized YAML configuration repository

Troubleshooting

Authentication Failures

Symptom: All JWT tokens rejected Solution: Verify ISSUER_URL matches SGIVU_AUTH_URL exactly
# Check the actual issuer in a JWT token
echo "eyJ..." | jq -R 'split(".") | .[1] | @base64d | fromjson | .iss'

# Compare with configuration
echo $ISSUER_URL
echo $SGIVU_AUTH_URL

Session Failures

Symptom: Users can’t stay logged in Solution: Verify Redis password matches in both places:
# Check Redis container
docker compose -f docker-compose.dev.yml exec sgivu-redis redis-cli
> AUTH your-redis-password

# Check gateway can connect
docker compose -f docker-compose.dev.yml logs sgivu-gateway | grep -i redis

Service Discovery Issues

Symptom: Gateway returns 503 for all routes Solution: Check services are registered with Eureka:
curl http://localhost:8761/eureka/apps | grep -i "<app>"

Database Connection Issues

Symptom: Services fail to start with database errors Solution: Verify credentials and database names:
# Test PostgreSQL connection
docker compose -f docker-compose.dev.yml exec sgivu-postgres psql -U postgres -c "\l"

# Check database logs
docker compose -f docker-compose.dev.yml logs sgivu-postgres

Security Best Practices

Never commit secrets to version control:
  • Add .env and .env.dev to .gitignore
  • Use secrets managers in production (AWS Secrets Manager, HashiCorp Vault)
  • Rotate secrets regularly
  • Use strong passwords (32+ characters)
Secret generation examples:
# Generate strong random secrets
openssl rand -base64 32

# For SERVICE_INTERNAL_SECRET_KEY
openssl rand -hex 64

# For JWT keystore password
openssl rand -base64 24

Next Steps

Docker Deployment

Learn about the Docker Compose architecture

Architecture Overview

Understand the microservices architecture

Security

Learn about OAuth2, JWT, and BFF pattern

API Reference

Explore the API documentation