Cache Nix Store in GitHub Actions to speed up workflows [maintainer=@deemp]
TypeScript
175
1,537 commits
updated Sep 24, 2026
A GitHub Action to restore and save Nix store paths using GitHub Actions cache.
This action is based on actions/cache.
Linux and macOS runners.Linux, macOS, and Windows runners.ACTIONS_CACHE_URL and ACTIONS_RESULTS_URL using CUSTOM_ACTIONS_CACHE_URL and CUSTOM_ACTIONS_RESULTS_URL environment variables.cache-nix-action is compatible with:
nixbuild/nix-quick-install-actioncachix/install-nix-actionDeterminateSystems/determinate-nix-action[!NOTE] See all available action inputs in Inputs.
[!NOTE] The action can't restore a cache when there's a mismatch in the cache version, e.g., when
pathsused to create a cache differ from those specified in the current job run.
One of the compatible actions installs Nix.
Restore phase:
The cache-nix-action tries to restore a cache whose key is the same as the specified one (input: primary-key).
When the cache-nix-action can't restore, it tries to restore a cache whose key matches a prefix in a given list of key prefixes (input: restore-prefixes-first-match).
The cache-nix-action restores all caches whose keys match some of the prefixes in another given list of key prefixes (input: restore-prefixes-all-matches).
Other job steps run.
Post Restore phase:
The cache-nix-action purges caches whose keys are the same as the primary key and that were created or last accessed more than a given time ago (inputs: purge, purge-created, purge-last-accessed, purge-primary-key).
When there's no cache whose key is the same as the primary key, the cache-nix-action collects garbage in the Nix store and saves a new cache (inputs: save, gc-max-store-size, gc-max-store-size-linux, gc-max-store-size-macos).
The cache-nix-action purges caches whose keys match some of the given prefixes in a given list of key prefixes and that were created or last accessed more than a given time ago relative to the start of the Post Restore phase (inputs: purge, purge-prefixes, purge-created, purge-last-accessed, purge-primary-key).
Linux and macOS GitHub Actions runners for Nix store caching.By default, the action caches and restores only /nix (see documentation for the paths input).
The action doesn't automatically cache stores specified via the --store flag (link).
The action removes existing Nix store database files after merging the existing database with the restored one.
GitHub allows only 10GB of caches and then removes the least recently used entries (see its eviction policy). Workarounds:
The Nix store size is limited by a runner storage size (link).
See Caching Approaches.
[!NOTE] For purging, the workflow or the job must have the permission
actions: write.
[!NOTE] If the
pathsinput is specified, the action will be able to restore only caches created with the samepaths.
- uses: nixbuild/nix-quick-install-action@v30
with:
nix_conf: |
keep-env-derivations = true
keep-outputs = true
- name: Restore and save Nix store
uses: nix-community/cache-nix-action@v7
with:
# restore and save a cache using this key
primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }}
# if there's no cache hit, restore a cache by this prefix
restore-prefixes-first-match: nix-${{ runner.os }}-
# collect garbage until the Nix store size (in bytes) is at most this number
# before trying to save a new cache
# 1G = 1073741824
gc-max-store-size-linux: 1G
# do purge caches
purge: true
# purge all versions of the cache
purge-prefixes: nix-${{ runner.os }}-
# created more than this number of seconds ago
purge-created: 0
# or last accessed this duration (ISO 8601 duration format)
# before the start of the `Post Restore and save Nix store` phase
purge-last-accessed: P1DT12H
# except any version with the key that is the same as the `primary-key`
purge-primary-key: never
nix-quick-install-action writes the supplied nix_conf to nix.conf (see action.yml, script).nix-quick-install-action enables flakes and accepts nixConfig from flake.nix (see script).gc-max-store-size-linux: 1G, on Linux runners, garbage in the Nix store is collected until the store size reaches 1GB or until there's no garbage to collect.gc-max-store-size-macos isn't set to a number, on macOS runners, no garbage is collected in the Nix store.cache-nix-action purges caches:
nix-${{ runner.os }}-) AND (created more than 0 seconds ago OR last accessed more than 0 seconds ago).See Always save cache.
See Merge caches, Example cache workflow, Caching Strategies.
See action.yml.
| name | description | required | default |
|---|---|---|---|
primary-key |
| true | "" |
restore-prefixes-first-match |
| false | "" |
restore-prefixes-all-matches |
| false | "" |
lookup-only |
| false | false |
fail-on |
| false | "" |
nix |
| false | true |
save |
| false | true |
paths |
| false | "" |
paths-macos |
| false | "" |
paths-linux |
| false | "" |
backend | Choose an implementation of the
| false | actions |
gc-max-store-size |
| false | "" |
gc-max-store-size-macos |
| false | "" |
gc-max-store-size-linux |
| false | "" |
purge |
| false | false |
purge-primary-key |
| false | "" |
purge-prefixes |
| false | "" |
purge-last-accessed |
| false | "" |
purge-created |
| false | "" |
upload-chunk-size |
| false | "" |
token |
| false | ${{ github.token }} |
| name | description |
|---|---|
primary-key |
|
hit |
|
hit-primary-key |
|
hit-first-match |
|
restored-key |
|
restored-keys |
|
The cache-nix-action allows to delete old caches after saving a new cache (see purge-* inputs in Inputs and the compare-run-times job in the Example workflow).
The purge-cache action allows to remove caches based on their last accessed or created time without branch limitations.
Alternatively, you can use the GitHub Actions Cache API.
GitHub evicts the least recently used caches when their total size exceeds 10GB (see Limitations).
If you have multiple similar caches produced on runners with the same OS (Linux or macOS), you can merge them into a single cache and store just it to save space.
In short:
See the make-similar-caches and merge-similar-caches jobs in the example workflow.
Pros: if N individual caches are very similar, a common cache will take approximately N times less space.
Cons: if caches aren't very similar, the run time may increase due to a bigger common cache.
When restoring a Nix store from a cache, the store may contain old unnecessary paths. These paths should be removed sometimes to limit cache size and ensure the fastest restore/save steps.
Produce a cache once, use it multiple times. Don't collect garbage.
Advantages:
Disadvantages:
A and saves a cache.B, and saves a cache. The cache has both A and B.Collect garbage before saving a cache.
Advantages:
Disadvantages:
atime: nix-heuristic-gc.One problem is that garbage collection doesn't differentiate between the least and the most recently used paths (issue).
Another problem is that derivations produced with the help of flake inputs don't retain references to these inputs (issue, issue).
saveFromGCThe Nix function is defined in ./saveFromGC.nix.
[!WARNING] We don't guarantee that
./saveFromGC.nixwill be available or won't have breaking changes in future.
Write an expression for a derivation that mentions the necessary paths and flake inputs. Next, add it to a profile or build it.
saveFromGC exampleExample or a flake with saveFromGC (from ./examples/saveFromGC/flake.nix):
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/def3da69945bbe338c373fddad5a1bb49cf199ce";
flake-utils = {
url = "github:numtide/flake-utils";
inputs.systems.follows = "systems";
};
cache-nix-action = {
url = "github:nix-community/cache-nix-action";
flake = false;
};
systems.url = "github:nix-systems/default";
};
outputs =
inputs:
inputs.flake-utils.lib.eachDefaultSystem (
system:
let
pkgs = inputs.nixpkgs.legacyPackages.${system};
packages = {
hello = pkgs.hello;
saveFromGC =
(import "${inputs.cache-nix-action}/saveFromGC.nix" {
inherit pkgs inputs;
# The `cache-nix-action` input won't be saved.
inputsInclude = [
"nixpkgs"
"flake-utils"
"systems"
];
derivations = [
packages.hello
devShells.default
];
paths = [ "${packages.hello}/bin/hello" ];
}).package;
};
devShells.default = pkgs.mkShell { buildInputs = [ pkgs.gcc ]; };
in
{
inherit packages devShells;
}
);
}
Example of GitHub Actions steps:
# ... Install Nix
#
# ... Restore cache
- name: Run gcc
run: nix develop -c 'gcc --version'
- name: Run hello
run: nix run .#hello -- --version
- name: Save packages from garbage collection
run: nix profile add .#saveFromGC
# ... Collect garbage and save cache
nix profile add or nix buildEach profile is a garbage collection root.
Each nix build result symlink is a garbage collection root.
To save particular Nix store paths, create an installable that contains these paths and
either add it to a profile via nix profile add
or nix build
Pros: Easy to use in CI.
Cons: These commands save only output paths. Use the solution 1 or solution 3 to save flake inputs.
saveFromGCThe saveFromGC attribute of the flake above is a script (an installable) that contains paths of elements of the flake closure (the flake itself, flake inputs, inputs of these inputs, etc.).
Enter the examples/saveFromGC directory.
cd examples/saveFromGC
Print the contents of saveFromGC.
cat $(nix build .#saveFromGC --no-link --print-out-paths)
# derivations:
- /nix/store/jrq3p609i85jsg27mr5zxm2imk3mjzyk-hello-2.12.2
- /nix/store/8xjhphvn58rrqydsx5569jn01yd5a0al-nix-shell
# derivationsAttrs:
# inputs:
- "flake-utils": /nix/store/01x5k4nlxcpyd85nnr0b9gm89rm8ff4x-source
- "nixpkgs": /nix/store/f3phg71mppsdj69cb63xllf1nnigzr2s-source
- "systems": /nix/store/yj1wxm9hh8610iyzqnz75kvs6xl8j3my-source
# paths:
- /nix/store/jrq3p609i85jsg27mr5zxm2imk3mjzyk-hello-2.12.2/bin/hello
# pathsAttrs:
Add the installable to the default profile.
nix profile remove examples/saveFromGC
nix profile add .#saveFromGC
nix profile list | grep save-from-gc
Store paths: /nix/store/6ypnwndqz9r8cxwywib0cysnbafzmp6f-save-from-gc
Or, build the installable and see the garbage collection roots that won't let it be garbage collected.
nix-store --query --roots $(nix build .#saveFromGC --print-out-paths)
nix-store --query --roots result
Output (edited):
...
<...>/.local/state/nix/profiles/profile-1-link -> /nix/store/pyvyymji6pvgify5gvnlvprlrxi42pdd-profile
<...>/cache-nix-action/examples/saveFromGC/result -> /nix/store/6ypnwndqz9r8cxwywib0cysnbafzmp6f-save-from-gc
nix flake archivedirenvRun direnv with nix-direnv in background.
Initially discussed here and here.
Caching approaches work at different "distances" from /nix/store of GitHub Actions runner.
These distances affect the restore and save speed.
nix-community/cache-nix-actionDeterminateSystems/magic-nix-cache-actionactions/cacherikhuijzer/cache-installnix-community/cache-nix-actionPros:
GitHub Actions Cache and works fast.Total duration.Cons: see Limitations
DeterminateSystems/magic-nix-cache-actionPros (source):
GitHub Actions Cache and works fast.Cons:
Caches.actions/cacheIf the action is used with nixbuild/nix-quick-install-action, it's similar to the nix-community/cache-nix-action.
If used with cachix/install-nix-action and a chroot local store:
Pros:
/tmp/nix.chroot store works only on Linux.Cons:
nix copy from /tmp/nix to /nix/store.If used with cachix/install-nix-action and this trick, it's similar to the nix-community/cache-nix-action but slower (link).
rikhuijzer/cache-installPros:
/nix/store, some /nix/var files, and profiles (link).Cons:
See binary cache, HTTP Binary Cache Store.
Pros:
Cachix, Attic is FOSS).Cachix, Attic).Cachix).Cachix, FlakeHub Cache).Cons:
Cachix gives only 5GB for open-source projects (src).FlakeHub Cache is available only to paid accounts (src).Attic needs to be hosted.git clone --recurse-submodules https://github.com/nix-community/cache-nix-action
Edit action.nix.
Update action.yml-s and README.md-s:
nix run .#write
actions-toolkit branch that contains a patched version of actions/toolkit.buildjet-toolkit branch that contains a patched version of BuildJet/toolkit synchronized with actions/toolkit.main branch.Example:
cd into the toolkit directorygit push origin <branch>This action allows caching dependencies and build outputs to improve workflow execution time.
Two other actions are available in addition to the primary
cacheaction:
See "Caching dependencies to speed up workflows".
[!IMPORTANT]
actions/cache@v5runs on the Node.js 24 runtime and requires a minimum Actions Runner version of2.327.1. If you are using self-hosted runners, ensure they are updated before upgrading.
The cache backend service has been rewritten from the ground up for improved performance and reliability. actions/cache now integrates with the new cache service (v2) APIs.
The new service will gradually roll out as of February 1st, 2025. The legacy service will also be sunset on the same date. Changes in these releases are fully backward compatible.
We are deprecating some versions of this action. We recommend upgrading to version v4 or v3 as soon as possible before February 1st, 2025. (Upgrade instructions below).
If you are using pinned SHAs, please use the SHAs of versions v4.2.0 or v3.4.0.
If you do not upgrade, all workflow runs using any of the deprecated actions/cache will fail.
Upgrading to the recommended versions will not break your workflows.
Additionally, if you are managing your own GitHub runners, you must update your runner version to
2.231.0or newer to ensure compatibility with the new cache service.
Failure to update both the action version and your runner version may result in workflow failures after the migration date.
Read more about the change & access the migration guide: reference to the announcement.
2.327.1~/ home folder on ubuntu-latest.SEGMENT_DOWNLOAD_TIMEOUT_MINS. Default is 10 minutes.See the v2 README.md for older updates.
Create a workflow .yml file in your repository's .github/workflows directory. An example workflow is available below. For more information, see the GitHub Help Documentation for Creating a workflow file.
If you are using this inside a container, a POSIX-compliant tar needs to be included and accessible from the execution path.
Note: actions/cache@v5 runs on Node.js 24 and requires a minimum Actions Runner version of 2.327.1.
If you are using a self-hosted Windows runner, GNU tar and zstd are required for Cross-OS caching to work. They are also recommended to be installed in general so the performance is on par with hosted Windows runners.
SEGMENT_DOWNLOAD_TIMEOUT_MINS - Segment download timeout (in minutes, default 10) to abort download of the segment if not completed in the defined number of minutes. Read moreThe cache is scoped to the key, version, and branch. The default branch cache is available to other branches.
See Matching a cache key for more info.
name: Caching Primes
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Cache Primes
id: cache-primes
uses: nix-community/cache-nix-action@v7
with:
primary-key: ${{ runner.os }}-primes
paths: prime-numbers
- name: Generate Prime Numbers
if: steps.cache-primes.outputs.hit-primary-key != 'true'
run: /generate-primes.sh -d prime-numbers
- name: Use Prime Numbers
run: /primes.sh -d prime-numbers
The cache-nix-action provides the hit-primary-key output which is set to 'true' when the cache is restored using the primary-key and 'false' otherwise.
[!NOTE] The
pathsinput in thecache-nix-action/restoreandcache-nix-action/savemust be the same.
name: Caching Primes
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Restore cached Primes
id: cache-primes-restore
uses: nix-community/cache-nix-action/restore@v7
with:
primary-key: ${{ runner.os }}-primes
paths: |
path/to/dependencies
some/other/dependencies
# other steps
- name: Save Primes
id: cache-primes-save
uses: nix-community/cache-nix-action/save@v7
with:
primary-key: ${{ steps.cache-primes-restore.outputs.cache-primary-key }}
paths: |
path/to/dependencies
some/other/dependencies
Note You must use the
cacheorrestoreaction in your workflow before you need to use the files that might be restored from the cache. If the providedprimary-keymatches an existing cache, a new cache is not created and if the providedprimary-keydoesn't match an existing cache, a new cache is automatically created provided the job completes successfully.
With the introduction of the restore and save actions, a lot of caching use cases can now be achieved. Please see the caching strategies document for understanding how you can use the actions strategically to achieve the desired goal.
Every programming language and framework has its own way of caching.
See Examples for a list of nix-community/cache-nix-action implementations for use with:
A cache key can include any of the contexts, functions, literals, and operators supported by GitHub Actions.
For example, using the hashFiles function allows you to create a new cache when dependencies change.
- uses: nix-community/cache-nix-action@v7
with:
primary-key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
paths: |
path/to/dependencies
some/other/dependencies
Additionally, you can use arbitrary command output in a cache key, such as a date or software version:
# http://man7.org/linux/man-pages/man1/date.1.html
- name: Get Date
id: get-date
run: echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT
shell: bash
- uses: nix-community/cache-nix-action@v7
with:
primary-key: ${{ runner.os }}-${{ steps.get-date.outputs.date }}-${{ hashFiles('**/lockfiles') }}
paths: path/to/dependencies
See Using contexts to create cache keys
A repository can have up to 10GB of caches. Once the 10GB limit is reached, older caches will be evicted based on when the cache was last accessed.
Caches that are not accessed within the last week will also be evicted.
Using the hit-primary-key output, subsequent steps (such as install or build) can be skipped when a cache hit occurs on the key.
It is recommended to install missing/updated dependencies in case of a partial key match when the key is dependent on the hash of the package file.
Example:
steps:
- uses: actions/checkout@v6
- uses: nix-community/cache-nix-action@v7
id: cache
with:
primary-key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
paths: path/to/dependencies
- name: Install Dependencies
if: steps.cache.outputs.hit-primary-key != 'true'
run: /install.sh
Note The
iddefined innix-community/cache-nix-actionmust match the[id]in theifstatement (i.e.steps.[id].outputs.hit-primary-key)
Cache version is a hash generated for a combination of compression tool used (Gzip, Zstd, etc. based on the runner OS) and the paths of directories being cached. If two caches have different versions, they are identified as unique caches while matching. This, for example, means that a cache created on a windows-latest runner can't be restored on ubuntu-latest as cache Versions are different.
Pro tip: The list caches API can be used to get the version of a cache. This can be helpful to troubleshoot cache miss due to version.
The workflow will create 3 unique caches with same keys. Ubuntu and Windows runners will use different compression technique and hence create two different caches. And build-linux will create two different caches as the paths are different.
jobs:
build-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Cache Primes
id: cache-primes
uses: nix-community/cache-nix-action@v7
with:
primary-key: primes
paths: prime-numbers
- name: Generate Prime Numbers
if: steps.cache-primes.outputs.hit-primary-key != 'true'
run: ./generate-primes.sh -d prime-numbers
- name: Cache Numbers
id: cache-numbers
uses: nix-community/cache-nix-action@v7
with:
primary-key: primes
paths: numbers
- name: Generate Numbers
if: steps.cache-numbers.outputs.hit-primary-key != 'true'
run: ./generate-primes.sh -d numbers
build-windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v6
- name: Cache Primes
id: cache-primes
uses: nix-community/cache-nix-action@v7
with:
primary-key: primes
paths: prime-numbers
- name: Generate Prime Numbers
if: steps.cache-primes.outputs.hit-primary-key != 'true'
run: ./generate-primes -d prime-numbers
There are a number of community practices/workarounds to fulfill specific requirements. You may choose to use them if they suit your use case. Note these are not necessarily the only solution or even a recommended solution.
Please note that Windows environment variables (like %LocalAppData%) will NOT be expanded by this action. Instead, prefer using ~ in your paths which will expand to the HOME directory. For example, instead of %LocalAppData%, use ~\AppData\Local. For a list of supported default environment variables, see the Learn GitHub Actions: Variables page.
We would love for you to contribute to nix-community/cache-nix-action. Pull requests are welcome! Please see the CONTRIBUTING.md for more information.
The scripts and documentation in this project are released under the MIT License
(top 30 of 143)
TypeScript
71.9%
Nix
27.1%
Cache Nix Store in GitHub Actions to speed up workflows [maintainer=@deemp]
TypeScript
175
1,537 commits
updated Sep 24, 2026
A GitHub Action to restore and save Nix store paths using GitHub Actions cache.
This action is based on actions/cache.
Linux and macOS runners.Linux, macOS, and Windows runners.ACTIONS_CACHE_URL and ACTIONS_RESULTS_URL using CUSTOM_ACTIONS_CACHE_URL and CUSTOM_ACTIONS_RESULTS_URL environment variables.cache-nix-action is compatible with:
nixbuild/nix-quick-install-actioncachix/install-nix-actionDeterminateSystems/determinate-nix-action[!NOTE] See all available action inputs in Inputs.
[!NOTE] The action can't restore a cache when there's a mismatch in the cache version, e.g., when
pathsused to create a cache differ from those specified in the current job run.
One of the compatible actions installs Nix.
Restore phase:
The cache-nix-action tries to restore a cache whose key is the same as the specified one (input: primary-key).
When the cache-nix-action can't restore, it tries to restore a cache whose key matches a prefix in a given list of key prefixes (input: restore-prefixes-first-match).
The cache-nix-action restores all caches whose keys match some of the prefixes in another given list of key prefixes (input: restore-prefixes-all-matches).
Other job steps run.
Post Restore phase:
The cache-nix-action purges caches whose keys are the same as the primary key and that were created or last accessed more than a given time ago (inputs: purge, purge-created, purge-last-accessed, purge-primary-key).
When there's no cache whose key is the same as the primary key, the cache-nix-action collects garbage in the Nix store and saves a new cache (inputs: save, gc-max-store-size, gc-max-store-size-linux, gc-max-store-size-macos).
The cache-nix-action purges caches whose keys match some of the given prefixes in a given list of key prefixes and that were created or last accessed more than a given time ago relative to the start of the Post Restore phase (inputs: purge, purge-prefixes, purge-created, purge-last-accessed, purge-primary-key).
Linux and macOS GitHub Actions runners for Nix store caching.By default, the action caches and restores only /nix (see documentation for the paths input).
The action doesn't automatically cache stores specified via the --store flag (link).
The action removes existing Nix store database files after merging the existing database with the restored one.
GitHub allows only 10GB of caches and then removes the least recently used entries (see its eviction policy). Workarounds:
The Nix store size is limited by a runner storage size (link).
See Caching Approaches.
[!NOTE] For purging, the workflow or the job must have the permission
actions: write.
[!NOTE] If the
pathsinput is specified, the action will be able to restore only caches created with the samepaths.
- uses: nixbuild/nix-quick-install-action@v30
with:
nix_conf: |
keep-env-derivations = true
keep-outputs = true
- name: Restore and save Nix store
uses: nix-community/cache-nix-action@v7
with:
# restore and save a cache using this key
primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }}
# if there's no cache hit, restore a cache by this prefix
restore-prefixes-first-match: nix-${{ runner.os }}-
# collect garbage until the Nix store size (in bytes) is at most this number
# before trying to save a new cache
# 1G = 1073741824
gc-max-store-size-linux: 1G
# do purge caches
purge: true
# purge all versions of the cache
purge-prefixes: nix-${{ runner.os }}-
# created more than this number of seconds ago
purge-created: 0
# or last accessed this duration (ISO 8601 duration format)
# before the start of the `Post Restore and save Nix store` phase
purge-last-accessed: P1DT12H
# except any version with the key that is the same as the `primary-key`
purge-primary-key: never
nix-quick-install-action writes the supplied nix_conf to nix.conf (see action.yml, script).nix-quick-install-action enables flakes and accepts nixConfig from flake.nix (see script).gc-max-store-size-linux: 1G, on Linux runners, garbage in the Nix store is collected until the store size reaches 1GB or until there's no garbage to collect.gc-max-store-size-macos isn't set to a number, on macOS runners, no garbage is collected in the Nix store.cache-nix-action purges caches:
nix-${{ runner.os }}-) AND (created more than 0 seconds ago OR last accessed more than 0 seconds ago).See Always save cache.
See Merge caches, Example cache workflow, Caching Strategies.
See action.yml.
| name | description | required | default |
|---|---|---|---|
primary-key |
| true | "" |
restore-prefixes-first-match |
| false | "" |
restore-prefixes-all-matches |
| false | "" |
lookup-only |
| false | false |
fail-on |
| false | "" |
nix |
| false | true |
save |
| false | true |
paths |
| false | "" |
paths-macos |
| false | "" |
paths-linux |
| false | "" |
backend | Choose an implementation of the
| false | actions |
gc-max-store-size |
| false | "" |
gc-max-store-size-macos |
| false | "" |
gc-max-store-size-linux |
| false | "" |
purge |
| false | false |
purge-primary-key |
| false | "" |
purge-prefixes |
| false | "" |
purge-last-accessed |
| false | "" |
purge-created |
| false | "" |
upload-chunk-size |
| false | "" |
token |
| false | ${{ github.token }} |
| name | description |
|---|---|
primary-key |
|
hit |
|
hit-primary-key |
|
hit-first-match |
|
restored-key |
|
restored-keys |
|
The cache-nix-action allows to delete old caches after saving a new cache (see purge-* inputs in Inputs and the compare-run-times job in the Example workflow).
The purge-cache action allows to remove caches based on their last accessed or created time without branch limitations.
Alternatively, you can use the GitHub Actions Cache API.
GitHub evicts the least recently used caches when their total size exceeds 10GB (see Limitations).
If you have multiple similar caches produced on runners with the same OS (Linux or macOS), you can merge them into a single cache and store just it to save space.
In short:
See the make-similar-caches and merge-similar-caches jobs in the example workflow.
Pros: if N individual caches are very similar, a common cache will take approximately N times less space.
Cons: if caches aren't very similar, the run time may increase due to a bigger common cache.
When restoring a Nix store from a cache, the store may contain old unnecessary paths. These paths should be removed sometimes to limit cache size and ensure the fastest restore/save steps.
Produce a cache once, use it multiple times. Don't collect garbage.
Advantages:
Disadvantages:
A and saves a cache.B, and saves a cache. The cache has both A and B.Collect garbage before saving a cache.
Advantages:
Disadvantages:
atime: nix-heuristic-gc.One problem is that garbage collection doesn't differentiate between the least and the most recently used paths (issue).
Another problem is that derivations produced with the help of flake inputs don't retain references to these inputs (issue, issue).
saveFromGCThe Nix function is defined in ./saveFromGC.nix.
[!WARNING] We don't guarantee that
./saveFromGC.nixwill be available or won't have breaking changes in future.
Write an expression for a derivation that mentions the necessary paths and flake inputs. Next, add it to a profile or build it.
saveFromGC exampleExample or a flake with saveFromGC (from ./examples/saveFromGC/flake.nix):
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/def3da69945bbe338c373fddad5a1bb49cf199ce";
flake-utils = {
url = "github:numtide/flake-utils";
inputs.systems.follows = "systems";
};
cache-nix-action = {
url = "github:nix-community/cache-nix-action";
flake = false;
};
systems.url = "github:nix-systems/default";
};
outputs =
inputs:
inputs.flake-utils.lib.eachDefaultSystem (
system:
let
pkgs = inputs.nixpkgs.legacyPackages.${system};
packages = {
hello = pkgs.hello;
saveFromGC =
(import "${inputs.cache-nix-action}/saveFromGC.nix" {
inherit pkgs inputs;
# The `cache-nix-action` input won't be saved.
inputsInclude = [
"nixpkgs"
"flake-utils"
"systems"
];
derivations = [
packages.hello
devShells.default
];
paths = [ "${packages.hello}/bin/hello" ];
}).package;
};
devShells.default = pkgs.mkShell { buildInputs = [ pkgs.gcc ]; };
in
{
inherit packages devShells;
}
);
}
Example of GitHub Actions steps:
# ... Install Nix
#
# ... Restore cache
- name: Run gcc
run: nix develop -c 'gcc --version'
- name: Run hello
run: nix run .#hello -- --version
- name: Save packages from garbage collection
run: nix profile add .#saveFromGC
# ... Collect garbage and save cache
nix profile add or nix buildEach profile is a garbage collection root.
Each nix build result symlink is a garbage collection root.
To save particular Nix store paths, create an installable that contains these paths and
either add it to a profile via nix profile add
or nix build
Pros: Easy to use in CI.
Cons: These commands save only output paths. Use the solution 1 or solution 3 to save flake inputs.
saveFromGCThe saveFromGC attribute of the flake above is a script (an installable) that contains paths of elements of the flake closure (the flake itself, flake inputs, inputs of these inputs, etc.).
Enter the examples/saveFromGC directory.
cd examples/saveFromGC
Print the contents of saveFromGC.
cat $(nix build .#saveFromGC --no-link --print-out-paths)
# derivations:
- /nix/store/jrq3p609i85jsg27mr5zxm2imk3mjzyk-hello-2.12.2
- /nix/store/8xjhphvn58rrqydsx5569jn01yd5a0al-nix-shell
# derivationsAttrs:
# inputs:
- "flake-utils": /nix/store/01x5k4nlxcpyd85nnr0b9gm89rm8ff4x-source
- "nixpkgs": /nix/store/f3phg71mppsdj69cb63xllf1nnigzr2s-source
- "systems": /nix/store/yj1wxm9hh8610iyzqnz75kvs6xl8j3my-source
# paths:
- /nix/store/jrq3p609i85jsg27mr5zxm2imk3mjzyk-hello-2.12.2/bin/hello
# pathsAttrs:
Add the installable to the default profile.
nix profile remove examples/saveFromGC
nix profile add .#saveFromGC
nix profile list | grep save-from-gc
Store paths: /nix/store/6ypnwndqz9r8cxwywib0cysnbafzmp6f-save-from-gc
Or, build the installable and see the garbage collection roots that won't let it be garbage collected.
nix-store --query --roots $(nix build .#saveFromGC --print-out-paths)
nix-store --query --roots result
Output (edited):
...
<...>/.local/state/nix/profiles/profile-1-link -> /nix/store/pyvyymji6pvgify5gvnlvprlrxi42pdd-profile
<...>/cache-nix-action/examples/saveFromGC/result -> /nix/store/6ypnwndqz9r8cxwywib0cysnbafzmp6f-save-from-gc
nix flake archivedirenvRun direnv with nix-direnv in background.
Initially discussed here and here.
Caching approaches work at different "distances" from /nix/store of GitHub Actions runner.
These distances affect the restore and save speed.
nix-community/cache-nix-actionDeterminateSystems/magic-nix-cache-actionactions/cacherikhuijzer/cache-installnix-community/cache-nix-actionPros:
GitHub Actions Cache and works fast.Total duration.Cons: see Limitations
DeterminateSystems/magic-nix-cache-actionPros (source):
GitHub Actions Cache and works fast.Cons:
Caches.actions/cacheIf the action is used with nixbuild/nix-quick-install-action, it's similar to the nix-community/cache-nix-action.
If used with cachix/install-nix-action and a chroot local store:
Pros:
/tmp/nix.chroot store works only on Linux.Cons:
nix copy from /tmp/nix to /nix/store.If used with cachix/install-nix-action and this trick, it's similar to the nix-community/cache-nix-action but slower (link).
rikhuijzer/cache-installPros:
/nix/store, some /nix/var files, and profiles (link).Cons:
See binary cache, HTTP Binary Cache Store.
Pros:
Cachix, Attic is FOSS).Cachix, Attic).Cachix).Cachix, FlakeHub Cache).Cons:
Cachix gives only 5GB for open-source projects (src).FlakeHub Cache is available only to paid accounts (src).Attic needs to be hosted.git clone --recurse-submodules https://github.com/nix-community/cache-nix-action
Edit action.nix.
Update action.yml-s and README.md-s:
nix run .#write
actions-toolkit branch that contains a patched version of actions/toolkit.buildjet-toolkit branch that contains a patched version of BuildJet/toolkit synchronized with actions/toolkit.main branch.Example:
cd into the toolkit directorygit push origin <branch>This action allows caching dependencies and build outputs to improve workflow execution time.
Two other actions are available in addition to the primary
cacheaction:
See "Caching dependencies to speed up workflows".
[!IMPORTANT]
actions/cache@v5runs on the Node.js 24 runtime and requires a minimum Actions Runner version of2.327.1. If you are using self-hosted runners, ensure they are updated before upgrading.
The cache backend service has been rewritten from the ground up for improved performance and reliability. actions/cache now integrates with the new cache service (v2) APIs.
The new service will gradually roll out as of February 1st, 2025. The legacy service will also be sunset on the same date. Changes in these releases are fully backward compatible.
We are deprecating some versions of this action. We recommend upgrading to version v4 or v3 as soon as possible before February 1st, 2025. (Upgrade instructions below).
If you are using pinned SHAs, please use the SHAs of versions v4.2.0 or v3.4.0.
If you do not upgrade, all workflow runs using any of the deprecated actions/cache will fail.
Upgrading to the recommended versions will not break your workflows.
Additionally, if you are managing your own GitHub runners, you must update your runner version to
2.231.0or newer to ensure compatibility with the new cache service.
Failure to update both the action version and your runner version may result in workflow failures after the migration date.
Read more about the change & access the migration guide: reference to the announcement.
2.327.1~/ home folder on ubuntu-latest.SEGMENT_DOWNLOAD_TIMEOUT_MINS. Default is 10 minutes.See the v2 README.md for older updates.
Create a workflow .yml file in your repository's .github/workflows directory. An example workflow is available below. For more information, see the GitHub Help Documentation for Creating a workflow file.
If you are using this inside a container, a POSIX-compliant tar needs to be included and accessible from the execution path.
Note: actions/cache@v5 runs on Node.js 24 and requires a minimum Actions Runner version of 2.327.1.
If you are using a self-hosted Windows runner, GNU tar and zstd are required for Cross-OS caching to work. They are also recommended to be installed in general so the performance is on par with hosted Windows runners.
SEGMENT_DOWNLOAD_TIMEOUT_MINS - Segment download timeout (in minutes, default 10) to abort download of the segment if not completed in the defined number of minutes. Read moreThe cache is scoped to the key, version, and branch. The default branch cache is available to other branches.
See Matching a cache key for more info.
name: Caching Primes
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Cache Primes
id: cache-primes
uses: nix-community/cache-nix-action@v7
with:
primary-key: ${{ runner.os }}-primes
paths: prime-numbers
- name: Generate Prime Numbers
if: steps.cache-primes.outputs.hit-primary-key != 'true'
run: /generate-primes.sh -d prime-numbers
- name: Use Prime Numbers
run: /primes.sh -d prime-numbers
The cache-nix-action provides the hit-primary-key output which is set to 'true' when the cache is restored using the primary-key and 'false' otherwise.
[!NOTE] The
pathsinput in thecache-nix-action/restoreandcache-nix-action/savemust be the same.
name: Caching Primes
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Restore cached Primes
id: cache-primes-restore
uses: nix-community/cache-nix-action/restore@v7
with:
primary-key: ${{ runner.os }}-primes
paths: |
path/to/dependencies
some/other/dependencies
# other steps
- name: Save Primes
id: cache-primes-save
uses: nix-community/cache-nix-action/save@v7
with:
primary-key: ${{ steps.cache-primes-restore.outputs.cache-primary-key }}
paths: |
path/to/dependencies
some/other/dependencies
Note You must use the
cacheorrestoreaction in your workflow before you need to use the files that might be restored from the cache. If the providedprimary-keymatches an existing cache, a new cache is not created and if the providedprimary-keydoesn't match an existing cache, a new cache is automatically created provided the job completes successfully.
With the introduction of the restore and save actions, a lot of caching use cases can now be achieved. Please see the caching strategies document for understanding how you can use the actions strategically to achieve the desired goal.
Every programming language and framework has its own way of caching.
See Examples for a list of nix-community/cache-nix-action implementations for use with:
A cache key can include any of the contexts, functions, literals, and operators supported by GitHub Actions.
For example, using the hashFiles function allows you to create a new cache when dependencies change.
- uses: nix-community/cache-nix-action@v7
with:
primary-key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
paths: |
path/to/dependencies
some/other/dependencies
Additionally, you can use arbitrary command output in a cache key, such as a date or software version:
# http://man7.org/linux/man-pages/man1/date.1.html
- name: Get Date
id: get-date
run: echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT
shell: bash
- uses: nix-community/cache-nix-action@v7
with:
primary-key: ${{ runner.os }}-${{ steps.get-date.outputs.date }}-${{ hashFiles('**/lockfiles') }}
paths: path/to/dependencies
See Using contexts to create cache keys
A repository can have up to 10GB of caches. Once the 10GB limit is reached, older caches will be evicted based on when the cache was last accessed.
Caches that are not accessed within the last week will also be evicted.
Using the hit-primary-key output, subsequent steps (such as install or build) can be skipped when a cache hit occurs on the key.
It is recommended to install missing/updated dependencies in case of a partial key match when the key is dependent on the hash of the package file.
Example:
steps:
- uses: actions/checkout@v6
- uses: nix-community/cache-nix-action@v7
id: cache
with:
primary-key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
paths: path/to/dependencies
- name: Install Dependencies
if: steps.cache.outputs.hit-primary-key != 'true'
run: /install.sh
Note The
iddefined innix-community/cache-nix-actionmust match the[id]in theifstatement (i.e.steps.[id].outputs.hit-primary-key)
Cache version is a hash generated for a combination of compression tool used (Gzip, Zstd, etc. based on the runner OS) and the paths of directories being cached. If two caches have different versions, they are identified as unique caches while matching. This, for example, means that a cache created on a windows-latest runner can't be restored on ubuntu-latest as cache Versions are different.
Pro tip: The list caches API can be used to get the version of a cache. This can be helpful to troubleshoot cache miss due to version.
The workflow will create 3 unique caches with same keys. Ubuntu and Windows runners will use different compression technique and hence create two different caches. And build-linux will create two different caches as the paths are different.
jobs:
build-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Cache Primes
id: cache-primes
uses: nix-community/cache-nix-action@v7
with:
primary-key: primes
paths: prime-numbers
- name: Generate Prime Numbers
if: steps.cache-primes.outputs.hit-primary-key != 'true'
run: ./generate-primes.sh -d prime-numbers
- name: Cache Numbers
id: cache-numbers
uses: nix-community/cache-nix-action@v7
with:
primary-key: primes
paths: numbers
- name: Generate Numbers
if: steps.cache-numbers.outputs.hit-primary-key != 'true'
run: ./generate-primes.sh -d numbers
build-windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v6
- name: Cache Primes
id: cache-primes
uses: nix-community/cache-nix-action@v7
with:
primary-key: primes
paths: prime-numbers
- name: Generate Prime Numbers
if: steps.cache-primes.outputs.hit-primary-key != 'true'
run: ./generate-primes -d prime-numbers
There are a number of community practices/workarounds to fulfill specific requirements. You may choose to use them if they suit your use case. Note these are not necessarily the only solution or even a recommended solution.
Please note that Windows environment variables (like %LocalAppData%) will NOT be expanded by this action. Instead, prefer using ~ in your paths which will expand to the HOME directory. For example, instead of %LocalAppData%, use ~\AppData\Local. For a list of supported default environment variables, see the Learn GitHub Actions: Variables page.
We would love for you to contribute to nix-community/cache-nix-action. Pull requests are welcome! Please see the CONTRIBUTING.md for more information.
The scripts and documentation in this project are released under the MIT License
(top 30 of 143)
TypeScript
71.9%
Nix
27.1%