# InternetPressure.io — production stack (BHS64b, OVH Beauharnois) and dev stores. # # prod: docker compose -f infra/compose.yml --env-file deploy/.env up -d --remove-orphans # dev: docker compose -f infra/compose.yml --profile dev up -d clickhouse postgres redis (stores only, host ports 5433/8124/6380) # # Public traffic arrives from the BHS64 gateway over WireGuard wg1: edge Caddy :8350 is bound to ${WG_IP} only. # Nothing is bound to 0.0.0.0 in production. The stores are only reachable from the compose network. name: ip x-logging: &logging driver: json-file options: { max-size: "50m", max-file: "5" } x-app: &app image: ip/backend:${IP_TAG:-latest} build: context: .. dockerfile: infra/docker/Dockerfile.backend restart: unless-stopped logging: *logging environment: &app-env IP_ENV: production IP_LOG_LEVEL: ${IP_LOG_LEVEL:-info} IP_SITE_URL: ${IP_SITE_URL:-https://www.internetpressure.io} IP_PG_DSN: postgresql://ip:${POSTGRES_PASSWORD}@postgres:5432/ip IP_CH_URL: http://clickhouse:8123 IP_CH_DB: ip IP_CH_USER: ip IP_CH_PASSWORD: ${CLICKHOUSE_PASSWORD} IP_REDIS_URL: redis://redis:6379/0 IP_ADMIN_TOKEN: ${IP_ADMIN_TOKEN} IP_TRUST_PROXY: "true" IP_CONFIG_PATH: /app/packages/config/pressure.yaml IP_REGIONS_PATH: /app/data/regions.yaml IP_TARGETS_PATH: /app/data/targets/targets.yaml IP_SERVICES_PATH: /app/data/seed/services.yaml IP_PROBES_PATH: /app/data/seed/probes.yaml IP_DATA_DIR: /var/lib/ip IP_RELEASES_DIR: /releases IP_RIS_COLLECTORS: ${IP_RIS_COLLECTORS:-} IP_BGP_STORE_RAW: ${IP_BGP_STORE_RAW:-true} TZ: UTC volumes: - ip-data:/var/lib/ip - ./releases:/releases:ro depends_on: postgres: { condition: service_healthy } clickhouse: { condition: service_healthy } redis: { condition: service_healthy } services: # ───────────────────────────── edge (the only thing the gateway talks to) edge: image: caddy:2.10-alpine restart: unless-stopped logging: *logging ports: - "${WG_IP:-127.0.0.1}:8350:8350" volumes: - ./edge/Caddyfile:/etc/caddy/Caddyfile:ro - caddy-data:/data depends_on: [web, api] healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:8350/api/v1/status"] interval: 30s timeout: 5s retries: 3 start_period: 30s mem_limit: 256m # ───────────────────────────── application web: image: ip/web:${IP_TAG:-latest} build: context: .. dockerfile: apps/web/Dockerfile args: NEXT_PUBLIC_SITE_URL: ${IP_SITE_URL:-https://www.internetpressure.io} restart: unless-stopped logging: *logging environment: NODE_ENV: production PORT: "8351" HOSTNAME: 0.0.0.0 API_URL: http://api:8352 API_URL_INTERNAL: http://api:8352 NEXT_PUBLIC_SITE_URL: ${IP_SITE_URL:-https://www.internetpressure.io} TZ: UTC depends_on: [api] mem_limit: 2g api: <<: *app command: ["ip", "api"] cap_add: [SYS_PTRACE] # lets `py-spy dump --pid 1` profile the process from `docker exec -u root` environment: <<: *app-env IP_API_PORT: "8352" healthcheck: test: ["CMD", "python", "-c", "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8352/api/v1/health', timeout=3).status==200 else 1)"] interval: 20s timeout: 5s retries: 3 start_period: 40s mem_limit: 2g engine: <<: *app command: ["ip", "engine"] mem_limit: 6g bgp: <<: *app command: ["ip", "bgp"] mem_limit: 1g corroboration: <<: *app command: ["ip", "corroboration"] mem_limit: 512m migrate: <<: *app command: ["sh", "-c", "ip migrate && ip seed"] restart: "no" profiles: [ops] cli: <<: *app entrypoint: ["ip"] restart: "no" profiles: [ops] # ───────────────────────────── stores postgres: image: postgres:17-alpine restart: unless-stopped logging: *logging environment: POSTGRES_DB: ip POSTGRES_USER: ip POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-ip} TZ: UTC volumes: - pg-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ip -d ip"] interval: 10s timeout: 5s retries: 6 mem_limit: 2g clickhouse: image: clickhouse/clickhouse-server:25.8 restart: unless-stopped logging: *logging ulimits: nofile: { soft: 262144, hard: 262144 } environment: CLICKHOUSE_DB: ip CLICKHOUSE_USER: ip CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD:-ip} CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: "1" TZ: UTC volumes: - ch-data:/var/lib/clickhouse - ./clickhouse/config.d:/etc/clickhouse-server/config.d:ro healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:8123/ping"] interval: 10s timeout: 5s retries: 10 start_period: 20s mem_limit: ${CLICKHOUSE_MEM:-20g} redis: image: redis:7-alpine restart: unless-stopped logging: *logging command: ["redis-server", "--save", "60", "1000", "--appendonly", "no", "--maxmemory", "3gb", "--maxmemory-policy", "volatile-lru"] volumes: - redis-data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 3s retries: 5 mem_limit: 3500m # dev-only host port publication of the stores (profile "dev") dev-ports: image: alpine/socat:1.8.0.0 profiles: [dev] command: ["-d", "TCP-LISTEN:1,fork,reuseaddr", "TCP:localhost:1"] network_mode: "service:postgres" volumes: pg-data: ch-data: redis-data: ip-data: caddy-data: