Outpost can route outgoing webhook traffic through an HTTP forward proxy. Common reasons:

  • Static-IP egress — destinations that allowlist a specific source IP
  • Network isolation — keep delivery workers off the public internet
  • Centralized egress policy — single chokepoint for outbound traffic

The proxy applies to every webhook destination served by the deployment.

Configuration

Env varDescription
DESTINATIONS_WEBHOOK_PROXY_URLProxy URL, e.g. http://user:pass@proxy.example.com:8080. Supports basic auth.

When set, Outpost installs an HTTP proxy on the webhook publisher's transport. HTTPS destinations use the standard CONNECT tunneling flow; HTTP destinations are forwarded request-by-request.

Failure attribution

Outpost separates failures the proxy is responsible for from failures the destination is responsible for:

  • Proxy-side failures (proxy unreachable, proxy auth rejected) are not charged to the destination. The message is redelivered by the queue, so a short proxy outage is transparent to the destination.
  • Destination-side failures reported via the proxy (DNS failure, connection refused, upstream timeout) are recorded as a normal delivery attempt with the matching network error code, the same as if no proxy were in path.

If you expect proxy outages longer than your queue's redelivery window, raise MinRetryBackoff, MaxRetryBackoff, and RetryLimit in your queue configuration so the redelivery window covers the worst case. See Configuration.

Using Envoy

When the proxy is Envoy, Outpost automatically reads x-envoy-response-flags from proxy responses and maps them to the same network error codes used elsewhere (e.g. UTtimeout, DFdns_error). No Outpost-side configuration is required, but Envoy must be configured to emit the header.

Add the response-flag header on the route configuration (not the HTTP connection manager — Envoy rejects it there):

route_config:
  response_headers_to_add:
    - header:
        key: "x-envoy-response-flags"
        value: "%RESPONSE_FLAGS%"
      append_action: OVERWRITE_IF_EXISTS_OR_ADD
    - header:
        key: "x-envoy-response-code-details"
        value: "%RESPONSE_CODE_DETAILS%"
      append_action: OVERWRITE_IF_EXISTS_OR_ADD
  virtual_hosts:
    # ...

OVERWRITE_IF_EXISTS_OR_ADD prevents a destination from spoofing the header. The response-code-details header is optional but gives operators a precise stage/reason string in logs.

Minimal reference Envoy

A minimal forward-proxy Envoy listener with response-flag reporting enabled:

admin:
  address:
    socket_address: { address: 127.0.0.1, port_value: 9901 }

static_resources:
  listeners:
    - name: forward_proxy
      address:
        socket_address: { address: 0.0.0.0, port_value: 10000 }
      filter_chains:
        - filters:
            - name: envoy.filters.network.http_connection_manager
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                stat_prefix: forward_proxy
                codec_type: AUTO
                http_filters:
                  - name: envoy.filters.http.dynamic_forward_proxy
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.dynamic_forward_proxy.v3.FilterConfig
                      dns_cache_config:
                        name: dfp_cache
                        dns_lookup_family: V4_ONLY
                  - name: envoy.filters.http.router
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
                upgrade_configs:
                  - upgrade_type: CONNECT
                route_config:
                  response_headers_to_add:
                    - header:
                        key: "x-envoy-response-flags"
                        value: "%RESPONSE_FLAGS%"
                      append_action: OVERWRITE_IF_EXISTS_OR_ADD
                    - header:
                        key: "x-envoy-response-code-details"
                        value: "%RESPONSE_CODE_DETAILS%"
                      append_action: OVERWRITE_IF_EXISTS_OR_ADD
                  virtual_hosts:
                    - name: proxy
                      domains: ["*"]
                      routes:
                        - match: { connect_matcher: {} }
                          route:
                            cluster: dfp_cluster
                            upgrade_configs:
                              - upgrade_type: CONNECT
                                connect_config: {}
                        - match: { prefix: "/" }
                          route: { cluster: dfp_cluster }

  clusters:
    - name: dfp_cluster
      lb_policy: CLUSTER_PROVIDED
      cluster_type:
        name: envoy.clusters.dynamic_forward_proxy
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig
          dns_cache_config:
            name: dfp_cache
            dns_lookup_family: V4_ONLY

Whether you need proxy authentication and TLS depends on your network topology: if Outpost and the proxy share a private network, neither is strictly required; if the proxy is reachable over the public internet, both are strongly recommended to prevent the proxy being used as an open relay.