services: # ========================================================================= # Ingress — routes gRPC traffic to Diode services # ========================================================================= ingress-nginx: image: nginx:1.27-alpine ports: - "8080:8080" volumes: - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro depends_on: diode-ingester: condition: service_started diode-reconciler: condition: service_started diode-auth: condition: service_started restart: unless-stopped # ========================================================================= # Diode Ingester — accepts gRPC, publishes to Redis streams # ========================================================================= diode-ingester: image: netboxlabs/diode-ingester:latest environment: REDIS_HOST: redis REDIS_PORT: "6379" REDIS_PASSWORD: "${REDIS_PASSWORD}" depends_on: redis: condition: service_healthy restart: unless-stopped # ========================================================================= # Diode Reconciler — consumes Redis streams, reconciles with NetBox # ========================================================================= diode-reconciler: image: netboxlabs/diode-reconciler:latest environment: REDIS_HOST: redis REDIS_PORT: "6379" REDIS_PASSWORD: "${REDIS_PASSWORD}" POSTGRES_HOST: postgres POSTGRES_PORT: "5432" POSTGRES_DB_NAME: "${DIODE_DB_NAME}" POSTGRES_USER: "${DIODE_DB_USER}" POSTGRES_PASSWORD: "${DIODE_DB_PASSWORD}" MIGRATION_ENABLED: "true" NETBOX_DIODE_PLUGIN_API_BASE_URL: "${NETBOX_API_URL}/api/plugins/diode" DIODE_AUTH_TOKEN_URL: http://diode-auth:8080/token DIODE_TO_NETBOX_CLIENT_ID: "${NETBOX_TO_DIODE_CLIENT_ID}" DIODE_TO_NETBOX_CLIENT_SECRET: "${NETBOX_TO_DIODE_CLIENT_SECRET}" volumes: - ./oauth2/client:/etc/config/oauth2/client:ro depends_on: redis: condition: service_healthy postgres: condition: service_healthy diode-auth-bootstrap: condition: service_completed_successfully restart: unless-stopped # ========================================================================= # Diode Auth — validates OAuth2 tokens via Hydra # ========================================================================= diode-auth: image: netboxlabs/diode-auth:latest environment: HTTP_PORT: "8080" OAUTH2_PUBLIC_SERVER_URL: http://hydra:4444 OAUTH2_ADMIN_SERVER_URL: http://hydra:4445 depends_on: hydra: condition: service_started restart: unless-stopped # ========================================================================= # Diode Auth Bootstrap — registers OAuth2 clients in Hydra (one-shot) # ========================================================================= diode-auth-bootstrap: image: netboxlabs/diode-auth:latest command: ["/bin/sh", "/etc/config/oauth2/client/bootstrap-clients.sh"] environment: HYDRA_ADMIN_URL: http://hydra:4445 volumes: - ./oauth2/client:/etc/config/oauth2/client:ro depends_on: hydra: condition: service_started restart: "no" # ========================================================================= # Hydra — OAuth2 / OpenID Connect server # ========================================================================= hydra: image: oryd/hydra:v25.4.0 command: serve all --dev ports: - "4444:4444" - "4445:4445" environment: DSN: "postgres://${HYDRA_DB_USER}:${HYDRA_DB_PASSWORD}@postgres:5432/${HYDRA_DB_NAME}?sslmode=disable" SECRETS_SYSTEM: "${HYDRA_SYSTEM_SECRET}" URLS_SELF_ISSUER: http://${HOST_IP}:4444/ URLS_SELF_PUBLIC: http://${HOST_IP}:4444/ STRATEGIES_ACCESS_TOKEN: jwt STRATEGIES_JWT_SCOPE_CLAIM: both depends_on: hydra-migrate: condition: service_completed_successfully restart: unless-stopped # ========================================================================= # Hydra Migrate — runs Hydra database migrations (one-shot) # ========================================================================= hydra-migrate: image: oryd/hydra:v25.4.0 command: migrate sql --yes "postgres://${HYDRA_DB_USER}:${HYDRA_DB_PASSWORD}@postgres:5432/${HYDRA_DB_NAME}?sslmode=disable" depends_on: postgres: condition: service_healthy restart: "no" # ========================================================================= # Redis — message streams for Diode ingester ↔ reconciler # ========================================================================= redis: image: redis/redis-stack-server:latest command: redis-server --requirepass "${REDIS_PASSWORD}" --appendonly yes ports: - "6378:6379" healthcheck: test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"] start_period: 5s interval: 5s timeout: 3s retries: 5 volumes: - diode-redis-data:/data restart: unless-stopped # ========================================================================= # PostgreSQL — stores Diode + Hydra databases # ========================================================================= postgres: image: postgres:16-alpine environment: POSTGRES_USER: "${DIODE_DB_USER}" POSTGRES_PASSWORD: "${DIODE_DB_PASSWORD}" POSTGRES_DB: "${DIODE_DB_NAME}" HYDRA_DB_USER: "${HYDRA_DB_USER}" HYDRA_DB_PASSWORD: "${HYDRA_DB_PASSWORD}" HYDRA_DB_NAME: "${HYDRA_DB_NAME}" healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DIODE_DB_USER} -d ${DIODE_DB_NAME}"] start_period: 10s interval: 10s timeout: 5s retries: 5 volumes: - diode-postgres-data:/var/lib/postgresql/data - ./init-hydra-db.sh:/docker-entrypoint-initdb.d/init-hydra-db.sh:ro restart: unless-stopped # ========================================================================= # Orb Agent — network discovery (NMAP, SNMP, NAPALM) # ========================================================================= orb-agent: image: netboxlabs/orb-agent:latest network_mode: host command: ["run", "-c", "/opt/orb/agent.yaml"] volumes: - ./orb-agent/agent.yaml:/opt/orb/agent.yaml:ro depends_on: diode-ingester: condition: service_started diode-auth-bootstrap: condition: service_completed_successfully restart: unless-stopped volumes: diode-redis-data: driver: local diode-postgres-data: driver: local