It's pretty simple to use a repo to aid the building of nix packages. You need:
- Two machines, let's call them
BuilderandRepo. - Each machine has nix installed. Let's say that
Repohas a nix installation owned by the usernix-repo, andBuilderhas one owned bynix-builder. nix-builderis able to SSH intoRepoasnix-repo.
Once you have this, to build a package on Builder using Repo:
Builder$ nix-build <thing_to_build> --option ssh-substituter-hosts nix-repo@RepoOnce a build is finished, it's likely that there will be one or more new objects that Builder built, that weren't on Repo. To upload these objects from Builder to Repo, we need to know what their paths are. nix-build prints to stdout the paths that were built, which we can store in a text file (this second build will complete instantly, so don't worry; of course, if you're reading ahead you could just run this the first time):
Builder$ nix-build <thing_to_build> --option ssh-substituter-hosts nix-repo@Repo > store_paths.txtThen we use nix-copy-closure to upload them back to the repo:
Builder$ cat store_paths.txt | xargs nix-copy-closure --to nix-repo@Repo(Note that it might be desirable to add extra options to nix-copy-closure; see the manual for details).
At this point the paths will exist on Repo, and be available to future builds and other build machines as well.
So let's show a quick example. Let's assume Builder has only nix installed and nothing else. Let's assume it has a nix expression for foo living in foo.nix, and that foo has not been built on the Builder or the Repo.
Builder$ nix-build foo.nix --option ssh-substituter-hosts nix-repo@Repo --dry-runThe --dry-run option will tell nix not to actually do the build, but to show what actions would be performed. It should say something along the lines of
these derivations will be built:
/nix/store/<some long hash>-foo.drv
It's saying that the derivations will be built, and not fetched. This means they will be built from scratch. So let's do the actual build, and put it in store_paths.txt:
Builder$ nix-build foo.nix --option ssh-substituter-hosts nix-repo@Repo > store_paths.txtWe can cat store_paths.txt and verify that it contains the path in the nix store. Now we upload that to the repo:
Builder$ cat store_paths.txt | xargs nix-copy-closure --to nix-repo@RepoAt this point, we can SSH into the repo and verify that the paths are found there:
Repo$ ls /nix/store | grep foo
/nix/store/<some long hash>-fooGoing back to the builder machine, let's delete the thing that we built. We have to delete the result symlink that was created by the nix-build or it won't let us:
Builder$ rm result
Builder$ nix-store --delete /nix/store/<some long hash>-fooNow let's try building foo again:
Builder$ nix-build foo.nix --option ssh-substituter-hosts nix-repo@Repo --dry-runThis time, it will be slightly different:
these paths will be fetched:
/nix/store/<some long hash>-foo
Now it's pulling down from the repo, so it doesn't need to build! Yay. We can confirm this by doing a build:
Builder$ nix-build foo.nix --option ssh-substituter-hosts nix-repo@RepoAnd see that it's fetching the path instead of building:
fetching path '/nix/store/<some long hash>-foo'And there we go, the repo is working.