Skip to content

configuration ​

Configuration is env vars only. All variables are required unless marked optional; there are no other defaults.

VariableMeaning
PORTHTTP listen port
STORAGE_PATHFilesystem root for cached data. Grows without bound unless MAX_STORAGE is set.
LOG_LEVELdebug, info, warn or error
LOG_FORMATtext or json (structured logs for machine parsing)
TAG_TTLGo duration (e.g. 60s). Tag manifests are served from cache without upstream revalidation within this window; after it expires the next request revalidates via upstream HEAD (digest compare). Digest manifests and blobs are immutable and never revalidated.
UPSTREAM_<ALIAS>_HOSTOne per upstream registry host (e.g. registry-1.docker.io). At least one required. See registries.
UPSTREAM_<ALIAS>_USERNAME / _PASSWORDOptional basic-auth pair for private upstreams. For ECR hosts: AWS access key id + secret access key (unset = AWS default credential chain).
MIRROR_UPSTREAMOptional. Alias that serves image names with no alias prefix, so docker pull postgres works with Stashito configured as a registry mirror. See mirror mode.
METRICS_ENABLEDOptional, default false. true exposes Prometheus metrics at GET /metrics.
METRICS_PORTOptional. Serve /metrics on this separate port; 0/unset serves it on PORT.
MAX_STORAGEOptional. Cap on cached bytes, e.g. 500MB, 50GB or 2TB (1024-based, as df -h reports; a bare number is bytes). Unset means unlimited. When a write would push the cache past the cap, the least recently pulled manifests and blobs are deleted first, inline, so the cap holds.
MAX_STORAGE_HEADROOMOptional, default 10%. How far below MAX_STORAGE each eviction frees, as a whole percent of the cap (10% or 10, 0 to 99). Evictions come in batches instead of one entry per write once the cache is full. 0 evicts exactly to the cap.

behavior ​

  • Cache hits are served from disk without contacting upstream.
  • If upstream is unreachable, cached content is served stale.
  • Layers stay cached even if the image is later deleted upstream.
  • With MAX_STORAGE set, eviction runs inline on writes and counts bytes still downloading, so concurrent pulls do not overshoot the cap. A write that crosses the cap frees down to the cap minus MAX_STORAGE_HEADROOM, so disk use moves between those two marks. Last access survives restarts (persisted to the file mtime at most once a minute per entry). A blob larger than the cap on its own is still served but is the first thing the next write evicts.
  • A blob that does not fit in the free space of the storage filesystem is refused with 507 Insufficient Storage before any byte is written, so a pull can never fill the disk. Bytes announced by downloads still in flight count as taken, so concurrent pulls cannot fill it together either. With MAX_STORAGE set, eviction runs first and the blob is refused only if evicting everything would still not make room.