Skip to main content

Caching Proxy

Kerrigan provides a Docker image that runs a private Squid forward proxy and an NGINX artifact cache. They solve two related but different problems:

  • Squid routes general HTTP and HTTPS traffic. It can cache plain HTTP. HTTPS uses a CONNECT tunnel, so Squid cannot read or cache the encrypted response.
  • NGINX caches SiMa artifact downloads. It is a fixed reverse proxy for the SiMa artifact CDN. NGINX terminates TLS using a private cache certificate, fetches a missing object from the CDN, and serves later requests from disk.

The reverse cache is not an open proxy. It always sends requests to the one configured artifact origin. This makes caching signed CDN and object-storage URLs predictable without decrypting arbitrary HTTPS traffic.

Container images​

The image workflow builds native linux/amd64 and linux/arm64 images, tests both architectures, and publishes a multi-architecture manifest to GHCR. Naming follows the SDK image convention:

SourcePublished image
mainghcr.io/sima-neat/caching-proxy:latest
developghcr.io/sima-neat/caching-proxy-develop:latest and ghcr.io/sima-neat/caching-proxy:develop
another branchghcr.io/sima-neat/caching-proxy-<branch>:latest and ghcr.io/sima-neat/caching-proxy:<branch>
version tagghcr.io/sima-neat/caching-proxy:<version>

Branch names are lowercased and characters that are not valid in a container repository name are replaced with hyphens. Commit-SHA and staged tags are kept for traceability. A moving tag is promoted only after both architecture smoke tests pass.

Install on Ubuntu​

Choose a Docker-capable Ubuntu host with enough disk space. Its DNS name or address must be reachable by every intended client. Docker Compose v2 is required. If the GHCR package is private, authenticate Docker before setup.

Run the script from the same Kerrigan branch whose image should be installed:

KERRIGAN_ARTIFACT_CACHE_HOST=cache.example.com \
KERRIGAN_PROXY_ALLOWED_NETWORKS="<trusted-client-cidr>" \
./scripts/setup_caching_proxy.sh

Replace <trusted-client-cidr> with the smallest network that contains the clients. Do not expose either listener to the public internet. The script uses the current Git branch to select its branch-specific image. Override that choice when needed:

KERRIGAN_CACHING_PROXY_IMAGE=ghcr.io/sima-neat/caching-proxy:develop \
KERRIGAN_ARTIFACT_CACHE_HOST=cache.example.com \
KERRIGAN_PROXY_ALLOWED_NETWORKS="<trusted-client-cidr>" \
./scripts/setup_caching_proxy.sh

The setup script:

  1. Verifies Docker and Docker Compose.
  2. Creates /opt/kerrigan/caching-proxy for persistent configuration, cache data, and TLS material.
  3. Pulls the architecture that matches the host.
  4. Starts the container with ports 3128 and 8443 published.
  5. Waits for both Squid and NGINX to become healthy.

The container creates a private CA on its first start and preserves it in the host-mounted TLS directory. It regenerates only the server certificate on later starts, so a changed cache hostname takes effect without replacing the trusted CA. Cache data also remains when the container is upgraded or recreated.

Common settings​

VariableDefaultPurpose
KERRIGAN_ARTIFACT_CACHE_HOSTrequiredDNS name or address used by clients and placed in the TLS certificate
KERRIGAN_CACHING_PROXY_IMAGEcurrent branch imageExact tagged GHCR image to deploy
KERRIGAN_CACHING_PROXY_ROOT/opt/kerrigan/caching-proxyPersistent deployment, cache, and TLS directory
KERRIGAN_PROXY_ALLOWED_NETWORKSprivate and tailnet rangesSpace-separated client addresses or CIDRs; narrow this for production
KERRIGAN_SQUID_PORT3128Host port published for Squid
KERRIGAN_ARTIFACT_CACHE_PORT8443Host port published for NGINX TLS
KERRIGAN_SQUID_CACHE_SIZE_MB20480Maximum Squid disk cache size in MiB
KERRIGAN_ARTIFACT_CACHE_SIZE100gMaximum NGINX artifact cache size
KERRIGAN_ARTIFACT_CACHE_INACTIVE30dRemove objects that have not been used for this long

Size the caches​

NGINX and Squid have independent disk caches. Set KERRIGAN_ARTIFACT_CACHE_SIZE for binary artifacts served by the repository cache, using a size such as 100g or 500g. Set KERRIGAN_SQUID_CACHE_SIZE_MB for general HTTP traffic through Squid, using a positive integer number of MiB.

For a new installation, pass both values to the setup script:

KERRIGAN_ARTIFACT_CACHE_HOST=cache.example.com \
KERRIGAN_PROXY_ALLOWED_NETWORKS="<trusted-client-cidr>" \
KERRIGAN_ARTIFACT_CACHE_SIZE=500g \
KERRIGAN_SQUID_CACHE_SIZE_MB=51200 \
./scripts/setup_caching_proxy.sh

To resize an existing installation, edit /opt/kerrigan/caching-proxy/caching-proxy.env and change the corresponding values:

KERRIGAN_ARTIFACT_CACHE_SIZE=500g
KERRIGAN_SQUID_CACHE_SIZE_MB=51200

Recreate the container so Compose applies the updated environment. The named cache and CA directories are preserved:

cd /opt/kerrigan/caching-proxy
sudo docker compose --env-file caching-proxy.env up -d
sudo docker compose --env-file caching-proxy.env ps

Leave disk capacity for the operating system, container images, logs, and temporary files. NGINX removes least-recently-used objects as its maximum size is approached and removes objects unused for KERRIGAN_ARTIFACT_CACHE_INACTIVE. Squid starts removing older objects at its 95 percent high-water mark until usage reaches its 90 percent low-water mark.

Configure a sima-cli client​

Copy only the public cache CA to each client over a trusted connection. Never copy the CA private key from the cache host.

mkdir -p ~/.config/sima-cli
scp cache.example.com:/opt/kerrigan/caching-proxy/tls/cache-ca.pem \
~/.config/sima-cli/cache-ca.pem
chmod 0644 ~/.config/sima-cli/cache-ca.pem

Configure general proxy routing and the SiMa artifact cache separately:

export HTTP_PROXY=http://cache.example.com:3128
export HTTPS_PROXY=http://cache.example.com:3128
export NO_PROXY=localhost,127.0.0.1,.internal.example.com
export SIMA_CLI_CACHE_URL=https://cache.example.com:8443

An http:// Squid URL is correct for HTTPS_PROXY: clients use the HTTP CONNECT method to carry end-to-end HTTPS through Squid. The NGINX cache URL is https:// because sima-cli sends artifact requests directly to that service and verifies its certificate with the dedicated cache CA.

The configured internal Artifactory origin remains direct in supported sima-cli versions. Keep it in NO_PROXY as well for other command-line tools that use the same environment.

What is cached​

NGINX accepts GET and HEAD requests for the fixed artifact origin. JSON indexes are always refreshed from the origin. Binary object paths are cached, and the cache key ignores the short-lived signature query string because artifact paths are immutable.

On the first request, NGINX returns X-SiMa-Cache: MISS and saves the response. Later requests for the same path return X-SiMa-Cache: HIT. Concurrent misses for the same object are collapsed so clients do not all download it from the origin. NGINX verifies the upstream CDN certificate against the Ubuntu CA bundle.

NGINX removes least-recently-used objects when the configured maximum size is exceeded and removes inactive objects after the configured interval. Squid manages its own disk cache using high- and low-water marks.

Operate and recover​

The installed Compose file and environment are under /opt/kerrigan/caching-proxy. Common commands are:

cd /opt/kerrigan/caching-proxy
sudo docker compose --env-file caching-proxy.env ps
sudo docker compose --env-file caching-proxy.env logs -f
sudo docker compose --env-file caching-proxy.env restart

Re-running scripts/setup_caching_proxy.sh is the supported upgrade and repair path. It pulls the selected image and recreates the container while preserving the CA and cache directories.

NGINX writes request logs to Docker's log stream. Its entries include cache=MISS, cache=HIT, or cache=BYPASS. JSON index requests should show BYPASS. A repeated binary request should show HIT.

If TLS verification fails, confirm that the client has the public CA at ~/.config/sima-cli/cache-ca.pem, that SIMA_CLI_CACHE_URL uses the same name or address supplied during setup, and that the cache host's clock is correct.