Files
bunkerwebpoc/roles/bunkerweb/templates/compose.yml.j2
T

139 lines
4.2 KiB
Django/Jinja

# {{ ansible_managed }}
# Stack BunkerWeb {{ bunkerweb_version }} : WAF + scheduler + UI + MariaDB + Redis
# Mode {{ poc_mode }}{% if poc_mode == 'split' %}, applis sur {{ apps_ip }}{% endif %}
{% macro upstream(name, site) -%}
{%- if site.upstream is match('^https?://') -%}
{{ site.upstream }}
{%- elif poc_mode == 'single' -%}
http://poc-{{ site.upstream }}:{{ apps_internal_ports[site.upstream] }}
{%- else -%}
http://{{ apps_ip }}:{{ apps_ports[site.upstream] }}
{%- endif -%}
{%- endmacro %}
{% macro val(v) %}{{ (v | string | replace('$', '$$')) | to_json }}{% endmacro %}
x-db-env: &db-env
DATABASE_URI: {{ val('mariadb+pymysql://bunkerweb:' ~ bw_db_password ~ '@bw-db:3306/db') }}
x-api-env: &api-env
API_WHITELIST_IP: "127.0.0.0/8 10.20.30.0/24"
services:
bunkerweb:
image: bunkerity/bunkerweb:{{ bunkerweb_version }}
container_name: bunkerweb
restart: unless-stopped
ports:
- "80:8080/tcp"
- "443:8443/tcp"
- "443:8443/udp" # HTTP/3 (QUIC)
labels:
- "bunkerweb.INSTANCE=yes"
environment:
<<: [*db-env, *api-env]
networks:
- bw-universe
- bw-services
bw-scheduler:
image: bunkerity/bunkerweb-scheduler:{{ bunkerweb_version }}
container_name: bw-scheduler
restart: unless-stopped
depends_on:
- bunkerweb
- bw-db
- bw-redis
volumes:
- bw-storage:/data
environment:
<<: [*db-env, *api-env]
BUNKERWEB_INSTANCES: "bunkerweb"
SERVER_NAME: {{ val(bw_sites.keys() | map('regex_replace', '$', '.' ~ poc_domain) | join(' ')) }}
# --- Réglages globaux ---
{% for k, v in bw_global_settings.items() %}
{{ k }}: {{ val(v) }}
{% endfor %}
{% for name, site in bw_sites.items() %}
{% set fqdn = name ~ '.' ~ poc_domain %}
# --- {{ fqdn }} ---
{{ fqdn }}_USE_REVERSE_PROXY: "yes"
{{ fqdn }}_REVERSE_PROXY_URL: "/"
{{ fqdn }}_REVERSE_PROXY_HOST: {{ val(upstream(name, site)) }}
{{ fqdn }}_SELF_SIGNED_SSL_SUBJ: {{ val('/CN=' ~ fqdn ~ '/') }}
{% for k, v in (site.settings | default({})).items() %}
{{ fqdn }}_{{ k }}: {{ val(v) }}
{% endfor %}
{% for k, v in (site.custom_confs | default({})).items() %}
{{ fqdn }}_CUSTOM_CONF_{{ k }}: {{ val(v) }}
{% endfor %}
{% if name in poc_restricted_sites and poc_allowed_sources | length > 0 %}
# Accès réservé (poc_allowed_sources + client de test), challenge ACME toujours permis
{{ fqdn }}_CUSTOM_CONF_MODSEC_poc-allowlist: {{ val('SecRule REMOTE_ADDR "!@ipMatch ' ~ ((poc_allowed_sources + [client_ip]) | join(',')) ~ '" "id:10002,phase:1,deny,status:403,log,msg:\'PoC BunkerWeb : source non autorisee\',chain"
SecRule REQUEST_URI "!@beginsWith /.well-known/acme-challenge/" "t:none"') }}
{% endif %}
{% endfor %}
networks:
- bw-universe
- bw-db
bw-ui:
image: bunkerity/bunkerweb-ui:{{ bunkerweb_version }}
container_name: bw-ui
restart: unless-stopped
depends_on:
- bw-db
volumes:
- bw-ui-data:/data # secrets Flask, clés TOTP et Biscuit
environment:
<<: *db-env
ADMIN_USERNAME: {{ val(bw_ui_admin_user) }}
ADMIN_PASSWORD: {{ val(bw_ui_admin_password) }}
TZ: "Europe/Paris"
networks:
- bw-universe
- bw-db
bw-db:
image: {{ mariadb_image }}
container_name: bw-db
restart: unless-stopped
command: --max-allowed-packet=67108864
environment:
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
MYSQL_DATABASE: "db"
MYSQL_USER: "bunkerweb"
MYSQL_PASSWORD: {{ val(bw_db_password) }}
volumes:
- bw-data:/var/lib/mysql
networks:
- bw-db
bw-redis:
image: {{ redis_image }}
container_name: bw-redis
restart: unless-stopped
command: ["redis-server", "--requirepass", {{ val(bw_redis_password) }}, "--save", "60", "1"]
volumes:
- bw-redis:/data
networks:
- bw-universe
volumes:
bw-data:
bw-storage:
bw-ui-data:
bw-redis:
networks:
bw-universe:
name: bw-universe
ipam:
driver: default
config:
- subnet: 10.20.30.0/24 # seul réseau autorisé à parler à l'API BunkerWeb
bw-services:
name: bw-services # réseau des applis (mode single), créé par Ansible
external: true
bw-db:
name: bw-db