add docs to docker build functions

bring back ls_tar

replace goPackages with go

don't hardcode /nix/store in vmTools

more docs
This commit is contained in:
Allen Nelson 2016-09-27 23:42:05 +00:00
parent 58dc2f9d49
commit 4abe579250
2 changed files with 313 additions and 158 deletions

View File

@ -1,12 +1,30 @@
{ stdenv, lib, callPackage, runCommand, writeReferencesToFile, writeText, vmTools, writeScript {
, docker, shadow, utillinux, coreutils, jshon, e2fsprogs, go, pigz, findutils }: callPackage,
coreutils,
docker,
e2fsprogs,
findutils,
go,
jshon,
lib,
pigz,
runCommand,
shadow,
stdenv,
storeDir ? builtins.storeDir,
utillinux,
vmTools,
writeReferencesToFile,
writeScript,
writeText,
}:
# WARNING: this API is unstable and may be subject to backwards-incompatible changes in the future. # WARNING: this API is unstable and may be subject to backwards-incompatible changes in the future.
rec { rec {
pullImage = callPackage ./pull.nix {}; pullImage = callPackage ./pull.nix {};
# We need to sum layer.tar, not a directory, hence tarsum instead of nix-hash. # We need to sum layer.tar, not a directory, hence tarsum instead of nix-hash.
# And we cannot untar it, because then we cannot preserve permissions ecc. # And we cannot untar it, because then we cannot preserve permissions ecc.
tarsum = runCommand "tarsum" { tarsum = runCommand "tarsum" {
@ -23,110 +41,138 @@ rec {
cp tarsum $out cp tarsum $out
''; '';
# buildEnv creates symlinks to dirs, which is hard to edit inside the overlay VM # buildEnv creates symlinks to dirs, which is hard to edit inside the overlay VM
mergeDrvs = { drvs, onlyDeps ? false }: mergeDrvs = {
derivations,
onlyDeps ? false
}:
runCommand "merge-drvs" { runCommand "merge-drvs" {
inherit drvs onlyDeps; inherit derivations onlyDeps;
} '' } ''
if [ -n "$onlyDeps" ]; then if [[ -n "$onlyDeps" ]]; then
echo $drvs > $out echo $derivations > $out
exit 0 exit 0
fi fi
mkdir $out mkdir $out
for drv in $drvs; do for derivation in $derivations; do
echo Merging $drv echo "Merging $derivation..."
if [ -d "$drv" ]; then if [[ -d "$derivation" ]]; then
cp -drf --preserve=mode -f $drv/* $out/ # If it's a directory, copy all of its contents into $out.
cp -drf --preserve=mode -f $derivation/* $out/
else else
# Otherwise treat the derivation as a tarball and extract it
# into $out.
tar -C $out -xpf $drv || true tar -C $out -xpf $drv || true
fi fi
done done
''; '';
shellScript = text:
writeScript "script.sh" ''
#!${stdenv.shell}
set -e
export PATH=${coreutils}/bin:/bin
${text}
'';
# Helper for setting up the base files for managing users and
# groups, only if such files don't exist already. It is suitable for
# being used in a runAsRoot script.
shadowSetup = '' shadowSetup = ''
export PATH=${shadow}/bin:$PATH export PATH=${shadow}/bin:$PATH
mkdir -p /etc/pam.d mkdir -p /etc/pam.d
if [ ! -f /etc/passwd ]; then if [[ ! -f /etc/passwd ]]; then
echo "root:x:0:0::/root:/bin/sh" > /etc/passwd echo "root:x:0:0::/root:/bin/sh" > /etc/passwd
echo "root:!x:::::::" > /etc/shadow echo "root:!x:::::::" > /etc/shadow
fi fi
if [ ! -f /etc/group ]; then if [[ ! -f /etc/group ]]; then
echo "root:x:0:" > /etc/group echo "root:x:0:" > /etc/group
echo "root:x::" > /etc/gshadow echo "root:x::" > /etc/gshadow
fi fi
if [ ! -f /etc/pam.d/other ]; then if [[ ! -f /etc/pam.d/other ]]; then
cat > /etc/pam.d/other <<EOF cat > /etc/pam.d/other <<EOF
account sufficient pam_unix.so account sufficient pam_unix.so
auth sufficient pam_rootok.so auth sufficient pam_rootok.so
password requisite pam_unix.so nullok sha512 password requisite pam_unix.so nullok sha512
session required pam_unix.so session required pam_unix.so
EOF EOF
fi fi
if [ ! -f /etc/login.defs ]; then if [[ ! -f /etc/login.defs ]]; then
touch /etc/login.defs touch /etc/login.defs
fi fi
''; '';
runWithOverlay = { name , fromImage ? null, fromImageName ? null, fromImageTag ? null # Run commands in a virtual machine.
, diskSize ? 1024, preMount ? "", postMount ? "", postUmount ? "" }: runWithOverlay = {
name,
fromImage ? null,
fromImageName ? null,
fromImageTag ? null,
diskSize ? 1024,
preMount ? "",
postMount ? "",
postUmount ? ""
}:
vmTools.runInLinuxVM ( vmTools.runInLinuxVM (
runCommand name { runCommand name {
preVM = vmTools.createEmptyImage { size = diskSize; fullName = "docker-run-disk"; }; preVM = vmTools.createEmptyImage {
size = diskSize;
fullName = "docker-run-disk";
};
inherit fromImage fromImageName fromImageTag; inherit fromImage fromImageName fromImageTag;
buildInputs = [ utillinux e2fsprogs jshon ]; buildInputs = [ utillinux e2fsprogs jshon ];
} '' } ''
rm -rf $out rm -rf $out
mkdir disk mkdir disk
mkfs /dev/${vmTools.hd} mkfs /dev/${vmTools.hd}
mount /dev/${vmTools.hd} disk mount /dev/${vmTools.hd} disk
cd disk cd disk
if [ -n "$fromImage" ]; then if [[ -n "$fromImage" ]]; then
echo Unpacking base image echo "Unpacking base image..."
mkdir image mkdir image
tar -C image -xpf "$fromImage" tar -C image -xpf "$fromImage"
if [ -z "$fromImageName" ]; then # If the image name isn't set, read it from the image repository json.
fromImageName=$(jshon -k < image/repositories|head -n1) if [[ -z "$fromImageName" ]]; then
fromImageName=$(jshon -k < image/repositories | head -n 1)
echo "From-image name wasn't set. Read $fromImageName."
fi fi
if [ -z "$fromImageTag" ]; then
fromImageTag=$(jshon -e $fromImageName -k < image/repositories|head -n1) # If the tag isn't set, use the name as an index into the json
# and read the first key found.
if [[ -z "$fromImageTag" ]]; then
fromImageTag=$(jshon -e $fromImageName -k < image/repositories \
| head -n1)
echo "From-image tag wasn't set. Read $fromImageTag."
fi fi
parentID=$(jshon -e $fromImageName -e $fromImageTag -u < image/repositories)
# Use the name and tag to get the parent ID field.
parentID=$(jshon -e $fromImageName -e $fromImageTag -u \
< image/repositories)
fi fi
# Unpack all of the parent layers into the image.
lowerdir="" lowerdir=""
while [ -n "$parentID" ]; do while [[ -n "$parentID" ]]; do
echo Unpacking layer $parentID echo "Unpacking layer $parentID"
mkdir -p image/$parentID/layer mkdir -p image/$parentID/layer
tar -C image/$parentID/layer -xpf image/$parentID/layer.tar tar -C image/$parentID/layer -xpf image/$parentID/layer.tar
rm image/$parentID/layer.tar rm image/$parentID/layer.tar
find image/$parentID/layer -name ".wh.*" -exec bash -c 'name="$(basename {}|sed "s/^.wh.//")"; mknod "$(dirname {})/$name" c 0 0; rm {}' \; find image/$parentID/layer -name ".wh.*" -exec bash -c 'name="$(basename {}|sed "s/^.wh.//")"; mknod "$(dirname {})/$name" c 0 0; rm {}' \;
# Get the next lower directory and continue the loop.
lowerdir=$lowerdir''${lowerdir:+:}image/$parentID/layer lowerdir=$lowerdir''${lowerdir:+:}image/$parentID/layer
parentID=$(cat image/$parentID/json|(jshon -e parent -u 2>/dev/null || true)) parentID=$(cat image/$parentID/json \
| (jshon -e parent -u 2>/dev/null || true))
done done
mkdir work mkdir work
mkdir layer mkdir layer
mkdir mnt mkdir mnt
${preMount} ${lib.optionalString (preMount != "") ''
# Execute pre-mount steps
echo "Executing pre-mount steps..."
${preMount}
''}
if [ -n "$lowerdir" ]; then if [ -n "$lowerdir" ]; then
mount -t overlay overlay -olowerdir=$lowerdir,workdir=work,upperdir=layer mnt mount -t overlay overlay -olowerdir=$lowerdir,workdir=work,upperdir=layer mnt
@ -134,13 +180,19 @@ EOF
mount --bind layer mnt mount --bind layer mnt
fi fi
${postMount} ${lib.optionalString (postMount != "") ''
# Execute post-mount steps
echo "Executing post-mount steps..."
${postMount}
''}
umount mnt umount mnt
pushd layer (
find . -type c -exec bash -c 'name="$(basename {})"; touch "$(dirname {})/.wh.$name"; rm "{}"' \; cd layer
popd cmd='name="$(basename {})"; touch "$(dirname {})/.wh.$name"; rm "{}"'
find . -type c -exec bash -c "$cmd" \;
)
${postUmount} ${postUmount}
''); '');
@ -150,76 +202,150 @@ EOF
inherit name fromImage fromImageName fromImageTag diskSize; inherit name fromImage fromImageName fromImageTag diskSize;
postMount = '' postMount = ''
echo Packing raw image echo "Packing raw image..."
tar -C mnt --mtime=0 -cf $out . tar -C mnt --mtime=0 -cf $out .
''; '';
}; };
mkPureLayer = { baseJson, contents ? null, extraCommands ? "" }:
runCommand "docker-layer" { # Create an executable shell script which has the coreutils in its
# PATH. Since root scripts are executed in a blank environment, even
# things like `ls` or `echo` will be missing.
shellScript = name: text:
writeScript name ''
#!${stdenv.shell}
set -e
export PATH=${coreutils}/bin:/bin
${text}
'';
# Create a "layer" (set of files).
mkPureLayer = {
# Name of the layer
name,
# JSON containing configuration and metadata for this layer.
baseJson,
# Files to add to the layer.
contents ? null,
# Additional commands to run on the layer before it is tar'd up.
extraCommands ? ""
}:
runCommand "docker-layer-${name}" {
inherit baseJson contents extraCommands; inherit baseJson contents extraCommands;
buildInputs = [ jshon ]; buildInputs = [ jshon ];
} '' }
''
mkdir layer mkdir layer
if [ -n "$contents" ]; then if [[ -n "$contents" ]]; then
echo Adding contents echo "Adding contents..."
for c in $contents; do for item in $contents; do
cp -drf $c/* layer/ echo "Adding $item"
chmod -R ug+w layer/ cp -drf $item/* layer/
done done
chmod -R ug+w layer/
else
echo "No contents to add to layer."
fi fi
pushd layer if [[ -n $extraCommands ]]; then
${extraCommands} (cd layer; eval "$extraCommands")
popd fi
echo Packing layer # Tar up the layer and throw it into 'layer.tar'.
echo "Packing layer..."
mkdir $out mkdir $out
tar -C layer --mtime=0 -cf $out/layer.tar . tar -C layer --mtime=0 -cf $out/layer.tar .
ts=$(${tarsum} < $out/layer.tar)
cat ${baseJson} | jshon -s "$ts" -i checksum > $out/json # Compute a checksum of the tarball.
echo "Computing layer checksum..."
tarsum=$(${tarsum} < $out/layer.tar)
# Add a 'checksum' field to the JSON, with the value set to the
# checksum of the tarball.
cat ${baseJson} | jshon -s "$tarsum" -i checksum > $out/json
# Indicate to docker that we're using schema version 1.0.
echo -n "1.0" > $out/VERSION echo -n "1.0" > $out/VERSION
echo "Finished building layer '${name}'"
''; '';
mkRootLayer = { runAsRoot, baseJson, fromImage ? null, fromImageName ? null, fromImageTag ? null # Make a "root" layer; required if we need to execute commands as a
, diskSize ? 1024, contents ? null, extraCommands ? "" }: # privileged user on the image. The commands themselves will be
let runAsRootScript = writeScript "run-as-root.sh" runAsRoot; # performed in a virtual machine sandbox.
mkRootLayer = {
# Name of the image.
name,
# Script to run as root. Bash.
runAsRoot,
# Files to add to the layer. If null, an empty layer will be created.
contents ? null,
# JSON containing configuration and metadata for this layer.
baseJson,
# Existing image onto which to append the new layer.
fromImage ? null,
# Name of the image we're appending onto.
fromImageName ? null,
# Tag of the image we're appending onto.
fromImageTag ? null,
# How much disk to allocate for the temporary virtual machine.
diskSize ? 1024,
# Commands (bash) to run on the layer; these do not require sudo.
extraCommands ? ""
}:
# Generate an executable script from the `runAsRoot` text.
let runAsRootScript = shellScript "run-as-root.sh" runAsRoot;
in runWithOverlay { in runWithOverlay {
name = "docker-layer"; name = "docker-layer-${name}";
inherit fromImage fromImageName fromImageTag diskSize; inherit fromImage fromImageName fromImageTag diskSize;
preMount = lib.optionalString (contents != null) '' preMount = lib.optionalString (contents != null && contents != []) ''
echo Adding contents echo "Adding contents..."
for c in ${builtins.toString contents}; do for item in ${toString contents}; do
cp -drf $c/* layer/ echo "Adding $item..."
chmod -R ug+w layer/ cp -drf $item/* layer/
done done
chmod -R ug+w layer/
''; '';
postMount = '' postMount = ''
mkdir -p mnt/{dev,proc,sys,nix/store} mkdir -p mnt/{dev,proc,sys} mnt${storeDir}
# Mount /dev, /sys and the nix store as shared folders.
mount --rbind /dev mnt/dev mount --rbind /dev mnt/dev
mount --rbind /sys mnt/sys mount --rbind /sys mnt/sys
mount --rbind /nix/store mnt/nix/store mount --rbind ${storeDir} mnt${storeDir}
# Execute the run as root script. See 'man unshare' for
# details on what's going on here; basically this command
# means that the runAsRootScript will be executed in a nearly
# completely isolated environment.
unshare -imnpuf --mount-proc chroot mnt ${runAsRootScript} unshare -imnpuf --mount-proc chroot mnt ${runAsRootScript}
umount -R mnt/dev mnt/sys mnt/nix/store
rmdir --ignore-fail-on-non-empty mnt/dev mnt/proc mnt/sys mnt/nix/store mnt/nix
'';
postUmount = ''
pushd layer
${extraCommands}
popd
echo Packing layer # Unmount directories and remove them.
umount -R mnt/dev mnt/sys mnt${storeDir}
rmdir --ignore-fail-on-non-empty \
mnt/dev mnt/proc mnt/sys mnt${storeDir} \
mnt$(dirname ${storeDir})
'';
postUmount = ''
(cd layer; eval "${extraCommands}")
echo "Packing layer..."
mkdir $out mkdir $out
tar -C layer --mtime=0 -cf $out/layer.tar . tar -C layer --mtime=0 -cf $out/layer.tar .
# Compute the tar checksum and add it to the output json.
echo "Computing checksum..."
ts=$(${tarsum} < $out/layer.tar) ts=$(${tarsum} < $out/layer.tar)
cat ${baseJson} | jshon -s "$ts" -i checksum > $out/json cat ${baseJson} | jshon -s "$ts" -i checksum > $out/json
# Indicate to docker that we're using schema version 1.0.
echo -n "1.0" > $out/VERSION echo -n "1.0" > $out/VERSION
echo "Finished building layer '${name}'"
''; '';
}; };
@ -229,116 +355,144 @@ EOF
# 4. compute the layer id # 4. compute the layer id
# 5. put the layer in the image # 5. put the layer in the image
# 6. repack the image # 6. repack the image
buildImage = args@{ name, tag ? "latest" buildImage = args@{
, fromImage ? null, fromImageName ? null, fromImageTag ? null # Image name.
, contents ? null, config ? null, runAsRoot ? null name,
, diskSize ? 1024, extraCommands ? "" }: # Image tag.
tag ? "latest",
# Parent image, to append to.
fromImage ? null,
# Name of the parent image; will be read from the image otherwise.
fromImageName ? null,
# Tag of the parent image; will be read from the image otherwise.
fromImageTag ? null,
# Files to put on the image (a nix store path or list of paths).
contents ? null,
# Docker config; e.g. what command to run on the container.
config ? null,
# Optional bash script to run on the files prior to fixturizing the layer.
extraCommands ? "",
# Optional bash script to run as root on the image when provisioning.
runAsRoot ? null,
# Size of the virtual machine disk to provision when building the image.
diskSize ? 1024,
}:
let let
baseName = baseNameOf name; baseName = baseNameOf name;
# Create a JSON blob of the configuration. Set the date to unix zero.
baseJson = writeText "${baseName}-config.json" (builtins.toJSON { baseJson = writeText "${baseName}-config.json" (builtins.toJSON {
created = "1970-01-01T00:00:01Z"; created = "1970-01-01T00:00:01Z";
architecture = "amd64"; architecture = "amd64";
os = "linux"; os = "linux";
config = config; config = config;
}); });
layer = (if runAsRoot == null layer =
then mkPureLayer { inherit baseJson contents extraCommands; } if runAsRoot == null
else mkRootLayer { inherit baseJson fromImage fromImageName fromImageTag contents runAsRoot diskSize extraCommands; }); then mkPureLayer { inherit name baseJson contents extraCommands; }
result = runCommand "${baseName}.tar.gz" { else mkRootLayer { inherit name baseJson fromImage fromImageName
fromImageTag contents runAsRoot diskSize
extraCommands; };
result = runCommand "docker-image-${baseName}.tar.gz" {
buildInputs = [ jshon pigz coreutils findutils ]; buildInputs = [ jshon pigz coreutils findutils ];
imageName = name; imageName = name;
imageTag = tag; imageTag = tag;
inherit fromImage baseJson; inherit fromImage baseJson;
layerClosure = writeReferencesToFile layer; layerClosure = writeReferencesToFile layer;
passthru.buildArgs = args;
passthru = { passthru.layer = layer;
buildArgs = args;
};
} '' } ''
# Print tar contents: # Print tar contents:
# 1: Interpreted as relative to the root directory # 1: Interpreted as relative to the root directory
# 2: With no trailing slashes on directories # 2: With no trailing slashes on directories
# This is useful for ensuring that the output matches the values generated by the "find" command # This is useful for ensuring that the output matches the
# values generated by the "find" command
ls_tar() { ls_tar() {
for f in $(tar -tf $1 | xargs realpath -ms --relative-to=.); do for f in $(tar -tf $1 | xargs realpath -ms --relative-to=.); do
if [ "$f" != "." ]; then if [[ "$f" != "." ]]; then
echo "/$f" echo "/$f"
fi fi
done done
} }
mkdir image mkdir image
touch baseFiles touch baseFiles
if [ -n "$fromImage" ]; then if [[ -n "$fromImage" ]]; then
echo Unpacking base image echo "Unpacking base image..."
tar -C image -xpf "$fromImage" tar -C image -xpf "$fromImage"
if [ -z "$fromImageName" ]; then if [[ -z "$fromImageName" ]]; then
fromImageName=$(jshon -k < image/repositories|head -n1) fromImageName=$(jshon -k < image/repositories|head -n1)
fi fi
if [ -z "$fromImageTag" ]; then if [[ -z "$fromImageTag" ]]; then
fromImageTag=$(jshon -e $fromImageName -k < image/repositories|head -n1) fromImageTag=$(jshon -e $fromImageName -k \
< image/repositories|head -n1)
fi fi
parentID=$(jshon -e $fromImageName -e $fromImageTag -u < image/repositories) parentID=$(jshon -e $fromImageName -e $fromImageTag -u \
< image/repositories)
for l in image/*/layer.tar; do for l in image/*/layer.tar; do
ls_tar $l >> baseFiles ls_tar image/*/layer.tar >> baseFiles
done done
fi fi
chmod -R ug+rw image chmod -R ug+rw image
mkdir temp mkdir temp
cp ${layer}/* temp/ cp ${layer}/* temp/
chmod ug+w temp/* chmod ug+w temp/*
echo "$(dirname ${storeDir})" >> layerFiles
echo '${storeDir}' >> layerFiles
for dep in $(cat $layerClosure); do for dep in $(cat $layerClosure); do
find $dep -path "${layer}" -prune -o -print >> layerFiles find $dep >> layerFiles
done done
if [ -s layerFiles ]; then echo "Adding layer..."
# FIXME: might not be /nix/store # Record the contents of the tarball with ls_tar.
echo '/nix' >> layerFiles
echo '/nix/store' >> layerFiles
fi
echo Adding layer
ls_tar temp/layer.tar >> baseFiles ls_tar temp/layer.tar >> baseFiles
comm <(sort -u baseFiles) <(sort -u layerFiles) -1 -3 > newFiles
tar -rpf temp/layer.tar --mtime=0 --no-recursion --files-from newFiles 2>/dev/null || true
echo Adding meta # Get the files in the new layer which were *not* present in
# the old layer, and record them as newFiles.
if [ -n "$parentID" ]; then comm <(sort -n baseFiles|uniq) \
<(sort -n layerFiles|uniq|grep -v ${layer}) -1 -3 > newFiles
# Append the new files to the layer.
tar -rpf temp/layer.tar --mtime=0 --no-recursion --files-from newFiles
echo "Adding meta..."
# If we have a parentID, add it to the json metadata.
if [[ -n "$parentID" ]]; then
cat temp/json | jshon -s "$parentID" -i parent > tmpjson cat temp/json | jshon -s "$parentID" -i parent > tmpjson
mv tmpjson temp/json mv tmpjson temp/json
fi fi
# Take the sha256 sum of the generated json and use it as the layer ID.
# Compute the size and add it to the json under the 'Size' field.
layerID=$(sha256sum temp/json|cut -d ' ' -f 1) layerID=$(sha256sum temp/json|cut -d ' ' -f 1)
size=$(stat --printf="%s" temp/layer.tar) size=$(stat --printf="%s" temp/layer.tar)
cat temp/json | jshon -s "$layerID" -i id -n $size -i Size > tmpjson cat temp/json | jshon -s "$layerID" -i id -n $size -i Size > tmpjson
mv tmpjson temp/json mv tmpjson temp/json
# Use the temp folder we've been working on to create a new image.
mv temp image/$layerID mv temp image/$layerID
# Store the json under the name image/repositories.
jshon -n object \ jshon -n object \
-n object -s "$layerID" -i "$imageTag" \ -n object -s "$layerID" -i "$imageTag" \
-i "$imageName" > image/repositories -i "$imageName" > image/repositories
# Make the image read-only.
chmod -R a-w image chmod -R a-w image
echo Cooking the image echo "Cooking the image..."
tar -C image --mtime=0 -c . | pigz -nT > $out tar -C image --mtime=0 -c . | pigz -nT > $out
echo "Finished."
''; '';
in in
result;
result;
} }

View File

@ -1,6 +1,7 @@
{ pkgs { pkgs
, kernel ? pkgs.linux , kernel ? pkgs.linux
, img ? "bzImage" , img ? "bzImage"
, storeDir ? builtins.storeDir
, rootModules ? , rootModules ?
[ "virtio_pci" "virtio_blk" "virtio_balloon" "virtio_rng" "ext4" "unix" "9p" "9pnet_virtio" "rtc_cmos" ] [ "virtio_pci" "virtio_blk" "virtio_balloon" "virtio_rng" "ext4" "unix" "9p" "9pnet_virtio" "rtc_cmos" ]
}: }:
@ -128,8 +129,8 @@ rec {
mount -t devpts none /fs/dev/pts mount -t devpts none /fs/dev/pts
echo "mounting Nix store..." echo "mounting Nix store..."
mkdir -p /fs/nix/store mkdir -p /fs${storeDir}
mount -t 9p store /fs/nix/store -o trans=virtio,version=9p2000.L,cache=loose mount -t 9p store /fs${storeDir} -o trans=virtio,version=9p2000.L,cache=loose
mkdir -p /fs/tmp /fs/run /fs/var mkdir -p /fs/tmp /fs/run /fs/var
mount -t tmpfs -o "mode=1777" none /fs/tmp mount -t tmpfs -o "mode=1777" none /fs/tmp
@ -172,7 +173,7 @@ rec {
# apparent KVM > 1.5.2 bug. # apparent KVM > 1.5.2 bug.
${pkgs.utillinux}/bin/hwclock -s ${pkgs.utillinux}/bin/hwclock -s
export NIX_STORE=/nix/store export NIX_STORE=${storeDir}
export NIX_BUILD_TOP=/tmp export NIX_BUILD_TOP=/tmp
export TMPDIR=/tmp export TMPDIR=/tmp
export PATH=/empty export PATH=/empty
@ -220,7 +221,7 @@ rec {
${lib.optionalString (pkgs.stdenv.system == "x86_64-linux") "-cpu kvm64"} \ ${lib.optionalString (pkgs.stdenv.system == "x86_64-linux") "-cpu kvm64"} \
-nographic -no-reboot \ -nographic -no-reboot \
-device virtio-rng-pci \ -device virtio-rng-pci \
-virtfs local,path=/nix/store,security_model=none,mount_tag=store \ -virtfs local,path=${storeDir},security_model=none,mount_tag=store \
-virtfs local,path=$TMPDIR/xchg,security_model=none,mount_tag=xchg \ -virtfs local,path=$TMPDIR/xchg,security_model=none,mount_tag=xchg \
-drive file=$diskImage,if=virtio,cache=unsafe,werror=report \ -drive file=$diskImage,if=virtio,cache=unsafe,werror=report \
-kernel ${kernel}/${img} \ -kernel ${kernel}/${img} \
@ -298,7 +299,7 @@ rec {
/* Run a derivation in a Linux virtual machine (using Qemu/KVM). By /* Run a derivation in a Linux virtual machine (using Qemu/KVM). By
default, there is no disk image; the root filesystem is a tmpfs, default, there is no disk image; the root filesystem is a tmpfs,
and /nix/store is shared with the host (via the 9P protocol). and the nix store is shared with the host (via the 9P protocol).
Thus, any pure Nix derivation should run unmodified, e.g. the Thus, any pure Nix derivation should run unmodified, e.g. the
call call
@ -434,8 +435,8 @@ rec {
chroot=$(type -tP chroot) chroot=$(type -tP chroot)
# Make the Nix store available in /mnt, because that's where the RPMs live. # Make the Nix store available in /mnt, because that's where the RPMs live.
mkdir -p /mnt/nix/store mkdir -p /mnt${storeDir}
${utillinux}/bin/mount -o bind /nix/store /mnt/nix/store ${utillinux}/bin/mount -o bind ${storeDir} /mnt${storeDir}
# Newer distributions like Fedora 18 require /lib etc. to be # Newer distributions like Fedora 18 require /lib etc. to be
# symlinked to /usr. # symlinked to /usr.
@ -474,7 +475,7 @@ rec {
rm /mnt/.debug rm /mnt/.debug
${utillinux}/bin/umount /mnt/nix/store /mnt/tmp ${lib.optionalString unifiedSystemDir "/mnt/proc"} ${utillinux}/bin/umount /mnt${storeDir} /mnt/tmp ${lib.optionalString unifiedSystemDir "/mnt/proc"}
${utillinux}/bin/umount /mnt ${utillinux}/bin/umount /mnt
''; '';
@ -605,8 +606,8 @@ rec {
done done
# Make the Nix store available in /mnt, because that's where the .debs live. # Make the Nix store available in /mnt, because that's where the .debs live.
mkdir -p /mnt/inst/nix/store mkdir -p /mnt/inst${storeDir}
${utillinux}/bin/mount -o bind /nix/store /mnt/inst/nix/store ${utillinux}/bin/mount -o bind ${storeDir} /mnt/inst${storeDir}
${utillinux}/bin/mount -o bind /proc /mnt/proc ${utillinux}/bin/mount -o bind /proc /mnt/proc
${utillinux}/bin/mount -o bind /dev /mnt/dev ${utillinux}/bin/mount -o bind /dev /mnt/dev
@ -654,7 +655,7 @@ rec {
rm /mnt/.debug rm /mnt/.debug
${utillinux}/bin/umount /mnt/inst/nix/store ${utillinux}/bin/umount /mnt/inst${storeDir}
${utillinux}/bin/umount /mnt/proc ${utillinux}/bin/umount /mnt/proc
${utillinux}/bin/umount /mnt/dev ${utillinux}/bin/umount /mnt/dev
${utillinux}/bin/umount /mnt ${utillinux}/bin/umount /mnt