Ctrl K
ComunidadGuías…

compose.integration.yaml

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
name: rootguard

services:
  unbound:
    build:
      context: ./rootguard-unbound
    image: rootguard-unbound:dev
    container_name: rootguard-unbound
    restart: unless-stopped
    read_only: true
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    volumes:
      - unbound-config:/etc/unbound/unbound.d
      - unbound-state:/var/lib/unbound
    networks:
      dns:
        ipv4_address: 172.29.53.2
      forwarding_test:
        ipv4_address: 172.30.54.3

  forwarder:
    image: rootguard-unbound:dev
    container_name: rootguard-forwarder
    restart: unless-stopped
    entrypoint: ["unbound", "-d", "-c", "/etc/unbound/forwarder.conf"]
    user: "0:0"
    read_only: true
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    security_opt:
      - no-new-privileges:true
    volumes:
      - ./testdata/forwarder/unbound.conf:/etc/unbound/forwarder.conf:ro
    networks:
      forwarding_test:
        ipv4_address: 172.30.54.2
    healthcheck:
      test: ["CMD", "dig", "+short", "+time=1", "+tries=1", "@127.0.0.1", "-p", "53", "example.", "A"]
      interval: 2s
      timeout: 2s
      retries: 15

  adguard:
    image: "${ROOTGUARD_ADGUARD_IMAGE:-adguard/adguardhome:v0.107.80}"
    container_name: rootguard-adguard
    restart: unless-stopped
    depends_on:
      updater:
        condition: service_healthy
      unbound:
        condition: service_healthy
    ports:
      - "${ROOTGUARD_DNS_BIND:-0.0.0.0}:${ROOTGUARD_DNS_PORT:-53}:53/tcp"
      - "${ROOTGUARD_DNS_BIND:-0.0.0.0}:${ROOTGUARD_DNS_PORT:-53}:53/udp"
    volumes:
      - adguard-work:/opt/adguardhome/work
      - adguard-config:/opt/adguardhome/conf
    networks:
      - dns

  core:
    build:
      context: ./rootguard-core
    image: rootguard-core:dev
    container_name: rootguard-core
    restart: unless-stopped
    depends_on:
      unbound:
        condition: service_healthy
      forwarder:
        condition: service_healthy
      adguard:
        condition: service_started
    environment:
      PORT: "8081"
      ROOTGUARD_API_TOKEN: "${ROOTGUARD_API_TOKEN:?set ROOTGUARD_API_TOKEN in .env}"
      # This file's own unbound/adguard are pre-provisioned compose
      # services (bootstrapped directly, never through
      # installer.Manager.deploy()), so the attestation gate's code path
      # isn't actually reached here today - added for consistency with
      # compose.yaml/compose.release.yaml anyway, so a future test that
      # does exercise POST /api/installation/deploy against this file
      # doesn't hit the same live-testing surprise compose.yaml did
      # (2026-08-29, see docs/security-audit-log.md).
      ROOTGUARD_SKIP_ATTESTATION: "${ROOTGUARD_SKIP_ATTESTATION:-false}"
      ROOTGUARD_INSTALLATION_DIR: /var/lib/rootguard/installation
      ROOTGUARD_CONTROL_PLANE_UPDATER_URL: http://updater:8082
      ROOTGUARD_CONTROL_PLANE_UPDATER_TOKEN: "${ROOTGUARD_API_TOKEN:?set ROOTGUARD_API_TOKEN in .env}"
      UNBOUND_CONFIG_DIR: /var/lib/rootguard/unbound
      UNBOUND_CONTAINER_CONFIG_DIR: /etc/unbound/unbound.d
      UNBOUND_CONTAINER_NAME: rootguard-unbound
      # Empty by default - Diagnose keeps querying the real internet
      # (example.com/dnssec-failed.org), correct for an actual
      # deployment. ci.yml sets both to a local, throwaway DNSSEC test
      # zone (scripts/ci/dnssec-test-zone) so its own integration test of
      # this exact endpoint doesn't depend on the runner's own network -
      # found in review, confirmed live: main's own scheduled run of that
      # check failed on a transient DNS hiccup unrelated to any code
      # change.
      ROOTGUARD_UNBOUND_DIAGNOSTIC_RESOLUTION_DOMAIN: "${ROOTGUARD_UNBOUND_DIAGNOSTIC_RESOLUTION_DOMAIN:-}"
      ROOTGUARD_UNBOUND_DIAGNOSTIC_DNSSEC_DOMAIN: "${ROOTGUARD_UNBOUND_DIAGNOSTIC_DNSSEC_DOMAIN:-}"
      ADGUARD_INSTALLER_URL: http://rootguard-adguard:3000
      ADGUARD_API_URL: http://rootguard-adguard:80
      ADGUARD_DATA_DIR: /var/lib/rootguard/adguard
      ADGUARD_UPSTREAM: 172.29.53.2:5335
      ADGUARD_DNS_ADDRESS: rootguard-adguard:53
      # Propagates the real host checkout directory into a
      # `docker compose -f /opt/rootguard/compose.yaml ...`
      # re-invocation from inside this container - see the matching
      # comment on the volumes line below and on compose.yaml's own core
      # service (the identical fix, applied there first).
      PWD: "${PWD}"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - rootguard-data:/var/lib/rootguard
      - unbound-config:/var/lib/rootguard/unbound
      # Aliased to the fixed "compose.yaml" name (not this file's own
      # "compose.integration.yaml") because
      # internal/updater/manager.go's composeUp hardcodes that filename -
      # same reason compose.yaml/compose.release.yaml's own core service
      # alias-mounts theirs. ${PWD}, not a relative "./...", for the same
      # reason those two files use it: a relative source re-resolves
      # against the wrong directory the moment this container re-invokes
      # `docker compose -f <this mounted path> ...` against itself.
      # Nothing in this file currently drives Core's own
      # updater-of-updater self-update path (no ROOTGUARD_SELF_UPDATE_DIR/
      # ROOTGUARD_COMPOSE_FILE wired here, no attestation-proxy service),
      # so this mount is currently unused - added so the same silent
      # "missing file" surprise found live in compose.yaml (2026-08-29,
      # see docs/security-audit-log.md) can't recur here the moment that
      # gets wired up.
      - ${PWD}/compose.integration.yaml:/opt/rootguard/compose.yaml:ro
    networks:
      - control
      - dns
    healthcheck:
      test: ["CMD", "wget", "-q", "-O", "-", "http://127.0.0.1:8081/api/health"]
      interval: 15s
      timeout: 5s
      retries: 5

  webapp:
    build:
      context: ./rootguard-webapp
    image: rootguard-webapp:dev
    container_name: rootguard-webapp
    restart: unless-stopped
    depends_on:
      core:
        condition: service_healthy
    environment:
      PORT: "8080"
      ROOTGUARD_CORE_URL: http://core:8081
      ROOTGUARD_API_TOKEN: "${ROOTGUARD_API_TOKEN:?set ROOTGUARD_API_TOKEN in .env}"
      ROOTGUARD_ADMIN_USER: "${ROOTGUARD_ADMIN_USER:-admin}"
      ROOTGUARD_ADMIN_PASSWORD: "${ROOTGUARD_ADMIN_PASSWORD:?set ROOTGUARD_ADMIN_PASSWORD in .env}"
      ROOTGUARD_RECOVERY_TOKEN: "${ROOTGUARD_RECOVERY_TOKEN:?set ROOTGUARD_RECOVERY_TOKEN in .env}"
      ROOTGUARD_SESSION_FILE: /var/lib/rootguard-sessions/sessions.json
    volumes:
      - rootguard-sessions:/var/lib/rootguard-sessions
    ports:
      - "${ROOTGUARD_WEB_PORT:-8080}:8080/tcp"
    networks:
      - control
      - edge
    # Found in review: missing here despite compose.yaml (dev) having it.
    # The distroless runtime image has neither wget nor a shell - unlike
    # core/updater's docker:29-cli base, there's nothing here for a
    # "CMD wget ..." style check to exec. rootguard-webapp itself
    # implements -healthcheck for exactly this (see cmd/rootguard-webapp).
    healthcheck:
      test: ["CMD", "/app/rootguard-webapp", "-healthcheck"]
      interval: 15s
      timeout: 5s
      retries: 5

  updater:
    build:
      context: ./rootguard-updater
    image: rootguard-updater:dev
    container_name: rootguard-updater
    restart: unless-stopped
    environment:
      ROOTGUARD_UPDATER_TOKEN: "${ROOTGUARD_API_TOKEN:?set ROOTGUARD_API_TOKEN in .env}"
      ROOTGUARD_UPDATER_DATA_DIR: /var/lib/rootguard/control-plane-updater
      ROOTGUARD_COMPOSE_FILE: /opt/rootguard/compose.integration.yaml
      ROOTGUARD_COMPOSE_PROJECT: rootguard
      ROOTGUARD_CORE_UPDATE_IMAGE: rootguard-core:dev
      ROOTGUARD_WEBAPP_UPDATE_IMAGE: rootguard-webapp:dev
      ROOTGUARD_UPDATER_SKIP_PULL: "true"
      ROOTGUARD_API_TOKEN: "${ROOTGUARD_API_TOKEN:?set ROOTGUARD_API_TOKEN in .env}"
      ROOTGUARD_ADMIN_USER: "${ROOTGUARD_ADMIN_USER:-admin}"
      ROOTGUARD_ADMIN_PASSWORD: "${ROOTGUARD_ADMIN_PASSWORD:?set ROOTGUARD_ADMIN_PASSWORD in .env}"
      ROOTGUARD_RECOVERY_TOKEN: "${ROOTGUARD_RECOVERY_TOKEN:?set ROOTGUARD_RECOVERY_TOKEN in .env}"
      ROOTGUARD_WEB_PORT: "${ROOTGUARD_WEB_PORT:-8080}"
      ROOTGUARD_SESSION_DIR: /var/lib/rootguard-sessions
      # See the matching PWD/${PWD} comments on the core service above
      # and on compose.yaml/compose.release.yaml's identical updater
      # service - required for the volumes line below to resolve
      # correctly when this container re-invokes `docker compose -f
      # /opt/rootguard/compose.integration.yaml ...` against itself.
      PWD: "${PWD}"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - rootguard-data:/var/lib/rootguard
      - rootguard-sessions:/var/lib/rootguard-sessions
      # ${PWD}, not a relative "./compose.integration.yaml" - found in
      # review: this file was missed when compose.yaml/compose.release.yaml
      # got the identical fix (2026-08-22, docs/security-audit-log.md). A
      # relative bind source resolves against the directory of whatever
      # -f file is being read, not this file's own location - breaks the
      # moment this container re-invokes `docker compose -f
      # /opt/rootguard/compose.integration.yaml ...` against itself,
      # silently mounting an auto-vivified empty directory instead of the
      # real file.
      - ${PWD}/compose.integration.yaml:/opt/rootguard/compose.integration.yaml:ro
    networks:
      - control
    healthcheck:
      test: ["CMD", "wget", "-q", "-O", "-", "http://127.0.0.1:8082/health"]
      interval: 5s
      timeout: 3s
      retries: 10

networks:
  edge:
  control:
    internal: true
  dns:
    ipam:
      config:
        - subnet: 172.29.53.0/24
  forwarding_test:
    internal: true
    ipam:
      config:
        - subnet: 172.30.54.0/24

volumes:
  adguard-work:
  adguard-config:
  unbound-config:
  unbound-state:
  rootguard-data:
  rootguard-sessions: