|
1 | | -# Build Caches |
| 1 | +# Mirrors and Build Caches |
| 2 | + |
| 3 | +Spack can use *mirrors* and *caches* to speed up image builds and to build on systems with limited or no internet access. |
| 4 | +They are configured in a single `mirrors.yaml` file in the [system configuration](cluster-config.md). |
| 5 | + |
| 6 | +A `mirrors.yaml` can describe four kinds of entry, each optional and each documented below: |
| 7 | + |
| 8 | +| Entry | Count | Purpose | |
| 9 | +|-------|-------|---------| |
| 10 | +| [`buildcache`](#build-cache) | one | binary cache of built packages (the big build-time speed up) | |
| 11 | +| [`bootstrap`](#bootstrap-mirror) | one | mirror used to bootstrap Spack itself | |
| 12 | +| [`sourcemirror`](#source-mirrors) | many | read-only mirrors that provide package sources | |
| 13 | +| [`sourcecache`](#source-cache) | one | writable local cache that fills with sources as you build | |
| 14 | + |
| 15 | +A complete example: |
| 16 | + |
| 17 | +```yaml title="mirrors.yaml" |
| 18 | +buildcache: |
| 19 | + url: file:///capstor/scratch/team/uenv-cache |
| 20 | + private_key: $SCRATCH/.keys/spack-push-key.gpg |
| 21 | + mount_specific: true |
| 22 | +bootstrap: |
| 23 | + url: https://bootstrap.spack.io |
| 24 | +sourcemirror: |
| 25 | + mirror1: |
| 26 | + url: https://example.com/spack-sources |
| 27 | +sourcecache: |
| 28 | + path: /capstor/scratch/$USER/spack-sources |
| 29 | +``` |
2 | 30 |
|
3 | | -Stackinator facilitates using Spack's binary build caches to speed up image builds. |
4 | | -Build caches are essential if you plan to build images regularly, as they generally lead to a roughly 10x speed up. |
5 | | -This is the difference between half an hour or 3 minutes to build a typical image. |
| 31 | +To stop using any entry, remove (or comment out) it from `mirrors.yaml`. |
6 | 32 |
|
7 | | -## Using Build caches |
| 33 | +## Build cache |
8 | 34 |
|
9 | | -To use a build cache, create a simple YAML file: |
| 35 | +A build cache is a binary cache of built packages. |
| 36 | +Reusing binaries instead of rebuilding from source is roughly a 10x speed up — the difference between a 3 minute and a 30 minute image build — so a build cache is essential if you build images regularly. |
10 | 37 |
|
11 | | -```yaml title='cache-config.yaml' |
12 | | -root: $SCRATCH/uenv-cache |
13 | | -key: $SCRATCH/.keys/spack-push-key.gpg |
| 38 | +During a build Spack fetches packages from the cache when it can, and signs and pushes any package it has to build itself, so the cache improves over time. |
| 39 | + |
| 40 | +```yaml title="mirrors.yaml" |
| 41 | +buildcache: |
| 42 | + url: file:///capstor/scratch/team/uenv-cache |
| 43 | + private_key: $SCRATCH/.keys/spack-push-key.gpg |
14 | 44 | ``` |
15 | 45 |
|
16 | | -To use the cache, pass the configuration as an option to `stack-config` via the `-c/--cache` flag: |
| 46 | +| Field | Required | Description | |
| 47 | +|-------|----------|-------------| |
| 48 | +| `url` | yes | location of the cache (a `file://` path, or an `http(s)://`, `s3://` or `oci://` URL) | |
| 49 | +| `private_key` | yes | PGP key used to sign and push packages (see [Keys](#keys)) | |
| 50 | +| `public_key` | no | PGP key used to verify downloaded packages | |
| 51 | +| `name` | no | name Spack registers the mirror under (default `buildcache`) | |
| 52 | +| `mount_specific` | no | store the cache in a per-mount-point sub-directory (default `false`) | |
| 53 | + |
| 54 | +### `mount_specific` |
| 55 | + |
| 56 | +Spack binaries embed the install prefix (the image's mount point), so binaries built for `/user-environment` cannot be reused at a different mount point. |
| 57 | +Set `mount_specific: true` to append the mount point to the cache URL, giving each mount point its own sub-directory and avoiding relocation issues: |
| 58 | + |
| 59 | +```yaml |
| 60 | +buildcache: |
| 61 | + url: file:///capstor/scratch/team/uenv-cache |
| 62 | + private_key: $SCRATCH/.keys/spack-push-key.gpg |
| 63 | + mount_specific: true # packages stored under .../uenv-cache/user-environment |
| 64 | +``` |
| 65 | + |
| 66 | +### Creating a build cache |
| 67 | + |
| 68 | +A build cache needs an empty directory and a PGP signing key: |
17 | 69 |
|
18 | 70 | ```bash |
19 | | -stack-config -b $build_path -r $recipe_path -s $system_config -c cache-config.yaml |
| 71 | +# 1. create the cache directory |
| 72 | +mkdir -p $SCRATCH/uenv-cache |
| 73 | +
|
| 74 | +# 2. generate and export a signing key |
| 75 | +spack gpg create <name> <e-mail> |
| 76 | +spack gpg export --secret $SCRATCH/.keys/spack-push-key.gpg |
20 | 77 | ``` |
21 | 78 |
|
22 | | -??? warning "If you using an old binary build cache" |
23 | | - Since v3, Stackinator creates a sub-directory in the build cache for each mount point. |
24 | | - For example, in the above example, the build cache for the `/user-environment` mount point would be `$SCRATCH/uenv-cache/user-environment`. |
25 | | - The rationale for this is so that packages for different mount points are not mixed, to avoid having to relocate binaries. |
| 79 | +See [Keys](#keys) for where to store the key. |
| 80 | + |
| 81 | +### Force pushing |
| 82 | + |
| 83 | +Packages are pushed to the cache after each environment builds successfully; nothing is pushed if a build fails. |
| 84 | +When iterating on a recipe with failing builds, force-push everything built so far with the `cache-force` target: |
26 | 85 |
|
27 | | - To continue using a build caches from before v3, first copy the `build_cache` path to a subdirectory, e.g.: |
| 86 | +```bash |
| 87 | +env --ignore-environment PATH=/usr/bin:/bin:`pwd -P`/spack/bin make cache-force |
| 88 | +``` |
28 | 89 |
|
29 | | - ```bash |
30 | | - mkdir $SCRATCH/uenv-cache/user-environment |
31 | | - mv $SCRATCH/uenv-cache/build_cache $SCRATCH/uenv-cache/user-environment |
32 | | - ``` |
| 90 | +## Bootstrap mirror |
33 | 91 |
|
34 | | -### Build-only caches |
| 92 | +Spack bootstraps some of its own dependencies (such as the `clingo` concretizer) on first use. |
| 93 | +A bootstrap mirror lets it do this without reaching the internet — useful on air-gapped systems. |
35 | 94 |
|
36 | | -A build cache can be configured to be read-only by not providing a `key` in the cache configuration file. |
| 95 | +```yaml title="mirrors.yaml" |
| 96 | +bootstrap: |
| 97 | + url: https://bootstrap.spack.io |
| 98 | +``` |
37 | 99 |
|
38 | | -## Creating a Build Cache |
| 100 | +| Field | Required | Description | |
| 101 | +|-------|----------|-------------| |
| 102 | +| `url` | yes | location of the bootstrap mirror | |
| 103 | +| `public_key` | no | PGP key used to verify the bootstrap binaries | |
39 | 104 |
|
40 | | -To create a build cache we need two things: |
| 105 | +## Source mirrors |
41 | 106 |
|
42 | | -1. An empty directory where the cache will be populated by Spack. |
43 | | -2. A private PGP key |
44 | | - * Only required for Stackinator to push packages to the cache when it builds a package that was not in the cache. |
| 107 | +Source mirrors provide package **source** archives, and are read-only: Spack fetches sources from them but never writes to them. |
| 108 | +Use them to build on air-gapped systems — populate a mirror on a connected system, mount it read-only, and Spack will fetch sources from it. |
| 109 | +Any number of source mirrors can be listed; Spack searches them in order. |
45 | 110 |
|
46 | | -Creating the cache directory is easy! For example, to create a cache on your scratch storage: |
47 | | -```bash |
48 | | -mkdir $SCRATCH/uenv-cache |
| 111 | +```yaml title="mirrors.yaml" |
| 112 | +sourcemirror: |
| 113 | + internal: |
| 114 | + url: https://mirror.example.com/spack-sources |
| 115 | + scratch: |
| 116 | + url: file:///capstor/scratch/team/spack-sources |
49 | 117 | ``` |
50 | 118 |
|
51 | | -### Generating Keys |
| 119 | +| Field | Required | Description | |
| 120 | +|-------|----------|-------------| |
| 121 | +| `url` | yes | location of the source mirror | |
| 122 | +| `public_key` | no | PGP key used to verify sources | |
52 | 123 |
|
53 | | -An installation of Spack can be used to generate the key file: |
| 124 | +Populate a source mirror on an internet-connected system with Spack: |
54 | 125 |
|
55 | 126 | ```bash |
56 | | -# create a key |
57 | | -spack gpg create <name> <e-mail> |
| 127 | +spack mirror create --directory /path/to/mirror --all |
| 128 | +``` |
| 129 | + |
| 130 | +## Source cache |
58 | 131 |
|
59 | | -# export key |
60 | | -spack gpg export --secret spack-push-key.gpg |
| 132 | +A source cache is a single, **writable** local directory that Spack fills as it downloads sources. |
| 133 | +On internet-connected systems Spack checks the cache first; on a miss it downloads the source and stores it, so later builds reuse it and download times shrink over time. |
| 134 | + |
| 135 | +Unlike a source mirror it needs no key, is written to automatically, and is created on demand. |
| 136 | + |
| 137 | +```yaml title="mirrors.yaml" |
| 138 | +sourcecache: |
| 139 | + path: /capstor/scratch/$USER/spack-sources |
61 | 140 | ``` |
62 | 141 |
|
63 | | -See the [spack documentation](https://spack.readthedocs.io/en/latest/getting_started.html#gpg-signing) for more information about GPG keys. |
| 142 | +| Field | Required | Description | |
| 143 | +|-------|----------|-------------| |
| 144 | +| `path` | yes | absolute path to a local directory (environment variables are expanded) | |
64 | 145 |
|
65 | | -### Managing Keys |
| 146 | +## Keys |
66 | 147 |
|
67 | | -The key needs to be in a location that is accessible during the build process, and secure. |
68 | | -To keep your PGP key secret, you can generate it then move it to a path with appropriate permissions. |
69 | | -In the example below, we create a path `.keys` for storing the key: |
70 | | -```bash |
71 | | -# create .keys path is visible only to you |
72 | | -mkdir $SCRATCH/.keys |
73 | | -chmod 700 $SCRATCH/.keys |
| 148 | +The `private_key` and `public_key` fields accept either: |
| 149 | + |
| 150 | +* a **path** — absolute, or relative to the system configuration directory; or |
| 151 | +* a **base64-encoded key** inlined directly in `mirrors.yaml`. |
| 152 | + |
| 153 | +```yaml |
| 154 | +buildcache: |
| 155 | + url: file:///capstor/scratch/team/uenv-cache |
| 156 | + private_key: $SCRATCH/.keys/spack-push-key.gpg # a path |
| 157 | + public_key: mQINBGm4GvsBEACTyzQF...== # inline base64 |
| 158 | +``` |
| 159 | + |
| 160 | +Generate a key with Spack, and keep the secret key somewhere private: |
74 | 161 |
|
75 | | -# generate the key |
| 162 | +```bash |
| 163 | +mkdir $SCRATCH/.keys && chmod 700 $SCRATCH/.keys |
76 | 164 | spack gpg create <name> <e-mail> |
77 | 165 | spack gpg export --secret $SCRATCH/.keys/spack-push-key.gpg |
78 | 166 | chmod 600 $SCRATCH/.keys/spack-push-key.gpg |
79 | 167 | ``` |
80 | 168 |
|
81 | | -The cache-configuration would look like the following, where we assume that the cache is in `$SCRATCH/uenv-cache`: |
82 | | -```yaml |
83 | | -root: $SCRATCH/uenv-cache |
84 | | -key: $SCRATCH/.keys/spack-push-key.gpg |
85 | | -``` |
86 | | -!!! warning |
87 | | - Don't blindly copy this documentation's advice on security settings. |
| 169 | +See the [Spack documentation](https://spack.readthedocs.io/en/latest/getting_started.html#gpg-signing) for more on GPG keys. |
88 | 170 |
|
89 | 171 | !!! failure "Don't use `$HOME`" |
90 | | - Don't put the keys in `$HOME`, because the build process remounts `~` as a tmpfs, and you will get error messages that Spack can't read the key. |
| 172 | + The build remounts `~` as a tmpfs, so keys under `$HOME` are not visible during the build and Spack will fail to read them. Use scratch storage instead. |
91 | 173 |
|
92 | | -## Force pushing to build cache |
| 174 | +## Legacy `--cache` option |
93 | 175 |
|
94 | | -When build caches are enabled, all packages in a each Spack environment are pushed to the build cache after the whole environment has been built successfully -- nothing will be pushed to the cache if there is an error when building one of the packages. |
| 176 | +Before `mirrors.yaml`, a build cache was configured with a separate `cache.yaml` file passed to `stack-config` via `-c/--cache`: |
95 | 177 |
|
96 | | -When debugging a recipe, where failing builds have to be run multiple times, the overheads of rebuilding all packages from scratch can be wasteful. |
97 | | -To force push all packages that have been built, use the `cache-force` makefile target: |
| 178 | +```yaml title="cache.yaml" |
| 179 | +root: $SCRATCH/uenv-cache |
| 180 | +key: $SCRATCH/.keys/spack-push-key.gpg |
| 181 | +``` |
98 | 182 |
|
99 | 183 | ```bash |
100 | | -env --ignore-environment PATH=/usr/bin:/bin:`pwd -P`/spack/bin make cache-force |
| 184 | +stack-config -b $build -r $recipe -s $system -c cache.yaml |
101 | 185 | ``` |
| 186 | + |
| 187 | +This is **deprecated** and equivalent to a single `buildcache` entry (with `mount_specific: true`). Prefer configuring the build cache in `mirrors.yaml`. |
| 188 | + |
| 189 | +Setting `key: null` configures a read-only cache that Spack fetches from but never pushes to. |
0 commit comments