{ 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; } ]; }; }) ]); }