Copy services:
###########################
# DEPENDENCIES #
###########################
# Generate RSA key for xtm-composer (PKCS#8 format)
rsa-key-generator:
image: alpine/openssl:3.5.4
volumes:
- rsakeys:/keys
entrypoint: [ "/bin/ash" ]
command: [ "-c", "if [ ! -f /keys/private_key.pem ]; then openssl genpkey -algorithm RSA -out /keys/private_key.pem -pkeyopt rsa_keygen_bits:4096; fi && tail -f /dev/null" ]
healthcheck:
test: [ "CMD", "test", "-f", "/keys/private_key.pem" ]
interval: 10s
timeout: 5s
retries: 3
restart: always
pgsql:
image: postgres:17-alpine
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: openaev
volumes:
- pgsqldata:/var/lib/postgresql/data
restart: always
healthcheck:
test: [ "CMD", "pg_isready", "-U", "${POSTGRES_USER}", "-d", "openaev" ]
interval: 10s
timeout: 5s
retries: 5
minio:
image: minio/minio:RELEASE.2025-06-13T11-33-47Z
volumes:
- s3data:/data
ports:
- "9000:9000"
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
command: server /data
restart: always
healthcheck:
test: [ "CMD", "mc", "ready", "local" ]
interval: 10s
timeout: 5s
retries: 5
rabbitmq:
image: rabbitmq:4.2-management
environment:
- RABBITMQ_DEFAULT_USER=${RABBITMQ_DEFAULT_USER}
- RABBITMQ_DEFAULT_PASS=${RABBITMQ_DEFAULT_PASS}
- RABBITMQ_NODENAME=rabbit01@localhost
volumes:
- type: bind
source: ./rabbitmq.conf
target: /etc/rabbitmq/rabbitmq.conf
- amqpdata:/var/lib/rabbitmq
restart: always
healthcheck:
test: [ "CMD", "rabbitmq-diagnostics", "-q", "ping" ]
interval: 10s
timeout: 5s
retries: 5
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.19.9
volumes:
- esdata:/usr/share/elasticsearch/data
environment:
# Comment-out the line below for a cluster of multiple nodes
- discovery.type=single-node
# Uncomment the line below below for a cluster of multiple nodes
# - cluster.name=docker-cluster
- xpack.ml.enabled=false
- xpack.security.enabled=false
- thread_pool.search.queue_size=5000
- logger.org.elasticsearch.discovery="ERROR"
# -XX:UseSVE=0 is necessary for Apple M4 architecture
- "ES_JAVA_OPTS=-Xms${ELASTIC_MEMORY_SIZE} -Xmx${ELASTIC_MEMORY_SIZE} -XX:+IgnoreUnrecognizedVMOptions -XX:UseSVE=0"
- "CLI_JAVA_OPTS=-XX:+IgnoreUnrecognizedVMOptions -XX:UseSVE=0"
restart: always
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
healthcheck:
test: curl -s http://elasticsearch:9200 >/dev/null || exit 1
interval: 30s
timeout: 10s
retries: 50
###########################
# COMMON #
###########################
xtm-composer:
image: filigran/xtm-composer:1.0.1
platform: linux/amd64
environment:
- MANAGER__ID=${XTM_COMPOSER_ID}
- "MANAGER__NAME=XTM Integrations Manager"
- MANAGER__CREDENTIALS_KEY_FILEPATH=/keys/private_key.pem
- OPENAEV__ENABLE=true
- OPENAEV__URL=http://openaev:8080
- OPENAEV__TOKEN=${OPENAEV_ADMIN_EMAIL}
- OPENAEV__DAEMON__SELECTOR=docker
- OPENAEV__DAEMON__DOCKER__NETWORK_MODE=${COMPOSE_PROJECT_NAME}_default
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- rsakeys:/keys:ro # RSA key mounted as read-only
depends_on:
rsa-key-generator:
condition: service_healthy
# opencti:
# condition: service_healthy
rabbitmq:
condition: service_healthy
restart: always
###########################
# OPENAEV #
###########################
openaev:
image: openaev/platform:2.0.9
environment:
- OPENAEV_BASE-URL=${OPENAEV_EXTERNAL_SCHEME}://${OPENAEV_HOST}:${OPENAEV_PORT}
- OPENAEV_AUTH-LOCAL-ENABLE=true
- OPENAEV_ADMIN_EMAIL=${OPENAEV_ADMIN_EMAIL}
- OPENAEV_ADMIN_PASSWORD=${OPENAEV_ADMIN_PASSWORD}
- OPENAEV_ADMIN_TOKEN=${OPENAEV_ADMIN_TOKEN}
- OPENAEV_HEALTHCHECK_KEY=${OPENAEV_HEALTHCHECK_KEY:-ChangeMe}
- OPENAEV_EXTRA-TRUSTED-CERTS-DIR=/opt/openaev/additional_certs
- SPRING_DATASOURCE_URL=jdbc:postgresql://pgsql:5432/openaev
- SPRING_DATASOURCE_USERNAME=${POSTGRES_USER}
- SPRING_DATASOURCE_PASSWORD=${POSTGRES_PASSWORD}
- MINIO_ENDPOINT=minio
- MINIO_ACCESS-KEY=${MINIO_ROOT_USER}
- MINIO_ACCESS-SECRET=${MINIO_ROOT_PASSWORD}
- OPENAEV_RABBITMQ_HOSTNAME=rabbitmq
- OPENAEV_RABBITMQ_USER=${RABBITMQ_DEFAULT_USER}
- OPENAEV_RABBITMQ_PASS=${RABBITMQ_DEFAULT_PASS}
- ENGINE_URL=http://elasticsearch:9200
- SPRING_MAIL_HOST=${SMTP_HOST}
- SPRING_MAIL_PORT=${SMTP_PORT}
- SPRING_MAIL_USERNAME=${SMTP_USERNAME}
- SPRING_MAIL_PASSWORD=${SMTP_PASSWORD}
- SPRING_MAIL_PROPERTIES_MAIL_SMTP_AUTH=${SMTP_AUTH}
- SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_ENABLE=${SMTP_SSL_ENABLE}
- SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_TRUST=*
- SPRING_MAIL_PROPERTIES_MAIL_SMTP_STARTTLS_ENABLE=${SMTP_STARTTLS_ENABLE}
- OPENAEV_MAIL_IMAP_ENABLED=${OPENAEV_MAIL_IMAP_ENABLED}
- OPENAEV_MAIL_IMAP_HOST=${IMAP_HOST}
- OPENAEV_MAIL_IMAP_PORT=${IMAP_PORT}
- OPENAEV_MAIL_IMAP_USERNAME=${IMAP_USERNAME}
- OPENAEV_MAIL_IMAP_PASSWORD=${IMAP_PASSWORD}
- OPENAEV_MAIL_IMAP_AUTH=${IMAP_AUTH}
- OPENAEV_MAIL_IMAP_SSL_ENABLE=${IMAP_SSL_ENABLE}
- OPENAEV_MAIL_IMAP_SSL_TRUST=*
- OPENAEV_MAIL_IMAP_STARTTLS_ENABLE=${IMAP_STARTTLS_ENABLE}
ports:
- "${OPENAEV_PORT}:8080"
depends_on:
pgsql:
condition: service_healthy
minio:
condition: service_healthy
rabbitmq:
condition: service_healthy
elasticsearch:
condition: service_healthy
restart: always
healthcheck:
test: [ "CMD", "wget", "-qO-", "http://openaev:8080/api/health?health_access_key=${OPENAEV_HEALTHCHECK_KEY}" ]
interval: 10s
timeout: 5s
retries: 20
###########################
# OPENAEV COLLECTORS #
###########################
collector-mitre-attack:
image: openaev/collector-mitre-attack:2.0.9
environment:
- OPENAEV_URL=http://openaev:8080
- OPENAEV_TOKEN=${OPENAEV_ADMIN_TOKEN}
- COLLECTOR_ID=${COLLECTOR_MITRE_ATTACK_ID} # Valid UUIDv4
- "COLLECTOR_NAME=MITRE ATT&CK"
- COLLECTOR_LOG_LEVEL=info
depends_on:
openaev:
condition: service_healthy
restart: always
collector-openaev:
image: openaev/collector-openaev:2.0.9
environment:
- OPENAEV_URL=http://openaev:8080
- OPENAEV_TOKEN=${OPENAEV_ADMIN_TOKEN}
- COLLECTOR_ID=${COLLECTOR_OPENAEV_ID} # Valid UUIDv4
- "COLLECTOR_NAME=OpenAEV Datasets"
- COLLECTOR_LOG_LEVEL=info
depends_on:
openaev:
condition: service_healthy
restart: always
collector-atomic-red-team:
image: openaev/collector-atomic-red-team:2.0.9
environment:
- OPENAEV_URL=http://openaev:8080
- OPENAEV_TOKEN=${OPENAEV_ADMIN_TOKEN}
- COLLECTOR_ID=${COLLECTOR_ATOMIC_RED_TEAM_ID} # Valid UUIDv4
- "COLLECTOR_NAME=Atomic Red Team"
- COLLECTOR_LOG_LEVEL=info
depends_on:
openaev:
condition: service_healthy
restart: always
collector-nvd-nist-cve:
image: openaev/collector-nvd-nist-cve:2.0.9
environment:
- OPENAEV_URL=http://openaev:8080
- OPENAEV_TOKEN=${OPENAEV_ADMIN_TOKEN}
- COLLECTOR_ID=${COLLECTOR_NVD_NIST_CVE_ID} # Valid UUIDv4
- NVD_NIST_CVE_API_KEY=${COLLECTOR_NVD_NIST_CVE_API_KEY}
- "COLLECTOR_NAME=CVE by NVD NIST"
- COLLECTOR_LOG_LEVEL=info
depends_on:
openaev:
condition: service_healthy
restart: always
###########################
# OPENAEV INJECTORS #
###########################
injector-nmap:
image: openaev/injector-nmap:2.0.9
environment:
- OPENAEV_URL=http://openaev:8080
- OPENAEV_TOKEN=${OPENAEV_ADMIN_TOKEN}
- INJECTOR_ID=${INJECTOR_NMAP_ID} # Valid UUIDv4
- INJECTOR_NAME=Nmap
- INJECTOR_LOG_LEVEL=info
depends_on:
openaev:
condition: service_healthy
restart: always
injector-nuclei:
image: openaev/injector-nuclei:2.0.9
environment:
- OPENAEV_URL=http://openaev:8080
- OPENAEV_TOKEN=${OPENAEV_ADMIN_TOKEN}
- INJECTOR_ID=${INJECTOR_NUCLEI_ID} # Valid UUIDv4
- INJECTOR_NAME=Nuclei
- INJECTOR_LOG_LEVEL=info
depends_on:
openaev:
condition: service_healthy
restart: always
volumes:
pgsqldata:
s3data:
amqpdata:
esdata:
rsakeys: