version: 1 security: requireProtectionOnPublicListen: true gateway: enabled: true listen: 0.0.0.0:8080 access: allowCIDRs: [172.16.0.0/12] trustedProxies: [172.16.0.0/12] auth: mode: usernamePassword username: local-gateway password: "${PROXY_POOL_GATEWAY_PASSWORD}" limits: maxConcurrentConnections: 20000 requestsPerMinutePerClient: 60000 retry: maxAttempts: 2 retryMethods: [GET, HEAD] destinationPolicy: denyPrivateNetworks: true denyLoopback: true denyLinkLocal: true denyCIDRs: [169.254.169.254/32] distribution: enabled: true listen: 0.0.0.0:8081 access: allowCIDRs: [172.16.0.0/12] trustedProxies: [172.16.0.0/12] auth: mode: apiKey header: X-API-Key token: "${PROXY_POOL_EXTRACT_TOKEN}" limits: requestsPerMinute: 6000 requestsPerMinutePerClient: 600 clientIdentification: mode: sourceIP extraction: fulfillment: partial maxCountPerRequest: 100 minRemainingTTL: 30s maxHealthCheckAge: 30s reserveForGateway: 1000 idempotencyTTL: 5m admin: enabled: true listen: 0.0.0.0:8082 access: allowCIDRs: [172.16.0.0/12] auth: mode: apiKey header: X-Admin-Key token: "${PROXY_POOL_ADMIN_TOKEN}" metrics: enabled: true listen: 0.0.0.0:9090 storage: postgresURL: postgres://proxy_pool:local-only-change-me@postgres:5432/proxy_pool?sslmode=disable redisURL: redis://redis:6379/0 routing: - name: gateway-default enabled: true purpose: gateway upstreams: [provider-a, provider-b] strategy: type: sequential switchAfterEmptyFetch: 5 endBehavior: stayLast onUnavailable: action: reject - name: extract-default enabled: true purpose: extract upstreams: [provider-a, provider-b] strategy: type: sequential switchAfterEmptyFetch: 5 endBehavior: stayLast onUnavailable: action: reject upstreams: provider-a: enabled: true exposure: [gateway, extract] provider: billingMode: fetch protocols: [http] api: url: https://provider-a.invalid/api/proxies method: GET auth: type: apiKey location: header name: Authorization value: "${PROVIDER_A_TOKEN}" template: '{{ . }}' proxyAuth: type: response pool: maxSize: 5000 shrinkDelay: 30s capacity: maxConcurrencyPerProxy: 20 lifecycle: ttl: 5m allocationSafetyMargin: 20s fetch: requestInterval: 1s timeout: 3s maxAttempts: 3 maxInFlight: 1 maxTotal: 100000 maxResponseBytes: 4194304 templateTimeout: 100ms retry: initial: 500ms max: 30s jitter: 20 check: interval: 30s jitter: 20 maxInFlight: 200 timeout: 3s maxAttempts: 2 maxConsecutiveFailures: 3 urls: [https://example.com/] provider-b: enabled: true exposure: [gateway, extract] provider: billingMode: fetch protocols: [http] api: url: https://provider-b.invalid/api/proxies method: GET auth: type: apiKey location: header name: Authorization value: "${PROVIDER_B_TOKEN}" template: '{{ . }}' proxyAuth: type: response pool: maxSize: 5000 shrinkDelay: 30s capacity: maxConcurrencyPerProxy: 20 lifecycle: ttl: 5m allocationSafetyMargin: 20s fetch: requestInterval: 1s timeout: 3s maxAttempts: 3 maxInFlight: 1 maxTotal: 100000 maxResponseBytes: 4194304 templateTimeout: 100ms retry: initial: 500ms max: 30s jitter: 20 check: interval: 30s jitter: 20 maxInFlight: 200 timeout: 3s maxAttempts: 2 maxConsecutiveFailures: 3 urls: [https://example.com/]