Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ COMPOSE_PROJECT_NAME=xtm
OPENAEV_HOST=localhost
OPENAEV_PORT=8080
OPENAEV_EXTERNAL_SCHEME=http
OPENAEV_ADMIN_EMAIL= # ChangeMe@domain.com
OPENAEV_ADMIN_PASSWORD= # ChangeMe
OPENAEV_ADMIN_EMAIL=admin@openaev.io
OPENAEV_ADMIN_PASSWORD=changeme
OPENAEV_ADMIN_TOKEN=00000000-0000-0000-0000-000000000000 # [MANDATORY] Replace with a valid UUIDv4
OPENAEV_HEALTHCHECK_KEY=ChangeMe
OPENAEV_ADMIN_ENCRYPTION_KEY= # ChangeMe
Expand All @@ -65,3 +65,31 @@ COLLECTOR_NVD_NIST_CVE_API_KEY= #Optionnal but recommended

INJECTOR_NMAP_ID=76f8f4d6-9f6f-4e61-befc-48f735876a4a
INJECTOR_NUCLEI_ID=e1bad898-9804-427d-99e4-dc32c5f2898d

###########################
# XTM ONE #
###########################

# Shared secret used by OpenAEV and XTM One to authenticate registration.
# Both platforms MUST use the same value.
PLATFORM_REGISTRATION_TOKEN=xtm-default-registration-token

XTM_ONE_HOST=localhost
XTM_ONE_PORT=4000
XTM_ONE_EXTERNAL_SCHEME=http
# Image tag for filigran/xtm-one and filigran/xtm-one-worker (e.g. rolling, 1.x.y)
XTM_ONE_VERSION=rolling
# Must match OPENAEV_ADMIN_EMAIL so XTM One's JWT is accepted by OpenAEV.
XTM_ONE_ADMIN_EMAIL=admin@openaev.io
XTM_ONE_ADMIN_PASSWORD=changeme
# Long random string (e.g. `openssl rand -hex 32`). Used to sign sessions/tokens.
XTM_ONE_SECRET_KEY=ChangeMeWithGeneratedRandomString
# Credentials for the dedicated pgsql-copilot Postgres instance.
XTM_ONE_POSTGRES_USER=copilot
XTM_ONE_POSTGRES_PASSWORD=ChangeMe
# Optional: bucket name in MinIO (auto-created on first boot)
XTM_ONE_S3_BUCKET=copilot-files
# Optional: enterprise license PEM (leave empty in xtm_one mode)
XTM_ONE_ENTERPRISE_LICENSE=
XTM_ONE_LOG_LEVEL=info
XTM_ONE_LOG_FORMAT=json
115 changes: 114 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,33 @@ services:
interval: 10s
timeout: 5s
retries: 5
pgsql-copilot:
# Dedicated pgvector-enabled instance for XTM One (kept separate from
# the OpenAEV pg cluster to isolate data and migrations).
image: pgvector/pgvector:pg17
environment:
POSTGRES_USER: ${XTM_ONE_POSTGRES_USER}
POSTGRES_PASSWORD: ${XTM_ONE_POSTGRES_PASSWORD}
POSTGRES_DB: copilot
volumes:
- pgsqlcopilotdata:/var/lib/postgresql/data
restart: always
healthcheck:
test: [ "CMD", "pg_isready", "-U", "${XTM_ONE_POSTGRES_USER}", "-d", "copilot" ]
interval: 10s
timeout: 5s
retries: 5
redis:
# Required by XTM One (queues, cache, websockets).
image: redis:8.6.3
restart: always
volumes:
- redisdata:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3
minio:
image: minio/minio:latest
volumes:
Expand Down Expand Up @@ -129,7 +156,9 @@ services:
openaev:
image: openaev/platform:latest
environment:
- OPENAEV_BASE-URL=${OPENAEV_EXTERNAL_SCHEME}://${OPENAEV_HOST}:${OPENAEV_PORT}
# OPENAEV_BASE-URL is used as the JWT ``aud`` validation target. It MUST
# match what XTM One puts in the JWT audience claim (the internal URL).
- OPENAEV_BASE-URL=http://openaev:8080
- OPENAEV_AUTH-LOCAL-ENABLE=true
- OPENAEV_ADMIN_EMAIL=${OPENAEV_ADMIN_EMAIL}
- OPENAEV_ADMIN_PASSWORD=${OPENAEV_ADMIN_PASSWORD}
Expand Down Expand Up @@ -166,6 +195,9 @@ services:
- OPENAEV_MAIL_IMAP_SSL_TRUST=*
- OPENAEV_MAIL_IMAP_STARTTLS_ENABLE=${IMAP_STARTTLS_ENABLE}
- OPENAEV_WITH-PROXY=${OPENAEV_WITH_PROXY}
# XTM One
- OPENAEV_XTM_ONE_URL=http://xtm-one:4000
- OPENAEV_XTM_ONE_TOKEN=${PLATFORM_REGISTRATION_TOKEN}
ports:
- "${OPENAEV_PORT}:8080"
depends_on:
Expand Down Expand Up @@ -266,9 +298,90 @@ services:
openaev:
condition: service_healthy
restart: always

###########################
# XTM ONE #
###########################

xtm-one:
build:
context: ../xtm-one
dockerfile: Dockerfile
image: filigran/xtm-one:${XTM_ONE_VERSION:-rolling}
environment:
- PLATFORM_MODE=xtm_one
- PLATFORM_REGISTRATION_TOKEN=${PLATFORM_REGISTRATION_TOKEN}
# BASE_URL is used as the JWT ``iss`` claim AND as the JWKS host that
# peer platforms (OpenAEV) fetch keys from. It MUST be the internal
# Docker hostname so peers can verify tokens.
- BASE_URL=http://xtm-one:4000
- FRONTEND_URL=${XTM_ONE_EXTERNAL_SCHEME}://${XTM_ONE_HOST}:${XTM_ONE_PORT}
- ADMIN_EMAIL=${XTM_ONE_ADMIN_EMAIL}
- ADMIN_PASSWORD=${XTM_ONE_ADMIN_PASSWORD}
- SECRET_KEY=${XTM_ONE_SECRET_KEY}
- DATABASE_URL=postgresql+asyncpg://${XTM_ONE_POSTGRES_USER}:${XTM_ONE_POSTGRES_PASSWORD}@pgsql-copilot:5432/copilot
- REDIS_URL=redis://redis:6379
- S3_ENDPOINT=minio:9000
- S3_ACCESS_KEY=${MINIO_ROOT_USER}
- S3_SECRET_KEY=${MINIO_ROOT_PASSWORD}
- S3_BUCKET=${XTM_ONE_S3_BUCKET:-copilot-files}
- S3_USE_SSL=false
- LOG_LEVEL=${XTM_ONE_LOG_LEVEL:-info}
- LOG_FORMAT=${XTM_ONE_LOG_FORMAT:-json}
- ENTERPRISE_LICENSE=${XTM_ONE_ENTERPRISE_LICENSE:-}
# OpenAEV federation
- OPENAEV_ENABLE=true
- OPENAEV_URL=${OPENAEV_EXTERNAL_SCHEME}://${OPENAEV_HOST}:${OPENAEV_PORT}
- OPENAEV_API_URL=http://openaev:8080
- OPENAEV_TOKEN=${OPENAEV_ADMIN_TOKEN}
ports:
- "${XTM_ONE_PORT}:4000"
depends_on:
pgsql-copilot:
condition: service_healthy
redis:
condition: service_healthy
minio:
condition: service_healthy
restart: always
healthcheck:
test: ["CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://localhost:4000/api/health')\""]
interval: 15s
timeout: 10s
retries: 5
start_period: 60s

xtm-one-worker:
build:
context: ../xtm-one
dockerfile: Dockerfile.worker
image: filigran/xtm-one-worker:${XTM_ONE_VERSION:-rolling}
environment:
- PLATFORM_MODE=xtm_one
- PLATFORM_REGISTRATION_TOKEN=${PLATFORM_REGISTRATION_TOKEN}
- ADMIN_EMAIL=${XTM_ONE_ADMIN_EMAIL}
- ADMIN_PASSWORD=${XTM_ONE_ADMIN_PASSWORD}
- SECRET_KEY=${XTM_ONE_SECRET_KEY}
- DATABASE_URL=postgresql+asyncpg://${XTM_ONE_POSTGRES_USER}:${XTM_ONE_POSTGRES_PASSWORD}@pgsql-copilot:5432/copilot
- REDIS_URL=redis://redis:6379
- S3_ENDPOINT=minio:9000
- S3_ACCESS_KEY=${MINIO_ROOT_USER}
- S3_SECRET_KEY=${MINIO_ROOT_PASSWORD}
- S3_BUCKET=${XTM_ONE_S3_BUCKET:-copilot-files}
- S3_USE_SSL=false
- LOG_LEVEL=${XTM_ONE_LOG_LEVEL:-info}
- LOG_FORMAT=${XTM_ONE_LOG_FORMAT:-json}
- ENTERPRISE_LICENSE=${XTM_ONE_ENTERPRISE_LICENSE:-}
depends_on:
xtm-one:
condition: service_healthy
restart: always

volumes:
pgsqldata:
pgsqlcopilotdata:
s3data:
amqpdata:
esdata:
rsakeys:
redisdata: