1
0
forked from c3d2/nix-config
nix-config/modules/microvm.nix

119 lines
3.3 KiB
Nix

{ zentralwerk, options, config, lib, pkgs, ... }:
let
inherit (config.c3d2.deployment) server;
serverFQDN = "${server}.cluster.zentralwerk.org";
serverConfig = zentralwerk.lib.config.site.hosts.${config.c3d2.deployment.server};
serverBridges = builtins.attrNames (
lib.filterAttrs (_: { type, ... }: type == "bridge")
serverConfig.interfaces
);
in
{
options.c3d2.deployment = with lib; {
server = mkOption {
type = types.enum [ "server10" ];
description = "Server that is supposed to host this MicroVM.";
};
interfaces = mkOption {
description = "Network interfaces";
type = types.listOf (types.submodule {
options = {
net = mkOption {
description = "Network to hook up to";
type = types.enum serverBridges;
};
mac = mkOption {
description = "Ethernet MAC address";
type = types.str;
};
};
});
};
mounts = mkOption {
description = "Persistent filesystems to create, without leading /.";
type = with types; listOf str;
default = [ "etc" ];
};
};
config.system.build = with pkgs; {
copyToServer = writeScript "copy-to-${server}" ''
#! ${runtimeShell} -e
nix copy --to ssh://root@${serverFQDN} $@
'';
runOnServer = writeScript "run-on-${server}" ''
#! ${runtimeShell} -e
ssh root@${serverFQDN} -- $@
'';
};
config = {
microvm = {
hypervisor = lib.mkDefault "cloud-hypervisor";
mem = lib.mkDefault 512;
interfaces = map ({ net, mac }: {
type = "tap";
id = builtins.substring 0 15 "${net}-${config.networking.hostName}";
inherit mac;
}) config.c3d2.deployment.interfaces;
shares = [ {
source = "/nix/store";
mountPoint = "/nix/.ro-store";
tag = "store";
proto = "virtiofs";
socket = "store.socket";
} ]
++ map (dir:
if lib.hasPrefix "/" dir
then throw "${dir} starts with a leading /. Just don't!"
else let
tag = builtins.replaceStrings ["/"] ["_"] dir;
in {
source = "/var/lib/microvms/${config.networking.hostName}/${dir}";
mountPoint = "/${dir}";
inherit tag;
proto = "virtiofs";
socket = "${tag}.socket";
}) config.c3d2.deployment.mounts;
};
systemd.services."microvm-zfs-datasets@" = {
description = "Create ZFS datasets for MicroVM '%i'";
before = [ "microvm-virtiofsd@%i.service" ];
after = [ "local-fs.target" ];
partOf = [ "microvm@%i.service" ];
unitConfig.ConditionPathExists = "/var/lib/microvms/%i/current/share/microvm/virtiofs";
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
WorkingDirectory = "/var/lib/microvms/%i";
SyslogIdentifier = "microvm-zfs-datasets@%i";
};
scriptArgs = "%i";
script = ''
zfsExists() {
zfs list $1 >/dev/null 2>/dev/null
}
NAME="$1"
BASE=$(hostname)/vm/$NAME
zfsExists $BASE || \
zfs create $BASE
for d in current/share/microvm/virtiofs/*; do
SOURCE=$(cat $d/source)
MNT=$(pwd)/$SOURCE
zfsExists $BASE/$d || \
zfs create -o mountpoint=$MNT $BASE/$d
done
'';
};
};
}