From 6cdba64ed76e54bcb84d0b5c3e42bc1ece81ebd0 Mon Sep 17 00:00:00 2001 From: Slendi Date: Tue, 16 Sep 2025 17:09:20 +0300 Subject: [PATCH] Initial commit --- .gitignore | 2 + flake.nix | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 .gitignore create mode 100644 flake.nix diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a88ab8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.direnv + diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..b940d5a --- /dev/null +++ b/flake.nix @@ -0,0 +1,140 @@ +{ + description = "Proot-based bundler"; + + inputs = { + nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = + { + self, + nixpkgs, + flake-utils, + ... + }: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = import nixpkgs { inherit system; }; + + prootPatched = (pkgs.proot.override { enablePython = false; }).overrideAttrs (prev: { + postFixup = (prev.postFixup or "") + '' + exe=$out/bin/proot + if interp="$(${pkgs.patchelf}/bin/patchelf --print-interpreter "$exe" 2>/dev/null)"; then + ${pkgs.patchelf}/bin/patchelf --set-interpreter ."$interp" "$exe" + fi + if rpath="$(${pkgs.patchelf}/bin/patchelf --print-rpath "$exe" 2>/dev/null)"; then + ${pkgs.patchelf}/bin/patchelf \ + --set-rpath "$(printf %s "$rpath" | sed 's|/nix/store/|./nix/store/|g')" "$exe" + fi + ''; + }); + in + { + bundlers = rec { + proot-bundler = + drv: + let + ci = pkgs.closureInfo { + rootPaths = [ + drv + prootPatched + ]; + }; + mainProgram = drv.meta.mainProgram or (throw "${drv.name} has no meta.mainProgram set"); + prootStoreBase = builtins.baseNameOf prootPatched; + PROOT_REL = "/nix/store/${prootStoreBase}/bin/proot"; + in + pkgs.stdenvNoCC.mkDerivation { + name = "${mainProgram}-bdl"; + nativeBuildInputs = with pkgs; [ + coreutils + findutils + gnutar + gzip + ]; + dontFixup = true; + buildCommand = '' + set -euo pipefail + + PAY="$PWD/payload" + mkdir -p "$PAY/nix/store" + + while IFS= read -r p; do + cp -a --no-preserve=ownership "$p" "$PAY/nix/store/" + done < ${ci}/store-paths + + APP_BIN="${drv}/bin/${mainProgram}" + if [ ! -x "$APP_BIN" ]; then + echo "mainProgram ${mainProgram} not found in ${drv}/bin" >&2 + exit 1 + fi + APP_REL="$APP_BIN" + + _TMP="$(mktemp -d)" + ( cd "$PAY" && tar \ + --owner=0 --group=0 \ + --mode=u+rw,uga+r \ + --hard-dereference \ + --format=gnu \ + --sort=name \ + -czf "$_TMP/payload.tar.gz" . ) + + cat > "$out" <<'SH' + #!/bin/sh + set -euf + umask 077 + unset LD_PRELOAD LD_LIBRARY_PATH LD_AUDIT LD_DEBUG LD_PROFILE LD_USE_LOAD_BIAS LD_ORIGIN_PATH LD_ASSUME_KERNEL + : "''${TMPDIR:=/tmp}" + EXTRACT_DIR="$(mktemp -d "''${TMPDIR%/}/nxbdl.XXXXXX")" + cleanup() { [ -n "''${KEEP_BUNDLE:-}" ] || rm -rf "$EXTRACT_DIR"; } + trap cleanup EXIT INT TERM + ARCHIVE_LINE=$(awk '/^__ARCHIVE_BELOW__/ {print NR+1; exit 0}' "$0") + sed -n "''${ARCHIVE_LINE},\$p" "$0" | tar -xzf - -C "$EXTRACT_DIR" + BUNDLE_PWD="''${BUNDLE_PWD:-$PWD}" + cd "$EXTRACT_DIR" + APP_REL='__APP_REL__' + PROOT_REL='__PROOT_REL__' + if [ -n "''${BUNDLE_PROOT:-}" ] && command -v "''${BUNDLE_PROOT}" >/dev/null 2>&1; then + PROOT_BIN="''${BUNDLE_PROOT}" + elif command -v proot >/dev/null 2>&1; then + PROOT_BIN="$(command -v proot)" + else + PROOT_BIN="$EXTRACT_DIR${PROOT_REL}" + fi + [ "''${BUNDLE_FORCE_BUNDLED_PROOT:-0}" = 1 ] && PROOT_BIN="$EXTRACT_DIR${PROOT_REL}" + [ -x "$PROOT_BIN" ] || { echo "proot not found/executable: $PROOT_BIN" >&2; exit 127; } + [ -x "$EXTRACT_DIR''${APP_REL}" ] || { echo "app not found/executable: $EXTRACT_DIR''${APP_REL}" >&2; exit 127; } + mkdir -p "$EXTRACT_DIR/etc" + cat > "$EXTRACT_DIR/etc/resolv.conf" <<'EOF' + nameserver 9.9.9.9 + nameserver 8.8.8.8 + nameserver 1.1.1.1 + nameserver 1.0.0.1 + EOF + "''${PROOT_BIN}" \ + -R / \ + -b "$EXTRACT_DIR/nix:/nix" \ + -b "$EXTRACT_DIR/etc/resolv.conf:/etc/resolv.conf" \ + -b /dev -b /proc -b /sys \ + -w "$BUNDLE_PWD" \ + "$EXTRACT_DIR''${APP_REL}" "$@" + exit $? + __ARCHIVE_BELOW__ + SH + + sed -i \ + -e "s|__APP_REL__|$APP_REL|g" \ + -e "s|__PROOT_REL__|${PROOT_REL}|g" \ + "$out" + cat "$_TMP/payload.tar.gz" >> "$out" + chmod +x "$out" + ''; + }; + + default = proot-bundler; + }; + } + ); +}