*: fully hermetic builds and nix shell support
This change is a slightly more polished version of Serge's experiment:
- https://review.monogon.dev/c/monogon/+/1148
- https://bin.monogon.dev/pasta/sloth-parrot-ant
- https://bin.monogon.dev/pasta/eel-seal-wolf
There are two execution environments we have to support:
- Most builds run inside a sandbox, which is a Fedora
environment and does not require any host dependencies at all.
- Bazel itself and the tooling we require to bootstrap
the sandbox (mainly, Go and Proto toolchains). This has to
work directly on the host.
We first make the sandbox fully hermetic by setting
--experimental_use_hermetic_linux_sandbox, which set up an empty /
instead of mounting over individual directories, removing any remaining
host paths from the sandbox (except /proc and /dev/shm, which are
required by some toolchains). We also force static values for the shell,
$TMPDIR and $PATH, which would otherwise leak into the sandbox.
For the host, we use buildFHSUserEnv to build an environment which
supports our static toolchains, and well as a clean Bazel build
without all the nixpkgs patches which would otherwise break our custom
toolchains and sandbox implementation.
This allows us to use the exact same toolchains on NixOS and other
distros for perfect reproducibility.
Fixes https://github.com/monogon-dev/monogon/issues/174.
Fixes https://github.com/monogon-dev/monogon/issues/175.
Co-authored-by: Serge Bazanski <serge@monogon.tech>
Change-Id: I665471a45b315ce7e93ef16d9d056d7622886959
Reviewed-on: https://review.monogon.dev/c/monogon/+/1929
Tested-by: Jenkins CI
Reviewed-by: Serge Bazanski <serge@monogon.tech>
diff --git a/shell.nix b/shell.nix
new file mode 100644
index 0000000..d64223f
--- /dev/null
+++ b/shell.nix
@@ -0,0 +1,87 @@
+# If you're on NixOS, use me! `nix-shell --pure`.
+with import (fetchTarball {
+ # nixpkgs 23.05 as of 2023/07/19
+ url = "https://github.com/NixOS/nixpkgs/archive/2fadc2426928c844054cd28fabe231ff26a70715.tar.gz";
+ sha256 = "sha256:06hpcqhaaqvd5gjcz2ps9lz6q2sf5fwgl5rwllpyl9x4g5g95ahv";
+}) {};
+let
+ wrapper = pkgs.writeScript "wrapper.sh"
+ ''
+ # Fancy colorful PS1 to make people notice easily they're in the Monogon Nix shell.
+ PS1='\[\033]0;\u/monogon:\w\007\]'
+ if type -P dircolors >/dev/null ; then
+ PS1+='\[\033[01;37m\]\u/monogon\[\033[01;36m\] \w \$\[\033[00m\] '
+ fi
+ export PS1
+
+ # Use Nix-provided cert store.
+ export NIX_SSL_CERT_FILE="${cacert}/etc/ssl/certs/ca-bundle.crt"
+ export SSL_CERT_FILE="${cacert}/etc/ssl/certs/ca-bundle.crt"
+
+ # Let some downstream machinery know we're on NixOS. This is used mostly to
+ # work around Bazel/NixOS interactions.
+ export MONOGON_NIXOS=yep
+
+ # Convince rules_go to use /bin/bash and not a NixOS store bash which has
+ # no idea how to resolve other things in the nix store once PATH is
+ # stripped by (host_)action_env.
+ export BAZEL_SH=/bin/bash
+
+ exec bash --noprofile --norc "$@"
+ '';
+in
+(pkgs.buildFHSUserEnv {
+ name = "monogon-nix";
+ targetPkgs = pkgs: with pkgs; [
+ git
+ (stdenv.mkDerivation {
+ name = "bazel";
+ src = builtins.fetchurl {
+ url = https://github.com/bazelbuild/bazel/releases/download/5.4.0/bazel-5.4.0-linux-x86_64;
+ sha256 = "1w58m1brwjfwsv48fmd66inry67m4vgb3bwvwmamhdv099v183jg";
+ };
+ unpackPhase = ''
+ true
+ '';
+ buildPhase = ''
+ mkdir -p $out/bin
+ cp $src $out/bin/.bazel-inner
+ chmod +x $out/bin/.bazel-inner
+
+ cat > $out/bin/bazel <<EOF
+ #!/usr/bin/bash
+ export BAZEL_REAL=$out/bin/.bazel-inner
+ function get_workspace_root() {
+ workspace_dir="\''${PWD}"
+ while [[ "\''${workspace_dir}" != / ]]; do
+ if [[ -e "\''${workspace_dir}/WORKSPACE" || -e "\''${workspace_dir}/WORKSPACE.bazel" ]]; then
+ readonly workspace_dir
+ return
+ fi
+ workspace_dir="$(dirname "\''${workspace_dir}")"
+ done
+ readonly workspace_dir=""
+ }
+
+ get_workspace_root
+ readonly wrapper="\''${workspace_dir}/tools/bazel"
+ if [ -f "\''${wrapper}" ]; then
+ exec -a "\$0" "\''${wrapper}" "\$@"
+ fi
+ exec -a "\$0" "\''${BAZEL_REAL}" "\$@"
+ EOF
+ chmod +x $out/bin/bazel
+ '';
+ dontStrip = true;
+ })
+ zlib
+ curl
+ gcc
+ binutils
+ openjdk11
+ patch
+ python3
+ ];
+ runScript = wrapper;
+}).env
+