forked from mirrors/nixpkgs
084238c6ec
We now map all guest accounts to the root user, because in the end the permissions of the current user boil down to the build user of the Nix builder of the host. That way it's not possible to gain more permissions at all and just makes the VM communication a lot easier. However, setting "writable" to yes instead of "read only" to no doesn't change anything here, I just found it to be clearer. Also, we now no longer need to have a "nobody" user. Signed-off-by: aszlig <aszlig@redmoonstudios.org>
207 lines
5.5 KiB
Nix
207 lines
5.5 KiB
Nix
{ sshKey
|
|
, qemuArgs ? []
|
|
, command ? "sync"
|
|
, suspendTo ? null
|
|
, resumeFrom ? null
|
|
, installMode ? false
|
|
}:
|
|
|
|
let
|
|
inherit (import <nixpkgs> {}) lib stdenv writeScript vmTools makeInitrd;
|
|
inherit (import <nixpkgs> {}) samba vde2 openssh socat netcat coreutils gzip;
|
|
|
|
preInitScript = writeScript "preinit.sh" ''
|
|
#!${vmTools.initrdUtils}/bin/ash -e
|
|
export PATH=${vmTools.initrdUtils}/bin
|
|
mount -t proc none /proc
|
|
mount -t sysfs none /sys
|
|
for arg in $(cat /proc/cmdline); do
|
|
if [ "x''${arg#command=}" != "x$arg" ]; then
|
|
command="''${arg#command=}"
|
|
fi
|
|
done
|
|
|
|
for i in $(cat ${modulesClosure}/insmod-list); do
|
|
insmod $i
|
|
done
|
|
|
|
mkdir -p /dev /fs
|
|
|
|
mount -t tmpfs none /dev
|
|
mknod /dev/null c 1 3
|
|
mknod /dev/zero c 1 5
|
|
mknod /dev/random c 1 8
|
|
mknod /dev/urandom c 1 9
|
|
mknod /dev/tty c 5 0
|
|
|
|
ifconfig lo up
|
|
ifconfig eth0 up 192.168.0.2
|
|
|
|
mount -t tmpfs none /fs
|
|
mkdir -p /fs/nix/store /fs/xchg /fs/dev /fs/sys /fs/proc /fs/etc /fs/tmp
|
|
|
|
mount -o bind /dev /fs/dev
|
|
mount -t sysfs none /fs/sys
|
|
mount -t proc none /fs/proc
|
|
|
|
mount -t 9p \
|
|
-o trans=virtio,version=9p2000.L,msize=262144,cache=loose \
|
|
store /fs/nix/store
|
|
|
|
mount -t 9p \
|
|
-o trans=virtio,version=9p2000.L,msize=262144,cache=loose \
|
|
xchg /fs/xchg
|
|
|
|
echo root:x:0:0::/root:/bin/false > /fs/etc/passwd
|
|
|
|
set +e
|
|
chroot /fs $command $out
|
|
echo $? > /fs/xchg/in-vm-exit
|
|
|
|
poweroff -f
|
|
'';
|
|
|
|
initrd = makeInitrd {
|
|
contents = lib.singleton {
|
|
object = preInitScript;
|
|
symlink = "/init";
|
|
};
|
|
};
|
|
|
|
shellEscape = x: "'${lib.replaceChars ["'"] [("'\\'" + "'")] x}'";
|
|
|
|
loopForever = "while :; do ${coreutils}/bin/sleep 1; done";
|
|
|
|
initScript = writeScript "init.sh" (''
|
|
#!${stdenv.shell}
|
|
${coreutils}/bin/cp -L "${sshKey}" /ssh.key
|
|
${coreutils}/bin/chmod 600 /ssh.key
|
|
'' + (if installMode then ''
|
|
echo -n "Waiting for Windows installation to finish..."
|
|
while ! ${netcat}/bin/netcat -z 192.168.0.1 22; do
|
|
echo -n .
|
|
# Print a dot every 10 seconds only to shorten line length.
|
|
${coreutils}/bin/sleep 10
|
|
done
|
|
echo " success."
|
|
# Loop forever, because this VM is going to be killed.
|
|
${loopForever}
|
|
'' else ''
|
|
${coreutils}/bin/mkdir -p /etc/samba /etc/samba/private \
|
|
/var/lib/samba /var/log /var/run
|
|
${coreutils}/bin/cat > /etc/samba/smb.conf <<CONFIG
|
|
[global]
|
|
security = user
|
|
map to guest = Bad User
|
|
guest account = root
|
|
workgroup = cygwin
|
|
netbios name = controller
|
|
server string = %h
|
|
log level = 1
|
|
max log size = 1000
|
|
log file = /var/log/samba.log
|
|
|
|
[nixstore]
|
|
path = /nix/store
|
|
writable = yes
|
|
guest ok = yes
|
|
|
|
[xchg]
|
|
path = /xchg
|
|
writable = yes
|
|
guest ok = yes
|
|
CONFIG
|
|
|
|
${samba}/sbin/nmbd -D
|
|
${samba}/sbin/smbd -D
|
|
|
|
echo -n "Waiting for Windows VM to become available..."
|
|
while ! ${netcat}/bin/netcat -z 192.168.0.1 22; do
|
|
echo -n .
|
|
${coreutils}/bin/sleep 1
|
|
done
|
|
echo " success."
|
|
|
|
${openssh}/bin/ssh \
|
|
-o UserKnownHostsFile=/dev/null \
|
|
-o StrictHostKeyChecking=no \
|
|
-i /ssh.key \
|
|
-l Administrator \
|
|
192.168.0.1 -- ${shellEscape command}
|
|
|
|
${lib.optionalString (suspendTo != null) ''
|
|
${coreutils}/bin/touch /xchg/suspend_now
|
|
${loopForever}
|
|
''}
|
|
''));
|
|
|
|
kernelAppend = lib.concatStringsSep " " [
|
|
"panic=1"
|
|
"loglevel=4"
|
|
"console=tty1"
|
|
"console=ttyS0"
|
|
"command=${initScript}"
|
|
];
|
|
|
|
controllerQemuArgs = lib.concatStringsSep " " (maybeKvm64 ++ [
|
|
"-nographic"
|
|
"-no-reboot"
|
|
"-virtfs local,path=/nix/store,security_model=none,mount_tag=store"
|
|
"-virtfs local,path=$XCHG_DIR,security_model=none,mount_tag=xchg"
|
|
"-kernel ${modulesClosure.kernel}/bzImage"
|
|
"-initrd ${initrd}/initrd"
|
|
"-append \"${kernelAppend}\""
|
|
"-net nic,vlan=0,macaddr=52:54:00:12:01:02,model=virtio"
|
|
"-net vde,vlan=0,sock=$QEMU_VDE_SOCKET"
|
|
]);
|
|
|
|
maybeKvm64 = lib.optional (stdenv.system == "x86_64-linux") "-cpu kvm64";
|
|
|
|
cygwinQemuArgs = lib.concatStringsSep " " (maybeKvm64 ++ [
|
|
"-monitor unix:$MONITOR_SOCKET,server,nowait"
|
|
"-nographic"
|
|
"-net nic,vlan=0,macaddr=52:54:00:12:01:01"
|
|
"-net vde,vlan=0,sock=$QEMU_VDE_SOCKET"
|
|
"-rtc base=2010-01-01,clock=vm"
|
|
] ++ qemuArgs ++ lib.optionals (resumeFrom != null) [
|
|
"-incoming 'exec: ${gzip}/bin/gzip -c -d \"${resumeFrom}\"'"
|
|
]);
|
|
|
|
modulesClosure = lib.overrideDerivation vmTools.modulesClosure (o: {
|
|
rootModules = o.rootModules ++ lib.singleton "virtio_net";
|
|
});
|
|
|
|
preVM = ''
|
|
XCHG_DIR="$(${coreutils}/bin/mktemp -d nix-vm.XXXXXXXXXX --tmpdir)"
|
|
QEMU_VDE_SOCKET="$(pwd)/vde.ctl"
|
|
MONITOR_SOCKET="$(pwd)/monitor"
|
|
${vde2}/bin/vde_switch -s "$QEMU_VDE_SOCKET" &
|
|
echo 'alive?' | ${socat}/bin/socat - \
|
|
UNIX-CONNECT:$QEMU_VDE_SOCKET/ctl,retry=20
|
|
'';
|
|
|
|
bgBoth = lib.optionalString (suspendTo != null) " &";
|
|
|
|
vmExec = if installMode then ''
|
|
${vmTools.qemuProg} ${controllerQemuArgs} &
|
|
${vmTools.qemuProg} ${cygwinQemuArgs}${bgBoth}
|
|
'' else ''
|
|
${vmTools.qemuProg} ${cygwinQemuArgs} &
|
|
${vmTools.qemuProg} ${controllerQemuArgs}${bgBoth}
|
|
'' + lib.optionalString (suspendTo != null) ''
|
|
while ! test -e "$XCHG_DIR/suspend_now"; do sleep 1; done
|
|
${socat}/bin/socat - UNIX-CONNECT:$MONITOR_SOCKET <<CMD
|
|
stop
|
|
migrate_set_speed 4095m
|
|
migrate "exec:${gzip}/bin/gzip -c > '${suspendTo}'"
|
|
quit
|
|
CMD
|
|
wait %-
|
|
'';
|
|
|
|
in writeScript "run-cygwin-vm.sh" ''
|
|
#!${stdenv.shell} -e
|
|
${preVM}
|
|
${vmExec}
|
|
''
|