
services:
  # 1. The "Firewall" / Router / Gateway
  gateway:
    build: ./gateway
    container_name: ot_gateway
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - NET_ADMIN
      - NET_RAW
      - DAC_OVERRIDE
    sysctls:
      - net.ipv4.ip_forward=1
    mem_limit: 1g
    command: /bin/sh -c "sh /network-config/firewall-rules.sh && sh /scripts/start_ids.sh && tail -f /dev/null"
    volumes:
      - ../detection/rules:/detection/rules
      - ../detection/logs:/detection/logs
      - ./network-config:/network-config
      - ./scripts:/scripts
    networks:
      it_network:
        ipv4_address: 172.24.0.2
      ops_network:
        ipv4_address: 172.23.0.2
      supervisory_network:
        ipv4_address: 172.22.0.2
      control_network:
        ipv4_address: 172.21.0.2

  # 2. Intake Process PLC (Level 1 - Control)
  plc_intake:
    image: ghcr.io/autonomy-logic/openplc-runtime:latest
    container_name: plc_intake
    restart: unless-stopped
    mem_limit: 256m
    ports:
      - "8443:8443"
    cap_add:
      - SYS_NICE
      - SYS_RESOURCE
    networks:
      control_network:
        ipv4_address: 172.21.0.10

  # 3. Treatment Process PLC (Level 1 - Control)
  plc_treatment:
    image: ghcr.io/autonomy-logic/openplc-runtime:latest
    container_name: plc_treatment
    restart: unless-stopped
    mem_limit: 256m
    ports:
      - "8444:8443"
    cap_add:
      - SYS_NICE
      - SYS_RESOURCE
    networks:
      control_network:
        ipv4_address: 172.21.0.11

  # 4. Distribution Process PLC (Level 1 - Control)
  plc_distribution:
    image: ghcr.io/autonomy-logic/openplc-runtime:latest
    container_name: plc_distribution
    restart: unless-stopped
    mem_limit: 256m
    ports:
      - "8445:8443"
    cap_add:
      - SYS_NICE
      - SYS_RESOURCE
    networks:
      control_network:
        ipv4_address: 172.21.0.12

  # 5. Human Machine Interface (Level 2 - Supervisory)
  hmi:
    image: scadalts/scadalts:latest
    container_name: ot_hmi
    restart: unless-stopped
    mem_limit: 1g
    ports:
      - "8080:8080"
    networks:
      supervisory_network:
        ipv4_address: 172.22.0.10
      control_network:
        ipv4_address: 172.21.0.20

  # 6. Process Historian (Level 3 - Operations)
  historian:
    image: influxdb:1.8.10
    container_name: ot_historian
    restart: unless-stopped
    mem_limit: 256m
    environment:
      - INFLUXDB_DB=ot_data
    networks:
      ops_network:
        ipv4_address: 172.23.0.10

  # 7. Attacker (Level 4/5 - Enterprise/Internet)
  attacker:
    build: ./attacker
    container_name: ot_attacker
    restart: unless-stopped
    mem_limit: 512m
    tty: true
    stdin_open: true
    cap_add:
      - NET_ADMIN
    depends_on:
      - gateway
    # Add the pivot routes to reach the OT zones via the gateway. Routes are
    # retried until the gateway is reachable (it is created in parallel).
    command: >
      /bin/sh -c "for net in 172.21.0.0/24 172.22.0.0/24 172.23.0.0/24; do
      until ip route add $$net via 172.24.0.2 2>/dev/null; do sleep 2; done; done;
      tail -f /dev/null"
    volumes:
      - ./attacker:/attacker
    networks:
      it_network:
        ipv4_address: 172.24.0.10

  # --- SIEM STACK (Level 3 & Level 4 Integration) ---

  # 8. Log Storage (Loki) - Level 4 Enterprise
  loki:
    image: grafana/loki:3.0.0
    container_name: ot_loki
    restart: unless-stopped
    mem_limit: 512m
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    volumes:
      - ../siem/configs/loki-config.yaml:/etc/loki/local-config.yaml
      - ../siem/configs/alerting-rules.yml:/etc/loki/rules/ot-security/rules.yml:ro
    networks:
      it_network:
        ipv4_address: 172.24.0.20

  # 9. Log Collector (Promtail) - Level 4 Enterprise
  promtail:
    image: grafana/promtail:3.0.0
    container_name: ot_promtail
    restart: unless-stopped
    mem_limit: 128m
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    volumes:
      - ../siem/configs/promtail-config.yaml:/etc/promtail/config.yml
      - ../detection/logs:/logs
    networks:
      it_network:
        ipv4_address: 172.24.0.21

  # 10. Visualization (Grafana) - Level 4 Enterprise
  grafana:
    image: grafana/grafana:11.0.0
    container_name: ot_grafana
    restart: unless-stopped
    mem_limit: 512m
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - SETGID
      - SETUID
    ports:
      - "3000:3000"
    environment:
      - GF_AUTH_ANONYMOUS_ENABLED=true
      - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
    volumes:
      - ../siem/configs/grafana-datasources.yaml:/etc/grafana/provisioning/datasources/datasources.yaml
      - ../siem/configs/grafana-dashboards-provider.yaml:/etc/grafana/provisioning/dashboards/provider.yaml
      - ../siem/dashboards:/var/lib/grafana/dashboards
    networks:
      it_network:
        ipv4_address: 172.24.0.22

  # 11. Alert Manager - Level 4 Enterprise
  alertmanager:
    image: prom/alertmanager:v0.27.0
    container_name: ot_alertmanager
    restart: unless-stopped
    mem_limit: 128m
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    volumes:
      - ../siem/configs/alertmanager-config.yaml:/etc/alertmanager/alertmanager.yml:ro
    networks:
      it_network:
        ipv4_address: 172.24.0.23

  # 12. Alert Webhook Receiver (SOAR-lite) - Level 4 Enterprise
  webhook:
    build: ../automation/playbooks
    container_name: ot_webhook
    restart: unless-stopped
    mem_limit: 256m
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - DAC_OVERRIDE
    environment:
      - OT_WEBHOOK_LOG=/logs/siem_alerts.json
    volumes:
      - ../detection/logs:/logs
    networks:
      it_network:
        ipv4_address: 172.24.0.24

networks:
  it_network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.24.0.0/24
  ops_network:
    internal: true
    ipam:
      config:
        - subnet: 172.23.0.0/24
  supervisory_network:
    internal: true
    ipam:
      config:
        - subnet: 172.22.0.0/24
  control_network:
    internal: true
    ipam:
      config:
        - subnet: 172.21.0.0/24
