.env file with production valuesCopy .env.example to .env and update:
cp .env.example .env
Critical variables to change:
JWT_SECRET: Use a strong, random 32+ character stringPOSTGRES_PASSWORD: Use a strong passwordADMIN_PASSWORD: Use a strong passwordCORS_ORIGINS: Set to your actual frontend domain(s)Generate secure secrets:
# Generate JWT secret
openssl rand -hex 32
# Generate password
openssl rand -base64 24
# Clone repository
git clone https://github.com/pangerlkr/ctias-lab.git
cd ctias-lab
# Create environment file
cp .env.example .env
# Edit .env with your settings
# Start services
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose down
Create docker-compose.prod.yml:
version: '3.9'
services:
postgres:
image: postgres:15-alpine
restart: always
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./backups:/backups
networks:
- internal
# Don't expose port publicly
redis:
image: redis:7-alpine
restart: always
command: redis-server --requirepass ${REDIS_PASSWORD}
networks:
- internal
gateway:
build:
context: ./gateway
dockerfile: Dockerfile
restart: always
environment:
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0
JWT_SECRET: ${JWT_SECRET}
ENVIRONMENT: production
LOG_LEVEL: warning
depends_on:
- postgres
- redis
networks:
- internal
- external
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`api.yourdomain.com`)"
- "traefik.http.routers.api.tls=true"
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
restart: always
environment:
REACT_APP_API_URL: https://api.yourdomain.com
networks:
- external
labels:
- "traefik.enable=true"
- "traefik.http.routers.web.rule=Host(`yourdomain.com`)"
- "traefik.http.routers.web.tls=true"
networks:
internal:
driver: bridge
external:
driver: bridge
volumes:
postgres_data:
docker-compose -f docker-compose.prod.yml up -d
kubectl create namespace ctias-lab
kubectl create secret generic ctias-secrets \
--from-literal=jwt-secret=$(openssl rand -hex 32) \
--from-literal=postgres-password=$(openssl rand -base64 24) \
--from-literal=redis-password=$(openssl rand -base64 24) \
-n ctias-lab
helm install postgres bitnami/postgresql \
--set auth.existingSecret=ctias-secrets \
--set auth.secretKeys.adminPasswordKey=postgres-password \
--namespace ctias-lab
helm install redis bitnami/redis \
--set auth.existingSecret=ctias-secrets \
--set auth.existingSecretPasswordKey=redis-password \
--namespace ctias-lab
kubectl apply -f k8s/ -n ctias-lab
/healthSet up alerts for:
# Automated daily backup
docker exec ctias-postgres pg_dump -U ctias ctias_lab > backup-$(date +%Y%m%d).sql
# Restore from backup
docker exec -i ctias-postgres psql -U ctias ctias_lab < backup-20240101.sql
Scale gateway and module services:
# Docker Compose
docker-compose up -d --scale gateway=3
# Kubernetes
kubectl scale deployment gateway --replicas=3 -n ctias-lab
Adjust resource limits in docker-compose.yml or k8s manifests:
resources:
limits:
memory: "2Gi"
cpu: "1000m"
requests:
memory: "1Gi"
cpu: "500m"
# Check logs
docker-compose logs gateway
# Check service status
docker-compose ps
# Verify environment variables
docker-compose config
# Check database is running
docker-compose ps postgres
# Test connection
docker exec -it ctias-postgres psql -U ctias -d ctias_lab
# Check environment variables
echo $DATABASE_URL
# Check container stats
docker stats
# Restart services
docker-compose restart
# Adjust memory limits
# Pull latest code
git pull origin main
# Rebuild containers
docker-compose build --no-cache
# Restart with new images
docker-compose up -d
# Vacuum database
docker exec ctias-postgres psql -U ctias -d ctias_lab -c "VACUUM ANALYZE;"
# Check database size
docker exec ctias-postgres psql -U ctias -d ctias_lab -c "SELECT pg_size_pretty(pg_database_size('ctias_lab'));"
For issues or questions: