Skip to main content

TLS AND PROXIES

This page covers two aspects of TLS in Swamp: client-side trust stores (certificate verification for outbound connections) and server-side TLS (terminating TLS on swamp serve).

Client-Side Trust Stores

Swamp consults the operating system's certificate trust store in addition to Deno's bundled Mozilla root certificates. Three environment variables control TLS certificate resolution. All three are evaluated on startup, before any network call. User-set values are never overwritten.

Environment Variables

Variable Purpose Default
DENO_TLS_CA_STORE Certificate stores to consult system,mozilla (set by Swamp)
DENO_CERT Path to a PEM file with additional CA certificates (unset)
SSL_CERT_FILE OpenSSL-convention path to a PEM CA bundle (unset — mapped to DENO_CERT)

DENO_TLS_CA_STORE

Controls which certificate stores Deno uses for TLS verification. Accepted values:

Value Behavior
system OS trust store only
mozilla Deno's bundled Mozilla roots only
system,mozilla Both stores merged (Swamp default when variable unset)

When DENO_TLS_CA_STORE is not set, Swamp sets it to system,mozilla on startup.

DENO_TLS_CA_STORE=system swamp workflow run deploy

DENO_CERT

Path to a PEM-encoded file containing one or more additional CA certificates. Certificates in this file are trusted in addition to those from the configured trust stores.

DENO_CERT=/etc/ssl/corporate-ca.pem swamp workflow run deploy

Swamp does not modify DENO_CERT when it is already set.


SSL_CERT_FILE

The OpenSSL-convention environment variable pointing to a PEM CA bundle. Deno does not read SSL_CERT_FILE natively. On startup, Swamp copies the value of SSL_CERT_FILE into DENO_CERT when DENO_CERT is not already set. If DENO_CERT is present, SSL_CERT_FILE has no effect.

SSL_CERT_FILE=/etc/pki/tls/certs/ca-bundle.crt swamp workflow run deploy

--ca-cert / SWAMP_CA_CERT

swamp worker connect accepts a --ca-cert flag (or the SWAMP_CA_CERT environment variable) pointing to a PEM-encoded CA certificate file. The certificate is trusted for TLS connections to the orchestrator, in addition to the certificates from the configured trust stores.

Mechanism Scope
DENO_CERT All TLS connections in the Deno process
SWAMP_CA_CERT Orchestrator connections from swamp worker connect only

Use --ca-cert when the orchestrator uses a self-signed or internal CA certificate and you want to trust it without modifying the OS trust store or setting process-wide variables.

swamp worker connect wss://orchestrator.internal:9090 \
    --token ci-runner.9ce100bf... \
    --ca-cert /etc/tls/internal-ca.pem
SWAMP_CA_CERT=/etc/tls/internal-ca.pem swamp worker connect wss://orchestrator.internal:9090 \
    --token ci-runner.9ce100bf...

The flag takes precedence over the environment variable when both are set. For the full swamp worker connect flag reference, see Worker Commands.


Limitations

SSL_CERT_DIR (the OpenSSL certificate-directory convention) is not supported. DENO_CERT accepts a single PEM file, not a directory of certificate files.

macOS: Incomplete System Trust Store

DENO_TLS_CA_STORE=system on macOS reads certificates from the Keychain but does not use Apple's full certificate trust evaluation. Root CAs distributed via Apple's over-the-air (OTA) trust updates are not recognized. This can cause UnknownIssuer errors for certificates that curl and browsers on the same machine accept without issue.

This is a known Deno limitation (denoland/deno#36402).

Swamp's default system,mozilla mitigates most cases because the Mozilla bundle covers the majority of public CAs. When UnknownIssuer errors persist, point SSL_CERT_FILE at a complete CA bundle. Swamp maps it to DENO_CERT automatically (see above).

# Homebrew OpenSSL (Apple Silicon)
SSL_CERT_FILE=/opt/homebrew/etc/openssl@3/cert.pem swamp workflow run deploy

# Homebrew OpenSSL (Intel)
SSL_CERT_FILE=/usr/local/etc/openssl@3/cert.pem swamp workflow run deploy

If Homebrew is not installed, export the system trust store to a PEM file:

security find-certificate -a -p /System/Library/Keychains/SystemRootCertificates.keychain \
  /Library/Keychains/System.keychain > ~/ca-bundle.pem
SSL_CERT_FILE=~/ca-bundle.pem swamp workflow run deploy

Server-Side TLS

swamp serve supports static TLS via the --cert-file and --key-file flags. When both are provided, the server listens over wss:// (WebSocket Secure) and https:// instead of plain ws:// and http://.

Flags

Flag Required Description Default
--cert-file <path> No Path to a PEM-encoded certificate file (unset)
--key-file <path> No Path to a PEM-encoded private key file (unset)

Both flags must be provided together. Providing only one is an error.

Environment Variables

Variable Equivalent flag
SWAMP_SERVE_CERT_FILE --cert-file
SWAMP_SERVE_KEY_FILE --key-file

Flags take precedence over environment variables when both are set.


--cert-file

Path to a PEM-encoded file containing the server certificate (and optionally the full certificate chain). The file must be readable by the swamp serve process.

swamp serve --cert-file /etc/tls/server.crt --key-file /etc/tls/server.key

--key-file

Path to a PEM-encoded file containing the private key corresponding to the certificate in --cert-file.

swamp serve --cert-file /etc/tls/server.crt --key-file /etc/tls/server.key

URL Scheme

When TLS is enabled, swamp serve listens on wss:// and https:// instead of ws:// and http://. Workers connecting via swamp worker connect to a wss:// URL automatically derive the data-plane URL over https:// — no --data-plane-url override is needed.

swamp worker connect wss://orchestrator.example.com:9090 \
    --token ci-runner.9ce100bf...

Limitations

Both --cert-file and --key-file must reference PEM-encoded files. Other formats (PKCS#12, DER) are not supported. Certificate rotation requires restarting swamp serve.


Client Extra Headers

When swamp serve sits behind a reverse proxy or tunnel that requires custom HTTP headers (e.g. a Tunnel-Token for Cloudflare Tunnel), clients can inject headers into every outbound connection via the SWAMP_SERVE_EXTRA_HEADERS environment variable.

Format

The value is one or more Name: value lines separated by newlines. Empty lines are ignored.

# Single header
SWAMP_SERVE_EXTRA_HEADERS="Tunnel-Token: abc123"

# Multiple headers (ANSI-C quoting)
SWAMP_SERVE_EXTRA_HEADERS=$'Tunnel-Token: abc123\nX-Custom-Org: ops-team'

Reserved Header Names

The following header names are reserved and cannot be overridden:

Header Reason
Authorization Managed by token/OAuth authentication
Host Set by the HTTP client
Upgrade Required for WebSocket negotiation
Connection Required for WebSocket negotiation

Setting a reserved header name causes Swamp to exit with an error.

Validation

Header names and values must not contain ASCII control characters (0x000x1F, 0x7F). Lines must follow the Name: value format — a missing colon or empty name is an error.

Scope

SWAMP_SERVE_EXTRA_HEADERS is a client-side variable. It applies to:

  • Remote runs via --server (swamp workflow run, swamp model method run)
  • Worker connections via swamp worker connect

It has no effect on the swamp serve server process itself.