From 7674f61b17d15808dc68a3ef70c041307cff3c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Tue, 3 Mar 2026 18:10:55 +0100 Subject: [PATCH 01/22] Re-enable nix-wrap libcap is no longer broken upstream Reviewed-by: Rodrigo Arias Mallo --- overlay.nix | 4 +--- pkgs/nix-wrap/default.nix | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/overlay.nix b/overlay.nix index 0683b8b8..42a7ccb0 100644 --- a/overlay.nix +++ b/overlay.nix @@ -39,9 +39,7 @@ let nanos6Debug = final.nanos6.override { enableDebug = true; }; nixtools = callPackage ./pkgs/nixtools/default.nix { }; nixgen = callPackage ./pkgs/nixgen/default.nix { }; - # Broken because of pkgsStatic.libcap - # See: https://github.com/NixOS/nixpkgs/pull/268791 - #nix-wrap = callPackage ./pkgs/nix-wrap/default.nix { }; + nix-wrap = callPackage ./pkgs/nix-wrap/default.nix { }; nodes = callPackage ./pkgs/nodes/default.nix { }; nosv = callPackage ./pkgs/nosv/default.nix { }; openmp = callPackage ./pkgs/llvm-ompss2/openmp.nix { monorepoSrc = final.clangOmpss2Unwrapped.src; version = final.clangOmpss2Unwrapped.version; }; diff --git a/pkgs/nix-wrap/default.nix b/pkgs/nix-wrap/default.nix index 8d74a221..3f69ae96 100644 --- a/pkgs/nix-wrap/default.nix +++ b/pkgs/nix-wrap/default.nix @@ -14,7 +14,7 @@ let nixConfDir = "share"; nix_wrap_sh = writeText "nix-wrap.sh" '' #!/usr/bin/env bash - # + busybox_bin="${nixPrefix}${busybox}/bin" bubblewrap_bin="${nixPrefix}/${bubblewrap}/bin" @@ -69,7 +69,6 @@ stdenv.mkDerivation rec { name = "nix-wrap"; buildInputs = [ bashInteractive - busybox nix ]; src = null; @@ -92,7 +91,6 @@ stdenv.mkDerivation rec { homepage = null; description = "nix bubblewrap wrapper"; maintainers = [ ]; - broken = true; platforms = lib.platforms.linux; license = lib.licenses.mit; }; -- 2.51.2 From 7195ca4cb6db8f9bdfa09905637add902633d7d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Wed, 4 Mar 2026 16:38:56 +0100 Subject: [PATCH 02/22] Add nix-portable repo: https://github.com/DavHau/nix-portable rev: 91122e3d94ba51d7d83fe990fa81d3de0968fb32 Reviewed-by: Rodrigo Arias Mallo --- overlay.nix | 9 + pkgs/nix-portable/default.nix | 665 ++++++++++++++++++++++++++++++++++ 2 files changed, 674 insertions(+) create mode 100644 pkgs/nix-portable/default.nix diff --git a/overlay.nix b/overlay.nix index 42a7ccb0..1be5bdf1 100644 --- a/overlay.nix +++ b/overlay.nix @@ -39,6 +39,15 @@ let nanos6Debug = final.nanos6.override { enableDebug = true; }; nixtools = callPackage ./pkgs/nixtools/default.nix { }; nixgen = callPackage ./pkgs/nixgen/default.nix { }; + nix-portable = callPackage ./pkgs/nix-portable/default.nix { + busybox = final.pkgsStatic.busybox; + bwrap = final.pkgsStatic.bubblewrap; + gnutar = final.pkgsStatic.gnutar; + perl = final.pkgsBuildBuild.perl; + xz = final.pkgsStatic.xz; + zstd = final.pkgsStatic.zstd; + bashInteractive = final.pkgsStatic.bashInteractive; + }; nix-wrap = callPackage ./pkgs/nix-wrap/default.nix { }; nodes = callPackage ./pkgs/nodes/default.nix { }; nosv = callPackage ./pkgs/nosv/default.nix { }; diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix new file mode 100644 index 00000000..8034a6ef --- /dev/null +++ b/pkgs/nix-portable/default.nix @@ -0,0 +1,665 @@ +with builtins; +{ + bwrap, + nix, + proot, + unzip, + zip, + unixtools, + stdenv, + buildPackages, + upx, + + busybox, + cacert ? pkgs.cacert, + compression ? "zstd -19 -T0", + gnutar ? pkgs.pkgsStatic.gnutar, + lib ? pkgs.lib, + perl ? pkgs.perl, + pkgs ? import {}, + xz ? pkgs.pkgsStatic.xz, + zstd ? pkgs.pkgsStatic.zstd, + nixStatic, + # hardcode executable to run. Useful when creating a bundle. + bundledPackage ? null, + ... +}@inp: +with lib; +let + + pname = + if bundledPackage == null + then "nix-portable" + else lib.getName bundledPackage; + + bundledExe = lib.getExe bundledPackage; + + nixpkgsSrc = pkgs.path; + + # TODO: git could be more minimal via: + # perlSupport=false; guiSupport=false; nlsSupport=false; + gitAttribute = "gitMinimal"; + git = pkgs."${gitAttribute}"; + + maketar = targets: + let + closureInfo = buildPackages.closureInfo { rootPaths = targets; }; + in + stdenv.mkDerivation { + name = "nix-portable-store-tarball"; + nativeBuildInputs = [ perl zstd ]; + exportReferencesGraph = map (x: [("closure-" + baseNameOf x) x]) targets; + buildCommand = '' + storePaths=$(cat ${closureInfo}/store-paths) + mkdir $out + echo $storePaths > $out/index + cp -r ${closureInfo} $out/closureInfo + + tar -cf - \ + --owner=0 --group=0 --mode=u+rw,uga+r \ + --hard-dereference \ + $storePaths | ${compression} > $out/tar + ''; + }; + + packStaticBin = binPath: let + binName = (last (splitString "/" binPath)); in + pkgs.runCommand + binName + { nativeBuildInputs = [ upx ]; } + '' + mkdir -p $out/bin + upx -9 -o $out/bin/${binName} ${binPath} + ''; + + installBin = pkg: bin: '' + unzip -qqoj "\$self" ${ lib.removePrefix "/" "${pkg}/bin/${bin}"} -d \$dir/bin + chmod +wx \$dir/bin/${bin}; + ''; + + caBundleZstd = pkgs.runCommand "cacerts" {} "cat ${cacert}/etc/ssl/certs/ca-bundle.crt | ${inp.zstd}/bin/zstd -19 > $out"; + + bwrap = packStaticBin "${inp.bwrap}/bin/bwrap"; + nixStatic = packStaticBin "${inp.nixStatic}/bin/nix"; + proot = packStaticBin "${inp.proot}/bin/proot"; + zstd = packStaticBin "${inp.zstd}/bin/zstd"; + + # the default nix store contents to extract when first used + storeTar = maketar ([ cacert nix nixpkgsSrc ] ++ lib.optional (bundledPackage != null) bundledPackage); + + + # The runtime script which unpacks the necessary files to $HOME/.nix-portable + # and then executes nix via proot or bwrap + # Some shell expressions will be evaluated at build time and some at run time. + # Variables/expressions escaped via `\$` will be evaluated at run time + runtimeScript = '' + #!/usr/bin/env bash + + set -eo pipefail + + start=\$(date +%s%N) # start time in nanoseconds + + # dump environment on exit if debug is enabled + if [ -n "\$NP_DEBUG" ] && [ "\$NP_DEBUG" -ge 1 ]; then + trap "declare -p > \''${TMPDIR:-/tmp}/np_env" EXIT + fi + + # there seem to be less issues with proot when disabling seccomp + # though on android it is needed + if [ -n "\$TERMUX_VERSION" ]; then + unset LD_PRELOAD + NP_RUNTIME=\''${NP_RUNTIME:-proot} + export PROOT_TMP_DIR="\$TMPDIR/proot" + mkdir -p "\$PROOT_TMP_DIR" + else + export PROOT_NO_SECCOMP=\''${PROOT_NO_SECCOMP:-1} + fi + + set -e + if [ -n "\$NP_DEBUG" ] && [ "\$NP_DEBUG" -ge 2 ]; then + set -x + fi + + # &3 is our error out which we either forward to &2 or to /dev/null + # depending on the setting + if [ -n "\$NP_DEBUG" ] && [ "\$NP_DEBUG" -ge 1 ]; then + debug(){ + echo \$@ || true + } + exec 3>&2 + else + debug(){ + true + } + exec 3>/dev/null + fi + + # to reference this script's file + self="\$(realpath \''${BASH_SOURCE[0]})" + + # fingerprint will be inserted by builder + fingerprint="_FINGERPRINT_PLACEHOLDER_" + + # user specified location for program files and nix store + [ -z "\$NP_LOCATION" ] && NP_LOCATION="\$HOME" + NP_LOCATION="\$(readlink -f "\$NP_LOCATION")" + dir="\$NP_LOCATION/.nix-portable" + store="\$dir/nix/store" + # create /nix/var/nix to prevent nix from falling back to chroot store. + mkdir -p \$dir/{bin,nix/var/nix,nix/store} + # sanitize the tmpbin directory + rm -rf "\$dir/tmpbin" + # create a directory to hold executable symlinks for overriding + mkdir -p "\$dir/tmpbin" + + # create minimal drv file for nix to spawn a nix shell + echo 'builtins.derivation {name="foo"; builder="/bin/sh"; args = ["-c" "echo hello \> \\\$out"]; system=builtins.currentSystem;}' > "\$dir/mini-drv.nix" + + # the fingerprint being present inside a file indicates that + # this version of nix-portable has already been initialized + if test -e \$dir/conf/fingerprint && [ "\$(cat \$dir/conf/fingerprint)" == "\$fingerprint" ]; then + newNPVersion=false + else + newNPVersion=true + fi + + # Nix portable ships its own nix.conf + export NIX_CONF_DIR=\$dir/conf/ + + NP_CONF_SANDBOX=\''${NP_CONF_SANDBOX:-false} + NP_CONF_STORE=\''${NP_CONF_STORE:-auto} + + + recreate_nix_conf(){ + mkdir -p "\$NIX_CONF_DIR" + rm -f "\$NIX_CONF_DIR/nix.conf" + + # static config + echo "build-users-group = " >> \$dir/conf/nix.conf + echo "experimental-features = nix-command flakes" >> \$dir/conf/nix.conf + echo "ignored-acls = security.selinux system.nfs4_acl" >> \$dir/conf/nix.conf + echo "sandbox-paths = /bin/sh=\$dir/busybox/bin/busybox" >> \$dir/conf/nix.conf + + # configurable config + echo "sandbox = \$NP_CONF_SANDBOX" >> \$dir/conf/nix.conf + echo "store = \$NP_CONF_STORE" >> \$dir/conf/nix.conf + } + + + ### install files + + PATH_OLD="\$PATH" + + # as soon as busybox is unpacked, restrict PATH to busybox to ensure reproducibility of this script + # only unpack binaries if necessary + if [ "\$newNPVersion" == "false" ]; then + + debug "binaries already installed" + # our busybox does not run on termux, therefore we suffix the PATH only on termux + export PATH="\''${TERMUX_VERSION:+\$PATH:}\$dir/busybox/bin" + + else + + debug "installing files" + + mkdir -p \$dir/emptyroot + + # install busybox + mkdir -p \$dir/busybox/bin + (base64 -d> "\$dir/busybox/bin/busybox" && chmod +x "\$dir/busybox/bin/busybox") << END + $(cat ${busybox}/bin/busybox | base64) + END + busyBins="${toString (attrNames (filterAttrs (d: type: type == "symlink") (readDir "${inp.busybox}/bin")))}" + for bin in \$busyBins; do + [ ! -e "\$dir/busybox/bin/\$bin" ] && ln -s busybox "\$dir/busybox/bin/\$bin" + done + + # our busybox does not run on termux, therefore we suffix the PATH only on termux + export PATH="\''${TERMUX_VERSION:+\$PATH:}\$dir/busybox/bin" + + # install other binaries + ${installBin zstd "zstd"} + ${installBin proot "proot"} + ${installBin bwrap "bwrap"} + ${installBin nixStatic "nix"} + + # install ssl cert bundle + unzip -poj "\$self" ${ lib.removePrefix "/" "${caBundleZstd}"} | \$dir/bin/zstd -d > \$dir/ca-bundle.crt + + recreate_nix_conf + fi + + + + ### setup SSL + # find ssl certs or use from nixpkgs + debug "figuring out ssl certs" + if [ -z "\$SSL_CERT_FILE" ]; then + debug "SSL_CERT_FILE not defined. trying to find certs automatically" + if [ -e /etc/ssl/certs/ca-bundle.crt ]; then + export SSL_CERT_FILE=\$(realpath /etc/ssl/certs/ca-bundle.crt) + debug "found /etc/ssl/certs/ca-bundle.crt with real path \$SSL_CERT_FILE" + elif [ -e /etc/ssl/certs/ca-certificates.crt ]; then + export SSL_CERT_FILE=\$(realpath /etc/ssl/certs/ca-certificates.crt) + debug "found /etc/ssl/certs/ca-certificates.crt with real path \$SSL_CERT_FILE" + elif [ ! -e /etc/ssl/certs ]; then + debug "/etc/ssl/certs does not exist. Will use certs from nixpkgs." + export SSL_CERT_FILE=\$dir/ca-bundle.crt + else + debug "certs seem to reside in /etc/ssl/certs. No need to set up anything" + fi + fi + if [ -n "\$SSL_CERT_FILE" ]; then + sslBind="\$(realpath \$SSL_CERT_FILE) \$dir/ca-bundle.crt" + export SSL_CERT_FILE="\$dir/ca-bundle.crt" + else + sslBind="/etc/ssl /etc/ssl" + fi + + + + ### detecting existing git installation + # we need to install git inside the wrapped environment + # unless custom git executable path is specified in NP_GIT, + # since the existing git might be incompatible to Nix (e.g. v1.x) + if [ -n "\$NP_GIT" ]; then + doInstallGit=false + ln -s "\$NP_GIT" "\$dir/tmpbin/git" + else + doInstallGit=true + fi + + + + storePathOfFile(){ + file=\$(realpath \$1) + sPath="\$(echo \$file | awk -F "/" 'BEGIN{OFS="/";}{print \$2,\$3,\$4}')" + echo "/\$sPath" + } + + + collectBinds(){ + ### gather paths to bind for proot + # we cannot bind / to / without running into a lot of trouble, therefore + # we need to collect all top level directories and bind them inside an empty root + + # for termux a fallback is needed as enumerating top level directories fails + if ! pathsTopLevel="\$(find / -mindepth 1 -maxdepth 1 -not -name nix -not -name dev 2>&3)"; then + debug "Error: unable to list top level directories. Falling back to default binds." + pathsTopLevel="/etc /proc" + fi + + + toBind="" + for p in \$pathsTopLevel; do + if [ -e "\$p" ]; then + real=\$(realpath \$p) + if [ -e "\$real" ]; then + if [[ "\$real" == /nix/store/* ]]; then + storePath=\$(storePathOfFile \$real) + toBind="\$toBind \$storePath \$storePath" + else + toBind="\$toBind \$real \$p" + fi + fi + fi + done + + + # TODO: add /var/run/dbus/system_bus_socket + paths="/etc/host.conf /etc/hosts /etc/hosts.equiv /etc/mtab /etc/netgroup /etc/networks /etc/passwd /etc/group /etc/nsswitch.conf /etc/resolv.conf /etc/localtime \$HOME" + + for p in \$paths; do + if [ -e "\$p" ]; then + real=\$(realpath \$p) + if [ -e "\$real" ]; then + if [[ "\$real" == /nix/store/* ]]; then + storePath=\$(storePathOfFile \$real) + toBind="\$toBind \$storePath \$storePath" + else + toBind="\$toBind \$real \$real" + fi + fi + fi + done + + # if we're on a nixos, the /bin/sh symlink will point + # to a /nix/store path which doesn't exit inside the wrapped env + # we fix this by binding busybox/bin to /bin + if test -s /bin/sh && [[ "\$(realpath /bin/sh)" == /nix/store/* ]]; then + toBind="\$toBind \$dir/busybox/bin /bin" + fi + + # provide /bin/sh via the shipped busybox + toBind="\$toBind \$dir/busybox/bin/busybox /bin/sh" + + # on termux, make sure termux packages still work inside the nix-portable environment + if [ -n "\$TERMUX_VERSION" ]; then + # binds required so termux native packages still run inside the nix-portable sandbox + # TODO: this doesn't quite work yet. debug and fix + toBind="\$toBind /system/lib64/libc.so /system/lib64/libc.so" + toBind="\$toBind /system/lib64/ld-android.so /system/lib64/ld-android.so" + toBind="\$toBind /system/lib64/libdl.so /system/lib64/libdl.so" + toBind="\$toBind /system/bin /system/bin" + toBind="\$toBind /system/lib64 /system/lib64" + toBind="\$toBind /apex/com.android.runtime/bin /apex/com.android.runtime/bin" + toBind="\$toBind /linkerconfig/ld.config.txt /linkerconfig/ld.config.txt" + toBind="\$toBind \$dir/ca-bundle.crt /etc/ssl/certs/ca-certificates.crt" + toBind="\$toBind \$(realpath \$HOME/../usr/etc/resolv.conf) /etc/resolv.conf" + fi + + } + + + makeBindArgs(){ + arg=\$1; shift + sep=\$1; shift + binds="" + while :; do + if [ -n "\$1" ]; then + from="\$1"; shift + to="\$1"; shift || { echo "no bind destination provided for \$from!"; exit 3; } + binds="\$binds \$arg \$from\$sep\$to"; + else + break + fi + done + } + + + + ### select container runtime + debug "figuring out which runtime to use" + [ -z "\$NP_BWRAP" ] && NP_BWRAP=\$(PATH="\$PATH_OLD:\$PATH" which bwrap 2>/dev/null) || true + [ -z "\$NP_BWRAP" ] && NP_BWRAP=\$dir/bin/bwrap + debug "bwrap executable: \$NP_BWRAP" + [ -z "\$NP_NIX" ] && NP_NIX=\$dir/bin/nix + debug "nix executable: \$NP_NIX" + [ -z "\$NP_PROOT" ] && NP_PROOT=\$(PATH="\$PATH_OLD:\$PATH" which proot 2>/dev/null) || true + [ -z "\$NP_PROOT" ] && NP_PROOT=\$dir/bin/proot + debug "proot executable: \$NP_PROOT" + debug "testing all available runtimes..." + if [ -z "\$NP_RUNTIME" ]; then + # read last automatic selected runtime from disk + if [ "\$newNPVersion" == "true" ]; then + debug "removing cached auto selected runtime" + rm -f "\$dir/conf/last_auto_runtime" + fi + if [ -f "\$dir/conf/last_auto_runtime" ]; then + last_auto_runtime="\$(cat "\$dir/conf/last_auto_runtime")" + else + last_auto_runtime= + fi + debug "last auto selected runtime: \$last_auto_runtime" + if [ "\$last_auto_runtime" != "" ]; then + NP_RUNTIME="\$last_auto_runtime" + # check if nix --store works + elif \\ + debug "testing nix --store" \\ + && mkdir -p \$dir/tmp/ \\ + && touch \$dir/tmp/testfile \\ + && "\$NP_NIX" --store "\$dir/tmp/__store" shell -f "\$dir/mini-drv.nix" -c "\$dir/bin/nix" store add-file --store "\$dir/tmp/__store" "\$dir/tmp/testfile" >/dev/null 2>&3; then + chmod -R +w \$dir/tmp/__store + rm -r \$dir/tmp/__store + debug "nix --store works on this system -> will use nix as runtime" + NP_RUNTIME=nix + # check if bwrap works properly + elif \\ + debug "nix --store failed -> testing bwrap" \\ + && \$NP_BWRAP --bind \$dir/emptyroot / --bind \$dir/ /nix --bind \$dir/busybox/bin/busybox "\$dir/true" "\$dir/true" 2>&3 ; then + debug "bwrap seems to work on this system -> will use bwrap" + NP_RUNTIME=bwrap + else + debug "bwrap doesn't work on this system -> will use proot" + NP_RUNTIME=proot + fi + echo -n "\$NP_RUNTIME" > "\$dir/conf/last_auto_runtime" + else + debug "runtime selected via NP_RUNTIME: \$NP_RUNTIME" + fi + debug "NP_RUNTIME: \$NP_RUNTIME" + if [ "\$NP_RUNTIME" == "nix" ]; then + run="\$NP_NIX shell -f \$dir/mini-drv.nix -c" + export PATH="\$PATH:\$store${lib.removePrefix "/nix/store" nix}/bin" + NP_CONF_STORE="\$dir" + recreate_nix_conf + elif [ "\$NP_RUNTIME" == "bwrap" ]; then + collectBinds + makeBindArgs --bind " " \$toBind \$sslBind + run="\$NP_BWRAP \$BWRAP_ARGS \\ + --bind \$dir/emptyroot /\\ + --dev-bind /dev /dev\\ + --bind \$dir/nix /nix\\ + \$binds" + # --bind \$dir/busybox/bin/busybox /bin/sh\\ + else + # proot + collectBinds + makeBindArgs -b ":" \$toBind \$sslBind + run="\$NP_PROOT \$PROOT_ARGS\\ + -r \$dir/emptyroot\\ + -b /dev:/dev\\ + -b \$dir/nix:/nix\\ + \$binds" + # -b \$dir/busybox/bin/busybox:/bin/sh\\ + fi + debug "base command will be: \$run" + + + + ### setup environment + export NIX_PATH="\$dir/channels:nixpkgs=\$dir/channels/nixpkgs" + mkdir -p \$dir/channels + [ -h \$dir/channels/nixpkgs ] || ln -s ${nixpkgsSrc} \$dir/channels/nixpkgs + + + ### install nix store + # Install all the nix store paths necessary for the current nix-portable version + # We only unpack missing store paths from the tar archive. + index="$(cat ${storeTar}/index)" + + export missing=\$( + for path in \$index; do + basepath=\$(basename \$path) + if [ ! -e \$store/\$basepath ]; then + echo "nix/store/\$basepath" + fi + done + ) + + if [ -n "\$missing" ]; then + debug "extracting missing store paths" + ( + mkdir -p \$dir/tmp \$store/ + rm -rf \$dir/tmp/* + cd \$dir/tmp + unzip -qqp "\$self" ${ lib.removePrefix "/" "${storeTar}/tar"} \ + | \$dir/bin/zstd -d \ + | tar -x \$missing --strip-components 2 + mv \$dir/tmp/* \$store/ + ) + rm -rf \$dir/tmp + fi + + if [ -n "\$missing" ]; then + debug "registering new store paths to DB" + reg="$(cat ${storeTar}/closureInfo/registration)" + cmd="\$run \$store${lib.removePrefix "/nix/store" nix}/bin/nix-store --load-db" + debug "running command: \$cmd" + echo "\$reg" | \$cmd + fi + + + ### select executable + # the executable can either be selected by + # - executing './nix-portable BIN_NAME', + # - symlinking to nix-portable, in which case the name of the symlink selects the nix executable + # Alternatively the executable can be hardcoded by specifying the argument 'executable' of nix-portable's default.nix file. + executable="${if bundledPackage == null then "" else bundledExe}" + if [ "\$executable" != "" ]; then + bin="\$executable" + debug "executable is hardcoded to: \$bin" + + elif [[ "\$(basename \$0)" == nix-portable* ]]; then\ + if [ -z "\$1" ]; then + echo "Error: please specify the nix binary to execute" + echo "Alternatively symlink against \$0" + exit 1 + elif [ "\$1" == "debug" ]; then + bin="\$(which \$2)" + shift; shift + else + bin="\$store${lib.removePrefix "/nix/store" nix}/bin/\$1" + shift + fi + # for binary selection via symlink + else + bin="\$store${lib.removePrefix "/nix/store" nix}/bin/\$(basename \$0)" + fi + + + + ### check which runtime has been used previously + if [ -f "\$dir/conf/last_runtime" ]; then + lastRuntime=\$(cat "\$dir/conf/last_runtime") + else + lastRuntime= + fi + + + + ### check if nix is functional with or without sandbox + # sandbox-fallback is not reliable: https://github.com/NixOS/nix/issues/4719 + if [ "\$newNPVersion" == "true" ] || [ "\$lastRuntime" != "\$NP_RUNTIME" ]; then + nixBin="\$(dirname \$bin)/nix" + debug "Testing if nix can build stuff without sandbox" + if ! \$run "\$nixBin" build --no-link -f "\$dir/mini-drv.nix" --option sandbox false >&3 2>&3; then + echo "Fatal error: nix is unable to build packages" + exit 1 + fi + + debug "Testing if nix sandbox is functional" + if ! \$run "\$nixBin" build --no-link -f "\$dir/mini-drv.nix" --option sandbox true >&3 2>&3; then + debug "Sandbox doesn't work -> disabling sandbox" + NP_CONF_SANDBOX=false + recreate_nix_conf + else + debug "Sandboxed builds work -> enabling sandbox" + NP_CONF_SANDBOX=true + recreate_nix_conf + fi + + fi + + + ### save fingerprint and lastRuntime + if [ "\$newNPVersion" == "true" ]; then + echo -n "\$fingerprint" > "\$dir/conf/fingerprint" + fi + if [ "\$lastRuntime" != \$NP_RUNTIME ]; then + echo -n \$NP_RUNTIME > "\$dir/conf/last_runtime" + fi + + + + ### set PATH + # restore original PATH and append busybox + export PATH="\$PATH_OLD:\$dir/busybox/bin" + # apply overriding executable paths in \$dir/tmpbin/ + export PATH="\$dir/tmpbin:\$PATH" + + + + ### install git via nix, if git installation is not in /nix path + if \$doInstallGit && [ ! -e \$store${lib.removePrefix "/nix/store" git.out} ] ; then + echo "Installing git. Disable this by specifying the git executable path with 'NP_GIT'" + \$run \$store${lib.removePrefix "/nix/store" nix}/bin/nix build --impure --no-link --expr " + (import ${nixpkgsSrc} {}).${gitAttribute}.out + " + else + debug "git already installed or manually specified" + fi + + ### override the possibly existing git in the environment with the installed one + # excluding the case NP_GIT is set. + if \$doInstallGit; then + export PATH="${git.out}/bin:\$PATH" + fi + + + ### print elapsed time + end=\$(date +%s%N) # end time in nanoseconds + # time elapsed in millis with two decimal places + + # print stats about initialization time of nix-portable + # skipt for termux, as it doesn't have bc installed + if [ -z "\$TERMUX_VERSION" ]; then + elapsed=\$(echo "scale=2; (\$end - \$start)/1000000" | bc) + debug "Time to initialize nix-portable: \$elapsed millis" + fi + + + ### run commands + [ -z "\$NP_RUN" ] && NP_RUN="\$run" + if [ "\$NP_RUNTIME" == "proot" ]; then + debug "running command: \$NP_RUN \$bin \$@" + exec \$NP_RUN \$bin "\$@" + else + cmd="\$NP_RUN \$bin \$@" + debug "running command: \$cmd" + exec \$NP_RUN \$bin "\$@" + fi + exit + ''; + + runtimeScriptEscaped = replaceStrings ["\""] ["\\\""] runtimeScript; + + nixPortable = pkgs.runCommand pname {nativeBuildInputs = [unixtools.xxd unzip];} '' + mkdir -p $out/bin + echo "${runtimeScriptEscaped}" > $out/bin/nix-portable.zip + xxd $out/bin/nix-portable.zip | tail + + sizeA=$(printf "%08x" `stat -c "%s" $out/bin/nix-portable.zip` | tac -rs ..) + echo 504b 0304 0000 0000 0000 0000 0000 0000 | xxd -r -p >> $out/bin/nix-portable.zip + echo 0000 0000 0000 0000 0000 0200 0000 4242 | xxd -r -p >> $out/bin/nix-portable.zip + + sizeB=$(printf "%08x" `stat -c "%s" $out/bin/nix-portable.zip` | tac -rs ..) + echo 504b 0102 0000 0000 0000 0000 0000 0000 | xxd -r -p >> $out/bin/nix-portable.zip + echo 0000 0000 0000 0000 0000 0000 0200 0000 | xxd -r -p >> $out/bin/nix-portable.zip + echo 0000 0000 0000 0000 0000 $sizeA 4242 | xxd -r -p >> $out/bin/nix-portable.zip + + echo 504b 0506 0000 0000 0000 0100 3000 0000 | xxd -r -p >> $out/bin/nix-portable.zip + echo $sizeB 0000 0000 0000 0000 0000 0000 | xxd -r -p >> $out/bin/nix-portable.zip + + unzip -vl $out/bin/nix-portable.zip + + zip="${zip}/bin/zip -0" + $zip $out/bin/nix-portable.zip ${bwrap}/bin/bwrap + $zip $out/bin/nix-portable.zip ${nixStatic}/bin/nix + $zip $out/bin/nix-portable.zip ${proot}/bin/proot + $zip $out/bin/nix-portable.zip ${zstd}/bin/zstd + $zip $out/bin/nix-portable.zip ${storeTar}/tar + $zip $out/bin/nix-portable.zip ${caBundleZstd} + + # create fingerprint + fp=$(sha256sum $out/bin/nix-portable.zip | cut -d " " -f 1) + sed -i "s/_FINGERPRINT_PLACEHOLDER_/$fp/g" $out/bin/nix-portable.zip + # fix broken zip header due to manual modification + ${zip}/bin/zip -F $out/bin/nix-portable.zip --out $out/bin/nix-portable-fixed.zip + + rm $out/bin/nix-portable.zip + executable=${if bundledPackage == null then "" else bundledExe} + if [ "$executable" == "" ]; then + target="$out/bin/nix-portable" + else + target="$out/bin/$(basename "$executable")" + fi + mv $out/bin/nix-portable-fixed.zip "$target" + chmod +x "$target" + ''; +in +nixPortable.overrideAttrs (prev: { + passthru = (prev.passthru or {}) // { + inherit bwrap proot; + }; +}) -- 2.51.2 From 1eaca98618c05b15689da6d194178b4874b4b900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Wed, 4 Mar 2026 16:42:49 +0100 Subject: [PATCH 03/22] Fix nix-portable pkgStatic symlink handling Reviewed-by: Rodrigo Arias Mallo --- pkgs/nix-portable/default.nix | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix index 8034a6ef..c04427e6 100644 --- a/pkgs/nix-portable/default.nix +++ b/pkgs/nix-portable/default.nix @@ -69,7 +69,13 @@ let { nativeBuildInputs = [ upx ]; } '' mkdir -p $out/bin - upx -9 -o $out/bin/${binName} ${binPath} + theBinPath=${binPath} + + if [[ -L "$theBinPath" ]]; then + theBinPath=$(readlink -f "$theBinPath") + fi + + upx -9 -o $out/bin/${binName} $theBinPath ''; installBin = pkg: bin: '' -- 2.51.2 From 06925bc0ca741c2e3e03c8658717be8a651fce24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Wed, 4 Mar 2026 16:49:43 +0100 Subject: [PATCH 04/22] Bind proc using --proc in nix-portable Reviewed-by: Rodrigo Arias Mallo --- pkgs/nix-portable/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix index c04427e6..c504d7da 100644 --- a/pkgs/nix-portable/default.nix +++ b/pkgs/nix-portable/default.nix @@ -435,6 +435,7 @@ let run="\$NP_BWRAP \$BWRAP_ARGS \\ --bind \$dir/emptyroot /\\ --dev-bind /dev /dev\\ + --proc /proc\\ --bind \$dir/nix /nix\\ \$binds" # --bind \$dir/busybox/bin/busybox /bin/sh\\ -- 2.51.2 From 71352ff5d1ef4c1546f2fdfd2e7b9f9a97d56cbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Wed, 4 Mar 2026 16:49:54 +0100 Subject: [PATCH 05/22] Restrict paths added to bwrap in nix-portable Reviewed-by: Rodrigo Arias Mallo --- pkgs/nix-portable/default.nix | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix index c504d7da..0bbc44ae 100644 --- a/pkgs/nix-portable/default.nix +++ b/pkgs/nix-portable/default.nix @@ -285,16 +285,7 @@ let collectBinds(){ - ### gather paths to bind for proot - # we cannot bind / to / without running into a lot of trouble, therefore - # we need to collect all top level directories and bind them inside an empty root - - # for termux a fallback is needed as enumerating top level directories fails - if ! pathsTopLevel="\$(find / -mindepth 1 -maxdepth 1 -not -name nix -not -name dev 2>&3)"; then - debug "Error: unable to list top level directories. Falling back to default binds." - pathsTopLevel="/etc /proc" - fi - + pathsTopLevel="/boot /run /sys \$PWD /gpfs /tmp /scratch" toBind="" for p in \$pathsTopLevel; do -- 2.51.2 From 79fdfc6c0ec0260f836882f9ae3acd3aca6b396d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Thu, 5 Mar 2026 16:55:21 +0100 Subject: [PATCH 06/22] Remove sgid from .nix-portable and set group This should prevent issues when putting it under /gpfs/{projects,scratch} that have sgid and group=nobody. Reviewed-by: Rodrigo Arias Mallo --- pkgs/nix-portable/default.nix | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix index 0bbc44ae..32b76f34 100644 --- a/pkgs/nix-portable/default.nix +++ b/pkgs/nix-portable/default.nix @@ -150,6 +150,15 @@ let [ -z "\$NP_LOCATION" ] && NP_LOCATION="\$HOME" NP_LOCATION="\$(readlink -f "\$NP_LOCATION")" dir="\$NP_LOCATION/.nix-portable" + + # Create NP_LOCATION and remove sgid bit + mkdir -p \$dir + if [ ! -z "\$BSC_MACHINE" ]; then + # Attempt to avoid issues with sgid folders + chmod g-s \$dir + chgrp bsc \$dir + fi + store="\$dir/nix/store" # create /nix/var/nix to prevent nix from falling back to chroot store. mkdir -p \$dir/{bin,nix/var/nix,nix/store} -- 2.51.2 From e7b3f972b0f92566fa1ae66d720c9b247f5dbc47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Thu, 5 Mar 2026 17:00:20 +0100 Subject: [PATCH 07/22] Only to busybox to /bin/sh in nix-portable Reviewed-by: Rodrigo Arias Mallo --- pkgs/nix-portable/default.nix | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix index 32b76f34..9cc8e4e7 100644 --- a/pkgs/nix-portable/default.nix +++ b/pkgs/nix-portable/default.nix @@ -329,13 +329,6 @@ let fi done - # if we're on a nixos, the /bin/sh symlink will point - # to a /nix/store path which doesn't exit inside the wrapped env - # we fix this by binding busybox/bin to /bin - if test -s /bin/sh && [[ "\$(realpath /bin/sh)" == /nix/store/* ]]; then - toBind="\$toBind \$dir/busybox/bin /bin" - fi - # provide /bin/sh via the shipped busybox toBind="\$toBind \$dir/busybox/bin/busybox /bin/sh" -- 2.51.2 From b96e3422b2a1fcd0d36d768b4677d7375172b7b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Thu, 5 Mar 2026 17:02:17 +0100 Subject: [PATCH 08/22] Install netcat, ssh and git in nix-portable These are needed by nix in order to properly download and build stuff. busybox's netcat does not work since it doesn't support -X. Reviewed-by: Rodrigo Arias Mallo --- pkgs/nix-portable/default.nix | 54 ++++++++++++++++------------------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix index 9cc8e4e7..eb2a11a9 100644 --- a/pkgs/nix-portable/default.nix +++ b/pkgs/nix-portable/default.nix @@ -10,6 +10,12 @@ with builtins; buildPackages, upx, + bootstrapPrograms ? [ + "gitMinimal" + "netcat-openbsd" + "openssh" + ], + busybox, cacert ? pkgs.cacert, compression ? "zstd -19 -T0", @@ -36,11 +42,6 @@ let nixpkgsSrc = pkgs.path; - # TODO: git could be more minimal via: - # perlSupport=false; guiSupport=false; nlsSupport=false; - gitAttribute = "gitMinimal"; - git = pkgs."${gitAttribute}"; - maketar = targets: let closureInfo = buildPackages.closureInfo { rootPaths = targets; }; @@ -83,6 +84,21 @@ let chmod +wx \$dir/bin/${bin}; ''; + installDynamic = pkgname: let + out = pkgs.${pkgname}.out; + in '' + if [ ! -e \$store${lib.removePrefix "/nix/store" pkgs.${pkgname}.out} ] ; then + debug "Installing ${pkgname}" + \$run \$store${lib.removePrefix "/nix/store" nix}/bin/nix build --impure --no-link --expr " + (import ${nixpkgsSrc} {}).${pkgname}.out + " + else + debug "${pkgname} already installed" + fi + + export PATH="${out}/bin:\$PATH" + ''; + caBundleZstd = pkgs.runCommand "cacerts" {} "cat ${cacert}/etc/ssl/certs/ca-bundle.crt | ${inp.zstd}/bin/zstd -19 > $out"; bwrap = packStaticBin "${inp.bwrap}/bin/bwrap"; @@ -271,17 +287,8 @@ let sslBind="/etc/ssl /etc/ssl" fi - - - ### detecting existing git installation - # we need to install git inside the wrapped environment - # unless custom git executable path is specified in NP_GIT, - # since the existing git might be incompatible to Nix (e.g. v1.x) if [ -n "\$NP_GIT" ]; then - doInstallGit=false - ln -s "\$NP_GIT" "\$dir/tmpbin/git" - else - doInstallGit=true + echo "WARN: NP_GIT is not supported, using nix version instead" fi @@ -570,22 +577,9 @@ let - ### install git via nix, if git installation is not in /nix path - if \$doInstallGit && [ ! -e \$store${lib.removePrefix "/nix/store" git.out} ] ; then - echo "Installing git. Disable this by specifying the git executable path with 'NP_GIT'" - \$run \$store${lib.removePrefix "/nix/store" nix}/bin/nix build --impure --no-link --expr " - (import ${nixpkgsSrc} {}).${gitAttribute}.out - " - else - debug "git already installed or manually specified" - fi - - ### override the possibly existing git in the environment with the installed one - # excluding the case NP_GIT is set. - if \$doInstallGit; then - export PATH="${git.out}/bin:\$PATH" - fi + ### install programs via nix + ${concatMapStringsSep "\n" installDynamic bootstrapPrograms} ### print elapsed time end=\$(date +%s%N) # end time in nanoseconds -- 2.51.2 From a71b12c60eb4dfb5b230ebde838720e8efb03349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Fri, 6 Mar 2026 12:42:09 +0100 Subject: [PATCH 09/22] Add bashInteractive in nix-portable bwrap Reviewed-by: Rodrigo Arias Mallo --- pkgs/nix-portable/default.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix index eb2a11a9..10cbffa8 100644 --- a/pkgs/nix-portable/default.nix +++ b/pkgs/nix-portable/default.nix @@ -14,6 +14,7 @@ with builtins; "gitMinimal" "netcat-openbsd" "openssh" + "bashInteractive" ], busybox, @@ -260,7 +261,9 @@ let recreate_nix_conf fi - + # Override $SHELL with nix bashInteractive + export SHELL="${pkgs.bashInteractive.out}/bin/bash" + export PS1="\n\[\033[1;32m\][\[\e]0;\u@\h: \w\a\]\u@\h:\w]\$\[\033[0m\] " ### setup SSL # find ssl certs or use from nixpkgs -- 2.51.2 From 1d02f7fae4f0f3d501980dfd6677177b028bec22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Fri, 6 Mar 2026 12:44:54 +0100 Subject: [PATCH 10/22] Remove nix-portable tmpbin feature It will not work without the host /lib64/ld Reviewed-by: Rodrigo Arias Mallo --- pkgs/nix-portable/default.nix | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix index 10cbffa8..4086069f 100644 --- a/pkgs/nix-portable/default.nix +++ b/pkgs/nix-portable/default.nix @@ -179,10 +179,6 @@ let store="\$dir/nix/store" # create /nix/var/nix to prevent nix from falling back to chroot store. mkdir -p \$dir/{bin,nix/var/nix,nix/store} - # sanitize the tmpbin directory - rm -rf "\$dir/tmpbin" - # create a directory to hold executable symlinks for overriding - mkdir -p "\$dir/tmpbin" # create minimal drv file for nix to spawn a nix shell echo 'builtins.derivation {name="foo"; builder="/bin/sh"; args = ["-c" "echo hello \> \\\$out"]; system=builtins.currentSystem;}' > "\$dir/mini-drv.nix" @@ -575,11 +571,6 @@ let ### set PATH # restore original PATH and append busybox export PATH="\$PATH_OLD:\$dir/busybox/bin" - # apply overriding executable paths in \$dir/tmpbin/ - export PATH="\$dir/tmpbin:\$PATH" - - - ### install programs via nix ${concatMapStringsSep "\n" installDynamic bootstrapPrograms} -- 2.51.2 From 14af841511dc215f662121661e4883164eaeb97a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Fri, 6 Mar 2026 12:45:36 +0100 Subject: [PATCH 11/22] Use nix bwrap in nix-portable Reviewed-by: Rodrigo Arias Mallo --- pkgs/nix-portable/default.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix index 4086069f..10b35104 100644 --- a/pkgs/nix-portable/default.nix +++ b/pkgs/nix-portable/default.nix @@ -375,7 +375,6 @@ let ### select container runtime debug "figuring out which runtime to use" - [ -z "\$NP_BWRAP" ] && NP_BWRAP=\$(PATH="\$PATH_OLD:\$PATH" which bwrap 2>/dev/null) || true [ -z "\$NP_BWRAP" ] && NP_BWRAP=\$dir/bin/bwrap debug "bwrap executable: \$NP_BWRAP" [ -z "\$NP_NIX" ] && NP_NIX=\$dir/bin/nix -- 2.51.2 From 7ac154a55bf609026a1b522da14aa62c8ddb9c2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Fri, 6 Mar 2026 12:46:01 +0100 Subject: [PATCH 12/22] Add jungle cache to nix-portable nix.conf Reviewed-by: Rodrigo Arias Mallo --- pkgs/nix-portable/default.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix index 10b35104..bfbe5505 100644 --- a/pkgs/nix-portable/default.nix +++ b/pkgs/nix-portable/default.nix @@ -207,6 +207,8 @@ let echo "experimental-features = nix-command flakes" >> \$dir/conf/nix.conf echo "ignored-acls = security.selinux system.nfs4_acl" >> \$dir/conf/nix.conf echo "sandbox-paths = /bin/sh=\$dir/busybox/bin/busybox" >> \$dir/conf/nix.conf + echo "extra-substituters = https://jungle.bsc.es/cache">> \$dir/conf/nix.conf + echo "extra-trusted-public-keys = jungle.bsc.es:pEc7MlAT0HEwLQYPtpkPLwRsGf80ZI26aj29zMw/HH0=" >> \$dir/conf/nix.conf # configurable config echo "sandbox = \$NP_CONF_SANDBOX" >> \$dir/conf/nix.conf -- 2.51.2 From 839b9b8c76580a70d6fab9d7dad98e89d29a69f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Fri, 6 Mar 2026 12:46:29 +0100 Subject: [PATCH 13/22] Bind /usr/bin/env in nix-portable Reviewed-by: Rodrigo Arias Mallo --- pkgs/nix-portable/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix index bfbe5505..032869df 100644 --- a/pkgs/nix-portable/default.nix +++ b/pkgs/nix-portable/default.nix @@ -339,6 +339,7 @@ let # provide /bin/sh via the shipped busybox toBind="\$toBind \$dir/busybox/bin/busybox /bin/sh" + toBind="\$toBind \$dir/busybox/bin/busybox /usr/bin/env" # on termux, make sure termux packages still work inside the nix-portable environment if [ -n "\$TERMUX_VERSION" ]; then -- 2.51.2 From 9dae6a6f38fe17f9f6a672b9ee4a948fb30a58e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Fri, 6 Mar 2026 15:18:19 +0100 Subject: [PATCH 14/22] Add meta with license to nix-portable Reviewed-by: Rodrigo Arias Mallo --- pkgs/nix-portable/default.nix | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix index 032869df..d08bf5e7 100644 --- a/pkgs/nix-portable/default.nix +++ b/pkgs/nix-portable/default.nix @@ -604,7 +604,17 @@ let runtimeScriptEscaped = replaceStrings ["\""] ["\\\""] runtimeScript; - nixPortable = pkgs.runCommand pname {nativeBuildInputs = [unixtools.xxd unzip];} '' + nixPortable = pkgs.runCommand pname { + nativeBuildInputs = [unixtools.xxd unzip]; + + meta = { + homepage = "https://github.com/DavHau/nix-portable"; + description = "Nix - Static, Permissionless, Installation-free, Pre-configured for mn5"; + maintainers = with lib.maintainers.bsc; [ abonerib ]; + platforms = lib.platforms.linux; + license = lib.licenses.mit; + }; + } '' mkdir -p $out/bin echo "${runtimeScriptEscaped}" > $out/bin/nix-portable.zip xxd $out/bin/nix-portable.zip | tail -- 2.51.2 From af512636ace00c2947bf25e80eab3a6d7628d5b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Fri, 6 Mar 2026 16:24:03 +0100 Subject: [PATCH 15/22] Add sys-devices feature to nix-portable nix.conf Reviewed-by: Rodrigo Arias Mallo --- pkgs/nix-portable/default.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix index d08bf5e7..9fc3d1ea 100644 --- a/pkgs/nix-portable/default.nix +++ b/pkgs/nix-portable/default.nix @@ -210,6 +210,9 @@ let echo "extra-substituters = https://jungle.bsc.es/cache">> \$dir/conf/nix.conf echo "extra-trusted-public-keys = jungle.bsc.es:pEc7MlAT0HEwLQYPtpkPLwRsGf80ZI26aj29zMw/HH0=" >> \$dir/conf/nix.conf + echo "extra-system-features = sys-devices" >> \$dir/conf/nix.conf + echo "extra-sandbox-paths = /sys/devices/system/cpu=/sys/devices/system/cpu /sys/devices/system/node=/sys/devices/system/node" >> \$dir/conf/nix.conf + # configurable config echo "sandbox = \$NP_CONF_SANDBOX" >> \$dir/conf/nix.conf echo "store = \$NP_CONF_STORE" >> \$dir/conf/nix.conf -- 2.51.2 From 0a255b1ffa027bf93960d8025fddbad33687d738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Fri, 6 Mar 2026 16:32:51 +0100 Subject: [PATCH 16/22] Make bsc users trusted in nix-portable Reviewed-by: Rodrigo Arias Mallo --- pkgs/nix-portable/default.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix index 9fc3d1ea..5a6f9dbc 100644 --- a/pkgs/nix-portable/default.nix +++ b/pkgs/nix-portable/default.nix @@ -212,6 +212,8 @@ let echo "extra-system-features = sys-devices" >> \$dir/conf/nix.conf echo "extra-sandbox-paths = /sys/devices/system/cpu=/sys/devices/system/cpu /sys/devices/system/node=/sys/devices/system/node" >> \$dir/conf/nix.conf + echo "extra-trusted-users = @bsc" >> \$dir/conf/nix.conf + # configurable config echo "sandbox = \$NP_CONF_SANDBOX" >> \$dir/conf/nix.conf -- 2.51.2 From f9db76c466d28d6648db607ecb8a197595596458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Fri, 6 Mar 2026 17:03:29 +0100 Subject: [PATCH 17/22] Enable parallelBuilding in jemalloc Reviewed-by: Rodrigo Arias Mallo --- pkgs/nanos6/jemalloc.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/nanos6/jemalloc.nix b/pkgs/nanos6/jemalloc.nix index 0eb35197..76c26d33 100644 --- a/pkgs/nanos6/jemalloc.nix +++ b/pkgs/nanos6/jemalloc.nix @@ -5,6 +5,7 @@ jemalloc.overrideAttrs (old: { "--with-jemalloc-prefix=nanos6_je_" "--enable-stats" ]; + enableParallelBuilding = true; hardeningDisable = [ "all" ]; meta = old.meta // { description = old.meta.description + " (for Nanos6)"; -- 2.51.2 From 386cfd8973fde7ba732514e6269dc434091cbd14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Mon, 9 Mar 2026 12:24:30 +0100 Subject: [PATCH 18/22] Use fetchurl for amd-uprof Reviewed-by: Rodrigo Arias Mallo --- pkgs/amd-uprof/default.nix | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/pkgs/amd-uprof/default.nix b/pkgs/amd-uprof/default.nix index 6f566c84..6e1f3ebe 100644 --- a/pkgs/amd-uprof/default.nix +++ b/pkgs/amd-uprof/default.nix @@ -1,8 +1,6 @@ { stdenv , lib -, curl -, cacert -, runCommandLocal +, fetchurl , autoPatchelfHook , elfutils , glib @@ -26,26 +24,22 @@ let tarball = "AMDuProf_Linux_x64_${version}.tar.bz2"; # NOTE: Remember to update the radare2 patch below if AMDuProfPcm changes. - uprofSrc = runCommandLocal tarball { - nativeBuildInputs = [ curl ]; - outputHash = "sha256-j9gxcBcIg6Zhc5FglUXf/VV9bKSo+PAKeootbN7ggYk="; - SSL_CERT_FILE="${cacert}/etc/ssl/certs/ca-bundle.crt"; - } '' - curl \ - -o $out \ - 'https://download.amd.com/developer/eula/uprof/uprof-5-1/${tarball}' \ - -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:139.0) Gecko/20100101 Firefox/139.0' \ - -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' \ - -H 'Accept-Language: en-US,en;q=0.5' \ - -H 'Accept-Encoding: gzip, deflate, br, zstd' \ - -H 'Referer: https://www.amd.com/' 2>&1 | tr '\r' '\n' - ''; + src = fetchurl { + url = "https://download.amd.com/developer/eula/uprof/uprof-5-1/${tarball}"; + sha256 = "sha256-j9gxcBcIg6Zhc5FglUXf/VV9bKSo+PAKeootbN7ggYk="; + curlOptsList = [ + "-H" "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:139.0) Gecko/20100101 Firefox/139.0" + "-H" "'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'" + "-H" "Accept-Language: en-US,en;q=0.5" + "-H" "Accept-Encoding: gzip, deflate, br, zstd" + "-H" "Referer: https://www.amd.com/" + ]; + }; in stdenv.mkDerivation { pname = "AMD-uProf"; - inherit version; - src = uprofSrc; + inherit src version; dontStrip = true; phases = [ "installPhase" "fixupPhase" ]; nativeBuildInputs = [ autoPatchelfHook radare2 ]; -- 2.51.2 From f5b1082ab910f64183bbbddb0a3b7fae215fde29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Mon, 9 Mar 2026 14:14:39 +0100 Subject: [PATCH 19/22] Do not restore original $PATH in nix-portable Reviewed-by: Rodrigo Arias Mallo --- pkgs/nix-portable/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix index 5a6f9dbc..deed9252 100644 --- a/pkgs/nix-portable/default.nix +++ b/pkgs/nix-portable/default.nix @@ -576,8 +576,8 @@ let ### set PATH - # restore original PATH and append busybox - export PATH="\$PATH_OLD:\$dir/busybox/bin" + export PATH="\$dir/busybox/bin" + export PATH="\$PATH:\$store${lib.removePrefix "/nix/store" nix}/bin" ### install programs via nix ${concatMapStringsSep "\n" installDynamic bootstrapPrograms} -- 2.51.2 From 1b36c70512d1439a0d5dcf1a55c77d6452588496 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Mon, 9 Mar 2026 14:20:37 +0100 Subject: [PATCH 20/22] Unset mn5 default bash functions in nix-portable Reviewed-by: Rodrigo Arias Mallo --- pkgs/nix-portable/default.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix index deed9252..a1b3c6e7 100644 --- a/pkgs/nix-portable/default.nix +++ b/pkgs/nix-portable/default.nix @@ -268,6 +268,9 @@ let export SHELL="${pkgs.bashInteractive.out}/bin/bash" export PS1="\n\[\033[1;32m\][\[\e]0;\u@\h: \w\a\]\u@\h:\w]\$\[\033[0m\] " + # unset bash function aliases + unset -f which ml module + ### setup SSL # find ssl certs or use from nixpkgs debug "figuring out ssl certs" -- 2.51.2 From 34238d81c719c0dc3b9784233c34a3d0a73cab47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Wed, 11 Mar 2026 14:25:56 +0100 Subject: [PATCH 21/22] Rework nix-portable derivation arguments Reviewed-by: Rodrigo Arias Mallo --- overlay.nix | 10 +--------- pkgs/nix-portable/default.nix | 31 ++++++++++++++++--------------- 2 files changed, 17 insertions(+), 24 deletions(-) diff --git a/overlay.nix b/overlay.nix index 1be5bdf1..1e2f350a 100644 --- a/overlay.nix +++ b/overlay.nix @@ -39,15 +39,7 @@ let nanos6Debug = final.nanos6.override { enableDebug = true; }; nixtools = callPackage ./pkgs/nixtools/default.nix { }; nixgen = callPackage ./pkgs/nixgen/default.nix { }; - nix-portable = callPackage ./pkgs/nix-portable/default.nix { - busybox = final.pkgsStatic.busybox; - bwrap = final.pkgsStatic.bubblewrap; - gnutar = final.pkgsStatic.gnutar; - perl = final.pkgsBuildBuild.perl; - xz = final.pkgsStatic.xz; - zstd = final.pkgsStatic.zstd; - bashInteractive = final.pkgsStatic.bashInteractive; - }; + nix-portable = callPackage ./pkgs/nix-portable/default.nix { }; nix-wrap = callPackage ./pkgs/nix-wrap/default.nix { }; nodes = callPackage ./pkgs/nodes/default.nix { }; nosv = callPackage ./pkgs/nosv/default.nix { }; diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix index a1b3c6e7..d4dc7ac4 100644 --- a/pkgs/nix-portable/default.nix +++ b/pkgs/nix-portable/default.nix @@ -1,8 +1,6 @@ with builtins; { - bwrap, nix, - proot, unzip, zip, unixtools, @@ -17,23 +15,26 @@ with builtins; "bashInteractive" ], - busybox, cacert ? pkgs.cacert, compression ? "zstd -19 -T0", - gnutar ? pkgs.pkgsStatic.gnutar, lib ? pkgs.lib, - perl ? pkgs.perl, pkgs ? import {}, - xz ? pkgs.pkgsStatic.xz, - zstd ? pkgs.pkgsStatic.zstd, - nixStatic, # hardcode executable to run. Useful when creating a bundle. bundledPackage ? null, - ... + + nixStatic, + busyboxStatic ? pkgs.pkgsStatic.busybox, + bwrapStatic ? pkgs.pkgsStatic.bubblewrap, + prootStatic ? pkgs.pkgsStatic.proot, + zstdStatic ? pkgs.pkgsStatic.zstd, + + perlBuildBuild ? pkgs.pkgsBuildBuild.perl, }@inp: with lib; let + perl = perlBuildBuild; + pname = if bundledPackage == null then "nix-portable" @@ -100,12 +101,12 @@ let export PATH="${out}/bin:\$PATH" ''; - caBundleZstd = pkgs.runCommand "cacerts" {} "cat ${cacert}/etc/ssl/certs/ca-bundle.crt | ${inp.zstd}/bin/zstd -19 > $out"; + caBundleZstd = pkgs.runCommand "cacerts" {} "cat ${cacert}/etc/ssl/certs/ca-bundle.crt | ${zstd}/bin/zstd -19 > $out"; - bwrap = packStaticBin "${inp.bwrap}/bin/bwrap"; + bwrap = packStaticBin "${bwrapStatic}/bin/bwrap"; nixStatic = packStaticBin "${inp.nixStatic}/bin/nix"; - proot = packStaticBin "${inp.proot}/bin/proot"; - zstd = packStaticBin "${inp.zstd}/bin/zstd"; + proot = packStaticBin "${prootStatic}/bin/proot"; + zstd = packStaticBin "${zstdStatic}/bin/zstd"; # the default nix store contents to extract when first used storeTar = maketar ([ cacert nix nixpkgsSrc ] ++ lib.optional (bundledPackage != null) bundledPackage); @@ -242,9 +243,9 @@ let # install busybox mkdir -p \$dir/busybox/bin (base64 -d> "\$dir/busybox/bin/busybox" && chmod +x "\$dir/busybox/bin/busybox") << END - $(cat ${busybox}/bin/busybox | base64) + $(cat ${busyboxStatic}/bin/busybox | base64) END - busyBins="${toString (attrNames (filterAttrs (d: type: type == "symlink") (readDir "${inp.busybox}/bin")))}" + busyBins="${toString (attrNames (filterAttrs (d: type: type == "symlink") (readDir "${busyboxStatic}/bin")))}" for bin in \$busyBins; do [ ! -e "\$dir/busybox/bin/\$bin" ] && ln -s busybox "\$dir/busybox/bin/\$bin" done -- 2.51.2 From 54dfaa9dffbbce4538eed04dd2241888f1630bce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Bon=C3=A9?= Date: Wed, 11 Mar 2026 15:05:54 +0100 Subject: [PATCH 22/22] Remove proot from nix-portable The pkgsStatic.proot is broken due to failed dependencies. In upstream nix-portable they have a custom derivation on top o proot gitlab. But since we don't need it, we can remove it safely. Reviewed-by: Rodrigo Arias Mallo --- pkgs/nix-portable/default.nix | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/pkgs/nix-portable/default.nix b/pkgs/nix-portable/default.nix index d4dc7ac4..dbe42415 100644 --- a/pkgs/nix-portable/default.nix +++ b/pkgs/nix-portable/default.nix @@ -25,7 +25,6 @@ with builtins; nixStatic, busyboxStatic ? pkgs.pkgsStatic.busybox, bwrapStatic ? pkgs.pkgsStatic.bubblewrap, - prootStatic ? pkgs.pkgsStatic.proot, zstdStatic ? pkgs.pkgsStatic.zstd, perlBuildBuild ? pkgs.pkgsBuildBuild.perl, @@ -105,7 +104,6 @@ let bwrap = packStaticBin "${bwrapStatic}/bin/bwrap"; nixStatic = packStaticBin "${inp.nixStatic}/bin/nix"; - proot = packStaticBin "${prootStatic}/bin/proot"; zstd = packStaticBin "${zstdStatic}/bin/zstd"; # the default nix store contents to extract when first used @@ -113,7 +111,7 @@ let # The runtime script which unpacks the necessary files to $HOME/.nix-portable - # and then executes nix via proot or bwrap + # and then executes nix via bwrap # Some shell expressions will be evaluated at build time and some at run time. # Variables/expressions escaped via `\$` will be evaluated at run time runtimeScript = '' @@ -128,17 +126,6 @@ let trap "declare -p > \''${TMPDIR:-/tmp}/np_env" EXIT fi - # there seem to be less issues with proot when disabling seccomp - # though on android it is needed - if [ -n "\$TERMUX_VERSION" ]; then - unset LD_PRELOAD - NP_RUNTIME=\''${NP_RUNTIME:-proot} - export PROOT_TMP_DIR="\$TMPDIR/proot" - mkdir -p "\$PROOT_TMP_DIR" - else - export PROOT_NO_SECCOMP=\''${PROOT_NO_SECCOMP:-1} - fi - set -e if [ -n "\$NP_DEBUG" ] && [ "\$NP_DEBUG" -ge 2 ]; then set -x @@ -255,7 +242,6 @@ let # install other binaries ${installBin zstd "zstd"} - ${installBin proot "proot"} ${installBin bwrap "bwrap"} ${installBin nixStatic "nix"} @@ -391,9 +377,6 @@ let debug "bwrap executable: \$NP_BWRAP" [ -z "\$NP_NIX" ] && NP_NIX=\$dir/bin/nix debug "nix executable: \$NP_NIX" - [ -z "\$NP_PROOT" ] && NP_PROOT=\$(PATH="\$PATH_OLD:\$PATH" which proot 2>/dev/null) || true - [ -z "\$NP_PROOT" ] && NP_PROOT=\$dir/bin/proot - debug "proot executable: \$NP_PROOT" debug "testing all available runtimes..." if [ -z "\$NP_RUNTIME" ]; then # read last automatic selected runtime from disk @@ -451,14 +434,8 @@ let # --bind \$dir/busybox/bin/busybox /bin/sh\\ else # proot - collectBinds - makeBindArgs -b ":" \$toBind \$sslBind - run="\$NP_PROOT \$PROOT_ARGS\\ - -r \$dir/emptyroot\\ - -b /dev:/dev\\ - -b \$dir/nix:/nix\\ - \$binds" - # -b \$dir/busybox/bin/busybox:/bin/sh\\ + echo Unsupported runtime: $NP_RUNTIME + exit 1 fi debug "base command will be: \$run" @@ -645,7 +622,6 @@ let zip="${zip}/bin/zip -0" $zip $out/bin/nix-portable.zip ${bwrap}/bin/bwrap $zip $out/bin/nix-portable.zip ${nixStatic}/bin/nix - $zip $out/bin/nix-portable.zip ${proot}/bin/proot $zip $out/bin/nix-portable.zip ${zstd}/bin/zstd $zip $out/bin/nix-portable.zip ${storeTar}/tar $zip $out/bin/nix-portable.zip ${caBundleZstd} @@ -669,6 +645,6 @@ let in nixPortable.overrideAttrs (prev: { passthru = (prev.passthru or {}) // { - inherit bwrap proot; + inherit bwrap; }; }) -- 2.51.2