156 lines
5.6 KiB
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;
|
|
}
|
|
];
|
|
};
|
|
})
|
|
]);
|
|
}
|