diff --git a/src/cli/tools/nix.spec.ts b/src/cli/tools/nix.spec.ts index fd0bdceb22..dfc0ba3812 100644 --- a/src/cli/tools/nix.spec.ts +++ b/src/cli/tools/nix.spec.ts @@ -72,7 +72,7 @@ describe('cli/tools/nix', () => { await expect(svc.install('2.35.0')).rejects.toThrow('download failed'); }); - test('link exports the nix dirs below the cache', async () => { + test('link exports the nix dirs below the cache unless already set', async () => { const { svc, pathSvc } = await toolContext(NixInstallService); const spy = vi.spyOn(LinkToolService.prototype, 'shellwrapper'); const cache = join(pathSvc.cachePath, 'nix'); @@ -81,7 +81,7 @@ describe('cli/tools/nix', () => { expect(spy).toHaveBeenCalledExactlyOnceWith('nix', { srcDir: join(pathSvc.versionedToolPath('nix', '2.35.2'), 'bin'), - exports: `NIX_STORE_DIR=${cache}/store NIX_DATA_DIR=${cache}/data NIX_LOG_DIR=${cache}/log NIX_STATE_DIR=${cache}/state NIX_CONF_DIR=${cache}/conf`, + exports: `NIX_STORE_DIR=\${NIX_STORE_DIR:-${cache}/store} NIX_DATA_DIR=\${NIX_DATA_DIR:-${cache}/data} NIX_LOG_DIR=\${NIX_LOG_DIR:-${cache}/log} NIX_STATE_DIR=\${NIX_STATE_DIR:-${cache}/state} NIX_CONF_DIR=\${NIX_CONF_DIR:-${cache}/conf}`, }); }); diff --git a/src/cli/tools/nix.ts b/src/cli/tools/nix.ts index 3612a3d5b6..dd56e4375b 100644 --- a/src/cli/tools/nix.ts +++ b/src/cli/tools/nix.ts @@ -42,7 +42,9 @@ export class NixInstallService extends BaseInstallService { /** * Links the `nix` binary into the global bin folder, with the nix store and - * state folders below the containerbase cache. + * state folders below the containerbase cache unless they are already set. + * Binary caches only serve `/nix/store`, so an image that provides a + * writable `/nix` can point nix back at it to make substitution work. */ override async link(version: string): Promise { const src = join(this.pathSvc.versionedToolPath(this.name, version), 'bin'); @@ -51,11 +53,11 @@ export class NixInstallService extends BaseInstallService { await this.shellwrapper({ srcDir: src, exports: [ - `NIX_STORE_DIR=${cache}/store`, - `NIX_DATA_DIR=${cache}/data`, - `NIX_LOG_DIR=${cache}/log`, - `NIX_STATE_DIR=${cache}/state`, - `NIX_CONF_DIR=${cache}/conf`, + `NIX_STORE_DIR=\${NIX_STORE_DIR:-${cache}/store}`, + `NIX_DATA_DIR=\${NIX_DATA_DIR:-${cache}/data}`, + `NIX_LOG_DIR=\${NIX_LOG_DIR:-${cache}/log}`, + `NIX_STATE_DIR=\${NIX_STATE_DIR:-${cache}/state}`, + `NIX_CONF_DIR=\${NIX_CONF_DIR:-${cache}/conf}`, ].join(' '), }); } diff --git a/test/nix/Dockerfile b/test/nix/Dockerfile index cfcb897685..ed90dc9c6a 100644 --- a/test/nix/Dockerfile +++ b/test/nix/Dockerfile @@ -91,6 +91,28 @@ RUN --mount=type=secret,id=GITHUB_TOKEN,uid=12021 \ RUN set -ex; \ ls -la $USER_HOME; \ true + +# without preset dirs the store stays below the cache +RUN set -ex; \ + [ "$(nix --extra-experimental-features nix-command eval --raw --expr builtins.storeDir)" != /nix/store ] + +#-------------------------------------- +# test: nix with preset dirs +#-------------------------------------- +FROM base AS testc + +RUN mkdir -p /nix && chown 12021:0 /nix + +ENV NIX_STORE_DIR=/nix/store NIX_STATE_DIR=/nix/var/nix NIX_LOG_DIR=/nix/var/log/nix + +USER 12021 + +# renovate: datasource=github-releases packageName=containerbase/nix-prebuild +RUN install-tool nix 2.35.2 + +RUN set -ex; \ + [ "$(nix --extra-experimental-features nix-command eval --raw --expr builtins.storeDir)" = /nix/store ] + #-------------------------------------- # final #-------------------------------------- @@ -98,3 +120,4 @@ FROM base COPY --from=testa /.dummy /.dummy COPY --from=testb /.dummy /.dummy +COPY --from=testc /.dummy /.dummy