New Base Snap: nix-base


#1

Hello Snap Friends,

I’ve started to publish a new base snap to support repackaging Nix-built applications in a snap.

Nix uses a different file structure from most applications, and has special requirements of the filesystem. In particular, the only directory it requires is /nix. The snap I’ve published looks like this, with 23 directories, and 1 file:

/snap/nix-base/current
├── bin
├── dev
├── etc
├── home
├── media
├── meta
│   └── snap.yaml
├── nix
├── proc
├── root
├── run
├── snap
├── sys
├── tmp
├── usr
│   ├── lib
│   │   └── snapd
│   └── src
└── var
    ├── lib
    │   └── snapd
    ├── log
    ├── snap
    └── tmp

Snaps building on top of this layer will provide their own /nix with a layout:

layout:
  /nix:
    bind: $SNAP/nix

Inside /nix will include the complete closure of the Snap’s dependencies.

UPDATE (jdstrand): there is a limitation in the layouts implementation that doesn’t allow toplevel directories under ‘/’ to be created. Since nix requires ‘/nix’ (as opposed to /usr/nix or similar), a base snap is needed which contains the /nix directory.


#2

@pedronis, this is a new and unique base snap where it only contains empty directories (meta/snap.yaml notwithstanding) for the required snapd mount points, plus /nix. This is needed because of the way nix operates-- @zyga and @grahamc came up with the idea that the snaps built which specify base: nix-base provide a /nix directory that has everything it needs to run and the bind layout ties them together. This all works in terms of security because the snap only executes what is in /nix (which is analgous to the snap executing anything in $SNAP) and therefore seccomp, apparmor (capabilities, signals, etc, etc) all work like normal. (Think of snaps that use base: nix-base sorta like statically linked binaries that use the bare base snap-- they need nothing else from the system or base and only use what they ship).

This snap is owned by the nix foundation and otherwise meets our base snap criteria as defined in Process for reviewing base snaps.

IMO, this is fine to approve as a base snap.


#3

If you want to support desktop applications, I would suggest also adding the following empty directories too:

  • /usr/share/fonts
  • /usr/local/share/fonts
  • /var/cache/fontconfig

The desktop interface will try to mount the host file system fonts at these points. While it can use the “writable mimic” code to add mount points where they don’t exist, having the directories there simplifies things.


#4

@jamesh Is correct. Here is the nix package of galculator transformed to a snap running on the base as described in the opening posting from @grahamc :sob:

nix-galculator-before

And the same galculator snap running on a nix-base snap that includes the fonts/fontconfig directories suggested by @jamesh :smiley:

nix-galculator-after


#5

Great! I have updated the nix-base snap:

/snap/nix-base/current
├── bin
├── dev
├── etc
├── home
├── media
├── meta
│   └── snap.yaml
├── nix
├── proc
├── root
├── run
├── snap
├── sys
├── tmp
├── usr
│   ├── lib
│   │   └── snapd
│   ├── local
│   │   └── share
│   │       └── fonts
│   ├── share
│   │   └── fonts
│   └── src
└── var
    ├── cache
    │   └── fontconfig
    ├── lib
    │   └── snapd
    ├── log
    ├── snap
    └── tmp

This is the version which produced the nice screenshot above ^

I think this is ready to go? Thank you for the tip on those directories!


#6

Thanks for this. The review-tools recently added checks for base snap mountpoints and these were omitted there too. I’ll adjust.


#7

Given the approach and fundamentals of nix and the limitations of layouts vs the top level/root directory, this seems reasonable.

Just the usual reminder that once in use things can be added to the base but not removed. If for some reason a new version with different layouts would be needed it would need to be called nix-base-YYMM or something like that.


#8

Yes, we discussed this and how to name it. @grahamc said this has been stable for more than a decade so decided ‘nix-base’ was sufficient for now.


#9

:+1: Yeah, we talked about that at the conference. The Nix layout (just /nix) has been stable since 2003 when it was first created. In that sense, it is almost unimaginable that we would create a different top level directory and still call it Nix.


#10

It has been approved! Thank you! My first snap based on this has been published, a tech demo building a (mostly) working Firefox:

snap install --edge grahamc-nix-snap-example-firefox

Here is the Nix expression I used:

let
  pkgs = import ./patched-nixpkgs {};
in pkgs.snapTools.makeSnap {
  meta = {
    name = "grahamc-nix-snap-example-firefox";
    summary = pkgs.firefox.meta.description;
    architectures = [ "amd64" ];
    apps.firefox = {
      command = "${pkgs.firefox}/bin/firefox";
      plugs = [
        "pulseaudio"
        "camera"
        "browser-support"
        "avahi-observe"
        "cups-control"
        "desktop"
        "desktop-legacy"
        "gsettings"
        "home"
        "network"
        "mount-observe"
        "removable-media"
        "x11"
      ];
    };
    confinement = "strict";
  };
}

I’m finishing up the patches needed by Nixpkgs, and then will push it as a PR and write some docs and post a blog about it.