Merge branch 'master' into extra-binds
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
{
|
||||
imports = [ <nixpkgs/nixos/modules/virtualisation/amazon-image.nix> ];
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
# This module automatically grows the root partition on Amazon EC2 HVM
|
||||
# instances. This allows an instance to be created with a bigger root
|
||||
# filesystem than provided by the AMI.
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
growpart = pkgs.stdenv.mkDerivation {
|
||||
name = "growpart";
|
||||
src = pkgs.fetchurl {
|
||||
url = "https://launchpad.net/cloud-utils/trunk/0.27/+download/cloud-utils-0.27.tar.gz";
|
||||
sha256 = "16shlmg36lidp614km41y6qk3xccil02f5n3r4wf6d1zr5n4v8vd";
|
||||
};
|
||||
patches = [ ./growpart-util-linux-2.26.patch ];
|
||||
buildPhase = ''
|
||||
cp bin/growpart $out
|
||||
sed -i 's|awk|gawk|' $out
|
||||
sed -i 's|sed|gnused|' $out
|
||||
'';
|
||||
dontInstall = true;
|
||||
dontPatchShebangs = true;
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
config = mkIf config.ec2.hvm {
|
||||
|
||||
boot.initrd.extraUtilsCommands = ''
|
||||
copy_bin_and_libs ${pkgs.gawk}/bin/gawk
|
||||
copy_bin_and_libs ${pkgs.gnused}/bin/sed
|
||||
copy_bin_and_libs ${pkgs.utillinux}/sbin/sfdisk
|
||||
cp -v ${growpart} $out/bin/growpart
|
||||
ln -s sed $out/bin/gnused
|
||||
'';
|
||||
|
||||
boot.initrd.postDeviceCommands = ''
|
||||
[ -e /dev/xvda ] && [ -e /dev/xvda1 ] && TMPDIR=/run sh $(type -P growpart) /dev/xvda 1
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,95 +1,28 @@
|
||||
# Configuration for Amazon EC2 instances. (Note that this file is a
|
||||
# misnomer - it should be "amazon-config.nix" or so, not
|
||||
# "amazon-image.nix", since it's used not only to build images but
|
||||
# also to reconfigure instances. However, we can't rename it because
|
||||
# existing "configuration.nix" files on EC2 instances refer to it.)
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
cfg = config.ec2;
|
||||
in
|
||||
|
||||
let cfg = config.ec2; in
|
||||
|
||||
{
|
||||
imports = [ ../profiles/headless.nix ./ec2-data.nix ];
|
||||
imports = [ ../profiles/headless.nix ./ec2-data.nix ./amazon-grow-partition.nix ];
|
||||
|
||||
config = {
|
||||
system.build.amazonImage =
|
||||
pkgs.vmTools.runInLinuxVM (
|
||||
pkgs.runCommand "amazon-image"
|
||||
{ preVM =
|
||||
''
|
||||
mkdir $out
|
||||
diskImage=$out/nixos.img
|
||||
${pkgs.vmTools.qemu}/bin/qemu-img create -f raw $diskImage "8G"
|
||||
mv closure xchg/
|
||||
'';
|
||||
buildInputs = [ pkgs.utillinux pkgs.perl ];
|
||||
exportReferencesGraph =
|
||||
[ "closure" config.system.build.toplevel ];
|
||||
}
|
||||
''
|
||||
${if cfg.hvm then ''
|
||||
# Create a single / partition.
|
||||
${pkgs.parted}/sbin/parted /dev/vda mklabel msdos
|
||||
${pkgs.parted}/sbin/parted /dev/vda -- mkpart primary ext2 1M -1s
|
||||
. /sys/class/block/vda1/uevent
|
||||
mknod /dev/vda1 b $MAJOR $MINOR
|
||||
|
||||
# Create an empty filesystem and mount it.
|
||||
${pkgs.e2fsprogs}/sbin/mkfs.ext4 -L nixos /dev/vda1
|
||||
${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda1
|
||||
mkdir /mnt
|
||||
mount /dev/vda1 /mnt
|
||||
'' else ''
|
||||
# Create an empty filesystem and mount it.
|
||||
${pkgs.e2fsprogs}/sbin/mkfs.ext4 -L nixos /dev/vda
|
||||
${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda
|
||||
mkdir /mnt
|
||||
mount /dev/vda /mnt
|
||||
''}
|
||||
|
||||
# The initrd expects these directories to exist.
|
||||
mkdir /mnt/dev /mnt/proc /mnt/sys
|
||||
|
||||
mount -o bind /proc /mnt/proc
|
||||
mount -o bind /dev /mnt/dev
|
||||
mount -o bind /sys /mnt/sys
|
||||
|
||||
# Copy all paths in the closure to the filesystem.
|
||||
storePaths=$(perl ${pkgs.pathsFromGraph} /tmp/xchg/closure)
|
||||
|
||||
mkdir -p /mnt/nix/store
|
||||
echo "copying everything (will take a while)..."
|
||||
cp -prd $storePaths /mnt/nix/store/
|
||||
|
||||
# Register the paths in the Nix database.
|
||||
printRegistration=1 perl ${pkgs.pathsFromGraph} /tmp/xchg/closure | \
|
||||
chroot /mnt ${config.nix.package}/bin/nix-store --load-db --option build-users-group ""
|
||||
|
||||
# Create the system profile to allow nixos-rebuild to work.
|
||||
chroot /mnt ${config.nix.package}/bin/nix-env --option build-users-group "" \
|
||||
-p /nix/var/nix/profiles/system --set ${config.system.build.toplevel}
|
||||
|
||||
# `nixos-rebuild' requires an /etc/NIXOS.
|
||||
mkdir -p /mnt/etc
|
||||
touch /mnt/etc/NIXOS
|
||||
|
||||
# `switch-to-configuration' requires a /bin/sh
|
||||
mkdir -p /mnt/bin
|
||||
ln -s ${config.system.build.binsh}/bin/sh /mnt/bin/sh
|
||||
|
||||
# Install a configuration.nix.
|
||||
mkdir -p /mnt/etc/nixos
|
||||
cp ${./amazon-config.nix} /mnt/etc/nixos/configuration.nix
|
||||
|
||||
# Generate the GRUB menu.
|
||||
ln -s vda /dev/xvda
|
||||
chroot /mnt ${config.system.build.toplevel}/bin/switch-to-configuration boot
|
||||
|
||||
umount /mnt/proc /mnt/dev /mnt/sys
|
||||
umount /mnt
|
||||
''
|
||||
);
|
||||
|
||||
fileSystems."/".device = "/dev/disk/by-label/nixos";
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-label/nixos";
|
||||
autoResize = true;
|
||||
};
|
||||
|
||||
boot.initrd.kernelModules = [ "xen-blkfront" ];
|
||||
boot.kernelModules = [ "xen-netfront" ];
|
||||
boot.kernelParams = mkIf cfg.hvm [ "console=ttyS0" ];
|
||||
|
||||
# Prevent the nouveau kernel module from being loaded, as it
|
||||
# interferes with the nvidia/nvidia-uvm modules needed for CUDA.
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
{ config, pkgs, modulesPath, ... }:
|
||||
|
||||
# This attempts to pull a nix expression from this EC2 instance's user-data.
|
||||
|
||||
let
|
||||
bootScript = pkgs.writeScript "bootscript.sh" ''
|
||||
#!${pkgs.stdenv.shell} -eux
|
||||
|
||||
echo "attempting to fetch configuration from user-data..."
|
||||
|
||||
export PATH=${config.nix.package}/bin:${pkgs.wget}/bin:${pkgs.systemd}/bin:${pkgs.gnugrep}/bin:${pkgs.gnused}/bin:${config.system.build.nixos-rebuild}/bin:$PATH
|
||||
export NIX_PATH=/nix/var/nix/profiles/per-user/root/channels/nixos:nixos-config=/etc/nixos/configuration.nix:/nix/var/nix/profiles/per-user/root/channels
|
||||
|
||||
userData="$(mktemp)"
|
||||
wget -q --wait=1 --tries=0 --retry-connrefused -O - http://169.254.169.254/2011-01-01/user-data > "$userData"
|
||||
|
||||
if [[ $? -eq 0 ]]; then
|
||||
echo "user-data fetched"
|
||||
# If the user-data looks like it could be a nix expression,
|
||||
# copy it over. Also, look for a magic three-hash comment and set
|
||||
# that as the channel.
|
||||
if sed '/^\(#\|SSH_HOST_.*\)/d' < "$userData" | grep -q '\S'; then
|
||||
channels="$(grep '^###' "$userData" | sed 's|###\s*||')"
|
||||
printf "%s" "$channels" | while read channel; do
|
||||
echo "writing channel: $channel"
|
||||
done
|
||||
|
||||
if [[ -n "$channels" ]]; then
|
||||
printf "%s" "$channels" > /root/.nix-channels
|
||||
nix-channel --update
|
||||
fi
|
||||
|
||||
echo "setting configuration"
|
||||
cp "$userData" /etc/nixos/configuration.nix
|
||||
else
|
||||
echo "user-data does not appear to be a nix expression; ignoring"
|
||||
fi
|
||||
else
|
||||
echo "failed to fetch user-data"
|
||||
fi
|
||||
|
||||
type -f nixos-rebuild
|
||||
|
||||
nixos-rebuild switch
|
||||
'';
|
||||
in {
|
||||
imports = [ "${modulesPath}/virtualisation/amazon-image.nix" ];
|
||||
boot.postBootCommands = ''
|
||||
${bootScript} &
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
{
|
||||
imports = [ ../profiles/headless.nix ];
|
||||
|
||||
boot.kernelParams = [ "console=ttyS0" "earlyprintk=ttyS0" "rootdelay=300" "panic=1" "boot.panic_on_fail" ];
|
||||
boot.initrd.kernelModules = [ "hv_vmbus" "hv_netvsc" "hv_utils" "hv_storvsc" ];
|
||||
|
||||
# Generate a GRUB menu.
|
||||
boot.loader.grub.device = "/dev/sda";
|
||||
boot.loader.grub.version = 2;
|
||||
boot.loader.grub.timeout = 0;
|
||||
|
||||
# Don't put old configurations in the GRUB menu. The user has no
|
||||
# way to select them anyway.
|
||||
boot.loader.grub.configurationLimit = 0;
|
||||
|
||||
fileSystems."/".device = "/dev/disk/by-label/nixos";
|
||||
|
||||
# Allow root logins only using the SSH key that the user specified
|
||||
# at instance creation time, ping client connections to avoid timeouts
|
||||
services.openssh.enable = true;
|
||||
services.openssh.permitRootLogin = "without-password";
|
||||
services.openssh.extraConfig = ''
|
||||
ClientAliveInterval 180
|
||||
'';
|
||||
|
||||
# Force getting the hostname from Azure
|
||||
networking.hostName = mkDefault "";
|
||||
|
||||
# Always include cryptsetup so that NixOps can use it.
|
||||
# sg_scan is needed to finalize disk removal on older kernels
|
||||
environment.systemPackages = [ pkgs.cryptsetup pkgs.sg3_utils ];
|
||||
|
||||
networking.usePredictableInterfaceNames = false;
|
||||
|
||||
services.udev.extraRules = ''
|
||||
ENV{DEVTYPE}=="disk", KERNEL!="sda" SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNELS=="?:0:0:0", ATTR{removable}=="0", SYMLINK+="disk/by-lun/0",
|
||||
ENV{DEVTYPE}=="disk", KERNEL!="sda" SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNELS=="?:0:0:1", ATTR{removable}=="0", SYMLINK+="disk/by-lun/1",
|
||||
ENV{DEVTYPE}=="disk", KERNEL!="sda" SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNELS=="?:0:0:2", ATTR{removable}=="0", SYMLINK+="disk/by-lun/2"
|
||||
ENV{DEVTYPE}=="disk", KERNEL!="sda" SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNELS=="?:0:0:3", ATTR{removable}=="0", SYMLINK+="disk/by-lun/3"
|
||||
|
||||
ENV{DEVTYPE}=="disk", KERNEL!="sda" SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNELS=="?:0:0:4", ATTR{removable}=="0", SYMLINK+="disk/by-lun/4"
|
||||
ENV{DEVTYPE}=="disk", KERNEL!="sda" SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNELS=="?:0:0:5", ATTR{removable}=="0", SYMLINK+="disk/by-lun/5"
|
||||
ENV{DEVTYPE}=="disk", KERNEL!="sda" SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNELS=="?:0:0:6", ATTR{removable}=="0", SYMLINK+="disk/by-lun/6"
|
||||
ENV{DEVTYPE}=="disk", KERNEL!="sda" SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNELS=="?:0:0:7", ATTR{removable}=="0", SYMLINK+="disk/by-lun/7"
|
||||
|
||||
ENV{DEVTYPE}=="disk", KERNEL!="sda" SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNELS=="?:0:0:8", ATTR{removable}=="0", SYMLINK+="disk/by-lun/8"
|
||||
ENV{DEVTYPE}=="disk", KERNEL!="sda" SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNELS=="?:0:0:9", ATTR{removable}=="0", SYMLINK+="disk/by-lun/9"
|
||||
ENV{DEVTYPE}=="disk", KERNEL!="sda" SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNELS=="?:0:0:10", ATTR{removable}=="0", SYMLINK+="disk/by-lun/10"
|
||||
ENV{DEVTYPE}=="disk", KERNEL!="sda" SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNELS=="?:0:0:11", ATTR{removable}=="0", SYMLINK+="disk/by-lun/11"
|
||||
|
||||
ENV{DEVTYPE}=="disk", KERNEL!="sda" SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNELS=="?:0:0:12", ATTR{removable}=="0", SYMLINK+="disk/by-lun/12"
|
||||
ENV{DEVTYPE}=="disk", KERNEL!="sda" SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNELS=="?:0:0:13", ATTR{removable}=="0", SYMLINK+="disk/by-lun/13"
|
||||
ENV{DEVTYPE}=="disk", KERNEL!="sda" SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNELS=="?:0:0:14", ATTR{removable}=="0", SYMLINK+="disk/by-lun/14"
|
||||
ENV{DEVTYPE}=="disk", KERNEL!="sda" SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNELS=="?:0:0:15", ATTR{removable}=="0", SYMLINK+="disk/by-lun/15"
|
||||
|
||||
'';
|
||||
|
||||
}
|
||||
@@ -5,8 +5,6 @@ let
|
||||
diskSize = "4096";
|
||||
in
|
||||
{
|
||||
imports = [ ../profiles/headless.nix ];
|
||||
|
||||
system.build.azureImage =
|
||||
pkgs.vmTools.runInLinuxVM (
|
||||
pkgs.runCommand "azure-image"
|
||||
@@ -24,12 +22,11 @@ in
|
||||
|
||||
postVM =
|
||||
''
|
||||
echo Converting
|
||||
mkdir -p $out
|
||||
${pkgs.vmTools.qemu}/bin/qemu-img convert -f raw -O vpc $diskImage $out/disk.vhd
|
||||
rm $diskImage
|
||||
'';
|
||||
diskImageBase = "nixos-${config.system.nixosVersion}-${pkgs.stdenv.system}.raw";
|
||||
diskImageBase = "nixos-image-${config.system.nixosVersion}-${pkgs.stdenv.system}.raw";
|
||||
buildInputs = [ pkgs.utillinux pkgs.perl ];
|
||||
exportReferencesGraph =
|
||||
[ "closure" config.system.build.toplevel ];
|
||||
@@ -93,34 +90,11 @@ in
|
||||
''
|
||||
);
|
||||
|
||||
fileSystems."/".device = "/dev/disk/by-label/nixos";
|
||||
imports = [ ./azure-common.nix ];
|
||||
|
||||
# Azure metadata is available as a CD-ROM drive.
|
||||
fileSystems."/metadata".device = "/dev/sr0";
|
||||
|
||||
boot.kernelParams = [ "console=ttyS0" "earlyprintk=ttyS0" "rootdelay=300" "panic=1" "boot.panic_on_fail" ];
|
||||
boot.initrd.kernelModules = [ "hv_vmbus" "hv_netvsc" "hv_utils" "hv_storvsc" ];
|
||||
|
||||
# Generate a GRUB menu.
|
||||
boot.loader.grub.device = "/dev/sda";
|
||||
boot.loader.grub.version = 2;
|
||||
boot.loader.grub.timeout = 0;
|
||||
|
||||
# Don't put old configurations in the GRUB menu. The user has no
|
||||
# way to select them anyway.
|
||||
boot.loader.grub.configurationLimit = 0;
|
||||
|
||||
# Allow root logins only using the SSH key that the user specified
|
||||
# at instance creation time.
|
||||
services.openssh.enable = true;
|
||||
services.openssh.permitRootLogin = "without-password";
|
||||
|
||||
# Force getting the hostname from Azure
|
||||
networking.hostName = mkDefault "";
|
||||
|
||||
# Always include cryptsetup so that NixOps can use it.
|
||||
environment.systemPackages = [ pkgs.cryptsetup ];
|
||||
|
||||
systemd.services.fetch-ssh-keys =
|
||||
{ description = "Fetch host keys and authorized_keys for root user";
|
||||
|
||||
@@ -157,8 +131,4 @@ in
|
||||
serviceConfig.StandardOutput = "journal+console";
|
||||
};
|
||||
|
||||
networking.usePredictableInterfaceNames = false;
|
||||
|
||||
#users.extraUsers.root.openssh.authorizedKeys.keys = [ (builtins.readFile <ssh-pub-key>) ];
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
{ config, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports = [ "${modulesPath}/virtualisation/brightbox-image.nix" ];
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
diskSize = "20G";
|
||||
in
|
||||
{
|
||||
imports = [ ../profiles/headless.nix ../profiles/qemu-guest.nix ];
|
||||
|
||||
system.build.brightboxImage =
|
||||
pkgs.vmTools.runInLinuxVM (
|
||||
pkgs.runCommand "brightbox-image"
|
||||
{ preVM =
|
||||
''
|
||||
mkdir $out
|
||||
diskImage=$out/$diskImageBase
|
||||
truncate $diskImage --size ${diskSize}
|
||||
mv closure xchg/
|
||||
'';
|
||||
|
||||
postVM =
|
||||
''
|
||||
PATH=$PATH:${pkgs.gnutar}/bin:${pkgs.gzip}/bin
|
||||
pushd $out
|
||||
${pkgs.qemu_kvm}/bin/qemu-img convert -c -O qcow2 $diskImageBase nixos.qcow2
|
||||
rm $diskImageBase
|
||||
popd
|
||||
'';
|
||||
diskImageBase = "nixos-image-${config.system.nixosVersion}-${pkgs.stdenv.system}.raw";
|
||||
buildInputs = [ pkgs.utillinux pkgs.perl ];
|
||||
exportReferencesGraph =
|
||||
[ "closure" config.system.build.toplevel ];
|
||||
}
|
||||
''
|
||||
# Create partition table
|
||||
${pkgs.parted}/sbin/parted /dev/vda mklabel msdos
|
||||
${pkgs.parted}/sbin/parted /dev/vda mkpart primary ext4 1 ${diskSize}
|
||||
${pkgs.parted}/sbin/parted /dev/vda print
|
||||
. /sys/class/block/vda1/uevent
|
||||
mknod /dev/vda1 b $MAJOR $MINOR
|
||||
|
||||
# Create an empty filesystem and mount it.
|
||||
${pkgs.e2fsprogs}/sbin/mkfs.ext4 -L nixos /dev/vda1
|
||||
${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda1
|
||||
|
||||
mkdir /mnt
|
||||
mount /dev/vda1 /mnt
|
||||
|
||||
# The initrd expects these directories to exist.
|
||||
mkdir /mnt/dev /mnt/proc /mnt/sys
|
||||
|
||||
mount --bind /proc /mnt/proc
|
||||
mount --bind /dev /mnt/dev
|
||||
mount --bind /sys /mnt/sys
|
||||
|
||||
# Copy all paths in the closure to the filesystem.
|
||||
storePaths=$(perl ${pkgs.pathsFromGraph} /tmp/xchg/closure)
|
||||
|
||||
mkdir -p /mnt/nix/store
|
||||
echo "copying everything (will take a while)..."
|
||||
cp -prd $storePaths /mnt/nix/store/
|
||||
|
||||
# Register the paths in the Nix database.
|
||||
printRegistration=1 perl ${pkgs.pathsFromGraph} /tmp/xchg/closure | \
|
||||
chroot /mnt ${config.nix.package}/bin/nix-store --load-db --option build-users-group ""
|
||||
|
||||
# Create the system profile to allow nixos-rebuild to work.
|
||||
chroot /mnt ${config.nix.package}/bin/nix-env \
|
||||
-p /nix/var/nix/profiles/system --set ${config.system.build.toplevel} \
|
||||
--option build-users-group ""
|
||||
|
||||
# `nixos-rebuild' requires an /etc/NIXOS.
|
||||
mkdir -p /mnt/etc
|
||||
touch /mnt/etc/NIXOS
|
||||
|
||||
# `switch-to-configuration' requires a /bin/sh
|
||||
mkdir -p /mnt/bin
|
||||
ln -s ${config.system.build.binsh}/bin/sh /mnt/bin/sh
|
||||
|
||||
# Install a configuration.nix.
|
||||
mkdir -p /mnt/etc/nixos /mnt/boot/grub
|
||||
cp ${./brightbox-config.nix} /mnt/etc/nixos/configuration.nix
|
||||
|
||||
# Generate the GRUB menu.
|
||||
ln -s vda /dev/sda
|
||||
chroot /mnt ${config.system.build.toplevel}/bin/switch-to-configuration boot
|
||||
|
||||
umount /mnt/proc /mnt/dev /mnt/sys
|
||||
umount /mnt
|
||||
''
|
||||
);
|
||||
|
||||
fileSystems."/".label = "nixos";
|
||||
|
||||
# Generate a GRUB menu. Amazon's pv-grub uses this to boot our kernel/initrd.
|
||||
boot.loader.grub.device = "/dev/vda";
|
||||
boot.loader.grub.timeout = 0;
|
||||
|
||||
# Don't put old configurations in the GRUB menu. The user has no
|
||||
# way to select them anyway.
|
||||
boot.loader.grub.configurationLimit = 0;
|
||||
|
||||
# Allow root logins only using the SSH key that the user specified
|
||||
# at instance creation time.
|
||||
services.openssh.enable = true;
|
||||
services.openssh.permitRootLogin = "without-password";
|
||||
|
||||
# Force getting the hostname from Google Compute.
|
||||
networking.hostName = mkDefault "";
|
||||
|
||||
# Always include cryptsetup so that NixOps can use it.
|
||||
environment.systemPackages = [ pkgs.cryptsetup ];
|
||||
|
||||
systemd.services."fetch-ec2-data" =
|
||||
{ description = "Fetch EC2 Data";
|
||||
|
||||
wantedBy = [ "multi-user.target" "sshd.service" ];
|
||||
before = [ "sshd.service" ];
|
||||
wants = [ "ip-up.target" ];
|
||||
after = [ "ip-up.target" ];
|
||||
|
||||
path = [ pkgs.wget pkgs.iproute ];
|
||||
|
||||
script =
|
||||
''
|
||||
wget="wget -q --retry-connrefused -O -"
|
||||
|
||||
${optionalString (config.networking.hostName == "") ''
|
||||
echo "setting host name..."
|
||||
${pkgs.nettools}/bin/hostname $($wget http://169.254.169.254/latest/meta-data/hostname)
|
||||
''}
|
||||
|
||||
# Don't download the SSH key if it has already been injected
|
||||
# into the image (a Nova feature).
|
||||
if ! [ -e /root/.ssh/authorized_keys ]; then
|
||||
echo "obtaining SSH key..."
|
||||
mkdir -m 0700 -p /root/.ssh
|
||||
$wget http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key > /root/key.pub
|
||||
if [ $? -eq 0 -a -e /root/key.pub ]; then
|
||||
if ! grep -q -f /root/key.pub /root/.ssh/authorized_keys; then
|
||||
cat /root/key.pub >> /root/.ssh/authorized_keys
|
||||
echo "new key added to authorized_keys"
|
||||
fi
|
||||
chmod 600 /root/.ssh/authorized_keys
|
||||
rm -f /root/key.pub
|
||||
fi
|
||||
fi
|
||||
|
||||
# Extract the intended SSH host key for this machine from
|
||||
# the supplied user data, if available. Otherwise sshd will
|
||||
# generate one normally.
|
||||
$wget http://169.254.169.254/2011-01-01/user-data > /root/user-data || true
|
||||
key="$(sed 's/|/\n/g; s/SSH_HOST_DSA_KEY://; t; d' /root/user-data)"
|
||||
key_pub="$(sed 's/SSH_HOST_DSA_KEY_PUB://; t; d' /root/user-data)"
|
||||
if [ -n "$key" -a -n "$key_pub" -a ! -e /etc/ssh/ssh_host_dsa_key ]; then
|
||||
mkdir -m 0755 -p /etc/ssh
|
||||
(umask 077; echo "$key" > /etc/ssh/ssh_host_dsa_key)
|
||||
echo "$key_pub" > /etc/ssh/ssh_host_dsa_key.pub
|
||||
fi
|
||||
'';
|
||||
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.RemainAfterExit = true;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -19,10 +19,6 @@ with lib;
|
||||
# Shut up warnings about not having a boot loader.
|
||||
system.build.installBootLoader = "${pkgs.coreutils}/bin/true";
|
||||
|
||||
systemd.services.systemd-remount-fs.enable = false;
|
||||
|
||||
systemd.services.systemd-random-seed.enable = false;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,12 @@ let
|
||||
perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl";
|
||||
su = "${pkgs.shadow.su}/bin/su";
|
||||
inherit (pkgs) utillinux;
|
||||
|
||||
postInstall = ''
|
||||
t=$out/etc/bash_completion.d
|
||||
mkdir -p $t
|
||||
cp ${./nixos-container-completion.sh} $t/nixos-container
|
||||
'';
|
||||
};
|
||||
|
||||
# The container's init script, a small wrapper around the regular
|
||||
@@ -137,7 +143,7 @@ in
|
||||
};
|
||||
|
||||
hostAddress = mkOption {
|
||||
type = types.nullOr types.string;
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "10.231.136.1";
|
||||
description = ''
|
||||
@@ -146,7 +152,7 @@ in
|
||||
};
|
||||
|
||||
localAddress = mkOption {
|
||||
type = types.nullOr types.string;
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "10.231.136.2";
|
||||
description = ''
|
||||
@@ -155,6 +161,15 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
interfaces = mkOption {
|
||||
type = types.listOf types.string;
|
||||
default = [];
|
||||
example = [ "eth1" "eth2" ];
|
||||
description = ''
|
||||
The list of interfaces to be moved into the container.
|
||||
'';
|
||||
};
|
||||
|
||||
autoStart = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
@@ -268,6 +283,10 @@ in
|
||||
extraFlags+=" --network-veth"
|
||||
fi
|
||||
|
||||
for iface in $INTERFACES; do
|
||||
extraFlags+=" --network-interface=$iface"
|
||||
done
|
||||
|
||||
for iface in $MACVLANS; do
|
||||
extraFlags+=" --network-macvlan=$iface"
|
||||
done
|
||||
@@ -339,7 +358,7 @@ in
|
||||
''
|
||||
#! ${pkgs.stdenv.shell} -e
|
||||
${nixos-container}/bin/nixos-container run "$INSTANCE" -- \
|
||||
bash --login -c "/nix/var/nix/profiles/system/bin/switch-to-configuration test"
|
||||
bash --login -c "''${SYSTEM_PATH:-/nix/var/nix/profiles/system}/bin/switch-to-configuration test"
|
||||
'';
|
||||
|
||||
SyslogIdentifier = "container %i";
|
||||
@@ -384,10 +403,11 @@ in
|
||||
LOCAL_ADDRESS=${cfg.localAddress}
|
||||
''}
|
||||
''}
|
||||
${optionalString cfg.autoStart ''
|
||||
AUTO_START=1
|
||||
''}
|
||||
EXTRA_NSPAWN_FLAGS="${mkBindFlags cfg.bindMounts}"
|
||||
INTERFACES="${toString cfg.interfaces}"
|
||||
${optionalString cfg.autoStart ''
|
||||
AUTO_START=1
|
||||
''}
|
||||
EXTRA_NSPAWN_FLAGS="${mkBindFlags cfg.bindMounts}"
|
||||
'';
|
||||
}) config.containers;
|
||||
|
||||
|
||||
@@ -43,9 +43,20 @@ in
|
||||
in future. So set this option explicitly to false if you wish.
|
||||
'';
|
||||
};
|
||||
storageDriver =
|
||||
mkOption {
|
||||
type = types.enum ["aufs" "btrfs" "devicemapper" "overlay" "zfs"];
|
||||
description =
|
||||
''
|
||||
This option determines which Docker storage driver to use.
|
||||
It is required but lacks a default value as its most
|
||||
suitable value will depend the filesystems available on the
|
||||
host.
|
||||
'';
|
||||
};
|
||||
extraOptions =
|
||||
mkOption {
|
||||
type = types.str;
|
||||
type = types.separatedString " ";
|
||||
default = "";
|
||||
description =
|
||||
''
|
||||
@@ -54,6 +65,21 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
postStart =
|
||||
mkOption {
|
||||
type = types.lines;
|
||||
default = ''
|
||||
while ! [ -e /var/run/docker.sock ]; do
|
||||
sleep 0.1
|
||||
done
|
||||
'';
|
||||
description = ''
|
||||
The postStart phase of the systemd service. You may need to
|
||||
override this if you are passing in flags to docker which
|
||||
don't cause the socket file to be created.
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -70,7 +96,7 @@ in
|
||||
after = [ "network.target" "docker.socket" ];
|
||||
requires = [ "docker.socket" ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.docker}/bin/docker --daemon=true --host=fd:// --group=docker ${cfg.extraOptions}";
|
||||
ExecStart = "${pkgs.docker}/bin/docker daemon --host=fd:// --group=docker --storage-driver=${cfg.storageDriver} ${cfg.extraOptions}";
|
||||
# I'm not sure if that limits aren't too high, but it's what
|
||||
# goes in config bundled with docker itself
|
||||
LimitNOFILE = 1048576;
|
||||
@@ -96,18 +122,17 @@ in
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.docker}/bin/docker --daemon=true --group=docker ${cfg.extraOptions}";
|
||||
ExecStart = "${pkgs.docker}/bin/docker daemon --group=docker --storage-driver=${cfg.storageDriver} ${cfg.extraOptions}";
|
||||
# I'm not sure if that limits aren't too high, but it's what
|
||||
# goes in config bundled with docker itself
|
||||
LimitNOFILE = 1048576;
|
||||
LimitNPROC = 1048576;
|
||||
} // proxy_env;
|
||||
|
||||
postStart = ''
|
||||
while ! [ -e /var/run/docker.sock ]; do
|
||||
sleep 0.1
|
||||
done
|
||||
'';
|
||||
path = [ pkgs.kmod ];
|
||||
environment.MODULE_DIR = "/run/current-system/kernel-modules/lib/modules";
|
||||
|
||||
postStart = cfg.postStart;
|
||||
|
||||
# Presumably some containers are running we don't want to interrupt
|
||||
restartIfChanged = false;
|
||||
|
||||
@@ -7,19 +7,9 @@
|
||||
with lib;
|
||||
|
||||
{
|
||||
options = {
|
||||
ec2.metadata = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to allow access to EC2 metadata.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
|
||||
systemd.services."fetch-ec2-data" =
|
||||
systemd.services.fetch-ec2-data =
|
||||
{ description = "Fetch EC2 Data";
|
||||
|
||||
wantedBy = [ "multi-user.target" "sshd.service" ];
|
||||
@@ -31,8 +21,6 @@ with lib;
|
||||
|
||||
script =
|
||||
''
|
||||
ip route del blackhole 169.254.169.254/32 || true
|
||||
|
||||
wget="wget -q --retry-connrefused -O -"
|
||||
|
||||
${optionalString (config.networking.hostName == "") ''
|
||||
@@ -60,21 +48,22 @@ with lib;
|
||||
# the supplied user data, if available. Otherwise sshd will
|
||||
# generate one normally.
|
||||
$wget http://169.254.169.254/2011-01-01/user-data > /root/user-data || true
|
||||
|
||||
mkdir -m 0755 -p /etc/ssh
|
||||
|
||||
key="$(sed 's/|/\n/g; s/SSH_HOST_DSA_KEY://; t; d' /root/user-data)"
|
||||
key_pub="$(sed 's/SSH_HOST_DSA_KEY_PUB://; t; d' /root/user-data)"
|
||||
if [ -n "$key" -a -n "$key_pub" -a ! -e /etc/ssh/ssh_host_dsa_key ]; then
|
||||
mkdir -m 0755 -p /etc/ssh
|
||||
(umask 077; echo "$key" > /etc/ssh/ssh_host_dsa_key)
|
||||
echo "$key_pub" > /etc/ssh/ssh_host_dsa_key.pub
|
||||
fi
|
||||
|
||||
${optionalString (! config.ec2.metadata) ''
|
||||
# Since the user data is sensitive, prevent it from
|
||||
# being accessed from now on. FIXME: remove at some
|
||||
# point, since current NixOps no longer relies on
|
||||
# metadata secrecy.
|
||||
ip route add blackhole 169.254.169.254/32
|
||||
''}
|
||||
key="$(sed 's/|/\n/g; s/SSH_HOST_ED25519_KEY://; t; d' /root/user-data)"
|
||||
key_pub="$(sed 's/SSH_HOST_ED25519_KEY_PUB://; t; d' /root/user-data)"
|
||||
if [ -n "$key" -a -n "$key_pub" -a ! -e /etc/ssh/ssh_host_ed25519_key ]; then
|
||||
(umask 077; echo "$key" > /etc/ssh/ssh_host_ed25519_key)
|
||||
echo "$key_pub" > /etc/ssh/ssh_host_ed25519_key.pub
|
||||
fi
|
||||
'';
|
||||
|
||||
serviceConfig.Type = "oneshot";
|
||||
@@ -91,7 +80,9 @@ with lib;
|
||||
# can obtain it securely by parsing the output of
|
||||
# ec2-get-console-output.
|
||||
echo "-----BEGIN SSH HOST KEY FINGERPRINTS-----" > /dev/console
|
||||
${pkgs.openssh}/bin/ssh-keygen -l -f /etc/ssh/ssh_host_dsa_key.pub > /dev/console
|
||||
for i in /etc/ssh/ssh_host_*_key.pub; do
|
||||
${config.programs.ssh.package}/bin/ssh-keygen -l -f $i > /dev/console
|
||||
done
|
||||
echo "-----END SSH HOST KEY FINGERPRINTS-----" > /dev/console
|
||||
'';
|
||||
serviceConfig.Type = "oneshot";
|
||||
|
||||
@@ -30,7 +30,7 @@ in
|
||||
rm $out/disk.raw
|
||||
popd
|
||||
'';
|
||||
diskImageBase = "nixos-${config.system.nixosVersion}-${pkgs.stdenv.system}.raw";
|
||||
diskImageBase = "nixos-image-${config.system.nixosVersion}-${pkgs.stdenv.system}.raw";
|
||||
buildInputs = [ pkgs.utillinux pkgs.perl ];
|
||||
exportReferencesGraph =
|
||||
[ "closure" config.system.build.toplevel ];
|
||||
@@ -137,40 +137,50 @@ in
|
||||
after = [ "network-online.target" "ip-up.target" ];
|
||||
wants = [ "network-online.target" "ip-up.target" ];
|
||||
|
||||
script = let wget = "${pkgs.wget}/bin/wget --retry-connrefused -t 15 --waitretry=10 --header='Metadata-Flavor: Google'"; in
|
||||
script = let wget = "${pkgs.wget}/bin/wget --retry-connrefused -t 15 --waitretry=10 --header='Metadata-Flavor: Google'";
|
||||
mktemp = "mktemp --tmpdir=/run"; in
|
||||
''
|
||||
# When dealing with cryptographic keys, we want to keep things private.
|
||||
umask 077
|
||||
# Don't download the SSH key if it has already been downloaded
|
||||
if ! [ -e /root/.ssh/authorized_keys ]; then
|
||||
echo "obtaining SSH key..."
|
||||
mkdir -m 0700 -p /root/.ssh
|
||||
${wget} -O /root/authorized-keys-metadata http://metadata.google.internal/0.1/meta-data/authorized-keys
|
||||
if [ $? -eq 0 -a -e /root/authorized-keys-metadata ]; then
|
||||
cat /root/authorized-keys-metadata | cut -d: -f2- > /root/key.pub
|
||||
if ! grep -q -f /root/key.pub /root/.ssh/authorized_keys; then
|
||||
cat /root/key.pub >> /root/.ssh/authorized_keys
|
||||
echo "new key added to authorized_keys"
|
||||
fi
|
||||
chmod 600 /root/.ssh/authorized_keys
|
||||
fi
|
||||
rm -f /root/key.pub /root/authorized-keys-metadata
|
||||
if ! [ -s /root/.ssh/authorized_keys ]; then
|
||||
echo "obtaining SSH key..."
|
||||
mkdir -m 0700 -p /root/.ssh
|
||||
AUTH_KEYS=$(${mktemp})
|
||||
${wget} -O $AUTH_KEYS http://metadata.google.internal/0.1/meta-data/authorized-keys
|
||||
if [ -s $AUTH_KEYS ]; then
|
||||
KEY_PUB=$(${mktemp})
|
||||
cat $AUTH_KEYS | cut -d: -f2- > $KEY_PUB
|
||||
if ! grep -q -f $KEY_PUB /root/.ssh/authorized_keys; then
|
||||
cat $KEY_PUB >> /root/.ssh/authorized_keys
|
||||
echo "New key added to authorized_keys."
|
||||
fi
|
||||
chmod 600 /root/.ssh/authorized_keys
|
||||
rm -f $KEY_PUB
|
||||
else
|
||||
echo "Downloading http://metadata.google.internal/0.1/meta-data/authorized-keys failed."
|
||||
false
|
||||
fi
|
||||
rm -f $AUTH_KEYS
|
||||
fi
|
||||
|
||||
countKeys=0
|
||||
${flip concatMapStrings config.services.openssh.hostKeys (k :
|
||||
let kName = baseNameOf k.path; in ''
|
||||
PRIV_KEY=$(${mktemp})
|
||||
echo "trying to obtain SSH private host key ${kName}"
|
||||
${wget} -O /root/${kName} http://metadata.google.internal/0.1/meta-data/attributes/${kName} && :
|
||||
if [ $? -eq 0 -a -e /root/${kName} ]; then
|
||||
${wget} -O $PRIV_KEY http://metadata.google.internal/0.1/meta-data/attributes/${kName} && :
|
||||
if [ $? -eq 0 -a -s $PRIV_KEY ]; then
|
||||
countKeys=$((countKeys+1))
|
||||
mv -f /root/${kName} ${k.path}
|
||||
echo "downloaded ${k.path}"
|
||||
mv -f $PRIV_KEY ${k.path}
|
||||
echo "Downloaded ${k.path}"
|
||||
chmod 600 ${k.path}
|
||||
${config.programs.ssh.package}/bin/ssh-keygen -y -f ${k.path} > ${k.path}.pub
|
||||
chmod 644 ${k.path}.pub
|
||||
else
|
||||
echo "Downloading http://metadata.google.internal/0.1/meta-data/attributes/${kName} failed."
|
||||
fi
|
||||
rm -f /root/${kName}
|
||||
rm -f $PRIV_KEY
|
||||
''
|
||||
)}
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
From 1895d10a7539d055a4e0206af1e7a9e5ea32a4f7 Mon Sep 17 00:00:00 2001
|
||||
From: Juerg Haefliger <juerg.haefliger@hp.com>
|
||||
Date: Wed, 25 Mar 2015 13:59:20 +0100
|
||||
Subject: [PATCH] Support new sfdisk version 2.26
|
||||
|
||||
The sfdisk usage with version 2.26 changed. Specifically, the option
|
||||
--show-pt-geometry and functionality for CHS have been removed.
|
||||
Also, restoring a backup MBR now needs to be done using dd.
|
||||
---
|
||||
bin/growpart | 28 ++++++++++------------------
|
||||
1 file changed, 10 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/bin/growpart b/bin/growpart
|
||||
index 595c40b..d4c995b 100755
|
||||
--- a/bin/growpart
|
||||
+++ b/bin/growpart
|
||||
@@ -28,7 +28,6 @@ PART=""
|
||||
PT_UPDATE=false
|
||||
DRY_RUN=0
|
||||
|
||||
-MBR_CHS=""
|
||||
MBR_BACKUP=""
|
||||
GPT_BACKUP=""
|
||||
_capture=""
|
||||
@@ -133,7 +132,8 @@ bad_Usage() {
|
||||
}
|
||||
|
||||
mbr_restore() {
|
||||
- sfdisk --no-reread "${DISK}" ${MBR_CHS} -I "${MBR_BACKUP}"
|
||||
+ dd if="${MBR_BACKUP}-${DISK#/dev/}-0x00000000.bak" of="${DISK}" bs=1 \
|
||||
+ conv=notrunc
|
||||
}
|
||||
|
||||
sfdisk_worked_but_blkrrpart_failed() {
|
||||
@@ -148,34 +148,26 @@ sfdisk_worked_but_blkrrpart_failed() {
|
||||
|
||||
mbr_resize() {
|
||||
RESTORE_HUMAN="${TEMP_D}/recovery"
|
||||
- MBR_BACKUP="${TEMP_D}/orig.save"
|
||||
+ MBR_BACKUP="${TEMP_D}/backup"
|
||||
|
||||
local change_out=${TEMP_D}/change.out
|
||||
local dump_out=${TEMP_D}/dump.out
|
||||
local new_out=${TEMP_D}/new.out
|
||||
local dump_mod=${TEMP_D}/dump.mod
|
||||
- local tmp="${TEMP_D}/tmp.out"
|
||||
- local err="${TEMP_D}/err.out"
|
||||
|
||||
- local _devc cyl _w1 heads _w2 sectors _w3 tot dpart
|
||||
+ local tot dpart
|
||||
local pt_start pt_size pt_end max_end new_size change_info
|
||||
|
||||
- # --show-pt-geometry outputs something like
|
||||
- # /dev/sda: 164352 cylinders, 4 heads, 32 sectors/track
|
||||
- rqe sfd_geom sfdisk "${DISK}" --show-pt-geometry >"${tmp}" &&
|
||||
- read _devc cyl _w1 heads _w2 sectors _w3 <"${tmp}" &&
|
||||
- MBR_CHS="-C ${cyl} -H ${heads} -S ${sectors}" ||
|
||||
- fail "failed to get CHS from ${DISK}"
|
||||
+ tot=$(sfdisk --list "${DISK}" | awk '{ print $(NF-1) ; exit }') ||
|
||||
+ fail "failed to get total number of sectors from ${DISK}"
|
||||
|
||||
- tot=$((${cyl}*${heads}*${sectors}))
|
||||
+ debug 1 "total number of sectors of ${DISK} is ${tot}"
|
||||
|
||||
- debug 1 "geometry is ${MBR_CHS}. total size=${tot}"
|
||||
- rqe sfd_dump sfdisk ${MBR_CHS} --unit=S --dump "${DISK}" \
|
||||
+ rqe sfd_dump sfdisk --dump "${DISK}" \
|
||||
>"${dump_out}" ||
|
||||
fail "failed to dump sfdisk info for ${DISK}"
|
||||
-
|
||||
{
|
||||
- echo "## sfdisk ${MBR_CHS} --unit=S --dump ${DISK}"
|
||||
+ echo "## sfdisk --dump ${DISK}"
|
||||
cat "${dump_out}"
|
||||
} >"${RESTORE_HUMAN}"
|
||||
[ $? -eq 0 ] || fail "failed to save sfdisk -d output"
|
||||
@@ -237,7 +229,7 @@ mbr_resize() {
|
||||
exit 0
|
||||
fi
|
||||
|
||||
- LANG=C sfdisk --no-reread "${DISK}" ${MBR_CHS} --force \
|
||||
+ LANG=C sfdisk --no-reread "${DISK}" --force \
|
||||
-O "${MBR_BACKUP}" <"${new_out}" >"${change_out}" 2>&1
|
||||
ret=$?
|
||||
[ $ret -eq 0 ] || RESTORE_FUNC="mbr_restore"
|
||||
--
|
||||
2.1.4
|
||||
|
||||
@@ -57,6 +57,17 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
virtualisation.libvirtd.extraOptions =
|
||||
mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
example = [ "--verbose" ];
|
||||
description =
|
||||
''
|
||||
Extra command line arguments passed to libvirtd on startup.
|
||||
'';
|
||||
};
|
||||
|
||||
virtualisation.libvirtd.onShutdown =
|
||||
mkOption {
|
||||
type = types.enum ["shutdown" "suspend" ];
|
||||
@@ -140,7 +151,7 @@ in
|
||||
done
|
||||
''; # */
|
||||
|
||||
serviceConfig.ExecStart = ''@${pkgs.libvirt}/sbin/libvirtd libvirtd --config "${configFile}" --daemon --verbose'';
|
||||
serviceConfig.ExecStart = ''@${pkgs.libvirt}/sbin/libvirtd libvirtd --config "${configFile}" --daemon ${concatStringsSep " " cfg.extraOptions}'';
|
||||
serviceConfig.Type = "forking";
|
||||
serviceConfig.KillMode = "process"; # when stopping, leave the VMs alone
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
# Systemd services for lxd.
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.virtualisation.lxd;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
|
||||
virtualisation.lxd.enable =
|
||||
mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description =
|
||||
''
|
||||
This option enables lxd, a daemon that manages
|
||||
containers. Users in the "lxd" group can interact with
|
||||
the daemon (e.g. to start or stop containers) using the
|
||||
<command>lxc</command> command line tool, among others.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
environment.systemPackages =
|
||||
[ pkgs.lxd ];
|
||||
|
||||
systemd.services.lxd =
|
||||
{ description = "LXD Container Management Daemon";
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "systemd-udev-settle.service" ];
|
||||
|
||||
# TODO(wkennington): Add lvm2 and thin-provisioning-tools
|
||||
path = with pkgs; [ acl rsync gnutar xz btrfsProgs ];
|
||||
|
||||
serviceConfig.ExecStart = "@${pkgs.lxd}/bin/lxd lxd --syslog --group lxd";
|
||||
serviceConfig.Type = "simple";
|
||||
serviceConfig.KillMode = "process"; # when stopping, leave the containers alone
|
||||
};
|
||||
|
||||
users.extraGroups.lxd.gid = config.ids.gids.lxd;
|
||||
|
||||
users.extraUsers.root = {
|
||||
subUidRanges = [ { startUid = 1000000; count = 65536; } ];
|
||||
subGidRanges = [ { startGid = 1000000; count = 65536; } ];
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
_nixos-container() {
|
||||
local cur prev opts
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
opts="list create destroy start stop status update login root-login run show-ip show-host-key"
|
||||
startstop_opts=$(nixos-container list)
|
||||
update_opts="--config"
|
||||
|
||||
if [[ "$prev" == "nixos-container" ]]
|
||||
then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ $(echo "$opts" | grep "$prev") ]]
|
||||
then
|
||||
if [[ "$prev" == "start" || "$prev" == "stop" ]]
|
||||
then
|
||||
COMPREPLY=( $(compgen -W "${startstop_opts}" -- ${cur}) )
|
||||
return 0
|
||||
elif [[ "$prev" == "update" ]]
|
||||
then
|
||||
COMPREPLY=( $(compgen -W "${update_opts}" -- ${cur}) )
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
complete -F _nixos-container nixos-container
|
||||
|
||||
@@ -290,7 +290,8 @@ elsif ($action eq "show-ip") {
|
||||
}
|
||||
|
||||
elsif ($action eq "show-host-key") {
|
||||
my $fn = "$root/etc/ssh/ssh_host_ecdsa_key.pub";
|
||||
my $fn = "$root/etc/ssh/ssh_host_ed25519_key.pub";
|
||||
$fn = "$root/etc/ssh/ssh_host_ecdsa_key.pub" unless -e $fn;
|
||||
exit 1 if ! -f $fn;
|
||||
print read_file($fn);
|
||||
}
|
||||
|
||||
@@ -46,16 +46,20 @@ with lib;
|
||||
|
||||
# Register the paths in the Nix database.
|
||||
printRegistration=1 perl ${pkgs.pathsFromGraph} /tmp/xchg/closure | \
|
||||
chroot /mnt ${config.nix.package}/bin/nix-store --load-db
|
||||
chroot /mnt ${config.nix.package}/bin/nix-store --load-db --option build-users-group ""
|
||||
|
||||
# Create the system profile to allow nixos-rebuild to work.
|
||||
chroot /mnt ${config.nix.package}/bin/nix-env \
|
||||
chroot /mnt ${config.nix.package}/bin/nix-env --option build-users-group "" \
|
||||
-p /nix/var/nix/profiles/system --set ${config.system.build.toplevel}
|
||||
|
||||
# `nixos-rebuild' requires an /etc/NIXOS.
|
||||
mkdir -p /mnt/etc
|
||||
touch /mnt/etc/NIXOS
|
||||
|
||||
# `switch-to-configuration' requires a /bin/sh
|
||||
mkdir -p /mnt/bin
|
||||
ln -s ${config.system.build.binsh}/bin/sh /mnt/bin/sh
|
||||
|
||||
# Install a configuration.nix.
|
||||
mkdir -p /mnt/etc/nixos
|
||||
cp ${./nova-config.nix} /mnt/etc/nixos/configuration.nix
|
||||
@@ -104,10 +108,6 @@ with lib;
|
||||
boot.initrd.supportedFilesystems = [ "unionfs-fuse" ];
|
||||
*/
|
||||
|
||||
# Since Nova allows VNC access to instances, it's nice to start to
|
||||
# start a few virtual consoles.
|
||||
services.mingetty.ttys = [ "tty1" "tty2" ];
|
||||
|
||||
# Allow root logins only using the SSH key that the user specified
|
||||
# at instance creation time.
|
||||
services.openssh.enable = true;
|
||||
|
||||
@@ -100,7 +100,7 @@ in
|
||||
|
||||
# `openssl' is required to generate the CA. `openssh' is
|
||||
# required to generate key pairs.
|
||||
path = [ pkgs.openssl pkgs.openssh pkgs.bash ];
|
||||
path = [ pkgs.openssl config.programs.ssh.package pkgs.bash ];
|
||||
|
||||
respawn = false;
|
||||
|
||||
|
||||
@@ -7,35 +7,45 @@ with lib;
|
||||
let
|
||||
cfg = config.virtualisation.vswitch;
|
||||
|
||||
in
|
||||
in {
|
||||
|
||||
{
|
||||
|
||||
options = {
|
||||
|
||||
virtualisation.vswitch.enable = mkOption {
|
||||
options.virtualisation.vswitch = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description =
|
||||
''
|
||||
Enable Open vSwitch. A configuration
|
||||
daemon (ovs-server) will be started.
|
||||
description = ''
|
||||
Whether to enable Open vSwitch. A configuration daemon (ovs-server)
|
||||
will be started.
|
||||
'';
|
||||
};
|
||||
|
||||
resetOnStart = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to reset the Open vSwitch configuration database to a default
|
||||
configuration on every start of the systemd <literal>ovsdb.service</literal>.
|
||||
'';
|
||||
};
|
||||
|
||||
virtualisation.vswitch.package = mkOption {
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.openvswitch;
|
||||
description =
|
||||
''
|
||||
description = ''
|
||||
Open vSwitch package to use.
|
||||
'';
|
||||
'';
|
||||
};
|
||||
|
||||
ipsec = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to start racoon service for openvswitch.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable (let
|
||||
config = mkIf cfg.enable (let
|
||||
|
||||
# Where the communication sockets live
|
||||
runDir = "/var/run/openvswitch";
|
||||
@@ -43,7 +53,7 @@ in
|
||||
# Where the config database live (can't be in nix-store)
|
||||
stateDir = "/var/db/openvswitch";
|
||||
|
||||
# The path to the an initialized version of the database
|
||||
# The path to the an initialized version of the database
|
||||
db = pkgs.stdenv.mkDerivation {
|
||||
name = "vswitch.db";
|
||||
unpackPhase = "true";
|
||||
@@ -51,15 +61,12 @@ in
|
||||
buildInputs = with pkgs; [
|
||||
cfg.package
|
||||
];
|
||||
installPhase =
|
||||
''
|
||||
ensureDir $out/
|
||||
'';
|
||||
installPhase = "mkdir -p $out";
|
||||
};
|
||||
|
||||
in {
|
||||
in (mkMerge [{
|
||||
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
environment.systemPackages = [ cfg.package pkgs.ipsecTools ];
|
||||
|
||||
boot.kernelModules = [ "tun" "openvswitch" ];
|
||||
|
||||
@@ -69,15 +76,15 @@ in
|
||||
description = "Open_vSwitch Database Server";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "systemd-udev-settle.service" ];
|
||||
wants = [ "vswitchd.service" ];
|
||||
path = [ cfg.package ];
|
||||
restartTriggers = [ db cfg.package ];
|
||||
# Create the config database
|
||||
preStart =
|
||||
preStart =
|
||||
''
|
||||
mkdir -p ${runDir}
|
||||
mkdir -p /var/db/openvswitch
|
||||
chmod +w /var/db/openvswitch
|
||||
${optionalString cfg.resetOnStart "rm -f /var/db/openvswitch/conf.db"}
|
||||
if [[ ! -e /var/db/openvswitch/conf.db ]]; then
|
||||
${cfg.package}/bin/ovsdb-tool create \
|
||||
"/var/db/openvswitch/conf.db" \
|
||||
@@ -85,33 +92,87 @@ in
|
||||
fi
|
||||
chmod -R +w /var/db/openvswitch
|
||||
'';
|
||||
serviceConfig.ExecStart =
|
||||
''
|
||||
${cfg.package}/bin/ovsdb-server \
|
||||
--remote=punix:${runDir}/db.sock \
|
||||
--private-key=db:Open_vSwitch,SSL,private_key \
|
||||
--certificate=db:Open_vSwitch,SSL,certificate \
|
||||
--bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert \
|
||||
--unixctl=ovsdb.ctl.sock \
|
||||
/var/db/openvswitch/conf.db
|
||||
'';
|
||||
serviceConfig.Restart = "always";
|
||||
serviceConfig.RestartSec = 3;
|
||||
postStart =
|
||||
''
|
||||
serviceConfig = {
|
||||
ExecStart =
|
||||
''
|
||||
${cfg.package}/bin/ovsdb-server \
|
||||
--remote=punix:${runDir}/db.sock \
|
||||
--private-key=db:Open_vSwitch,SSL,private_key \
|
||||
--certificate=db:Open_vSwitch,SSL,certificate \
|
||||
--bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert \
|
||||
--unixctl=ovsdb.ctl.sock \
|
||||
--pidfile=/var/run/openvswitch/ovsdb.pid \
|
||||
--detach \
|
||||
/var/db/openvswitch/conf.db
|
||||
'';
|
||||
Restart = "always";
|
||||
RestartSec = 3;
|
||||
PIDFile = "/var/run/openvswitch/ovsdb.pid";
|
||||
# Use service type 'forking' to correctly determine when ovsdb-server is ready.
|
||||
Type = "forking";
|
||||
};
|
||||
postStart = ''
|
||||
${cfg.package}/bin/ovs-vsctl --timeout 3 --retry --no-wait init
|
||||
'';
|
||||
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.vswitchd = {
|
||||
description = "Open_vSwitch Daemon";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
bindsTo = [ "ovsdb.service" ];
|
||||
after = [ "ovsdb.service" ];
|
||||
path = [ cfg.package ];
|
||||
serviceConfig.ExecStart = ''${cfg.package}/bin/ovs-vswitchd'';
|
||||
serviceConfig = {
|
||||
ExecStart = ''
|
||||
${cfg.package}/bin/ovs-vswitchd \
|
||||
--pidfile=/var/run/openvswitch/ovs-vswitchd.pid \
|
||||
--detach
|
||||
'';
|
||||
PIDFile = "/var/run/openvswitch/ovs-vswitchd.pid";
|
||||
# Use service type 'forking' to correctly determine when vswitchd is ready.
|
||||
Type = "forking";
|
||||
};
|
||||
};
|
||||
|
||||
});
|
||||
}
|
||||
(mkIf cfg.ipsec {
|
||||
services.racoon.enable = true;
|
||||
services.racoon.configPath = "${runDir}/ipsec/etc/racoon/racoon.conf";
|
||||
|
||||
networking.firewall.extraCommands = ''
|
||||
iptables -I INPUT -t mangle -p esp -j MARK --set-mark 1/1
|
||||
iptables -I INPUT -t mangle -p udp --dport 4500 -j MARK --set-mark 1/1
|
||||
'';
|
||||
|
||||
systemd.services.ovs-monitor-ipsec = {
|
||||
description = "Open_vSwitch Ipsec Daemon";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
requires = [ "ovsdb.service" ];
|
||||
before = [ "vswitchd.service" "racoon.service" ];
|
||||
environment.UNIXCTLPATH = "/tmp/ovsdb.ctl.sock";
|
||||
serviceConfig = {
|
||||
ExecStart = ''
|
||||
${cfg.package}/bin/ovs-monitor-ipsec \
|
||||
--root-prefix ${runDir}/ipsec \
|
||||
--pidfile /var/run/openvswitch/ovs-monitor-ipsec.pid \
|
||||
--monitor --detach \
|
||||
unix:/var/run/openvswitch/db.sock
|
||||
'';
|
||||
PIDFile = "/var/run/openvswitch/ovs-monitor-ipsec.pid";
|
||||
# Use service type 'forking' to correctly determine when ovs-monitor-ipsec is ready.
|
||||
Type = "forking";
|
||||
};
|
||||
|
||||
preStart = ''
|
||||
rm -r ${runDir}/ipsec/etc/racoon/certs || true
|
||||
mkdir -p ${runDir}/ipsec/{etc/racoon,etc/init.d/,usr/sbin/}
|
||||
ln -fs ${pkgs.ipsecTools}/bin/setkey ${runDir}/ipsec/usr/sbin/setkey
|
||||
ln -fs ${pkgs.writeScript "racoon-restart" ''
|
||||
#!${pkgs.stdenv.shell}
|
||||
/var/run/current-system/sw/bin/systemctl $1 racoon
|
||||
''} ${runDir}/ipsec/etc/init.d/racoon
|
||||
'';
|
||||
};
|
||||
})]));
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ in
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
This enables Parallel Tools for Linux guests, along with provided
|
||||
This enables Parallels Tools for Linux guests, along with provided
|
||||
video, mouse and other hardware drivers.
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -61,8 +61,8 @@ let
|
||||
idx=2
|
||||
extraDisks=""
|
||||
${flip concatMapStrings cfg.emptyDiskImages (size: ''
|
||||
${pkgs.qemu_kvm}/bin/qemu-img create -f raw "empty$idx" "${toString size}M"
|
||||
extraDisks="$extraDisks -drive index=$idx,file=$(pwd)/empty$idx,if=virtio,werror=report"
|
||||
${pkgs.qemu_kvm}/bin/qemu-img create -f qcow2 "empty$idx.qcow2" "${toString size}M"
|
||||
extraDisks="$extraDisks -drive index=$idx,file=$(pwd)/empty$idx.qcow2,if=${cfg.qemu.diskInterface},werror=report"
|
||||
idx=$((idx + 1))
|
||||
'')}
|
||||
|
||||
@@ -76,14 +76,14 @@ let
|
||||
-virtfs local,path=$TMPDIR/xchg,security_model=none,mount_tag=xchg \
|
||||
-virtfs local,path=''${SHARED_DIR:-$TMPDIR/xchg},security_model=none,mount_tag=shared \
|
||||
${if cfg.useBootLoader then ''
|
||||
-drive index=0,id=drive1,file=$NIX_DISK_IMAGE,if=virtio,cache=writeback,werror=report \
|
||||
-drive index=0,id=drive1,file=$NIX_DISK_IMAGE,if=${cfg.qemu.diskInterface},cache=writeback,werror=report \
|
||||
-drive index=1,id=drive2,file=$TMPDIR/disk.img,media=disk \
|
||||
${if cfg.useEFIBoot then ''
|
||||
-pflash $TMPDIR/bios.bin \
|
||||
'' else ''
|
||||
''}
|
||||
'' else ''
|
||||
-drive file=$NIX_DISK_IMAGE,if=virtio,cache=writeback,werror=report \
|
||||
-drive index=0,id=drive1,file=$NIX_DISK_IMAGE,if=${cfg.qemu.diskInterface},cache=writeback,werror=report \
|
||||
-kernel ${config.system.build.toplevel}/kernel \
|
||||
-initrd ${config.system.build.toplevel}/initrd \
|
||||
-append "$(cat ${config.system.build.toplevel}/kernel-params) init=${config.system.build.toplevel}/init regInfo=${regInfo} ${kernelConsole} $QEMU_KERNEL_PARAMS" \
|
||||
@@ -165,7 +165,7 @@ let
|
||||
${config.system.build.toplevel}/bin/switch-to-configuration boot
|
||||
|
||||
umount /boot
|
||||
''
|
||||
'' # */
|
||||
);
|
||||
|
||||
in
|
||||
@@ -204,17 +204,25 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
virtualisation.bootDevice =
|
||||
mkOption {
|
||||
type = types.str;
|
||||
example = "/dev/vda";
|
||||
description =
|
||||
''
|
||||
The disk to be used for the root filesystem.
|
||||
'';
|
||||
};
|
||||
|
||||
virtualisation.emptyDiskImages =
|
||||
mkOption {
|
||||
default = [];
|
||||
type = types.listOf types.int;
|
||||
description =
|
||||
''
|
||||
Additional disk images to provide to the VM, the value is a list of
|
||||
sizes in megabytes the empty disk should be.
|
||||
|
||||
These disks are writeable by the VM and will be thrown away
|
||||
afterwards.
|
||||
Additional disk images to provide to the VM. The value is
|
||||
a list of size in megabytes of each disk. These disks are
|
||||
writeable by the VM.
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -310,6 +318,17 @@ in
|
||||
to keep the default runtime behaviour.
|
||||
'';
|
||||
};
|
||||
|
||||
diskInterface =
|
||||
mkOption {
|
||||
default = "virtio";
|
||||
example = "scsi";
|
||||
type = types.str;
|
||||
description = ''
|
||||
The interface used for the virtual hard disks
|
||||
(<literal>virtio</literal> or <literal>scsi</literal>).
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
virtualisation.useBootLoader =
|
||||
@@ -341,7 +360,7 @@ in
|
||||
|
||||
config = {
|
||||
|
||||
boot.loader.grub.device = mkVMOverride "/dev/vda";
|
||||
boot.loader.grub.device = mkVMOverride cfg.bootDevice;
|
||||
|
||||
boot.initrd.extraUtilsCommands =
|
||||
''
|
||||
@@ -353,9 +372,9 @@ in
|
||||
''
|
||||
# If the disk image appears to be empty, run mke2fs to
|
||||
# initialise.
|
||||
FSTYPE=$(blkid -o value -s TYPE /dev/vda || true)
|
||||
FSTYPE=$(blkid -o value -s TYPE ${cfg.bootDevice} || true)
|
||||
if test -z "$FSTYPE"; then
|
||||
mke2fs -t ext4 /dev/vda
|
||||
mke2fs -t ext4 ${cfg.bootDevice}
|
||||
fi
|
||||
'';
|
||||
|
||||
@@ -385,6 +404,12 @@ in
|
||||
fi
|
||||
'';
|
||||
|
||||
boot.initrd.availableKernelModules =
|
||||
optional (cfg.qemu.diskInterface == "scsi") "sym53c8xx";
|
||||
|
||||
virtualisation.bootDevice =
|
||||
mkDefault (if cfg.qemu.diskInterface == "scsi" then "/dev/sda" else "/dev/vda");
|
||||
|
||||
virtualisation.pathsInNixDB = [ config.system.build.toplevel ];
|
||||
|
||||
virtualisation.qemu.options = [ "-vga std" "-usbdevice tablet" ];
|
||||
@@ -396,7 +421,7 @@ in
|
||||
# attribute should be disregarded for the purpose of building a VM
|
||||
# test image (since those filesystems don't exist in the VM).
|
||||
fileSystems = mkVMOverride (
|
||||
{ "/".device = "/dev/vda";
|
||||
{ "/".device = cfg.bootDevice;
|
||||
${if cfg.writableStore then "/nix/.ro-store" else "/nix/store"} =
|
||||
{ device = "store";
|
||||
fsType = "9p";
|
||||
|
||||
@@ -6,7 +6,7 @@ with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.virtualboxGuest;
|
||||
cfg = config.virtualisation.virtualbox.guest;
|
||||
kernel = config.boot.kernelPackages;
|
||||
|
||||
in
|
||||
@@ -15,20 +15,11 @@ in
|
||||
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
|
||||
services.virtualboxGuest = {
|
||||
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
description = "Whether to enable the VirtualBox service and other guest additions.";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
options.virtualisation.virtualbox.guest.enable = mkOption {
|
||||
default = false;
|
||||
description = "Whether to enable the VirtualBox service and other guest additions.";
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
@@ -41,7 +32,8 @@ in
|
||||
|
||||
boot.extraModulePackages = [ kernel.virtualboxGuestAdditions ];
|
||||
|
||||
boot.kernelModules = [ "vboxsf" ];
|
||||
boot.supportedFilesystems = [ "vboxsf" ];
|
||||
boot.initrd.supportedFilesystems = [ "vboxsf" ];
|
||||
|
||||
users.extraGroups.vboxsf.gid = config.ids.gids.vboxsf;
|
||||
|
||||
@@ -54,7 +46,7 @@ in
|
||||
|
||||
unitConfig.ConditionVirtualization = "oracle";
|
||||
|
||||
serviceConfig.ExecStart = "@${kernel.virtualboxGuestAdditions}/sbin/VBoxService VBoxService --foreground";
|
||||
serviceConfig.ExecStart = "@${kernel.virtualboxGuestAdditions}/bin/VBoxService VBoxService --foreground";
|
||||
};
|
||||
|
||||
services.xserver.videoDrivers = mkOverride 50 [ "virtualbox" ];
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.virtualisation.virtualbox.host;
|
||||
virtualbox = config.boot.kernelPackages.virtualbox.override {
|
||||
inherit (cfg) enableHardening;
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
options.virtualisation.virtualbox.host = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable VirtualBox.
|
||||
|
||||
<note><para>
|
||||
In order to pass USB devices from the host to the guests, the user
|
||||
needs to be in the <literal>vboxusers</literal> group.
|
||||
</para></note>
|
||||
'';
|
||||
};
|
||||
|
||||
addNetworkInterface = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Automatically set up a vboxnet0 host-only network interface.
|
||||
'';
|
||||
};
|
||||
|
||||
enableHardening = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Enable hardened VirtualBox, which ensures that only the binaries in the
|
||||
system path get access to the devices exposed by the kernel modules
|
||||
instead of all users in the vboxusers group.
|
||||
|
||||
<important><para>
|
||||
Disabling this can put your system's security at risk, as local users
|
||||
in the vboxusers group can tamper with the VirtualBox device files.
|
||||
</para></important>
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable (mkMerge [{
|
||||
boot.kernelModules = [ "vboxdrv" "vboxnetadp" "vboxnetflt" ];
|
||||
boot.extraModulePackages = [ virtualbox ];
|
||||
environment.systemPackages = [ virtualbox ];
|
||||
|
||||
security.setuidOwners = let
|
||||
mkSuid = program: {
|
||||
inherit program;
|
||||
source = "${virtualbox}/libexec/virtualbox/${program}";
|
||||
owner = "root";
|
||||
group = "vboxusers";
|
||||
setuid = true;
|
||||
};
|
||||
in mkIf cfg.enableHardening (map mkSuid [
|
||||
"VBoxHeadless"
|
||||
"VBoxNetAdpCtl"
|
||||
"VBoxNetDHCP"
|
||||
"VBoxNetNAT"
|
||||
"VBoxSDL"
|
||||
"VBoxVolInfo"
|
||||
"VirtualBox"
|
||||
]);
|
||||
|
||||
users.extraGroups.vboxusers.gid = config.ids.gids.vboxusers;
|
||||
|
||||
services.udev.extraRules =
|
||||
''
|
||||
KERNEL=="vboxdrv", OWNER="root", GROUP="vboxusers", MODE="0660", TAG+="systemd"
|
||||
KERNEL=="vboxdrvu", OWNER="root", GROUP="root", MODE="0666", TAG+="systemd"
|
||||
KERNEL=="vboxnetctl", OWNER="root", GROUP="vboxusers", MODE="0660", TAG+="systemd"
|
||||
SUBSYSTEM=="usb_device", ACTION=="add", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh $major $minor $attr{bDeviceClass}"
|
||||
SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh $major $minor $attr{bDeviceClass}"
|
||||
SUBSYSTEM=="usb_device", ACTION=="remove", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh --remove $major $minor"
|
||||
SUBSYSTEM=="usb", ACTION=="remove", ENV{DEVTYPE}=="usb_device", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh --remove $major $minor"
|
||||
'';
|
||||
|
||||
# Since we lack the right setuid binaries, set up a host-only network by default.
|
||||
} (mkIf cfg.addNetworkInterface {
|
||||
systemd.services."vboxnet0" =
|
||||
{ description = "VirtualBox vboxnet0 Interface";
|
||||
requires = [ "dev-vboxnetctl.device" ];
|
||||
after = [ "dev-vboxnetctl.device" ];
|
||||
wantedBy = [ "network.target" "sys-subsystem-net-devices-vboxnet0.device" ];
|
||||
path = [ virtualbox ];
|
||||
serviceConfig.RemainAfterExit = true;
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.PrivateTmp = true;
|
||||
environment.VBOX_USER_HOME = "/tmp";
|
||||
script =
|
||||
''
|
||||
if ! [ -e /sys/class/net/vboxnet0 ]; then
|
||||
VBoxManage hostonlyif create
|
||||
cat /tmp/VBoxSVC.log >&2
|
||||
fi
|
||||
'';
|
||||
postStop =
|
||||
''
|
||||
VBoxManage hostonlyif remove vboxnet0
|
||||
'';
|
||||
};
|
||||
|
||||
networking.interfaces.vboxnet0.ip4 = [ { address = "192.168.56.1"; prefixLength = 24; } ];
|
||||
})]);
|
||||
}
|
||||
@@ -101,7 +101,7 @@ in {
|
||||
system.build.virtualBoxOVA = pkgs.runCommand "virtualbox-ova"
|
||||
{ buildInputs = [ pkgs.linuxPackages.virtualbox ];
|
||||
vmName = "NixOS ${config.system.nixosVersion} (${pkgs.stdenv.system})";
|
||||
fileName = "nixos-${config.system.nixosVersion}-${pkgs.stdenv.system}.ova";
|
||||
fileName = "nixos-image-${config.system.nixosVersion}-${pkgs.stdenv.system}.ova";
|
||||
}
|
||||
''
|
||||
echo "creating VirtualBox VM..."
|
||||
@@ -109,7 +109,8 @@ in {
|
||||
VBoxManage createvm --name "$vmName" --register \
|
||||
--ostype ${if pkgs.stdenv.system == "x86_64-linux" then "Linux26_64" else "Linux26"}
|
||||
VBoxManage modifyvm "$vmName" \
|
||||
--memory 1536 --acpi on --vram 10 \
|
||||
--memory 1536 --acpi on --vram 32 \
|
||||
${optionalString (pkgs.stdenv.system == "i686-linux") "--pae on"} \
|
||||
--nictype1 virtio --nic1 nat \
|
||||
--audiocontroller ac97 --audio alsa \
|
||||
--rtcuseutc on \
|
||||
@@ -128,6 +129,6 @@ in {
|
||||
boot.loader.grub.version = 2;
|
||||
boot.loader.grub.device = "/dev/sda";
|
||||
|
||||
services.virtualboxGuest.enable = true;
|
||||
virtualisation.virtualbox.guest.enable = true;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.vmwareGuest;
|
||||
open-vm-tools = pkgs.open-vm-tools;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.vmwareGuest.enable = mkEnableOption "VMWare Guest Support";
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [ {
|
||||
assertion = pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64;
|
||||
message = "VMWare guest is not currently supported on ${pkgs.stdenv.system}";
|
||||
} ];
|
||||
|
||||
environment.systemPackages = [ open-vm-tools ];
|
||||
|
||||
systemd.services.vmware =
|
||||
{ description = "VMWare Guest Service";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig.ExecStart = "${open-vm-tools}/bin/vmtoolsd";
|
||||
};
|
||||
|
||||
services.xserver = {
|
||||
videoDrivers = mkOverride 50 [ "vmware" ];
|
||||
|
||||
config = ''
|
||||
Section "InputDevice"
|
||||
Identifier "VMMouse"
|
||||
Driver "vmmouse"
|
||||
EndSection
|
||||
'';
|
||||
|
||||
serverLayoutSection = ''
|
||||
InputDevice "VMMouse"
|
||||
'';
|
||||
|
||||
displayManager.sessionCommands = ''
|
||||
${open-vm-tools}/bin/vmware-user-suid-wrapper
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -6,7 +6,6 @@ with lib;
|
||||
|
||||
let
|
||||
cfg = config.virtualisation.xen;
|
||||
xen = pkgs.xen;
|
||||
in
|
||||
|
||||
{
|
||||
@@ -48,13 +47,32 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
virtualisation.xen.bridge =
|
||||
mkOption {
|
||||
default = "xenbr0";
|
||||
description =
|
||||
''
|
||||
Create a bridge for the Xen domUs to connect to.
|
||||
virtualisation.xen.bridge = {
|
||||
name = mkOption {
|
||||
default = "xenbr0";
|
||||
description = ''
|
||||
Name of bridge the Xen domUs connect to.
|
||||
'';
|
||||
};
|
||||
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
default = "172.16.0.1";
|
||||
description = ''
|
||||
IPv4 address of the bridge.
|
||||
'';
|
||||
};
|
||||
|
||||
prefixLength = mkOption {
|
||||
type = types.addCheck types.int (n: n >= 0 && n <= 32);
|
||||
default = 16;
|
||||
description = ''
|
||||
Subnet mask of the bridge interface, specified as the number of
|
||||
bits in the prefix (<literal>24</literal>).
|
||||
A DHCP server will provide IP addresses for the whole, remaining
|
||||
subnet.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
virtualisation.xen.stored =
|
||||
@@ -88,9 +106,9 @@ in
|
||||
message = "Xen currently does not support EFI boot";
|
||||
} ];
|
||||
|
||||
virtualisation.xen.stored = mkDefault "${xen}/bin/oxenstored";
|
||||
virtualisation.xen.stored = mkDefault "${pkgs.xen}/bin/oxenstored";
|
||||
|
||||
environment.systemPackages = [ xen ];
|
||||
environment.systemPackages = [ pkgs.xen ];
|
||||
|
||||
# Make sure Domain 0 gets the required configuration
|
||||
#boot.kernelPackages = pkgs.boot.kernelPackages.override { features={xen_dom0=true;}; };
|
||||
@@ -103,6 +121,10 @@ in
|
||||
"xenfs"
|
||||
];
|
||||
|
||||
# The xenfs module is needed in system.activationScripts.xen, but
|
||||
# the modprobe command there fails silently. Include xenfs in the
|
||||
# initrd as a work around.
|
||||
boot.initrd.kernelModules = [ "xenfs" ];
|
||||
|
||||
# The radeonfb kernel module causes the screen to go black as soon
|
||||
# as it's loaded, so don't load it.
|
||||
@@ -122,7 +144,7 @@ in
|
||||
|
||||
system.extraSystemBuilderCmds =
|
||||
''
|
||||
ln -s ${xen}/boot/xen.gz $out/xen.gz
|
||||
ln -s ${pkgs.xen}/boot/xen.gz $out/xen.gz
|
||||
echo "${toString cfg.bootParams}" > $out/xen-params
|
||||
'';
|
||||
|
||||
@@ -158,13 +180,19 @@ in
|
||||
|
||||
|
||||
environment.etc =
|
||||
[ { source = "${xen}/etc/xen/xl.conf";
|
||||
[ { source = "${pkgs.xen}/etc/xen/xl.conf";
|
||||
target = "xen/xl.conf";
|
||||
}
|
||||
{ source = "${pkgs.xen}/etc/xen/scripts";
|
||||
target = "xen/scripts";
|
||||
}
|
||||
{ source = "${pkgs.xen}/etc/default/xendomains";
|
||||
target = "default/xendomains";
|
||||
}
|
||||
];
|
||||
|
||||
# Xen provides udev rules.
|
||||
services.udev.packages = [ xen ];
|
||||
services.udev.packages = [ pkgs.xen ];
|
||||
|
||||
services.udev.path = [ pkgs.bridge-utils pkgs.iproute ];
|
||||
|
||||
@@ -178,7 +206,8 @@ in
|
||||
rm -f "$XENSTORED_ROOTDIR"/tdb* &>/dev/null
|
||||
|
||||
mkdir -p /var/run
|
||||
${optionalString cfg.trace "mkdir -p /var/log/xen"}
|
||||
mkdir -p /var/log/xen # Running xl requires /var/log/xen and /var/lib/xen,
|
||||
mkdir -p /var/lib/xen # so we create them here unconditionally.
|
||||
grep -q control_d /proc/xen/capabilities
|
||||
'';
|
||||
serviceConfig.ExecStart = ''
|
||||
@@ -259,17 +288,74 @@ in
|
||||
description = "Xen bridge";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
before = [ "xen-domains.service" ];
|
||||
serviceConfig.RemainAfterExit = "yes";
|
||||
serviceConfig.ExecStart = ''
|
||||
${pkgs.bridge-utils}/bin/brctl addbr ${cfg.bridge}
|
||||
${pkgs.inetutils}/bin/ifconfig ${cfg.bridge} up
|
||||
'';
|
||||
serviceConfig.ExecStop = ''
|
||||
${pkgs.inetutils}/bin/ifconfig ${cfg.bridge} down
|
||||
${pkgs.bridge-utils}/bin/brctl delbr ${cfg.bridge}
|
||||
'';
|
||||
preStart = ''
|
||||
mkdir -p /var/run/xen
|
||||
touch /var/run/xen/dnsmasq.pid
|
||||
touch /var/run/xen/dnsmasq.etherfile
|
||||
touch /var/run/xen/dnsmasq.leasefile
|
||||
|
||||
IFS='-' read -a data <<< `${pkgs.sipcalc}/bin/sipcalc ${cfg.bridge.address}/${toString cfg.bridge.prefixLength} | grep Usable\ range`
|
||||
export XEN_BRIDGE_IP_RANGE_START="${"\${data[1]//[[:blank:]]/}"}"
|
||||
export XEN_BRIDGE_IP_RANGE_END="${"\${data[2]//[[:blank:]]/}"}"
|
||||
|
||||
IFS='-' read -a data <<< `${pkgs.sipcalc}/bin/sipcalc ${cfg.bridge.address}/${toString cfg.bridge.prefixLength} | grep Network\ address`
|
||||
export XEN_BRIDGE_NETWORK_ADDRESS="${"\${data[1]//[[:blank:]]/}"}"
|
||||
|
||||
echo "${cfg.bridge.address} host gw dns" > /var/run/xen/dnsmasq.hostsfile
|
||||
|
||||
cat <<EOF > /var/run/xen/dnsmasq.conf
|
||||
no-daemon
|
||||
pid-file=/var/run/xen/dnsmasq.pid
|
||||
interface=${cfg.bridge.name}
|
||||
except-interface=lo
|
||||
bind-interfaces
|
||||
auth-server=dns.xen.local,${cfg.bridge.name}
|
||||
auth-zone=xen.local,$XEN_BRIDGE_NETWORK_ADDRESS/${toString cfg.bridge.prefixLength}
|
||||
domain=xen.local
|
||||
addn-hosts=/var/run/xen/dnsmasq.hostsfile
|
||||
expand-hosts
|
||||
strict-order
|
||||
no-hosts
|
||||
bogus-priv
|
||||
no-resolv
|
||||
no-poll
|
||||
filterwin2k
|
||||
clear-on-reload
|
||||
domain-needed
|
||||
dhcp-hostsfile=/var/run/xen/dnsmasq.etherfile
|
||||
dhcp-authoritative
|
||||
dhcp-range=$XEN_BRIDGE_IP_RANGE_START,$XEN_BRIDGE_IP_RANGE_END,$XEN_BRIDGE_NETWORK_ADDRESS
|
||||
dhcp-no-override
|
||||
no-ping
|
||||
dhcp-leasefile=/var/run/xen/dnsmasq.leasefile
|
||||
EOF
|
||||
|
||||
# DHCP
|
||||
${pkgs.iptables}/bin/iptables -I INPUT -i ${cfg.bridge.name} -p tcp -s $XEN_BRIDGE_NETWORK_ADDRESS/${toString cfg.bridge.prefixLength} --sport 68 --dport 67 -j ACCEPT
|
||||
${pkgs.iptables}/bin/iptables -I INPUT -i ${cfg.bridge.name} -p udp -s $XEN_BRIDGE_NETWORK_ADDRESS/${toString cfg.bridge.prefixLength} --sport 68 --dport 67 -j ACCEPT
|
||||
# DNS
|
||||
${pkgs.iptables}/bin/iptables -I INPUT -i ${cfg.bridge.name} -p tcp -d ${cfg.bridge.address} --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT
|
||||
${pkgs.iptables}/bin/iptables -I INPUT -i ${cfg.bridge.name} -p udp -d ${cfg.bridge.address} --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT
|
||||
|
||||
${pkgs.bridge-utils}/bin/brctl addbr ${cfg.bridge.name}
|
||||
${pkgs.inetutils}/bin/ifconfig ${cfg.bridge.name} ${cfg.bridge.address}
|
||||
${pkgs.inetutils}/bin/ifconfig ${cfg.bridge.name} up
|
||||
'';
|
||||
serviceConfig.ExecStart = "${pkgs.dnsmasq}/bin/dnsmasq --conf-file=/var/run/xen/dnsmasq.conf";
|
||||
postStop = ''
|
||||
${pkgs.inetutils}/bin/ifconfig ${cfg.bridge.name} down
|
||||
${pkgs.bridge-utils}/bin/brctl delbr ${cfg.bridge.name}
|
||||
|
||||
# DNS
|
||||
${pkgs.iptables}/bin/iptables -D INPUT -i ${cfg.bridge.name} -p udp -d ${cfg.bridge.address} --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT
|
||||
${pkgs.iptables}/bin/iptables -D INPUT -i ${cfg.bridge.name} -p tcp -d ${cfg.bridge.address} --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT
|
||||
# DHCP
|
||||
${pkgs.iptables}/bin/iptables -D INPUT -i ${cfg.bridge.name} -p udp --sport 68 --dport 67 -j ACCEPT
|
||||
${pkgs.iptables}/bin/iptables -D INPUT -i ${cfg.bridge.name} -p tcp --sport 68 --dport 67 -j ACCEPT
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
systemd.services.xen-domains = {
|
||||
description = "Xen domains - automatically starts, saves and restores Xen domains";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
Reference in New Issue
Block a user