# BRouter host compose project — runs on the dedicated Hetzner Robot
# server `ullrich.is` under the `trails` user. See README.md for first-time
# provisioning notes.
#
# Exposed surface: Caddy listens on 10.0.1.10:17777 (vSwitch IP only).
# BRouter itself is not published to the host — only reachable via the
# internal Docker network from the Caddy sidecar.
#
# Logging: the host's default logging driver is `loki` (user's personal
# Loki). Every service here explicitly overrides to `json-file` so logs
# stay local and are picked up by the promtail sidecar (section 6.3) for
# shipping to trails.cool's Loki.

services:
  brouter:
    image: ghcr.io/trails-cool/brouter:latest
    container_name: trails-brouter
    restart: unless-stopped
    # Planet-scale coverage: segments live on the host and are mounted in.
    # 8 GB heap for segment cache; -Xms generous because routing is
    # memory-heavy and we don't benefit from a slow JVM warmup.
    # 16 routing threads on the 32 GB / multi-core dedicated host absorbs
    # burst traffic from "click around wildly" editing without triggering
    # BRouter's contention watchdog on the 4-thread default.
    environment:
      JAVA_OPTS: "-Xmx8g -Xms512M"
      BROUTER_THREADS: "16"
    volumes:
      - ./segments:/data/segments:ro
    networks:
      - trails-brouter-internal
    # Scope logs to json-file so we don't leak to the host's default Loki
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
    labels:
      trails.cool.service: "brouter"
    # No custom healthcheck: the BRouter image strips wget/curl post-build,
    # and /bin/sh in the base image doesn't support /dev/tcp. Real health
    # is observed via Caddy upstream (502 on outage) and the Planner-side
    # brouter_request_duration_seconds metric.

  caddy:
    image: caddy:2-alpine
    container_name: trails-brouter-caddy
    restart: unless-stopped
    depends_on:
      brouter:
        condition: service_started
    # Bind ONLY to the vSwitch IP on the host — the dedicated host's
    # public IP remains unaffected. UFW further restricts this to traffic
    # sourced from the flagship's private IP (10.0.0.2).
    ports:
      - "10.0.1.10:17777:17777"
    environment:
      BROUTER_AUTH_TOKEN: ${BROUTER_AUTH_TOKEN:?BROUTER_AUTH_TOKEN must be set}
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy-data:/data
      - caddy-config:/config
    networks:
      - trails-brouter-internal
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
    labels:
      trails.cool.service: "brouter-caddy"

  # cAdvisor — container metrics scraped by flagship Prometheus over the
  # vSwitch. We set container label filters so the exposed metrics only
  # cover trails-labeled containers (brouter + caddy), not the operator's
  # other workloads on this shared host.
  cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    container_name: trails-brouter-cadvisor
    restart: unless-stopped
    privileged: true
    ports:
      - "10.0.1.10:8080:8080"
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker:/var/lib/docker:ro
      - /dev/disk/:/dev/disk:ro
    command:
      # Only consider containers (not the host) and only those that carry
      # our label; filters out everything else on the shared host.
      - --docker_only=true
      - --store_container_labels=false
      - --whitelisted_container_labels=trails.cool.service
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
    labels:
      trails.cool.service: "brouter-cadvisor"

  # Promtail — tails Docker logs for trails-labeled containers only and
  # pushes to flagship Loki over the vSwitch. Does NOT scrape other
  # containers' logs on this host.
  promtail:
    image: grafana/promtail:latest
    container_name: trails-brouter-promtail
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./promtail-config.yml:/etc/promtail/config.yml:ro
      - promtail-positions:/tmp
    command: ["-config.file=/etc/promtail/config.yml"]
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
    labels:
      trails.cool.service: "brouter-promtail"

volumes:
  caddy-data:
  caddy-config:
  promtail-positions:

networks:
  trails-brouter-internal:
    driver: bridge
    # Container-to-container only; no host-level exposure via this net
