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:
| Source | Published image |
|---|---|
main | ghcr.io/sima-neat/caching-proxy:latest |
develop | ghcr.io/sima-neat/caching-proxy-develop:latest and ghcr.io/sima-neat/caching-proxy:develop |
| another branch | ghcr.io/sima-neat/caching-proxy-<branch>:latest and ghcr.io/sima-neat/caching-proxy:<branch> |
| version tag | ghcr.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:
- Verifies Docker and Docker Compose.
- Creates
/opt/kerrigan/caching-proxyfor persistent configuration, cache data, and TLS material. - Pulls the architecture that matches the host.
- Starts the container with ports
3128and8443published. - 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
| Variable | Default | Purpose |
|---|---|---|
KERRIGAN_ARTIFACT_CACHE_HOST | required | DNS name or address used by clients and placed in the TLS certificate |
KERRIGAN_CACHING_PROXY_IMAGE | current branch image | Exact tagged GHCR image to deploy |
KERRIGAN_CACHING_PROXY_ROOT | /opt/kerrigan/caching-proxy | Persistent deployment, cache, and TLS directory |
KERRIGAN_PROXY_ALLOWED_NETWORKS | private and tailnet ranges | Space-separated client addresses or CIDRs; narrow this for production |
KERRIGAN_SQUID_PORT | 3128 | Host port published for Squid |
KERRIGAN_ARTIFACT_CACHE_PORT | 8443 | Host port published for NGINX TLS |
KERRIGAN_SQUID_CACHE_SIZE_MB | 20480 | Maximum Squid disk cache size in MiB |
KERRIGAN_ARTIFACT_CACHE_SIZE | 100g | Maximum NGINX artifact cache size |
KERRIGAN_ARTIFACT_CACHE_INACTIVE | 30d | Remove 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.