Getting started
Installation
Flakes
To install nono.nix using flakes, add it to your flake inputs:
# flake.nix
{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
inputs.nono-nix.url = "gitlab:jhebden/nono.nix";
outputs = { nixpkgs, nono-nix, ... }: {
# ...
};
}
nono.nix requires pkgs.nono, which is available in nixpkgs unstable (Linux 5.13+ for Landlock, 6.7+ for per-port network rules).
callPackage
To install nono.nix using a different dependency manager like
niv, you can use pkgs.callPackage:
let
sources = import ./nix/sources.nix;
pkgs = import sources.nixpkgs {};
nono-nix = pkgs.callPackage sources."nono.nix" {};
nono = nono-nix.nono pkgs;
in
# ...
Initializing
The core of nono.nix is a nono function that wraps derivations in a
kernel-enforced sandbox. To set it up, initialize the library with an
instantiated nixpkgs.
Call nono-nix.lib.nono for a basic setup, or nono-nix.lib.extend for
advanced configuration.
Basic configuration
pkgs = import nixpkgs { system = "x86_64-linux"; };
nono = nono-nix.lib.nono pkgs;
Advanced configuration
Use nono-nix.lib.extend to set additional options:
pkgs = import nixpkgs { system = "x86_64-linux"; };
nono = nono-nix.lib.extend {
inherit pkgs;
# Other configuration options here...
};
For a full list of options see Advanced Configuration.
Usage
Once you have an initialized nono function, it takes the
following positional arguments:
- name: (String) — the nix store name of the wrapper script.
- executable to wrap: (String or Derivation) — the program to sandbox. Can
be a derivation like
pkgs.hello, or a string path like"${pkgs.hello}/bin/hello". A derivation is passed tolib.getExe. - permissions: (List of Permissions) — controls what the sandbox can
access. By default the wrapped program runs with very limited permissions;
use combinators here to grant what it needs. If this argument is a function,
nono.combinatorsis passed in and the return value is used.
Overlays
You can sandbox packages in a nixpkgs overlay using nono-nix.lib.mkOverlay.
This takes an attribute set with prev, final, and packages (a function
from combinators to {packageName = permissions}).
All Advanced Configuration options can be passed
into mkOverlay as well.
Example:
nonoOverlay = final: prev: nono-nix.lib.mkOverlay {
inherit final prev;
packages = combinators: with combinators; {
nodejs = [ network ];
firefox = [ network gui gpu ];
};
};
pkgs = import nixpkgs {
system = "x86_64-linux";
overlays = [ nonoOverlay ];
};
Each overlaid package gets .jailed and .unjailed variants:
{
environment.systemPackages = [
pkgs.firefox # sandboxed (default)
pkgs.firefox.jailed # sandboxed (explicit)
pkgs.firefox.unjailed # original
];
}
Examples
Provide nono.nix as a module arg in a NixOS configuration
# flake.nix
{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
inputs.nono-nix.url = "gitlab:jhebden/nono.nix";
outputs = { nixpkgs, nono-nix, ... }: {
nixosConfigurations.my-host = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
({ pkgs, ... }: { _module.args.nono = nono-nix.lib.nono pkgs; })
({ nono, pkgs, ... }: {
environment.systemPackages = [
(nono "sandboxed-hello" pkgs.hello [])
];
})
];
};
};
}
Sandbox a flake package
# flake.nix
{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
inputs.nono-nix.url = "gitlab:jhebden/nono.nix";
outputs = { nixpkgs, nono-nix, ... }: {
packages.x86_64-linux =
let
pkgs = import nixpkgs { system = "x86_64-linux"; };
nono = nono-nix.lib.nono pkgs;
in {
my-sandboxed-package = nono "sandboxed-hello" pkgs.hello [];
};
};
}