nixpkgs/pkgs/build-support/singularity-tools/default.nix
Yueh-Shun Li 50788d2fb0 apptainer, singularity: fix defaultPath and reflect upstream changes
Upstream changes:
singularity 3.8.7 (the legacy) -> apptainer 1.1.3 (the renamed) / singularity 3.10.4 (Sylabs's fork)

Build process:
*   Share between different sources
*   Fix the sed regexp to make defaultPath patch work
*   allowGoReference is now true
*   Provied input parameter removeCompat (default to false)
    that removes the compatible "*singularity*" symbolic links
    and related autocompletion files when projectName != "singularity"
*   Change localstatedir to /var/lib
*   Format with nixpkgs-fmt
*   Fix the defaultPath patching
    and use it instead of the `<executable> path` config directive
    deprecated in Apptainer
*   Provide dependencies for new functionalities such as
    squashfuse (unprivileged squashfs mount)
*   Provide an attribute `defaultPathInputs` to override
    prefix of container runtime default PATH

NixOS module programs.singularity:
*   Allow users to specify packages
*   Place related directories to /var/lib
*   Format with nixpkgs-fmt

singularity-tools:
*   Allow users to specify packages
*   Place related directories to /var/lib when building images in VM
2023-02-08 18:03:11 +08:00

123 lines
3.2 KiB
Nix

{ runCommand
, lib
, stdenv
, storeDir ? builtins.storeDir
, writeScript
, singularity
, writeReferencesToFile
, bash
, vmTools
, gawk
, util-linux
, runtimeShell
, e2fsprogs
}:
rec {
shellScript = name: text:
writeScript name ''
#!${runtimeShell}
set -e
${text}
'';
mkLayer =
{ name
, contents ? [ ]
# May be "apptainer" instead of "singularity"
, projectName ? (singularity.projectName or "singularity")
}:
runCommand "${projectName}-layer-${name}"
{
inherit contents;
} ''
mkdir $out
for f in $contents ; do
cp -ra $f $out/
done
'';
buildImage =
let
defaultSingularity = singularity;
in
{ name
, contents ? [ ]
, diskSize ? 1024
, runScript ? "#!${stdenv.shell}\nexec /bin/sh"
, runAsRoot ? null
, memSize ? 512
, singularity ? defaultSingularity
}:
let
projectName = singularity.projectName or "singularity";
layer = mkLayer {
inherit name;
contents = contents ++ [ bash runScriptFile ];
inherit projectName;
};
runAsRootFile = shellScript "run-as-root.sh" runAsRoot;
runScriptFile = shellScript "run-script.sh" runScript;
result = vmTools.runInLinuxVM (
runCommand "${projectName}-image-${name}.img"
{
buildInputs = [ singularity e2fsprogs util-linux gawk ];
layerClosure = writeReferencesToFile layer;
preVM = vmTools.createEmptyImage {
size = diskSize;
fullName = "${projectName}-run-disk";
};
inherit memSize;
}
''
rm -rf $out
mkdir disk
mkfs -t ext3 -b 4096 /dev/${vmTools.hd}
mount /dev/${vmTools.hd} disk
mkdir -p disk/img
cd disk/img
mkdir proc sys dev
# Run root script
${lib.optionalString (runAsRoot != null) ''
mkdir -p ./${storeDir}
mount --rbind ${storeDir} ./${storeDir}
unshare -imnpuf --mount-proc chroot ./ ${runAsRootFile}
umount -R ./${storeDir}
''}
# Build /bin and copy across closure
mkdir -p bin ./${builtins.storeDir}
for f in $(cat $layerClosure) ; do
cp -ar $f ./$f
done
for c in ${toString contents} ; do
for f in $c/bin/* ; do
if [ ! -e bin/$(basename $f) ] ; then
ln -s $f bin/
fi
done
done
# Create runScript and link shell
if [ ! -e bin/sh ]; then
ln -s ${runtimeShell} bin/sh
fi
mkdir -p .${projectName}.d
ln -s ${runScriptFile} .${projectName}.d/runscript
# Fill out .${projectName}.d
mkdir -p .${projectName}.d/env
touch .${projectName}.d/env/94-appsbase.sh
cd ..
mkdir -p /var/lib/${projectName}/mnt/{container,final,overlay,session,source}
echo "root:x:0:0:System administrator:/root:/bin/sh" > /etc/passwd
echo > /etc/resolv.conf
TMPDIR=$(pwd -P) ${projectName} build $out ./img
'');
in
result;
}