diff options
Diffstat (limited to 'doc/manual/src/package-management')
11 files changed, 748 insertions, 0 deletions
diff --git a/doc/manual/src/package-management/basic-package-mgmt.md b/doc/manual/src/package-management/basic-package-mgmt.md new file mode 100644 index 000000000..9702a29eb --- /dev/null +++ b/doc/manual/src/package-management/basic-package-mgmt.md @@ -0,0 +1,172 @@ +# Basic Package Management + +The main command for package management is +[`nix-env`](../command-ref/nix-env.md). You can use it to install, +upgrade, and erase packages, and to query what packages are installed +or are available for installation. + +In Nix, different users can have different “views” on the set of +installed applications. That is, there might be lots of applications +present on the system (possibly in many different versions), but users +can have a specific selection of those active — where “active” just +means that it appears in a directory in the user’s `PATH`. Such a view +on the set of installed applications is called a *user environment*, +which is just a directory tree consisting of symlinks to the files of +the active applications. + +Components are installed from a set of *Nix expressions* that tell Nix +how to build those packages, including, if necessary, their +dependencies. There is a collection of Nix expressions called the +Nixpkgs package collection that contains packages ranging from basic +development stuff such as GCC and Glibc, to end-user applications like +Mozilla Firefox. (Nix is however not tied to the Nixpkgs package +collection; you could write your own Nix expressions based on Nixpkgs, +or completely new ones.) + +You can manually download the latest version of Nixpkgs from +<http://nixos.org/nixpkgs/download.html>. However, it’s much more +convenient to use the Nixpkgs [*channel*](channels.md), since it makes +it easy to stay up to date with new versions of Nixpkgs. Nixpkgs is +automatically added to your list of “subscribed” channels when you +install Nix. If this is not the case for some reason, you can add it +as follows: + +```console +$ nix-channel --add https://nixos.org/channels/nixpkgs-unstable +$ nix-channel --update +``` + +> **Note** +> +> On NixOS, you’re automatically subscribed to a NixOS channel +> corresponding to your NixOS major release (e.g. +> <http://nixos.org/channels/nixos-14.12>). A NixOS channel is identical +> to the Nixpkgs channel, except that it contains only Linux binaries +> and is updated only if a set of regression tests succeed. + +You can view the set of available packages in Nixpkgs: + +```console +$ nix-env -qa +aterm-2.2 +bash-3.0 +binutils-2.15 +bison-1.875d +blackdown-1.4.2 +bzip2-1.0.2 +… +``` + +The flag `-q` specifies a query operation, and `-a` means that you want +to show the “available” (i.e., installable) packages, as opposed to the +installed packages. If you downloaded Nixpkgs yourself, or if you +checked it out from GitHub, then you need to pass the path to your +Nixpkgs tree using the `-f` flag: + +```console +$ nix-env -qaf /path/to/nixpkgs +``` + +where */path/to/nixpkgs* is where you’ve unpacked or checked out +Nixpkgs. + +You can select specific packages by name: + +```console +$ nix-env -qa firefox +firefox-34.0.5 +firefox-with-plugins-34.0.5 +``` + +and using regular expressions: + +```console +$ nix-env -qa 'firefox.*' +``` + +It is also possible to see the *status* of available packages, i.e., +whether they are installed into the user environment and/or present in +the system: + +```console +$ nix-env -qas +… +-PS bash-3.0 +--S binutils-2.15 +IPS bison-1.875d +… +``` + +The first character (`I`) indicates whether the package is installed in +your current user environment. The second (`P`) indicates whether it is +present on your system (in which case installing it into your user +environment would be a very quick operation). The last one (`S`) +indicates whether there is a so-called *substitute* for the package, +which is Nix’s mechanism for doing binary deployment. It just means that +Nix knows that it can fetch a pre-built package from somewhere +(typically a network server) instead of building it locally. + +You can install a package using `nix-env -i`. For instance, + +```console +$ nix-env -i subversion +``` + +will install the package called `subversion` (which is, of course, the +[Subversion version management system](http://subversion.tigris.org/)). + +> **Note** +> +> When you ask Nix to install a package, it will first try to get it in +> pre-compiled form from a *binary cache*. By default, Nix will use the +> binary cache <https://cache.nixos.org>; it contains binaries for most +> packages in Nixpkgs. Only if no binary is available in the binary +> cache, Nix will build the package from source. So if `nix-env +> -i subversion` results in Nix building stuff from source, then either +> the package is not built for your platform by the Nixpkgs build +> servers, or your version of Nixpkgs is too old or too new. For +> instance, if you have a very recent checkout of Nixpkgs, then the +> Nixpkgs build servers may not have had a chance to build everything +> and upload the resulting binaries to <https://cache.nixos.org>. The +> Nixpkgs channel is only updated after all binaries have been uploaded +> to the cache, so if you stick to the Nixpkgs channel (rather than +> using a Git checkout of the Nixpkgs tree), you will get binaries for +> most packages. + +Naturally, packages can also be uninstalled: + +```console +$ nix-env -e subversion +``` + +Upgrading to a new version is just as easy. If you have a new release of +Nix Packages, you can do: + +```console +$ nix-env -u subversion +``` + +This will *only* upgrade Subversion if there is a “newer” version in the +new set of Nix expressions, as defined by some pretty arbitrary rules +regarding ordering of version numbers (which generally do what you’d +expect of them). To just unconditionally replace Subversion with +whatever version is in the Nix expressions, use `-i` instead of `-u`; +`-i` will remove whatever version is already installed. + +You can also upgrade all packages for which there are newer versions: + +```console +$ nix-env -u +``` + +Sometimes it’s useful to be able to ask what `nix-env` would do, without +actually doing it. For instance, to find out what packages would be +upgraded by `nix-env -u`, you can do + +```console +$ nix-env -u --dry-run +(dry run; not doing anything) +upgrading `libxslt-1.1.0' to `libxslt-1.1.10' +upgrading `graphviz-1.10' to `graphviz-1.12' +upgrading `coreutils-5.0' to `coreutils-5.2.1' +``` diff --git a/doc/manual/src/package-management/binary-cache-substituter.md b/doc/manual/src/package-management/binary-cache-substituter.md new file mode 100644 index 000000000..bdc5038fc --- /dev/null +++ b/doc/manual/src/package-management/binary-cache-substituter.md @@ -0,0 +1,50 @@ +# Serving a Nix store via HTTP + +You can easily share the Nix store of a machine via HTTP. This allows +other machines to fetch store paths from that machine to speed up +installations. It uses the same *binary cache* mechanism that Nix +usually uses to fetch pre-built binaries from <https://cache.nixos.org>. + +The daemon that handles binary cache requests via HTTP, `nix-serve`, is +not part of the Nix distribution, but you can install it from Nixpkgs: + +```console +$ nix-env -i nix-serve +``` + +You can then start the server, listening for HTTP connections on +whatever port you like: + +```console +$ nix-serve -p 8080 +``` + +To check whether it works, try the following on the client: + +```console +$ curl http://avalon:8080/nix-cache-info +``` + +which should print something like: + + StoreDir: /nix/store + WantMassQuery: 1 + Priority: 30 + +On the client side, you can tell Nix to use your binary cache using +`--option extra-binary-caches`, e.g.: + +```console +$ nix-env -i firefox --option extra-binary-caches http://avalon:8080/ +``` + +The option `extra-binary-caches` tells Nix to use this binary cache in +addition to your default caches, such as <https://cache.nixos.org>. +Thus, for any path in the closure of Firefox, Nix will first check if +the path is available on the server `avalon` or another binary caches. +If not, it will fall back to building from source. + +You can also tell Nix to always use your binary cache by adding a line +to the `nix.conf` configuration file like this: + + binary-caches = http://avalon:8080/ https://cache.nixos.org/ diff --git a/doc/manual/src/package-management/channels.md b/doc/manual/src/package-management/channels.md new file mode 100644 index 000000000..93c8b41a6 --- /dev/null +++ b/doc/manual/src/package-management/channels.md @@ -0,0 +1,50 @@ +# Channels + +If you want to stay up to date with a set of packages, it’s not very +convenient to manually download the latest set of Nix expressions for +those packages and upgrade using `nix-env`. Fortunately, there’s a +better way: *Nix channels*. + +A Nix channel is just a URL that points to a place that contains a set +of Nix expressions and a manifest. Using the command +[`nix-channel`](../command-ref/nix-channel.md) you can automatically +stay up to date with whatever is available at that URL. + +To see the list of official NixOS channels, visit +<https://nixos.org/channels>. + +You can “subscribe” to a channel using `nix-channel --add`, e.g., + +```console +$ nix-channel --add https://nixos.org/channels/nixpkgs-unstable +``` + +subscribes you to a channel that always contains that latest version of +the Nix Packages collection. (Subscribing really just means that the URL +is added to the file `~/.nix-channels`, where it is read by subsequent +calls to `nix-channel +--update`.) You can “unsubscribe” using `nix-channel +--remove`: + +```console +$ nix-channel --remove nixpkgs +``` + +To obtain the latest Nix expressions available in a channel, do + +```console +$ nix-channel --update +``` + +This downloads and unpacks the Nix expressions in every channel +(downloaded from `url/nixexprs.tar.bz2`). It also makes the union of +each channel’s Nix expressions available by default to `nix-env` +operations (via the symlink `~/.nix-defexpr/channels`). Consequently, +you can then say + +```console +$ nix-env -u +``` + +to upgrade all packages in your profile to the latest versions available +in the subscribed channels. diff --git a/doc/manual/src/package-management/copy-closure.md b/doc/manual/src/package-management/copy-closure.md new file mode 100644 index 000000000..d3fac4d76 --- /dev/null +++ b/doc/manual/src/package-management/copy-closure.md @@ -0,0 +1,34 @@ +# Copying Closures via SSH + +The command `nix-copy-closure` copies a Nix store path along with all +its dependencies to or from another machine via the SSH protocol. It +doesn’t copy store paths that are already present on the target machine. +For example, the following command copies Firefox with all its +dependencies: + + $ nix-copy-closure --to alice@itchy.example.org $(type -p firefox) + +See the [manpage for `nix-copy-closure`](../command-ref/nix-copy-closure.md) for details. + +With `nix-store +--export` and `nix-store --import` you can write the closure of a store +path (that is, the path and all its dependencies) to a file, and then +unpack that file into another Nix store. For example, + + $ nix-store --export $(nix-store -qR $(type -p firefox)) > firefox.closure + +writes the closure of Firefox to a file. You can then copy this file to +another machine and install the closure: + + $ nix-store --import < firefox.closure + +Any store paths in the closure that are already present in the target +store are ignored. It is also possible to pipe the export into another +command, e.g. to copy and install a closure directly to/on another +machine: + + $ nix-store --export $(nix-store -qR $(type -p firefox)) | bzip2 | \ + ssh alice@itchy.example.org "bunzip2 | nix-store --import" + +However, `nix-copy-closure` is generally more efficient because it only +copies paths that are not already present in the target Nix store. diff --git a/doc/manual/src/package-management/garbage-collection.md b/doc/manual/src/package-management/garbage-collection.md new file mode 100644 index 000000000..fecb30fd6 --- /dev/null +++ b/doc/manual/src/package-management/garbage-collection.md @@ -0,0 +1,73 @@ +# Garbage Collection + +`nix-env` operations such as upgrades (`-u`) and uninstall (`-e`) never +actually delete packages from the system. All they do (as shown above) +is to create a new user environment that no longer contains symlinks to +the “deleted” packages. + +Of course, since disk space is not infinite, unused packages should be +removed at some point. You can do this by running the Nix garbage +collector. It will remove from the Nix store any package not used +(directly or indirectly) by any generation of any profile. + +Note however that as long as old generations reference a package, it +will not be deleted. After all, we wouldn’t be able to do a rollback +otherwise. So in order for garbage collection to be effective, you +should also delete (some) old generations. Of course, this should only +be done if you are certain that you will not need to roll back. + +To delete all old (non-current) generations of your current profile: + +```console +$ nix-env --delete-generations old +``` + +Instead of `old` you can also specify a list of generations, e.g., + +```console +$ nix-env --delete-generations 10 11 14 +``` + +To delete all generations older than a specified number of days (except +the current generation), use the `d` suffix. For example, + +```console +$ nix-env --delete-generations 14d +``` + +deletes all generations older than two weeks. + +After removing appropriate old generations you can run the garbage +collector as follows: + +```console +$ nix-store --gc +``` + +The behaviour of the gargage collector is affected by the +`keep-derivations` (default: true) and `keep-outputs` (default: false) +options in the Nix configuration file. The defaults will ensure that all +derivations that are build-time dependencies of garbage collector roots +will be kept and that all output paths that are runtime dependencies +will be kept as well. All other derivations or paths will be collected. +(This is usually what you want, but while you are developing it may make +sense to keep outputs to ensure that rebuild times are quick.) If you +are feeling uncertain, you can also first view what files would be +deleted: + +```console +$ nix-store --gc --print-dead +``` + +Likewise, the option `--print-live` will show the paths that *won’t* be +deleted. + +There is also a convenient little utility `nix-collect-garbage`, which +when invoked with the `-d` (`--delete-old`) switch deletes all old +generations of all profiles in `/nix/var/nix/profiles`. So + +```console +$ nix-collect-garbage -d +``` + +is a quick and easy way to clean up your system. diff --git a/doc/manual/src/package-management/garbage-collector-roots.md b/doc/manual/src/package-management/garbage-collector-roots.md new file mode 100644 index 000000000..30c5b7f8d --- /dev/null +++ b/doc/manual/src/package-management/garbage-collector-roots.md @@ -0,0 +1,18 @@ +# Garbage Collector Roots + +The roots of the garbage collector are all store paths to which there +are symlinks in the directory `prefix/nix/var/nix/gcroots`. For +instance, the following command makes the path +`/nix/store/d718ef...-foo` a root of the collector: + +```console +$ ln -s /nix/store/d718ef...-foo /nix/var/nix/gcroots/bar +``` + +That is, after this command, the garbage collector will not remove +`/nix/store/d718ef...-foo` or any of its dependencies. + +Subdirectories of `prefix/nix/var/nix/gcroots` are also searched for +symlinks. Symlinks to non-store paths are followed and searched for +roots, but symlinks to non-store paths *inside* the paths reached in +that way are not followed to prevent infinite recursion. diff --git a/doc/manual/src/package-management/package-management.md b/doc/manual/src/package-management/package-management.md new file mode 100644 index 000000000..bd26a09ab --- /dev/null +++ b/doc/manual/src/package-management/package-management.md @@ -0,0 +1,5 @@ +This chapter discusses how to do package management with Nix, i.e., +how to obtain, install, upgrade, and erase packages. This is the +“user’s” perspective of the Nix system — people who want to *create* +packages should consult the [chapter on writing Nix +expressions](../expressions/writing-nix-expressions.md). diff --git a/doc/manual/src/package-management/profiles.md b/doc/manual/src/package-management/profiles.md new file mode 100644 index 000000000..fbbfb7320 --- /dev/null +++ b/doc/manual/src/package-management/profiles.md @@ -0,0 +1,133 @@ +# Profiles + +Profiles and user environments are Nix’s mechanism for implementing the +ability to allow different users to have different configurations, and +to do atomic upgrades and rollbacks. To understand how they work, it’s +useful to know a bit about how Nix works. In Nix, packages are stored in +unique locations in the *Nix store* (typically, `/nix/store`). For +instance, a particular version of the Subversion package might be stored +in a directory +`/nix/store/dpmvp969yhdqs7lm2r1a3gng7pyq6vy4-subversion-1.1.3/`, while +another version might be stored in +`/nix/store/5mq2jcn36ldlmh93yj1n8s9c95pj7c5s-subversion-1.1.2`. The long +strings prefixed to the directory names are cryptographic hashes (to be +precise, 160-bit truncations of SHA-256 hashes encoded in a base-32 +notation) of *all* inputs involved in building the package — sources, +dependencies, compiler flags, and so on. So if two packages differ in +any way, they end up in different locations in the file system, so they +don’t interfere with each other. Here is what a part of a typical Nix +store looks like: + +![](../figures/user-environments.png) + +Of course, you wouldn’t want to type + +```console +$ /nix/store/dpmvp969yhdq...-subversion-1.1.3/bin/svn +``` + +every time you want to run Subversion. Of course we could set up the +`PATH` environment variable to include the `bin` directory of every +package we want to use, but this is not very convenient since changing +`PATH` doesn’t take effect for already existing processes. The solution +Nix uses is to create directory trees of symlinks to *activated* +packages. These are called *user environments* and they are packages +themselves (though automatically generated by `nix-env`), so they too +reside in the Nix store. For instance, in the figure above, the user +environment `/nix/store/0c1p5z4kda11...-user-env` contains a symlink to +just Subversion 1.1.2 (arrows in the figure indicate symlinks). This +would be what we would obtain if we had done + +```console +$ nix-env -i subversion +``` + +on a set of Nix expressions that contained Subversion 1.1.2. + +This doesn’t in itself solve the problem, of course; you wouldn’t want +to type `/nix/store/0c1p5z4kda11...-user-env/bin/svn` either. That’s why +there are symlinks outside of the store that point to the user +environments in the store; for instance, the symlinks `default-42-link` +and `default-43-link` in the example. These are called *generations* +since every time you perform a `nix-env` operation, a new user +environment is generated based on the current one. For instance, +generation 43 was created from generation 42 when we did + +```console +$ nix-env -i subversion firefox +``` + +on a set of Nix expressions that contained Firefox and a new version of +Subversion. + +Generations are grouped together into *profiles* so that different users +don’t interfere with each other if they don’t want to. For example: + +```console +$ ls -l /nix/var/nix/profiles/ +... +lrwxrwxrwx 1 eelco ... default-42-link -> /nix/store/0c1p5z4kda11...-user-env +lrwxrwxrwx 1 eelco ... default-43-link -> /nix/store/3aw2pdyx2jfc...-user-env +lrwxrwxrwx 1 eelco ... default -> default-43-link +``` + +This shows a profile called `default`. The file `default` itself is +actually a symlink that points to the current generation. When we do a +`nix-env` operation, a new user environment and generation link are +created based on the current one, and finally the `default` symlink is +made to point at the new generation. This last step is atomic on Unix, +which explains how we can do atomic upgrades. (Note that the +building/installing of new packages doesn’t interfere in any way with +old packages, since they are stored in different locations in the Nix +store.) + +If you find that you want to undo a `nix-env` operation, you can just do + +```console +$ nix-env --rollback +``` + +which will just make the current generation link point at the previous +link. E.g., `default` would be made to point at `default-42-link`. You +can also switch to a specific generation: + +```console +$ nix-env --switch-generation 43 +``` + +which in this example would roll forward to generation 43 again. You can +also see all available generations: + +```console +$ nix-env --list-generations +``` + +You generally wouldn’t have `/nix/var/nix/profiles/some-profile/bin` in +your `PATH`. Rather, there is a symlink `~/.nix-profile` that points to +your current profile. This means that you should put +`~/.nix-profile/bin` in your `PATH` (and indeed, that’s what the +initialisation script `/nix/etc/profile.d/nix.sh` does). This makes it +easier to switch to a different profile. You can do that using the +command `nix-env --switch-profile`: + +```console +$ nix-env --switch-profile /nix/var/nix/profiles/my-profile + +$ nix-env --switch-profile /nix/var/nix/profiles/default +``` + +These commands switch to the `my-profile` and default profile, +respectively. If the profile doesn’t exist, it will be created +automatically. You should be careful about storing a profile in another +location than the `profiles` directory, since otherwise it might not be +used as a root of the [garbage collector](garbage-collection.md). + +All `nix-env` operations work on the profile pointed to by +`~/.nix-profile`, but you can override this using the `--profile` option +(abbreviation `-p`): + +```console +$ nix-env -p /nix/var/nix/profiles/other-profile -i subversion +``` + +This will *not* change the `~/.nix-profile` symlink. diff --git a/doc/manual/src/package-management/s3-substituter.md b/doc/manual/src/package-management/s3-substituter.md new file mode 100644 index 000000000..a4f4d561f --- /dev/null +++ b/doc/manual/src/package-management/s3-substituter.md @@ -0,0 +1,145 @@ +# Serving a Nix store via S3 + +Nix has built-in support for storing and fetching store paths from +Amazon S3 and S3-compatible services. This uses the same *binary* +cache mechanism that Nix usually uses to fetch prebuilt binaries from +[cache.nixos.org](https://cache.nixos.org/). + +The following options can be specified as URL parameters to the S3 URL: + + - `profile` + The name of the AWS configuration profile to use. By default Nix + will use the `default` profile. + + - `region` + The region of the S3 bucket. `us–east-1` by default. + + If your bucket is not in `us–east-1`, you should always explicitly + specify the region parameter. + + - `endpoint` + The URL to your S3-compatible service, for when not using Amazon S3. + Do not specify this value if you're using Amazon S3. + + > **Note** + > + > This endpoint must support HTTPS and will use path-based + > addressing instead of virtual host based addressing. + + - `scheme` + The scheme used for S3 requests, `https` (default) or `http`. This + option allows you to disable HTTPS for binary caches which don't + support it. + + > **Note** + > + > HTTPS should be used if the cache might contain sensitive + > information. + +In this example we will use the bucket named `example-nix-cache`. + +## Anonymous Reads to your S3-compatible binary cache + +If your binary cache is publicly accessible and does not require +authentication, the simplest and easiest way to use Nix with your S3 +compatible binary cache is to use the HTTP URL for that cache. + +For AWS S3 the binary cache URL for example bucket will be exactly +<https://example-nix-cache.s3.amazonaws.com> or +<s3://example-nix-cache>. For S3 compatible binary caches, consult that +cache's documentation. + +Your bucket will need the following bucket policy: + +```json +{ + "Id": "DirectReads", + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "AllowDirectReads", + "Action": [ + "s3:GetObject", + "s3:GetBucketLocation" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::example-nix-cache", + "arn:aws:s3:::example-nix-cache/*" + ], + "Principal": "*" + } + ] +} +``` + +## Authenticated Reads to your S3 binary cache + +For AWS S3 the binary cache URL for example bucket will be exactly +<s3://example-nix-cache>. + +Nix will use the [default credential provider +chain](https://docs.aws.amazon.com/sdk-for-cpp/v1/developer-guide/credentials.html) +for authenticating requests to Amazon S3. + +Nix supports authenticated reads from Amazon S3 and S3 compatible binary +caches. + +Your bucket will need a bucket policy allowing the desired users to +perform the `s3:GetObject` and `s3:GetBucketLocation` action on all +objects in the bucket. The [anonymous policy given +above](#anonymous-reads-to-your-s3-compatible-binary-cache) can be +updated to have a restricted `Principal` to support this. + +## Authenticated Writes to your S3-compatible binary cache + +Nix support fully supports writing to Amazon S3 and S3 compatible +buckets. The binary cache URL for our example bucket will be +<s3://example-nix-cache>. + +Nix will use the [default credential provider +chain](https://docs.aws.amazon.com/sdk-for-cpp/v1/developer-guide/credentials.html) +for authenticating requests to Amazon S3. + +Your account will need the following IAM policy to upload to the cache: + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "UploadToCache", + "Effect": "Allow", + "Action": [ + "s3:AbortMultipartUpload", + "s3:GetBucketLocation", + "s3:GetObject", + "s3:ListBucket", + "s3:ListBucketMultipartUploads", + "s3:ListMultipartUploadParts", + "s3:PutObject" + ], + "Resource": [ + "arn:aws:s3:::example-nix-cache", + "arn:aws:s3:::example-nix-cache/*" + ] + } + ] +} +``` + +## Examples + +To upload with a specific credential profile for Amazon S3: + +```console +$ nix copy nixpkgs.hello \ + --to 's3://example-nix-cache?profile=cache-upload®ion=eu-west-2' +``` + +To upload to an S3-compatible binary cache: + +```console +$ nix copy nixpkgs.hello --to \ + 's3://example-nix-cache?profile=cache-upload&scheme=https&endpoint=minio.example.com' +``` diff --git a/doc/manual/src/package-management/sharing-packages.md b/doc/manual/src/package-management/sharing-packages.md new file mode 100644 index 000000000..846ca6934 --- /dev/null +++ b/doc/manual/src/package-management/sharing-packages.md @@ -0,0 +1,6 @@ +# Sharing Packages Between Machines + +Sometimes you want to copy a package from one machine to another. Or, +you want to install some packages and you know that another machine +already has some or all of those packages or their dependencies. In that +case there are mechanisms to quickly copy packages between machines. diff --git a/doc/manual/src/package-management/ssh-substituter.md b/doc/manual/src/package-management/ssh-substituter.md new file mode 100644 index 000000000..6e5e258bc --- /dev/null +++ b/doc/manual/src/package-management/ssh-substituter.md @@ -0,0 +1,62 @@ +# Serving a Nix store via SSH + +You can tell Nix to automatically fetch needed binaries from a remote +Nix store via SSH. For example, the following installs Firefox, +automatically fetching any store paths in Firefox’s closure if they are +available on the server `avalon`: + +```console +$ nix-env -i firefox --substituters ssh://alice@avalon +``` + +This works similar to the binary cache substituter that Nix usually +uses, only using SSH instead of HTTP: if a store path `P` is needed, Nix +will first check if it’s available in the Nix store on `avalon`. If not, +it will fall back to using the binary cache substituter, and then to +building from source. + +> **Note** +> +> The SSH substituter currently does not allow you to enter an SSH +> passphrase interactively. Therefore, you should use `ssh-add` to load +> the decrypted private key into `ssh-agent`. + +You can also copy the closure of some store path, without installing it +into your profile, e.g. + +```console +$ nix-store -r /nix/store/m85bxg…-firefox-34.0.5 --substituters +ssh://alice@avalon +``` + +This is essentially equivalent to doing + +```console +$ nix-copy-closure --from alice@avalon +/nix/store/m85bxg…-firefox-34.0.5 +``` + +You can use SSH’s *forced command* feature to set up a restricted user +account for SSH substituter access, allowing read-only access to the +local Nix store, but nothing more. For example, add the following lines +to `sshd_config` to restrict the user `nix-ssh`: + + Match User nix-ssh + AllowAgentForwarding no + AllowTcpForwarding no + PermitTTY no + PermitTunnel no + X11Forwarding no + ForceCommand nix-store --serve + Match All + +On NixOS, you can accomplish the same by adding the following to your +`configuration.nix`: + +```nix +nix.sshServe.enable = true; +nix.sshServe.keys = [ "ssh-dss AAAAB3NzaC1k... bob@example.org" ]; +``` + +where the latter line lists the public keys of users that are allowed to +connect. |