services: db: restart: always image: "postgres:18-alpine" environment: - POSTGRES_DB=${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - POSTGRES_PORT=${POSTGRES_PORT} ports: - "127.0.0.1:5432:5432" volumes: # PostgreSQL 18 images keep PGDATA in a version directory under /var/lib/postgresql, so mount there. # A new volume: the old PostgreSQL 12 data cannot be opened by 18 (see scripts/upgrade-postgres.sh). - postgres18_data:/var/lib/postgresql networks: - rengine_network redis: restart: always image: "redis:alpine" hostname: redis networks: - rengine_network celery: mem_limit: "${CELERY_MEM_LIMIT:-4g}" # container ceiling; heavy scanner jobs queue inside it (reNgine/resources.py) extra_hosts: - "host.docker.internal:host-gateway" # lets "localhost" in Settings > AI model mean this server (see reNgine/ai_providers.py reachable_url) build: context: ./web restart: always entrypoint: /usr/src/app/celery-entrypoint.sh volumes: - ./web:/usr/src/app - github_repos:/usr/src/github - scan_results:/usr/src/scan_results - nuclei_templates:/root/nuclei-templates - generated_templates:/root/cvengine-generated-templates # validated AI-written templates survive an update - tool_config:/root/.config - static_volume:/usr/src/app/staticfiles/ # every variable in .env reaches the container (the explicit entries below win, so the internal # settings compose sets on purpose, such as the broker URLs and DEBUG, cannot be overridden from .env) env_file: - path: .env required: false environment: - DEBUG=0 - CVENGINE_ALLOW_PRIVATE_TARGETS=${CVENGINE_ALLOW_PRIVATE_TARGETS:-0} - CVENGINE_TRUSTED_PROXIES=${CVENGINE_TRUSTED_PROXIES:-172.16.0.0/12} - CELERY_BROKER=redis://redis:6379/0 - DISCOVERY_CONCURRENCY=${DISCOVERY_CONCURRENCY:-3} - CELERY_BACKEND=redis://redis:6379/0 - DOMAIN_NAME=${DOMAIN_NAME} - POSTGRES_DB=${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - POSTGRES_PORT=${POSTGRES_PORT} - POSTGRES_HOST=${POSTGRES_HOST} depends_on: - db - redis networks: - rengine_network celery-beat: mem_limit: "${BEAT_MEM_LIMIT:-512m}" # container ceiling; heavy scanner jobs queue inside it (reNgine/resources.py) restart: always build: ./web entrypoint: /usr/src/app/beat-entrypoint.sh command: celery -A reNgine beat -l INFO --scheduler cveFeed.scan_control:PauseAwareScheduler # every variable in .env reaches the container (the explicit entries below win, so the internal # settings compose sets on purpose, such as the broker URLs and DEBUG, cannot be overridden from .env) env_file: - path: .env required: false environment: - DEBUG=0 - CELERY_BROKER=redis://redis:6379/0 - DISCOVERY_CONCURRENCY=${DISCOVERY_CONCURRENCY:-3} - CELERY_BACKEND=redis://redis:6379/0 - POSTGRES_DB=${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - POSTGRES_PORT=${POSTGRES_PORT} - POSTGRES_HOST=${POSTGRES_HOST} depends_on: - celery - db volumes: - ./web:/usr/src/app - github_repos:/usr/src/github - scan_results:/usr/src/scan_results - nuclei_templates:/root/nuclei-templates - generated_templates:/root/cvengine-generated-templates # validated AI-written templates survive an update - tool_config:/root/.config networks: - rengine_network web: mem_limit: "${WEB_MEM_LIMIT:-1g}" # container ceiling; heavy scanner jobs queue inside it (reNgine/resources.py) extra_hosts: - "host.docker.internal:host-gateway" # lets "localhost" in Settings > AI model mean this server (see reNgine/ai_providers.py reachable_url) build: context: ./web entrypoint: /usr/src/app/entrypoint.sh # GUNICORN_WORKERS is pinned below (not read from .env): the lockout counters are in the shared Redis cache, so two workers is safe, # and a stray value in .env cannot change it restart: always image: cvengine/web:latest # every variable in .env reaches the container (the explicit entries below win, so the internal # settings compose sets on purpose, such as the broker URLs and DEBUG, cannot be overridden from .env) env_file: - path: .env required: false environment: - DEBUG=0 - CVENGINE_ALLOW_PRIVATE_TARGETS=${CVENGINE_ALLOW_PRIVATE_TARGETS:-0} - CVENGINE_TRUSTED_PROXIES=${CVENGINE_TRUSTED_PROXIES:-172.16.0.0/12} - CELERY_BROKER=redis://redis:6379/0 - DISCOVERY_CONCURRENCY=${DISCOVERY_CONCURRENCY:-3} - CELERY_BACKEND=redis://redis:6379/0 - GUNICORN_WORKERS=2 - DOMAIN_NAME=${DOMAIN_NAME} - POSTGRES_DB=${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - POSTGRES_PORT=${POSTGRES_PORT} - POSTGRES_HOST=${POSTGRES_HOST} - DJANGO_SUPERUSER_PASSWORD=${DJANGO_SUPERUSER_PASSWORD} volumes: - ./web:/usr/src/app - github_repos:/usr/src/github - scan_results:/usr/src/scan_results - nuclei_templates:/root/nuclei-templates - generated_templates:/root/cvengine-generated-templates # validated AI-written templates survive an update - tool_config:/root/.config - static_volume:/usr/src/app/staticfiles/ ports: - "127.0.0.1:8000:8000" depends_on: - db - celery - celery-beat networks: rengine_network: aliases: - rengine proxy: restart: always image: nginx:alpine ports: - 8082:8082/tcp - 443:443/tcp depends_on: - web - db - redis secrets: - source: proxy.ca target: /etc/nginx/certs/rengine_chain.pem - source: proxy.cert target: /etc/nginx/certs/rengine.pem - source: proxy.key target: /etc/nginx/certs/rengine_rsa.key volumes: - ./config/nginx/rengine.conf:/etc/nginx/conf.d/rengine.conf:ro - static_volume:/usr/src/app/staticfiles/ - scan_results:/usr/src/scan_results networks: - rengine_network networks: rengine_network: volumes: tool_config: postgres18_data: nuclei_templates: generated_templates: github_repos: scan_results: static_volume: secrets: proxy.ca: file: ./secrets/certs/rengine_chain.pem proxy.key: file: ./secrets/certs/rengine_rsa.key proxy.cert: file: ./secrets/certs/rengine.pem