Configuration
Every variable is also a command-line flag of the same name in kebab case, e.g. API_BASE_URL is --api-base-url. A flag overrides its variable. Run the binary with --help to list them all. An empty variable counts as unset.
The server refuses to start on invalid configuration. A missing required value or a value that does not parse exits with code 2, a conflicting combination of variables with code 1.
| Variable | Default |
|---|---|
API_BASE_URL |
required |
PORT |
3000 |
HOST |
all interfaces |
DEFAULT_ACTIONS_RESULTS_URL |
https://results-receiver.actions.githubusercontent.com |
DEBUG |
unset |
STORAGE_DRIVER |
filesystem |
DB_DRIVER |
sqlite |
ENABLE_DIRECT_DOWNLOADS |
false |
DIRECT_DOWNLOAD_URL_TTL_SECONDS |
600 |
EAGER_MERGE |
false |
MAX_CONCURRENT_MERGES |
16 |
DOWNLOAD_IDLE_TIMEOUT_MS |
300000 |
CACHE_CLEANUP_OLDER_THAN_DAYS |
90 |
CACHE_MAX_SIZE_BYTES |
unset |
CACHE_FILESYSTEM_MAX_USAGE_PERCENT |
90 |
ORPHANED_STORAGE_GRACE_PERIOD_HOURS |
24 |
DISABLE_CLEANUP_JOBS |
false |
ACTIONS_TOKEN_ISSUER |
https://token.actions.githubusercontent.com |
ACTIONS_TOKEN_JWKS_URL |
discovered from the issuer |
ACTIONS_TOKEN_AUDIENCE |
unset |
SKIP_TOKEN_VALIDATION |
false |
UNSAFE_ALLOW_DIRECT_DOWNLOADS_WITHOUT_TOKEN_VALIDATION |
false |
MANAGEMENT_API_KEY |
unset |
Server
Section titled “Server”API_BASE_URL
Section titled “API_BASE_URL”- Required
- Example:
http://cache-server.internal:3000
The URL runners use to reach this server. Upload and download URLs handed to runners start with it, so every runner must be able to reach it.
- Default:
3000
The port the server should listen on.
- Default: all interfaces
The interface the server should listen on.
DEFAULT_ACTIONS_RESULTS_URL
Section titled “DEFAULT_ACTIONS_RESULTS_URL”- Default:
https://results-receiver.actions.githubusercontent.com
The upstream GitHub Actions Results service that requests the cache server does not handle (e.g. artifact uploads/downloads) are transparently forwarded to. On GitHub Enterprise Server this must point at your instance’s Results host (see GitHub Enterprise Server).
- Optional
Any value enables debug logging.
Storage and database
Section titled “Storage and database”STORAGE_DRIVER
Section titled “STORAGE_DRIVER”- Default:
filesystem
The storage driver to use for storing cache data. For more information, see storage drivers.
DB_DRIVER
Section titled “DB_DRIVER”- Default:
sqlite
The database driver to use for storing cache metadata. For more information, see database drivers.
Downloads and merges
Section titled “Downloads and merges”ENABLE_DIRECT_DOWNLOADS
Section titled “ENABLE_DIRECT_DOWNLOADS”- Default:
false
If set to true, will send a signed URL to the runner. The runner can then download the cache directly from the storage provider. This is useful if you have a large cache and don’t want to proxy the download through the cache server.
A signed URL is a storage credential, so the server refuses to start with both ENABLE_DIRECT_DOWNLOADS=true and SKIP_TOKEN_VALIDATION=true, unless UNSAFE_ALLOW_DIRECT_DOWNLOADS_WITHOUT_TOKEN_VALIDATION is set. The filesystem storage driver has no direct downloads.
DIRECT_DOWNLOAD_URL_TTL_SECONDS
Section titled “DIRECT_DOWNLOAD_URL_TTL_SECONDS”- Default:
600 - Range:
1to3600 - Helm:
config.directDownloadUrlTtlSeconds
How long a signed direct-download URL stays valid. A shorter lifetime limits the replay of a leaked URL. Clients that fetch the URL some time after receiving it, such as BuildKit, need a longer one.
EAGER_MERGE
Section titled “EAGER_MERGE”- Default:
false
Cache data arrives in parts. By default the server merges them into one object on the first download, so with ENABLE_DIRECT_DOWNLOADS the first restore of every entry is still proxied through the server. With EAGER_MERGE=true the merge starts right after the upload completes, and the first restore can be a direct download.
On S3, GCS and Azure Blob Storage the server streams the parts through itself into the merged object, so every upload is read back once. On the filesystem driver the merge is a kernel copy (copy_file_range). Eager and lazy merges share the MAX_CONCURRENT_MERGES limit.
MAX_CONCURRENT_MERGES
Section titled “MAX_CONCURRENT_MERGES”- Default:
16
How many merges one process runs at once, eager or lazy. Past that limit, restores stream the parts and a later download does the merge.
DOWNLOAD_IDLE_TIMEOUT_MS
Section titled “DOWNLOAD_IDLE_TIMEOUT_MS”- Default:
300000
Closes a connection whose client has not read a response for this long. 0 disables it.
Eviction and cleanup
Section titled “Eviction and cleanup”CACHE_CLEANUP_OLDER_THAN_DAYS
Section titled “CACHE_CLEANUP_OLDER_THAN_DAYS”- Default:
90
The number of days to keep stale cache data and metadata before deleting it. Set to 0 to disable cache cleanup. A negative value fails startup.
CACHE_MAX_SIZE_BYTES
Section titled “CACHE_MAX_SIZE_BYTES”- Optional
Hard cap, in bytes, on the total size of finalized cache payloads. When set, the server runs capacity-based eviction after each completed upload: if the total exceeds this budget, the least-recently-used cache entries are deleted until usage is back down to 90% of the budget. Recency is the last time an entry was downloaded, falling back to when it was last saved. Entries with an in-progress download are never evicted.
Applies to any storage driver. Leave unset for unlimited object storage, or use CACHE_FILESYSTEM_MAX_USAGE_PERCENT below to cap by disk usage instead.
CACHE_FILESYSTEM_MAX_USAGE_PERCENT
Section titled “CACHE_FILESYSTEM_MAX_USAGE_PERCENT”- Default:
90 - Only applies to the
filesystemstorage driver whenCACHE_MAX_SIZE_BYTESis not set.
Maximum percentage of the storage volume’s total capacity (including data outside the cache directory) that may be used before capacity-based eviction starts reclaiming space. Ignored when CACHE_MAX_SIZE_BYTES is set.
ORPHANED_STORAGE_GRACE_PERIOD_HOURS
Section titled “ORPHANED_STORAGE_GRACE_PERIOD_HOURS”- Default:
24
How long a storage folder that no database record references must stay untouched before cleanup deletes it. At least 1.
DISABLE_CLEANUP_JOBS
Section titled “DISABLE_CLEANUP_JOBS”- Default:
false
Disables all cleanup jobs. Each job runs once at startup, then once per period:
| Period | Job |
|---|---|
| 5 minutes | Delete uploads without activity for over a minute |
| 10 minutes | Delete parts of merged entries, and storage locations without an entry |
| 1 hour | Reset stalled merges and expired leases |
| 24 hours | Delete entries older than CACHE_CLEANUP_OLDER_THAN_DAYS, and orphaned storage |
Token validation
Section titled “Token validation”ACTIONS_TOKEN_ISSUER
Section titled “ACTIONS_TOKEN_ISSUER”- Default:
https://token.actions.githubusercontent.com
The OIDC issuer whose signature the cache server verifies on runner tokens. It must match the iss claim of a runner’s OIDC token exactly. The signing keys are looked up from the issuer’s OIDC discovery document ({issuer}/.well-known/openid-configuration), so the JWKS location is picked up automatically.
Change this if your runner tokens are not issued by https://token.actions.githubusercontent.com:
- GitHub Enterprise Server, where tokens are issued by your own instance (see GitHub Enterprise Server).
- GitHub Enterprise Cloud with a customized issuer, where the issuer becomes
https://token.actions.githubusercontent.com/<enterpriseSlug>. Nothing else is needed: the JWKS stays at the default host, and discovery finds it there.
ACTIONS_TOKEN_JWKS_URL
Section titled “ACTIONS_TOKEN_JWKS_URL”- Optional
- Default: discovered from
ACTIONS_TOKEN_ISSUER
Explicit JWKS endpoint, skipping OIDC discovery. You should not need this: the URL is normally discovered from the issuer, and if discovery is unavailable the server falls back to {issuer}/.well-known/jwks. Set it only if your deployment serves its keys somewhere neither of those finds. A warning naming the fallback URL is logged when discovery fails.
ACTIONS_TOKEN_AUDIENCE
Section titled “ACTIONS_TOKEN_AUDIENCE”- Optional
- Example:
https://github.com/my-org
Comma-separated list of accepted aud claims. When set, a runner token must carry one of them. Unset skips the audience check. A value that lists no audience (e.g. ,) fails startup.
SKIP_TOKEN_VALIDATION
Section titled “SKIP_TOKEN_VALIDATION”- Default:
false
Skip verification of the GitHub token used for computing the cache scope. This is useful for testing and development purposes, but should not be used in production. Cannot be combined with ENABLE_DIRECT_DOWNLOADS unless UNSAFE_ALLOW_DIRECT_DOWNLOADS_WITHOUT_TOKEN_VALIDATION is set.
UNSAFE_ALLOW_DIRECT_DOWNLOADS_WITHOUT_TOKEN_VALIDATION
Section titled “UNSAFE_ALLOW_DIRECT_DOWNLOADS_WITHOUT_TOKEN_VALIDATION”- Default:
false
Allows ENABLE_DIRECT_DOWNLOADS=true together with SKIP_TOKEN_VALIDATION=true. Anyone who can reach the server then gets signed storage URLs for any repository’s cache. For local testing only.
Management API
Section titled “Management API”MANAGEMENT_API_KEY
Section titled “MANAGEMENT_API_KEY”Set this to a random string to enable the management API. Unset or empty disables it. Docs can be found at https://<your-cache-server-url>/management-api/_docs.
DELETE /management-api/storage-locations/{id} answers 409 while the storage location is being downloaded.
Driver-specific variables are on the storage driver and database driver pages.