docker-compose.demo.yml
Rama main · réplica de lectura del repositorio original.
# Mac-free, one-command demo stack for evaluating RawTrail.
#
# docker compose -f docker-compose.demo.yml up
# # then open https://localhost:8088/ui/ and sign in: demo@rawtrail.local / demo
#
# It boots the real server + embedded UI against MySQL, generates a self-signed
# localhost TLS cert, bundles a dex IdP for SSO, and runs a one-shot seeder that
# replays a curated attack + noise corpus through the real ingest + detection
# pipeline so the UI shows a process graph, fired ATT&CK alerts, and an
# application-control block. No Mac, MDM, or Apple entitlement required.
#
# Images default to the `latest` released tag so the demo always shows the
# newest published product; pin a specific release with EDR_VERSION=vX.Y.Z. To
# run from a local source build instead (no published tag needed), layer the
# build override:
#
# docker compose -f docker-compose.demo.yml -f docker-compose.demo.build.yml up --build
#
# This stack is for evaluation only: empty MySQL password, self-signed cert,
# checked-in dev secrets. Do not expose it or use it in production.
name: rawtrail-demo
services:
mysql:
image: mysql:8.4.9@sha256:c36050afdca850f23cef85703f84c7531a5ae155a11b5ee1c60acb09937c4084
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
MYSQL_DATABASE: edr
# No named volume: data lives in an anonymous volume that persists across `up`/`down`
# but is discarded by `docker compose ... down -v`. Re-runs are safe regardless: the
# seeder is idempotent and skips replay when the demo data is already present.
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 5s
retries: 20
start_period: 10s
# ClickHouse event store (ADR-0015): the server stores events here and does not start without it. Anonymous volume like mysql:
# persists across up/down, discarded by `down -v`.
clickhouse:
image: clickhouse/clickhouse-server:24.8@sha256:1ffa82edee000a42c09313bd9f1293d94c570aee74babc1b3ca9983a35fa597b
environment:
CLICKHOUSE_DB: edr
CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: "1"
ulimits:
nofile:
soft: 262144
hard: 262144
healthcheck:
test: ["CMD", "clickhouse-client", "--query", "SELECT 1"]
interval: 5s
timeout: 5s
retries: 20
start_period: 10s
dex:
image: ghcr.io/dexidp/dex:v2.41.1
command: ["dex", "serve", "/etc/dex/config.yaml"]
volumes:
- ./config/dex/demo-config.yaml:/etc/dex/config.yaml:ro
- dex-data:/var/dex
networks:
default:
# The server reaches the issuer host (dex.demo.localhost) through this
# alias; the browser reaches the same host via *.localhost -> 127.0.0.1
# and the published port below. See config/dex/demo-config.yaml.
aliases:
- dex.demo.localhost
ports:
- "127.0.0.1:5556:5556"
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:5556/dex/.well-known/openid-configuration"]
interval: 5s
timeout: 5s
retries: 20
cert-init:
# Generate a self-signed localhost cert into the shared tls volume before the
# server boots (the distroless server image has no openssl). SAN covers
# `localhost` (the browser-facing URL) and `server` (the in-network hostname
# the seeder verifies). Runs once and exits; idempotent across restarts.
image: alpine:3.21
command:
- sh
- -c
- |
set -e
if [ -s /tls/dev.crt ] && [ -s /tls/dev.key ]; then
echo "cert already present, skipping"
exit 0
fi
apk add --no-cache openssl >/dev/null
openssl req -x509 -newkey rsa:2048 -nodes -days 365 \
-keyout /tls/dev.key -out /tls/dev.crt \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,DNS:server,IP:127.0.0.1,IP:::1"
chmod 0644 /tls/dev.crt /tls/dev.key
echo "generated /tls/dev.crt"
volumes:
- tls:/tls
server:
image: ghcr.io/rawtrail/rawtrail-server:${EDR_VERSION:-latest}
restart: unless-stopped
# Longer than every stage of a graceful stop put together: the drain (EDR_SHUTDOWN_DRAIN,
# 30s), the in-flight deadline (15s), the two loop joins (10s + 5s) and the telemetry
# flush (5s): 65s in all. Docker's default is 10s, which cuts the drain the load
# balancer is watching and severs in-flight requests (#1127). test/arch keeps this
# in step with those five constants. Raise it too if you raise EDR_SHUTDOWN_DRAIN.
stop_grace_period: 90s
depends_on:
mysql:
condition: service_healthy
clickhouse:
condition: service_healthy
dex:
condition: service_healthy
cert-init:
condition: service_completed_successfully
environment:
EDR_DSN: "root@tcp(mysql:3306)/edr?parseTime=true&tls=false"
# Required by the source-built server (ADR-0015); ignored by the released `latest` image.
EDR_CLICKHOUSE_DSN: "clickhouse://default:@clickhouse:9000/edr"
EDR_ENROLL_SECRET: demo-enroll-secret
EDR_TLS_CERT_FILE: /tls/dev.crt
EDR_TLS_KEY_FILE: /tls/dev.key
EDR_LOG_FORMAT: json
EDR_SECRET_KEY: demo-only-secret-key-do-not-use-in-prod-0123456789
# SSO against the bundled dex is configured by the seeder below, which writes the dex connection into the durable oidc_config
# store (issue #512). The server reads no EDR_OIDC_* and picks up the seeded config at login.
# Break-glass is available as an alternative login (a redemption URL prints
# to the server logs on first boot). See README "Notes for reviewers".
EDR_BREAKGLASS_RP_ID: localhost
EDR_BREAKGLASS_RP_ORIGINS: https://localhost:8088
ports:
- "127.0.0.1:8088:8088"
volumes:
- tls:/tls:ro
seeder:
image: ghcr.io/rawtrail/rawtrail-demo-seed:${EDR_VERSION:-latest}
# One-shot: enrolls hosts, replays the corpus, verifies, seeds the dex SSO config, then exits 0.
restart: "no"
depends_on:
mysql:
condition: service_healthy
clickhouse:
condition: service_healthy
cert-init:
condition: service_completed_successfully
server:
# The server image is distroless (no shell for a container healthcheck),
# so the seeder polls /readyz itself rather than gating on health.
condition: service_started
environment:
EDR_DEMO_SERVER_URL: https://server:8088
EDR_ENROLL_SECRET: demo-enroll-secret
EDR_DSN: "root@tcp(mysql:3306)/edr?parseTime=true&tls=false"
# Lets the source-built seeder slide archived-event timestamps on restart (ADR-0015); ignored by the released `latest` image.
EDR_CLICKHOUSE_DSN: "clickhouse://default:@clickhouse:9000/edr"
EDR_DEMO_CA_CERT: /tls/dev.crt
# SSO seed (issue #512): the seeder writes the dex connection config into the durable oidc_config store; the server reads no
# EDR_OIDC_* and picks it up at login. EDR_SECRET_KEY MUST match the server's so the sealed client secret decrypts at login.
# EDR_DEMO_OIDC_EXTERNAL_URL is the browser-facing base; the redirect is <url>/api/auth/callback. JIT lands dex users at analyst.
EDR_SECRET_KEY: demo-only-secret-key-do-not-use-in-prod-0123456789
EDR_DEMO_OIDC_ISSUER: http://dex.demo.localhost:5556/dex
EDR_DEMO_OIDC_CLIENT_ID: edr-demo
EDR_DEMO_OIDC_CLIENT_SECRET: edr-demo-client-secret-do-not-use-in-prod
EDR_DEMO_OIDC_EXTERNAL_URL: https://localhost:8088
EDR_DEMO_OIDC_DEFAULT_ROLE: analyst
# Pre-provision the demo SSO account so first dex login lands as `admin` instead of the JIT default analyst: the seeder binds the
# dex-issued OIDC subject below to an `admin` user, and login matches that (provider, subject) identity and reuses it rather than
# JIT-provisioning. This is the only sound way to seed a privileged demo user: the JIT default role is clamped to analyst/auditor
# by design (identity/bootstrap clampJITRole), so an SSO claim can never auto-grant admin. EDR_DEMO_OIDC_SUBJECT is the dex
# local-connector subject for the demo@rawtrail.local static user (userID de300000-...-0001, connID `local`), stable for the
# checked-in dex config. Break-glass (admin@rawtrail.local) stays the super_admin path.
EDR_DEMO_OIDC_SUBJECT: "CiRkZTMwMDAwMC0wMDAwLTQwMDAtODAwMC0wMDAwMDAwMDAwMDESBWxvY2Fs"
EDR_DEMO_ROLE: admin
volumes:
- tls:/tls:ro
volumes:
dex-data:
tls: