netbox-diode-project/docker-compose.yml
sam c5a0245dd2 Add project infrastructure and configuration files
Docker Compose stack, nginx config, OAuth2 client bootstrap,
Hydra DB init, setup script, and gitignore for secrets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 20:46:59 -07:00

174 lines
6.2 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/nginx.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:
DIODE_REDIS_HOST: redis
DIODE_REDIS_PORT: "6379"
DIODE_REDIS_PASSWORD: "${REDIS_PASSWORD}"
DIODE_GRPC_PORT: "8081"
DIODE_AUTH_GRPC_TARGET: diode-auth:8081
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:
DIODE_REDIS_HOST: redis
DIODE_REDIS_PORT: "6379"
DIODE_REDIS_PASSWORD: "${REDIS_PASSWORD}"
DIODE_GRPC_PORT: "8081"
DIODE_NETBOX_API_URL: "${NETBOX_API_URL}"
DIODE_NETBOX_API_TOKEN: "${NETBOX_API_TOKEN}"
DIODE_RECONCILER_CLIENT_ID: "${RECONCILER_CLIENT_ID}"
DIODE_RECONCILER_CLIENT_SECRET: "${RECONCILER_CLIENT_SECRET}"
DIODE_AUTH_GRPC_TARGET: diode-auth:8081
DIODE_TO_NETBOX_CLIENT_ID: "${NETBOX_TO_DIODE_CLIENT_ID}"
DIODE_TO_NETBOX_CLIENT_SECRET: "${NETBOX_TO_DIODE_CLIENT_SECRET}"
depends_on:
redis:
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:
DIODE_GRPC_PORT: "8081"
DIODE_HYDRA_ADMIN_URL: http://hydra:4445
DIODE_HYDRA_PUBLIC_URL: http://hydra:4444
depends_on:
hydra:
condition: service_started
restart: unless-stopped
# =========================================================================
# Diode Auth Bootstrap — registers OAuth2 clients in Hydra (one-shot)
# =========================================================================
diode-auth-bootstrap:
image: python:3.12-alpine
command: /client-credentials/bootstrap-clients.sh
environment:
HYDRA_ADMIN_URL: http://hydra:4445
volumes:
- ./oauth2/client:/client-credentials:ro
depends_on:
hydra:
condition: service_started
restart: "no"
# =========================================================================
# Hydra — OAuth2 / OpenID Connect server
# =========================================================================
hydra:
image: oryd/hydra:v2.2
command: serve all --dev --config /etc/hydra/hydra.yml
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://hydra:4444/
URLS_SELF_PUBLIC: http://hydra:4444/
depends_on:
hydra-migrate:
condition: service_completed_successfully
restart: unless-stopped
# =========================================================================
# Hydra Migrate — runs Hydra database migrations (one-shot)
# =========================================================================
hydra-migrate:
image: oryd/hydra:v2.2
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}"
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
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