Nixpkgs: chrootenv: buildFHSUserEnv doesn't work inside sandbox

Created on 1 Nov 2017  Â·  4Comments  Â·  Source: NixOS/nixpkgs

Issue description

buildFHSUserEnv doesn't work inside sandbox. It can sometimes be useful to build, or unpack something in an environment that has a lot of assumptions (say, self-extracting checksummed executable, or build system that expects FHS-compliant paths).

Steps to reproduce

Given /etc/nixos/configuration.nix containing:

nix.useSandbox = true;

Given example.nix:

{ stdenv, buildFHSUserEnv }:

let
  buildEnv = buildFHSUserEnv {
    name = "example-build-env";
    runScript = "echo hello";
    targetPkgs = pkgs: [];
  };
in

stdenv.mkDerivation {
  name = "example";
  unpackPhase = ":";
  buildPhase = "${buildEnv}/bin/${buildEnv.name}";
  installPhase = "ln -s ${buildEnv} $out";
}
$ nix-build -E "with import <nixpkgs> {}; callPackage ./example.nix {}"
these derivations will be built:
  /nix/store/dm11jjsk39lh8lhi8l88pzvvw85d5c3h-example.drv
building path(s) ‘/nix/store/mq3nlfsalghxj87v41yc4wvkm8196mzs-example’
unpacking sources
patching sources
configuring
no configure script, doing nothing
building
/nix/store/iwxs4nwk80arwkvqdjqcy74r34wcg3wl-chroot-user:45:in `block in make_fcall': No such file or directory (Errno::ENOENT)
    from /nix/store/iwxs4nwk80arwkvqdjqcy74r34wcg3wl-chroot-user:131:in `block in <main>'
    from /nix/store/iwxs4nwk80arwkvqdjqcy74r34wcg3wl-chroot-user:128:in `each'
    from /nix/store/iwxs4nwk80arwkvqdjqcy74r34wcg3wl-chroot-user:128:in `<main>'
builder for ‘/nix/store/dm11jjsk39lh8lhi8l88pzvvw85d5c3h-example.drv’ failed with exit code 1

Technical details

  • System: 18.03pre118631.66b63d2f5a (Impala)
  • Nix version: 1.11.15
  • Nixpkgs version: e2edccae47dc4972ec16bdeb6eb5374f7631fea8
  • Sandboxing enabled: yes

/cc @abbradar

Most helpful comment

I have noticed the same. I came up with this simpler FHS environment to run Altera Quartus installer on NixOS with sandbox build:

 setup-chroot-and-exec = writeScript "setup-chroot-and-exec"
    (''
      #!${bash}/bin/sh
      chrootdir=chroot  # relative to the current directory
      mkdir -p "$chrootdir"/host
      mkdir -p "$chrootdir"/proc
      mkdir -p "$chrootdir"/nix
      mkdir -p "$chrootdir"/tmp
      mkdir -p "$chrootdir"/dev
      mkdir -p "$chrootdir"/lib
      mkdir -p "$chrootdir"/lib64
      mkdir -p "$chrootdir"/bin
      ${utillinux}/bin/mount --rbind /     "$chrootdir"/host
      ${utillinux}/bin/mount --rbind /proc "$chrootdir"/proc
      ${utillinux}/bin/mount --rbind /nix  "$chrootdir"/nix
      ${utillinux}/bin/mount --rbind /tmp  "$chrootdir"/tmp
      ${utillinux}/bin/mount --rbind /dev  "$chrootdir"/dev
    '' + (if is32bitPackage then ''
      ${utillinux}/bin/mount --rbind "${glibc_lib32_for_installer}"/lib "$chrootdir"/lib
    '' else ''
      ${utillinux}/bin/mount --rbind "${glibc_lib_for_installer}"/lib64 "$chrootdir"/lib64
    '') + ''
      ${utillinux}/bin/mount --rbind "${bash}"/bin "$chrootdir"/bin
      chroot "$chrootdir" "$@"
    '');

  # buildFHSUserEnv from nixpkgs tries to mount a few directories that are not
  # available in sandboxed Nix builds (/sys, /run), hence we have our own
  # slimmed down variant.
  run-in-fhs-env = writeScript "run-in-fhs-env"
    ''
      #!${bash}/bin/sh
      if [ "$*" = "" ]; then
          echo "Usage: run-in-fhs-env <COMMAND> [ARGS...]"
          exit 1
      fi
      "${utillinux}/bin/unshare" -r -U -m "${setup-chroot-and-exec}" "$@"
    '';

All 4 comments

I think at this point you would need to use the vmtools to do this. See e.g. buildRPM.

I have noticed the same. I came up with this simpler FHS environment to run Altera Quartus installer on NixOS with sandbox build:

 setup-chroot-and-exec = writeScript "setup-chroot-and-exec"
    (''
      #!${bash}/bin/sh
      chrootdir=chroot  # relative to the current directory
      mkdir -p "$chrootdir"/host
      mkdir -p "$chrootdir"/proc
      mkdir -p "$chrootdir"/nix
      mkdir -p "$chrootdir"/tmp
      mkdir -p "$chrootdir"/dev
      mkdir -p "$chrootdir"/lib
      mkdir -p "$chrootdir"/lib64
      mkdir -p "$chrootdir"/bin
      ${utillinux}/bin/mount --rbind /     "$chrootdir"/host
      ${utillinux}/bin/mount --rbind /proc "$chrootdir"/proc
      ${utillinux}/bin/mount --rbind /nix  "$chrootdir"/nix
      ${utillinux}/bin/mount --rbind /tmp  "$chrootdir"/tmp
      ${utillinux}/bin/mount --rbind /dev  "$chrootdir"/dev
    '' + (if is32bitPackage then ''
      ${utillinux}/bin/mount --rbind "${glibc_lib32_for_installer}"/lib "$chrootdir"/lib
    '' else ''
      ${utillinux}/bin/mount --rbind "${glibc_lib_for_installer}"/lib64 "$chrootdir"/lib64
    '') + ''
      ${utillinux}/bin/mount --rbind "${bash}"/bin "$chrootdir"/bin
      chroot "$chrootdir" "$@"
    '');

  # buildFHSUserEnv from nixpkgs tries to mount a few directories that are not
  # available in sandboxed Nix builds (/sys, /run), hence we have our own
  # slimmed down variant.
  run-in-fhs-env = writeScript "run-in-fhs-env"
    ''
      #!${bash}/bin/sh
      if [ "$*" = "" ]; then
          echo "Usage: run-in-fhs-env <COMMAND> [ARGS...]"
          exit 1
      fi
      "${utillinux}/bin/unshare" -r -U -m "${setup-chroot-and-exec}" "$@"
    '';

@bjornfor Thanks! This looks nice, and no Ruby dependency.

BTW, just commenting out line 45 in chroot-user script (one that raises the exception) solves the issue. Probably makes sense to mount /run and /sys only if available.

Probably makes sense to mount /run and /sys only if available.

Yes, +1 for working buildFHSUserEnv in sandboxed build.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

chris-martin picture chris-martin  Â·  3Comments

copumpkin picture copumpkin  Â·  3Comments

teto picture teto  Â·  3Comments

ayyess picture ayyess  Â·  3Comments

matthiasbeyer picture matthiasbeyer  Â·  3Comments