Deploy & Security
Three deployment topologies, one security model. The proxy is designed to be safe by default — it binds localhost, forwards only to the single configured upstream, and never touches your secrets.
Deployment topologies
Local dev sidecar
Run distil proxy on your laptop alongside your application. Default bind is 127.0.0.1:8788 — not reachable from the network. Zero infra overhead.
Container sidecar
Add the proxy as a sidecar container in the same Pod or Compose stack. Your app container calls http://localhost:8788; only the sidecar egresses to the upstream API.
Shared gateway
Run one proxy instance accessible to multiple services on a private network. Bind to an internal interface (--host 0.0.0.0), keep it behind a firewall or service mesh, never expose it to the public internet.
Local dev sidecar
# Terminal 1 distil proxy --port 8788 --upstream https://api.anthropic.com # Terminal 2 — your application ANTHROPIC_BASE_URL=http://127.0.0.1:8788 python my_agent.py
Container sidecar (Docker Compose)
services:
app:
build: .
environment:
- ANTHROPIC_BASE_URL=http://distil-proxy:8788
depends_on:
- distil-proxy
distil-proxy:
image: python:3.12-slim
command: >
sh -c "pip install distil-llm &&
distil proxy --host 0.0.0.0 --port 8788
--upstream https://api.anthropic.com"
ports: [] # not exposed externally
Shared gateway (Kubernetes)
apiVersion: apps/v1
kind: Deployment
metadata:
name: distil-proxy
spec:
replicas: 2
template:
spec:
containers:
- name: distil
image: python:3.12-slim
command:
- sh
- -c
- pip install distil-llm && distil proxy --host 0.0.0.0 --port 8788
env:
- name: DISTIL_UPSTREAM
value: https://api.anthropic.com
---
apiVersion: v1
kind: Service
metadata:
name: distil-proxy
spec:
clusterIP: ... # internal only — no LoadBalancer type
ports:
- port: 8788
Security model
Localhost-only by default
The proxy binds to 127.0.0.1 by default. It is not reachable from any other host unless you explicitly pass --host 0.0.0.0. In production topologies, always restrict network access to the proxy with a firewall rule or service mesh policy.
Single configured upstream — no SSRF
The upstream URL is set once at startup (--upstream). The proxy does not read the destination from the incoming request, so a malicious request body cannot redirect traffic to an attacker-controlled server. All outbound connections go to exactly one destination.
No request body logging
The proxy overrides log_message to suppress all request logs. It reads the request body to compress it, then discards it — nothing is written to disk or stdout. API keys, message content, and tool results are never logged.
# In distil/proxy.py — request logs are silenced by design
def log_message(self, fmt: str, *args: object) -> None:
pass
Auth-mode gating — lossless subscriptions stay lossless
Anthropic's cache-control and subscription/OAuth sessions require byte-for-byte stability in the system prefix. Pass --lossless-only to restrict the proxy to Tier-0 lossless transforms only (JSON minification, run-length collapse). No digests, no content changes that could break a cached prefix or OAuth flow.
distil proxy --lossless-only --upstream https://api.anthropic.com
Hop-by-hop header stripping
The proxy strips connection-specific headers (Connection, Transfer-Encoding, Keep-Alive, etc.) before forwarding. This prevents header injection attacks and ensures clean HTTP/1.1 semantics at the upstream boundary.
Data retention and zero-data retention (ZDR)
Distil itself retains no data. The proxy is stateless: it reads a request, compresses the messages array in memory, forwards it, and relays the response. Nothing is written to disk.
If your Anthropic contract includes Zero Data Retention (ZDR), the compressed payload forwarded by the proxy is covered by the same ZDR terms as a direct call — Distil does not introduce any additional retention surface.
Threat model summary
| Threat | Mitigation |
|---|---|
| Network exposure of the proxy | Binds 127.0.0.1 by default; explicit --host required to listen externally. |
| SSRF via request body | Upstream is set once at startup; cannot be overridden by request content. |
| Secret exfiltration via logs | Request logging is disabled; no body content is written anywhere. |
| Cache prefix corruption | --lossless-only mode restricts to byte-stable Tier-0 transforms only. |
| Header injection | Hop-by-hop headers are stripped before forwarding in both directions. |
| Data retention beyond request | Stateless handler; RestoreStore is in-process, not persisted. |