diff --git a/docs/4_work_plan/1.1-development-environment-setup.md b/docs/4_work_plan/1.1-development-environment-setup.md index 1e877e7..15aa506 100644 --- a/docs/4_work_plan/1.1-development-environment-setup.md +++ b/docs/4_work_plan/1.1-development-environment-setup.md @@ -678,7 +678,7 @@ scrape_configs: ```bash # Database POSTGRES_USER=knowfoolery -POSTGRES_PASSWORD=devpassword +POSTGRES_PASSWORD=knowfoolery POSTGRES_HOST=localhost POSTGRES_PORT=5432 POSTGRES_DB=knowfoolery diff --git a/infrastructure/dev/docker-compose.yml b/infrastructure/dev/docker-compose.yml new file mode 100644 index 0000000..cfa41c8 --- /dev/null +++ b/infrastructure/dev/docker-compose.yml @@ -0,0 +1,158 @@ +services: + # PostgreSQL Database + postgres: + image: postgres:15-alpine + container_name: knowfoolery-postgres + env_file: + - .env + environment: + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_DB: ${POSTGRES_DB} + ports: + - "${POSTGRES_PORT}:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + - ./init-scripts:/docker-entrypoint-initdb.d + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] + interval: 10s + timeout: 5s + retries: 5 + networks: + - knowfoolery-network + + # Redis Cache + redis: + image: redis:7-alpine + container_name: knowfoolery-redis + env_file: + - .env + ports: + - "${REDIS_PORT}:6379" + volumes: + - redis_data:/data + command: redis-server --appendonly yes + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + networks: + - knowfoolery-network + + # Zitadel Authentication (optional for initial setup) + zitadel: + image: ghcr.io/zitadel/zitadel:latest + container_name: knowfoolery-zitadel + command: start-from-init --masterkeyFromEnv --tlsMode disabled + env_file: + - .env + environment: + ZITADEL_MASTERKEY: "MasterkeyNeedsToHave32Characters" + ZITADEL_DATABASE_COCKROACH_HOST: crdb + ZITADEL_EXTERNALSECURE: false + ZITADEL_FIRSTINSTANCE_ORG_NAME: "KnowFoolery" + ZITADEL_FIRSTINSTANCE_ORG_HUMAN_USERNAME: "admin" + ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORD: "AdminPassword123!" + ports: + - "${ZITADEL_PORT}:8080" + depends_on: + crdb: + condition: service_healthy + networks: + - knowfoolery-network + profiles: + - auth + + # CockroachDB for Zitadel + crdb: + image: cockroachdb/cockroach:latest + container_name: knowfoolery-crdb + command: start-single-node --insecure --http-addr :9090 + env_file: + - .env + ports: + - "${CRDB_PORT}:26257" + - "${CRDB_HTTP_PORT}:9090" + volumes: + - crdb_data:/cockroach/cockroach-data + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9090/health?ready=1"] + interval: 10s + timeout: 5s + retries: 10 + networks: + - knowfoolery-network + profiles: + - auth + + # Prometheus Metrics + prometheus: + image: prom/prometheus:latest + container_name: knowfoolery-prometheus + env_file: + - .env + ports: + - "${PROMETHEUS_PORT}:9090" + volumes: + - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml + - prometheus_data:/prometheus + command: + - '--config.file=/etc/prometheus/prometheus.yml' + - '--storage.tsdb.path=/prometheus' + - '--web.enable-lifecycle' + networks: + - knowfoolery-network + profiles: + - observability + + # Grafana Dashboards + grafana: + image: grafana/grafana:latest + container_name: knowfoolery-grafana + env_file: + - .env + ports: + - "${GRAFANA_PORT}:3000" + environment: + GF_SECURITY_ADMIN_USER: admin + GF_SECURITY_ADMIN_PASSWORD: admin + GF_USERS_ALLOW_SIGN_UP: false + volumes: + - grafana_data:/var/lib/grafana + - ./grafana/provisioning:/etc/grafana/provisioning + depends_on: + - prometheus + networks: + - knowfoolery-network + profiles: + - observability + + # Jaeger Tracing + jaeger: + image: jaegertracing/all-in-one:latest + container_name: knowfoolery-jaeger + env_file: + - .env + ports: + - "${JAEGER_UI_PORT}:16686" # UI + - "${JAEGER_COLLECTOR_PORT}:14268" # Collector HTTP + - "${JAEGER_AGENT_PORT}:6831/udp" # Agent + environment: + COLLECTOR_ZIPKIN_HOST_PORT: ":9411" + networks: + - knowfoolery-network + profiles: + - observability + +volumes: + postgres_data: + redis_data: + crdb_data: + prometheus_data: + grafana_data: + +networks: + knowfoolery-network: + driver: bridge diff --git a/infrastructure/dev/init-scripts/01-create-databases.sql b/infrastructure/dev/init-scripts/01-create-databases.sql new file mode 100644 index 0000000..f5b782c --- /dev/null +++ b/infrastructure/dev/init-scripts/01-create-databases.sql @@ -0,0 +1,18 @@ +-- Create separate databases for each service +SELECT 'CREATE DATABASE game_sessions' +WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'game_sessions')\gexec +SELECT 'CREATE DATABASE questions' +WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'questions')\gexec +SELECT 'CREATE DATABASE users' +WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'users')\gexec +SELECT 'CREATE DATABASE leaderboards' +WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'leaderboards')\gexec +SELECT 'CREATE DATABASE admin' +WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'admin')\gexec + +-- Grant privileges +GRANT ALL PRIVILEGES ON DATABASE game_sessions TO knowfoolery; +GRANT ALL PRIVILEGES ON DATABASE questions TO knowfoolery; +GRANT ALL PRIVILEGES ON DATABASE users TO knowfoolery; +GRANT ALL PRIVILEGES ON DATABASE leaderboards TO knowfoolery; +GRANT ALL PRIVILEGES ON DATABASE admin TO knowfoolery; diff --git a/infrastructure/dev/prometheus/prometheus.yml b/infrastructure/dev/prometheus/prometheus.yml new file mode 100644 index 0000000..0382d50 --- /dev/null +++ b/infrastructure/dev/prometheus/prometheus.yml @@ -0,0 +1,33 @@ +global: + scrape_interval: 15s + evaluation_interval: 15s + +scrape_configs: + - job_name: 'prometheus' + static_configs: + - targets: ['localhost:9090'] + + - job_name: 'game-session-service' + static_configs: + - targets: ['host.docker.internal:8080'] + metrics_path: /metrics + + - job_name: 'question-bank-service' + static_configs: + - targets: ['host.docker.internal:8081'] + metrics_path: /metrics + + - job_name: 'user-service' + static_configs: + - targets: ['host.docker.internal:8082'] + metrics_path: /metrics + + - job_name: 'leaderboard-service' + static_configs: + - targets: ['host.docker.internal:8083'] + metrics_path: /metrics + + - job_name: 'gateway-service' + static_configs: + - targets: ['host.docker.internal:8086'] + metrics_path: /metrics