A TLS forward proxy for routing AI API traffic through enterprise egress controls.
HERALD sits between your agent and the public internet. Your agent calls HERALD instead of the external API directly; HERALD terminates TLS, validates the certificate chain, rewrites the host, and forwards the request through your egress path.
Agent → HERALD (TLS) → Enterprise egress gateway → External AI API
Only the endpoint URL in your agent's config changes — no client code changes required.
- TLS 1.2 minimum enforced on all connections — no plaintext HTTP mode
- Real certificate validation — no skip-verify shortcuts
- Configurable CA trust via
HERALD_CA_BUNDLE— accepts a single file or a directory of.pem/.crtfiles, for local development or private/internal CAs - Falls back to the system trust store when no custom CA bundle is set — correct default for hitting public upstream APIs
- Structured JSON logging
- Server-level timeouts (read/write/idle) configured by default
/healthendpoint for liveness checks- Configuration entirely via environment variables — no config files
# .env
HERALD_UPSTREAM_URL=
HERALD_LISTEN_ADDR=
HERALD_LOG_LEVEL=
HERALD_TLS_KEY=
HERALD_TLS_CERT=
HERALD_CA_BUNDLE=| Variable | Required | Default | Description |
|---|---|---|---|
HERALD_UPSTREAM_URL |
Yes | — | The upstream API HERALD forwards requests to |
HERALD_LISTEN_ADDR |
No | :8080 |
Address HERALD binds to |
HERALD_LOG_LEVEL |
No | info |
Log verbosity: debug / info / warn / error |
HERALD_TLS_CERT |
Yes | — | Path to the TLS certificate HERALD serves |
HERALD_TLS_KEY |
Yes | — | Path to the TLS private key HERALD serves |
HERALD_CA_BUNDLE |
No | — | Path to a custom CA file or directory. Replaces the system trust store when set — see note below. |
HERALD_CA_BUNDLEbehaviour: when set, this replaces the system trust store rather than adding to it. Use it for local development (e.g. amkcert-generated CA) or to pin strictly to a private internal CA. Leave it unset in production if your upstream uses a standard publicly-trusted certificate — setting it will break verification against that upstream.
HERALD always serves TLS, including locally. Use mkcert to generate a certificate your system trusts:
brew install mkcert
mkcert -install
mkcert localhost 127.0.0.1 ::1HERALD_UPSTREAM_URL=https://your-upstream-api.com
HERALD_LISTEN_ADDR=:8080
HERALD_LOG_LEVEL=debug
HERALD_TLS_CERT=./caBundle/localhost+2.pem
HERALD_TLS_KEY=./caBundle/localhost+2-key.pem
HERALD_CA_BUNDLE=export $(cat .env | xargs) && go run ./herald.godocker build -t herald:v0.1.0 .Certs and .env must never be copied into the image build context. Confirm you have a .dockerignore with at least:
caBundle/
.git/
.env
*.pem
*.key
docker run \
--env-file .env \
-v "$(pwd)/caBundle:/certs:ro" \
-e HERALD_TLS_CERT=/certs/localhost+2.pem \
-e HERALD_TLS_KEY=/certs/localhost+2-key.pem \
-p 8080:8080 \
herald:v0.1.0Certs are mounted read-only at runtime — never baked into the image — so they can be rotated without a rebuild, and a leaked image layer never exposes a private key.
If you're using HERALD_CA_BUNDLE, mount that the same way and point the env var at the in-container path:
-v "$(pwd)/caBundle:/certs:ro" \
-e HERALD_CA_BUNDLE=/certscurl -k https://localhost:8080/healthEarly-stage. TLS handling and CA trust are in place. Allowlist enforcement, graceful shutdown, and request size limits are known gaps, not yet built.
- Allowlist enforcement on upstream domains
- Header injection for enterprise auth
- Pluggable scanning hooks for AI-specific security controls
- Rate limiting and audit logging
- Graceful shutdown on SIGTERM
Part of c0d3x-io.
Issues and pull requests are welcome. See CONTRIBUTING.md.
v0.1.0 — TLS-only forward proxy, configurable trust.