Merge branch 'master' into extra-binds

This commit is contained in:
Ian-Woo Kim
2015-09-28 06:02:52 +00:00
4305 changed files with 686345 additions and 86079 deletions
@@ -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
'';
};
}
+15 -82
View File
@@ -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"
'';
}
+2 -32
View File
@@ -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;
};
}
+27 -7
View File
@@ -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;
+33 -8
View File
@@ -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;
+13 -22
View File
@@ -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
+12 -1
View File
@@ -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
+64
View File
@@ -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);
}
+6 -6
View File
@@ -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;
+1 -1
View File
@@ -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;
+103 -42
View File
@@ -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.
'';
};
+39 -14
View File
@@ -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
'';
};
};
}
+108 -22
View File
@@ -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" ];