Working Behind a Corporate HTTP Proxy
Many enterprise networks do not allow workloads to reach the internet directly. Instead, all outbound traffic must go through a corporate HTTP proxy (for example Squid, Zscaler, or a Blue Coat/Symantec gateway). The LinearB On-Premise Agent supports this topology so that its traffic to the LinearB cloud can be routed through your proxy.
This guide explains what the proxy feature does, how to enable it, and — just as important — what it does not cover, so you can plan the rest of your network allowlisting accordingly.
Overview
The agent runs a small internal reverse proxy called forward-proxy (an NGINX pod). Most LinearB services and job pods do not talk to the LinearB cloud directly — they send their outbound requests to forward-proxy, which applies routing rules and forwards the request to LinearB's cloud API at on-prem-api.linearb.io.
forward-proxy is itself a proxy, and NGINX cannot be told to send its own upstream traffic through another (corporate) HTTP proxy. To bridge that gap, enabling the proxy feature deploys a second component — socat-tunneller — which is proxy-aware. When the feature is on, forward-proxy sends its upstream traffic to socat-tunneller, which relays it through your corporate proxy.
The effective traffic chain becomes:
internal LinearB pods
│ (in-cluster HTTP, ports 3128–3136)
▼
forward-proxy (NGINX reverse proxy)
│ (EXTERNAL_PROXY=true → upstream repointed at socat)
▼
socat-tunneller (proxy-aware relay, port 8443)
│ (HTTP CONNECT or raw TCP)
▼
corporate HTTP proxy (EXTERNAL_PROXY_HOST:EXTERNAL_PROXY_PORT)
│
▼
on-prem-api.linearb.io:443
When the feature is off (the default), forward-proxy connects to on-prem-api.linearb.io directly and socat-tunneller is not deployed.
Scope: only the LinearB cloud API is proxied
This feature routes only the agent's traffic to on-prem-api.linearb.io through your corporate proxy. It does not inject HTTP_PROXY/HTTPS_PROXY environment variables into the pods, so every other outbound flow — Git provider APIs and clones, project-management tools (Jira/Azure Boards/etc.), Datadog, S3, GitStream analytics, and container image pulls — is not affected. See Scope and limitations below.
Configuration
The feature is controlled by four values under global in your local-values.yaml:
| Value | Default | Description |
|---|---|---|
EXTERNAL_PROXY | false | Master switch. Set to true to route LinearB-API egress through your proxy. |
EXTERNAL_PROXY_HOST | localhost | Hostname or IP of your corporate proxy. Must be overridden when enabling. |
EXTERNAL_PROXY_PORT | 3128 | Listening port of your corporate proxy. |
EXTERNAL_PROXY_TYPE | connect | How socat-tunneller talks to the proxy: connect or transparent (see below). |
When EXTERNAL_PROXY is true, EXTERNAL_PROXY_HOST, EXTERNAL_PROXY_PORT and EXTERNAL_PROXY_TYPE are all required.
EXTERNAL_PROXY_HOST defaults to localhost
If you set EXTERNAL_PROXY: true but forget to change EXTERNAL_PROXY_HOST, the tunnel will try to reach a proxy on its own pod (localhost) and all LinearB-cloud traffic will fail with connection-refused errors. Always set a real proxy host.
connect vs transparent
-
connect(default, recommended for a standard forward proxy):socat-tunnelleropens an HTTPCONNECTtunnel to your proxy, asking it to establish a connection toon-prem-api.linearb.io:443. The TLS session then flows end-to-end from the agent to LinearB through that tunnel. Use this for a normal explicit corporate proxy. -
transparent:socat-tunnellerforwards a raw TCP stream toEXTERNAL_PROXY_HOST:EXTERNAL_PROXY_PORTwith noCONNECTverb. Your proxy must be pre-configured to forward that connection on toon-prem-api.linearb.io(typically by inspecting the TLS SNI). Only use this if you operate a transparent/intercepting gateway that is explicitly set up to route this traffic.
The corporate proxy's TLS certificate is not involved
In both modes the TLS connection is tunneled through to on-prem-api.linearb.io — the agent does not terminate TLS at your proxy. You therefore do not need to add your corporate proxy's CA certificate to make this feature work. (A custom CA may still be needed for other, non-proxied flows — see Custom CA vs. the proxy.)
Enabling the proxy
- In your
local-values.yaml, set the four values underglobal:
global:
EXTERNAL_PROXY: true
EXTERNAL_PROXY_HOST: "proxy.corp.example.com"
EXTERNAL_PROXY_PORT: "3128"
EXTERNAL_PROXY_TYPE: "connect"
-
Make sure your corporate proxy allows outbound HTTPS to
on-prem-api.linearb.io:443(see Firewall / allowlisting). -
Deploy or upgrade the agent as usual (
helm upgrade --install …). Enabling the feature deploys the additionalsocat-tunnellerworkload.
Verifying
After deploying with the proxy enabled:
# The socat-tunneller pod should be running (it only exists when EXTERNAL_PROXY=true)
kubectl get pods -n linearb | grep socat
# Confirm forward-proxy is pointed at socat rather than directly at the internet
kubectl get configmap common-chart-values -n linearb \
-o jsonpath='{.data.PROXY_PASS_API_DESTINATION}{"\n"}'
# Expected (proxy on): on-prem-agent-socat-tunneller.linearb.svc.cluster.local:8443
# Expected (proxy off): on-prem-api.linearb.io
# Inspect socat-tunneller logs for connection activity/errors
kubectl logs -n linearb deploy/on-prem-agent-socat-tunneller
If the agent cannot report to the LinearB cloud after enabling the proxy, check, in order: the socat-tunneller pod is running, EXTERNAL_PROXY_HOST/PORT point at the real proxy (not localhost), and the proxy itself is allowed to reach on-prem-api.linearb.io:443.
Scope and limitations
The proxy feature deliberately covers only the LinearB-cloud API egress. Everything below is not routed through EXTERNAL_PROXY and must be planned separately.
What is not routed through the corporate proxy
The following flows egress directly from the agent pods/nodes even when EXTERNAL_PROXY is on. In a locked-down network, allowlist these on your firewall (or arrange another egress path):
| Flow | Destination(s) |
|---|---|
| Git provider API + repo clones | Your SCM's API and HTTPS endpoints (GitHub/GitLab/Bitbucket/etc.) |
| Project-management connectors | Your PM tool's API (Jira, Azure Boards, etc.) |
| Datadog agent (metrics & logs) | api.datadoghq.com (and *.datadoghq.com) |
| Log/monitoring uploads | linearb-data-lake.s3.amazonaws.com |
GitStream (if EXT_GITSTREAM) | api.segment.io, public-api.linearb.io |
| Container image pulls | LinearB's JFrog registry and any mirror you configure |
See the Prerequisites guide for the full egress FQDN list.
Datadog does not use the proxy automatically
If the Datadog subchart is enabled (datadog-agent.enabled: true), the Datadog agent egresses directly to api.datadoghq.com — the EXTERNAL_PROXY setting does not apply to it. In a network where only the corporate proxy has internet access, this means metrics and logs will silently fail to reach Datadog.
You have three options:
- Allowlist
api.datadoghq.com(and*.datadoghq.com) directly on your firewall — it is already listed as a direct egress FQDN in the Prerequisites guide. - Point the Datadog agent at your corporate proxy by adding proxy environment variables to the Datadog subchart (no chart change required). Add them under
envDict— see the warning below for whyenvis the wrong key:
datadog-agent:
datadog:
envDict:
DD_PROXY_HTTPS: "http://proxy.corp.example.com:3128"
DD_PROXY_HTTP: "http://proxy.corp.example.com:3128"
# Match the entries below as suffixes and CIDRs, not as exact hostnames
DD_NO_PROXY_NONEXACT_MATCH: "true"
# Space-separated — that is the format Datadog defines for DD_PROXY_NO_PROXY
DD_PROXY_NO_PROXY: "on-prem-agent-rabbitmq-headless kubernetes.default.svc localhost 127.0.0.1 169.254.169.254 .svc .svc.cluster.local .cluster.local 10.0.0.0/8"
# The Cluster Agent does not inherit datadog.envDict — repeat the variables here.
clusterAgent:
envDict:
DD_PROXY_HTTPS: "http://proxy.corp.example.com:3128"
DD_PROXY_HTTP: "http://proxy.corp.example.com:3128"
DD_NO_PROXY_NONEXACT_MATCH: "true"
# Space-separated, as above
DD_PROXY_NO_PROXY: "on-prem-agent-rabbitmq-headless kubernetes.default.svc localhost 127.0.0.1 169.254.169.254 .svc .svc.cluster.local .cluster.local 10.0.0.0/8"
The proxy value points at your corporate proxy directly — not at forward-proxy/socat, which only know how to reach the LinearB API. 3. Disable Datadog (datadog-agent.enabled: false) if you do not need it.
Use envDict, not env — a list override deletes the chart's own entries
Helm merges maps but replaces lists. datadog-agent.datadog.env and datadog-agent.clusterAgent.env are lists, and the chart already populates both with the credentials the Datadog agent uses for its RabbitMQ check. Setting either of them in your values file silently removes those entries, and the check then fails to authenticate. envDict is a map, so it merges with what the chart ships and cannot drop anything.
If your values file already overrides datadog-agent.datadog.env — or datadog-agent.clusterAgent.env, which carries the same two entries — either move the proxy variables to the matching envDict, or keep the list and repeat the credential entries alongside them:
datadog-agent:
datadog:
env:
- name: RABBITMQ_USER
valueFrom:
secretKeyRef:
name: rabbitmq-secret
key: rabbitmq-user
- name: RABBITMQ_PASSWORD
valueFrom:
secretKeyRef:
name: rabbitmq-secret
key: rabbitmq-password
- name: DD_PROXY_HTTPS
value: "http://proxy.corp.example.com:3128"
# ...and the remaining proxy variables
# If you also override clusterAgent.env, repeat the same two credential entries there.
After upgrading, confirm the credentials and the proxy variables are both present:
# substitute your Helm release name if it is not `on-prem-agent`
kubectl -n linearb set env daemonset/on-prem-agent-datadog-agent \
--containers=agent --list | grep -E 'RABBITMQ_|DD_PROXY_|DD_NO_PROXY_'
kubectl -n linearb set env deployment/on-prem-agent-datadog-agent-cluster-agent \
--containers=cluster-agent --list | grep -E 'RABBITMQ_|DD_PROXY_|DD_NO_PROXY_'
DD_PROXY_NO_PROXY must cover in-cluster names, including dot-less Service names
Entries are space-separated, and by default only core Agent HTTP(S) requests match them exactly — requests made by Agent integrations already use non-exact (suffix and CIDR) matching. So a value such as "kubernetes.default.svc.cluster.local 10.0.0.0/8" excludes almost nothing from core Agent traffic. DD_NO_PROXY_NONEXACT_MATCH: "true" applies the same suffix and CIDR rules to core Agent requests.
Under either matching mode, a suffix entry never matches a dot-less Service name. The agent's RabbitMQ check targets on-prem-agent-rabbitmq-headless, so that name must be listed verbatim. That hostname is fixed by the chart and does not change with your Helm release name. When the check is being proxied, the corporate proxy typically refuses it with 403 and an HTML error page. List any other dot-less host used by a check you add yourself, and replace 10.0.0.0/8 with your cluster's actual Pod and Service CIDRs.
Fluent Bit does not egress
When log shipping is enabled via Fluent Bit, it writes to a local volume rather than sending logs to the internet, so it needs no proxy configuration.
Container image pulls are not proxied
Kubernetes pulls the agent's container images using the node's container runtime (containerd/Docker), which is outside the forward-proxy/socat-tunneller path. If your cluster nodes have no direct internet access, image pulls will fail unless you either:
- configure the container runtime on each node with proxy settings (for containerd, a systemd drop-in that sets
HTTP_PROXY/HTTPS_PROXY/NO_PROXYfor thecontainerdservice), or - mirror the images into a registry your nodes can reach and point the chart at it (see Customizing Container Registry).
This is node/OS-level configuration and is not managed by the agent's Helm chart.
Proxy authentication is not supported
The tunnel connects to your corporate proxy without credentials. Proxies that require authentication (Basic/NTLM/Kerberos) are not currently supported by this feature. If your proxy enforces authentication, you will need an unauthenticated allowlist entry (or a dedicated egress path) for the agent to reach on-prem-api.linearb.io.
Custom CA vs. the proxy
The corporate-proxy feature and the custom-CA feature (global.CUSTOM_ROOT_CERTIFICATES) are independent:
- You do not need a custom CA to make
EXTERNAL_PROXYwork — TLS is tunneled end-to-end to LinearB, so your proxy's certificate is never validated by the agent for that path. - You may still need
CUSTOM_ROOT_CERTIFICATES: true(with your CA bundle) if your proxy performs TLS interception (MITM) on the other, non-proxied flows above — for example git clones or Jira API calls. Those are direct HTTPS calls from the agent and will fail certificate validation against an intercepting proxy unless the proxy's CA is trusted.
Single point of egress
When the proxy is enabled, all LinearB-cloud traffic for every service and job flows through the single forward-proxy → socat-tunneller path. If your corporate proxy is unreachable, all cloud reporting and ingestion stops until it recovers. Treat proxy availability as a dependency of the agent, and monitor socat-tunneller/forward-proxy pod health.
OpenShift: DNS resolver
Because forward-proxy resolves its upstream at runtime, on OpenShift you must point NGINX at the OpenShift DNS service or the proxied requests will fail DNS resolution:
See the v5 upgrade guide for details.
Firewall / allowlisting
When EXTERNAL_PROXY is enabled, plan connectivity as follows:
- The agent nodes/pods must be able to reach your corporate proxy at
EXTERNAL_PROXY_HOST:EXTERNAL_PROXY_PORT. - Your corporate proxy must be allowed to reach
on-prem-api.linearb.io:443. - All other egress destinations listed in What is not routed through the corporate proxy must be reachable directly from the agent (they do not traverse the proxy).
Reference
| Value | Where | Notes |
|---|---|---|
global.EXTERNAL_PROXY | local-values.yaml | true/false. Enables the feature and deploys socat-tunneller. |
global.EXTERNAL_PROXY_HOST | local-values.yaml | Corporate proxy hostname/IP. Override the localhost default. |
global.EXTERNAL_PROXY_PORT | local-values.yaml | Corporate proxy port (e.g. 3128). |
global.EXTERNAL_PROXY_TYPE | local-values.yaml | connect (explicit proxy) or transparent (intercepting gateway). |
forward-proxy.resolver | local-values.yaml | DNS resolver for NGINX; override on OpenShift. |