nix-config/modules/nixos-modules/server/virt-home-assistant.nix

156 lines
5.6 KiB
Nix

{
config,
lib,
pkgs,
...
}: {
options.services.virt-home-assistant = {
enable = lib.mkEnableOption "Wether to enable home assistant virtual machine";
networkBridge = lib.mkOption {
type = lib.types.str;
description = "what network bridge should we attach to the image";
};
hostDevice = lib.mkOption {
type = lib.types.str;
description = "what host devices should be attached to the image";
};
initialVersion = lib.mkOption {
type = lib.types.str;
description = "what home assistant image version should we pull for initial instal";
default = "15.0";
};
imageName = lib.mkOption {
type = lib.types.str;
description = "where should the image be installed to";
default = "home-assistant.qcow2";
};
installLocation = lib.mkOption {
type = lib.types.str;
description = "where should the image be installed to";
default = "/etc/hass";
};
virtualMachineName = lib.mkOption {
type = lib.types.str;
description = "what name should we give the virtual machine";
default = "home-assistant";
};
subdomain = lib.mkOption {
type = lib.types.str;
description = "subdomain of base domain that home-assistant will be hosted at";
default = "home-assistant";
};
};
config = lib.mkIf config.services.virt-home-assistant.enable (lib.mkMerge [
{
# environment.systemPackages = with pkgs; [
# virt-manager
# ];
# TODO: move this to external module and just have an assertion here that its enabled
# enable virtualization on the system
virtualisation = {
libvirtd = {
enable = true;
qemu.ovmf.enable = true;
};
};
# TODO: deactivation script?
# create service to install and start the container
systemd.services.virt-install-home-assistant = let
# TODO: all of these need to be escaped to be used in commands reliably
bridgedNetwork = config.services.virt-home-assistant.networkBridge;
hostDevice = config.services.virt-home-assistant.hostDevice;
virtualMachineName = config.services.virt-home-assistant.virtualMachineName;
imageName = config.services.virt-home-assistant.imageName;
installLocation = config.services.virt-home-assistant.installLocation;
installImage = "${installLocation}/${imageName}";
initialVersion = config.services.virt-home-assistant.initialVersion;
home-assistant-qcow2 = pkgs.fetchurl {
name = "home-assistant.qcow2";
url = "https://github.com/home-assistant/operating-system/releases/download/${initialVersion}/haos_ova-${initialVersion}.qcow2.xz";
hash = "sha256-V1BEjvvLNbMMKJVyMCmipjQ/3owoJteeVxoF9LDHo1U=";
postFetch = ''
cp $out src.xz
rm -r $out
${pkgs.xz}/bin/unxz src.xz --stdout > $out/${imageName}
'';
};
# Write a script to install the Home Assistant OS qcow2 image
virtInstallScript = pkgs.writeShellScriptBin "virt-install-hass" ''
# Copy the initial image out of the package store to the install location if we don't have one yet
if [ ! -f ${installImage} ]; then
cp ${home-assistant-qcow2} ${installLocation}
fi
# Check if VM already exists, and other pre-conditions
if ! ${pkgs.libvirt}/bin/virsh list --all | grep -q ${virtualMachineName}; then
${pkgs.virt-manager}/bin/virt-install --name ${virtualMachineName} \
--description "Home Assistant OS" \
--os-variant=generic \
--boot uefi \
--ram=2048 \
--vcpus=2 \
--import \
--disk ${installImage},bus=sata \
--network bridge=${bridgedNetwork} \
--host-device ${hostDevice} \
--graphics none
${pkgs.libvirt}/bin/virsh autostart ${virtualMachineName}
fi
'';
in {
description = "Install and start Home Assistant";
wantedBy = ["multi-user.target"];
after = ["local-fs.target"];
requires = ["libvirtd.service"];
serviceConfig.Type = "oneshot";
serviceConfig = {
ExecStart = "${virtInstallScript}/bin/virt-install-hass";
};
};
# TODO: figure out what we need to proxy to the virtual image
# host = {
# reverse_proxy.subdomains.${config.services.virt-home-assistant.subdomain} = {
# target = "http://localhost:${toString config.services.home-assistant.config.http.server_port}";
# websockets.enable = true;
# forwardHeaders.enable = true;
# extraConfig = ''
# add_header Upgrade $http_upgrade;
# add_header Connection \"upgrade\";
# proxy_buffering off;
# proxy_read_timeout 90;
# '';
# };
# };
}
(lib.mkIf config.services.fail2ban.enable {
# TODO: figure out how to write a config for this, prob based on nginx proxy logs?
})
(lib.mkIf config.host.impermanence.enable {
# assertions = [
# {
# assertion = config.services.virt-home-assistant.installLocation == configDir;
# message = "home assistant install location does not match persistence";
# }
# ];
environment.persistence."/persist/system/root" = {
enable = true;
hideMounts = true;
directories = [
{
directory = config.services.virt-home-assistant.installLocation;
}
];
};
})
]);
}