netbox-diode-project/docker-compose.yml
sam 2f459e6f4a Fix Diode stack configuration to match upstream architecture
Major changes to align with the official netboxlabs/diode docker-compose:

docker-compose.yml:
- Upgrade Hydra from v2.2 to v25.4.0 (latest stable)
- Fix env var names: drop DIODE_ prefix on ingester/reconciler/auth
  (DIODE_REDIS_HOST -> REDIS_HOST, DIODE_GRPC_PORT -> removed, etc.)
- Remove AUTH_GRPC_TARGET from ingester — auth is handled by nginx
  via HTTP subrequests to diode-auth, not by the ingester directly
- Point DIODE_AUTH_TOKEN_URL to diode-auth:8080/token (not Hydra)
- Add Postgres connection vars to reconciler (MIGRATION_ENABLED, etc.)
- Mount nginx.conf as /etc/nginx/conf.d/default.conf (not nginx.conf)
- Use netboxlabs/diode-auth image for bootstrap (has hydra CLI + jq)
- Add Hydra JWT strategy config (STRATEGIES_ACCESS_TOKEN: jwt)
- Add orb-agent run command with explicit config path
- Expose Hydra ports 4444/4445 for external token requests
- Add Hydra DB env vars to Postgres for init script

nginx/nginx.conf:
- Rewrite to match official Diode nginx architecture
- Auth via auth_request subrequests to diode-auth:8080 (HTTP)
- gRPC pass to ingester/reconciler on :8081 after auth
- Add /diode/auth proxy for token endpoint access
- Add error handlers for 401/403

oauth2/client/bootstrap-clients.sh:
- Rewrite to use hydra CLI (create/get oauth2-client) instead of
  raw wget calls to Hydra admin API
- Use jq for JSON parsing instead of python3
- Idempotent: checks if client exists before creating

setup.sh:
- Fix OAuth2 scope: diode:ingester -> diode:ingest
- Rewrite orb-agent config to match current agent.yaml schema
  (config_manager, policies with cron schedules, scope-based targets)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 21:51:40 -07:00

187 lines
6.6 KiB
YAML

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