# Configurations that should only be overrided by # overrideAttrs { pname , version , src , projectName # "apptainer" or "singularity" , vendorHash ? null , deleteVendor ? false , proxyVendor ? false , extraConfigureFlags ? [ ] , extraDescription ? "" , extraMeta ? { } }: let # Workaround for vendor-related attributes not overridable (#86349) # should be removed when the issue is resolved _defaultGoVendorArgs = { inherit vendorHash deleteVendor proxyVendor ; }; in { lib , buildGoModule , runCommandLocal # Native build inputs , addDriverRunpath , makeWrapper , pkg-config , util-linux , which # Build inputs , bash , callPackage , conmon , coreutils , cryptsetup , e2fsprogs , fakeroot , fuse2fs ? e2fsprogs.fuse2fs , go , gpgme , libseccomp , libuuid # This is for nvidia-container-cli , nvidia-docker , openssl , squashfsTools , squashfuse # Test dependencies , singularity-tools , cowsay , hello # Overridable configurations , enableNvidiaContainerCli ? true # --nvccli currently requires extra privileges: # https://github.com/apptainer/apptainer/issues/1893#issuecomment-1881240800 , forceNvcCli ? false # Compile with seccomp support # SingularityCE 3.10.0 and above requires explicit --without-seccomp when libseccomp is not available. , enableSeccomp ? true # Whether the configure script treat SUID support as default # When equal to enableSuid, it supress the --with-suid / --without-suid build flag # It can be set to `null` to always pass either --with-suid or --without-suided # Type: null or boolean , defaultToSuid ? true # Whether to compile with SUID support , enableSuid ? false , starterSuidPath ? null , substituteAll # newuidmapPath and newgidmapPath are to support --fakeroot # where those SUID-ed executables are unavailable from the FHS system PATH. # Path to SUID-ed newuidmap executable , newuidmapPath ? null # Path to SUID-ed newgidmap executable , newgidmapPath ? null # External LOCALSTATEDIR , externalLocalStateDir ? null # Remove the symlinks to `singularity*` when projectName != "singularity" , removeCompat ? false # Workaround #86349 # should be removed when the issue is resolved , vendorHash ? _defaultGoVendorArgs.vendorHash , deleteVendor ? _defaultGoVendorArgs.deleteVendor , proxyVendor ? _defaultGoVendorArgs.proxyVendor }: let defaultPathOriginal = "/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin"; privileged-un-utils = if ((newuidmapPath == null) && (newgidmapPath == null)) then null else (runCommandLocal "privileged-un-utils" { } '' mkdir -p "$out/bin" ln -s ${lib.escapeShellArg newuidmapPath} "$out/bin/newuidmap" ln -s ${lib.escapeShellArg newgidmapPath} "$out/bin/newgidmap" ''); in (buildGoModule { inherit pname version src; patches = lib.optionals (projectName == "apptainer") [ (substituteAll { src = ./apptainer/0001-ldCache-patch-for-driverLink.patch; inherit (addDriverRunpath) driverLink; }) ]; # Override vendorHash with the output got from # nix-prefetch -E "{ sha256 }: ((import ./. { }).apptainer.override { vendorHash = sha256; }).goModules" # or with `null` when using vendored source tarball. inherit vendorHash deleteVendor proxyVendor; # go is used to compile extensions when building container images allowGoReference = true; strictDeps = true; passthru = { inherit enableSeccomp enableSuid externalLocalStateDir projectName removeCompat starterSuidPath ; }; nativeBuildInputs = [ makeWrapper pkg-config util-linux which ]; # Search inside the project sources # and see the `control` file of the Debian package from upstream repos # for build-time dependencies and run-time utilities # apptainer/apptainer: https://github.com/apptainer/apptainer/blob/main/dist/debian/control # sylabs/singularity: https://github.com/sylabs/singularity/blob/main/debian/control buildInputs = [ bash # To patch /bin/sh shebangs. conmon cryptsetup gpgme libuuid openssl squashfsTools # Required at build time by SingularityCE ] ++ lib.optional enableNvidiaContainerCli nvidia-docker ++ lib.optional enableSeccomp libseccomp ; configureScript = "./mconfig"; configureFlags = [ "--localstatedir=${if externalLocalStateDir != null then externalLocalStateDir else "${placeholder "out"}/var/lib"}" "--runstatedir=/var/run" ] ++ lib.optional (!enableSeccomp) "--without-seccomp" ++ lib.optional (enableSuid != defaultToSuid) (if enableSuid then "--with-suid" else "--without-suid") ++ extraConfigureFlags ; # causes redefinition of _FORTIFY_SOURCE hardeningDisable = [ "fortify3" ]; # Packages to prefix to the Apptainer/Singularity container runtime default PATH # Use overrideAttrs to override defaultPathInputs = [ bash coreutils cryptsetup # cryptsetup fakeroot fuse2fs # Mount ext3 filesystems go privileged-un-utils squashfsTools # mksquashfs unsquashfs # Make / unpack squashfs image squashfuse # squashfuse_ll squashfuse # Mount (without unpacking) a squashfs image without privileges ] ++ lib.optional enableNvidiaContainerCli nvidia-docker ; postPatch = '' if [[ ! -e .git || ! -e VERSION ]]; then echo "${version}" > VERSION fi # Patch shebangs for script run during build patchShebangs --build "$configureScript" makeit e2e scripts mlocal/scripts # Patching the hard-coded defaultPath by prefixing the packages in defaultPathInputs substituteInPlace cmd/internal/cli/actions.go \ --replace "defaultPath = \"${defaultPathOriginal}\"" "defaultPath = \"''${defaultPathInputs// /\/bin:}''${defaultPathInputs:+/bin:}${defaultPathOriginal}\"" substituteInPlace internal/pkg/util/gpu/nvidia.go \ --replace \ 'return fmt.Errorf("/usr/bin not writable in the container")' \ "" ''; postConfigure = '' # Code borrowed from pkgs/stdenv/generic/setup.sh configurePhase() # set to empty if unset : ''${configureFlags=} # shellcheck disable=SC2086 $configureScript -V ${version} "''${prefixKey:---prefix=}$prefix" $configureFlags "''${configureFlagsArray[@]}" # End of the code from pkgs/stdenv/generic/setup.sh configurPhase() ''; buildPhase = '' runHook preBuild make -C builddir -j"$NIX_BUILD_CORES" runHook postBuild ''; installPhase = '' runHook preInstall make -C builddir install LOCALSTATEDIR="$out/var/lib" runHook postInstall ''; postFixup = '' substituteInPlace "$out/bin/run-singularity" \ --replace "/usr/bin/env ${projectName}" "$out/bin/${projectName}" wrapProgram "$out/bin/${projectName}" \ --prefix PATH : "''${defaultPathInputs// /\/bin:}''${defaultPathInputs:+/bin:}" # Make changes in the config file ${lib.optionalString forceNvcCli '' substituteInPlace "$out/etc/${projectName}/${projectName}.conf" \ --replace "use nvidia-container-cli = no" "use nvidia-container-cli = yes" ''} ${lib.optionalString (enableNvidiaContainerCli && projectName == "singularity") '' substituteInPlace "$out/etc/${projectName}/${projectName}.conf" \ --replace "# nvidia-container-cli path =" "nvidia-container-cli path = ${nvidia-docker}/bin/nvidia-container-cli" ''} ${lib.optionalString (removeCompat && (projectName != "singularity")) '' unlink "$out/bin/singularity" for file in "$out"/share/man/man?/singularity*.gz; do if [[ -L "$file" ]]; then unlink "$file" fi done for file in "$out"/share/*-completion/completions/singularity; do if [[ -e "$file" ]] rm "$file" done ''} ${lib.optionalString enableSuid (lib.warnIf (starterSuidPath == null) "${projectName}: Null starterSuidPath when enableSuid produces non-SUID-ed starter-suid and run-time permission denial." '' chmod +x $out/libexec/${projectName}/bin/starter-suid '')} ${lib.optionalString (enableSuid && (starterSuidPath != null)) '' mv "$out"/libexec/${projectName}/bin/starter-suid{,.orig} ln -s ${lib.escapeShellArg starterSuidPath} "$out/libexec/${projectName}/bin/starter-suid" ''} ''; meta = with lib; { description = "Application containers for linux" + extraDescription; longDescription = '' Singularity (the upstream) renamed themselves to Apptainer to distinguish themselves from a fork made by Sylabs Inc.. See https://sylabs.io/2021/05/singularity-community-edition https://apptainer.org/news/community-announcement-20211130 ''; license = licenses.bsd3; platforms = platforms.linux; maintainers = with maintainers; [ jbedo ShamrockLee ]; mainProgram = projectName; } // extraMeta; }).overrideAttrs (finalAttrs: prevAttrs: { passthru = prevAttrs.passthru or { } // { tests = { image-hello-cowsay = singularity-tools.buildImage { name = "hello-cowsay"; contents = [ hello cowsay ]; singularity = finalAttrs.finalPackage; }; }; gpuChecks = lib.optionalAttrs (projectName == "apptainer") { # Should be in tests, but Ofborg would skip image-hello-cowsay because # saxpy is unfree. image-saxpy = callPackage ({ singularity-tools, cudaPackages }: singularity-tools.buildImage { name = "saxpy"; contents = [ cudaPackages.saxpy ]; memSize = 2048; diskSize = 2048; singularity = finalAttrs.finalPackage; }) { }; saxpy = callPackage ({ runCommand, writeShellScriptBin }: let unwrapped = writeShellScriptBin "apptainer-cuda-saxpy" '' ${lib.getExe finalAttrs.finalPackage} exec --nv $@ ${finalAttrs.passthru.gpuChecks.image-saxpy} saxpy ''; in runCommand "run-apptainer-cuda-saxpy" { requiredSystemFeatures = [ "cuda" ]; nativeBuildInputs = [ unwrapped ]; passthru = { inherit unwrapped; }; } '' apptainer-cuda-saxpy '') { }; }; }; })