forked from jan-leila/nix-config
		
	main #5
					 6 changed files with 122 additions and 268 deletions
				
			
		|  | @ -282,10 +282,11 @@ | ||||||
|       subdomain = "search"; |       subdomain = "search"; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     virt-home-assistant = { |     home-assistant = { | ||||||
|       enable = false; |       enable = true; | ||||||
|       networkBridge = "bond0"; |       subdomain = "home"; | ||||||
|       hostDevice = "0x10c4:0xea60"; |       openFirewall = true; | ||||||
|  |       database = "postgres"; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     qbittorrent = { |     qbittorrent = { | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ | ||||||
|   dnsPort = 53; |   dnsPort = 53; | ||||||
| in { | in { | ||||||
|   options.host.adguardhome = { |   options.host.adguardhome = { | ||||||
|     enable = lib.mkEnableOption "should home-assistant be enabled on this computer"; |     enable = lib.mkEnableOption "should ad guard home be enabled on this computer"; | ||||||
|     directory = lib.mkOption { |     directory = lib.mkOption { | ||||||
|       type = lib.types.str; |       type = lib.types.str; | ||||||
|       default = "/var/lib/AdGuardHome/"; |       default = "/var/lib/AdGuardHome/"; | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ | ||||||
|     ./jellyfin.nix |     ./jellyfin.nix | ||||||
|     ./forgejo.nix |     ./forgejo.nix | ||||||
|     ./searx.nix |     ./searx.nix | ||||||
|     ./virt-home-assistant.nix |     ./home-assistant.nix | ||||||
|     ./adguardhome.nix |     ./adguardhome.nix | ||||||
|     ./immich.nix |     ./immich.nix | ||||||
|     ./qbittorent.nix |     ./qbittorent.nix | ||||||
|  |  | ||||||
|  | @ -1,130 +1,138 @@ | ||||||
| { | { | ||||||
|   lib, |   lib, | ||||||
|   config, |   config, | ||||||
|   inputs, |  | ||||||
|   ... |   ... | ||||||
| }: let | }: let | ||||||
|   configDir = "/var/lib/hass"; |   configDir = "/var/lib/hass"; | ||||||
|  |   dbUser = "hass"; | ||||||
| in { | in { | ||||||
|   options.host.home-assistant = { |   options.services.home-assistant = { | ||||||
|     enable = lib.mkEnableOption "should home-assistant be enabled on this computer"; |  | ||||||
|     subdomain = lib.mkOption { |     subdomain = lib.mkOption { | ||||||
|       type = lib.types.str; |       type = lib.types.str; | ||||||
|       description = "subdomain of base domain that home-assistant will be hosted at"; |       description = "subdomain of base domain that home-assistant will be hosted at"; | ||||||
|       default = "home-assistant"; |       default = "home-assistant"; | ||||||
|     }; |     }; | ||||||
|  | 
 | ||||||
|  |     database = lib.mkOption { | ||||||
|  |       type = lib.types.enum [ | ||||||
|  |         "builtin" | ||||||
|  |         "postgres" | ||||||
|  |       ]; | ||||||
|  |       description = "what database do we want to use"; | ||||||
|  |       default = "builtin"; | ||||||
|  |     }; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   config = lib.mkIf config.host.home-assistant.enable (lib.mkMerge [ |   config = lib.mkIf config.services.home-assistant.enable (lib.mkMerge [ | ||||||
|     { |     { | ||||||
|       virtualisation.libvirt = { |       host = { | ||||||
|         swtpm.enable = true; |         reverse_proxy.subdomains.${config.services.home-assistant.subdomain} = { | ||||||
|         connections."qemu:///session" = { |           target = "http://localhost:${toString config.services.home-assistant.config.http.server_port}"; | ||||||
|           networks = [ | 
 | ||||||
|             { |           websockets.enable = true; | ||||||
|               definition = inputs.nix-virt.lib.network.writeXML (inputs.nix-virt.lib.network.templates.bridge |           forwardHeaders.enable = true; | ||||||
|                 { | 
 | ||||||
|                   uuid = "d57e37e2-311f-4e5c-a484-97c2210c2770"; |           extraConfig = '' | ||||||
|                   subnet_byte = 71; |             add_header Upgrade $http_upgrade; | ||||||
|                 }); |             add_header Connection \"upgrade\"; | ||||||
|               active = true; | 
 | ||||||
|             } |             proxy_buffering off; | ||||||
|           ]; | 
 | ||||||
|           domains = [ |             proxy_read_timeout 90; | ||||||
|             { |           ''; | ||||||
|               definition = inputs.nix-virt.lib.domain.writeXML (inputs.nix-virt.lib.domain.templates.linux |  | ||||||
|                 { |  | ||||||
|                   name = "Home Assistant"; |  | ||||||
|                   uuid = "c5cc0efc-6101-4c1d-be31-acbba203ccde"; |  | ||||||
|                   memory = { |  | ||||||
|                     count = 4; |  | ||||||
|                     unit = "GiB"; |  | ||||||
|         }; |         }; | ||||||
|                   # storage_vol = { |       }; | ||||||
|                   #   pool = "MyPool"; | 
 | ||||||
|                   #   volume = "Penguin.qcow2"; |       services.home-assistant = { | ||||||
|                   # }; |         configDir = configDir; | ||||||
|                 }); |         extraComponents = [ | ||||||
|             } |           "met" | ||||||
|  |           "radio_browser" | ||||||
|  |           "isal" | ||||||
|  |           "zha" | ||||||
|  |           "jellyfin" | ||||||
|  |           "webostv" | ||||||
|  |           "tailscale" | ||||||
|  |           "syncthing" | ||||||
|  |           "sonos" | ||||||
|  |           "analytics_insights" | ||||||
|  |           "unifi" | ||||||
|  |           "openweathermap" | ||||||
|  |           "ollama" | ||||||
|  |         ]; | ||||||
|  |         config = { | ||||||
|  |           http = { | ||||||
|  |             server_port = 8123; | ||||||
|  |             use_x_forwarded_for = true; | ||||||
|  |             trusted_proxies = ["127.0.0.1" "::1"]; | ||||||
|  |             ip_ban_enabled = true; | ||||||
|  |             login_attempts_threshold = 10; | ||||||
|  |           }; | ||||||
|  |           recorder.db_url = "postgresql://@/${dbUser}"; | ||||||
|  |           "automation manual" = []; | ||||||
|  |           "automation ui" = "!include automations.yaml"; | ||||||
|  |         }; | ||||||
|  |         extraPackages = python3Packages: | ||||||
|  |           with python3Packages; [ | ||||||
|  |             hassil | ||||||
|  |             numpy | ||||||
|  |             gtts | ||||||
|           ]; |           ]; | ||||||
|       }; |       }; | ||||||
|  | 
 | ||||||
|  |       systemd.tmpfiles.rules = [ | ||||||
|  |         "f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass" | ||||||
|  |       ]; | ||||||
|  |     } | ||||||
|  |     (lib.mkIf (config.services.home-assistant.database == "postgres") { | ||||||
|  |       host = { | ||||||
|  |         postgres = { | ||||||
|  |           enable = true; | ||||||
|  |           extraUsers = { | ||||||
|  |             ${dbUser} = { | ||||||
|  |               isClient = true; | ||||||
|  |               createUser = true; | ||||||
|  |             }; | ||||||
|  |           }; | ||||||
|  |           extraDatabases = { | ||||||
|  |             ${dbUser} = { | ||||||
|  |               name = dbUser; | ||||||
|  |             }; | ||||||
|  |           }; | ||||||
|  |         }; | ||||||
|       }; |       }; | ||||||
| 
 | 
 | ||||||
|       # systemd.tmpfiles.rules = [ |       services.home-assistant = { | ||||||
|       #   "f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass" |         extraPackages = python3Packages: | ||||||
|       # ]; |           with python3Packages; [ | ||||||
|       # services.home-assistant = { |             psycopg2 | ||||||
|       #   enable = true; |           ]; | ||||||
|       #   configDir = configDir; |       }; | ||||||
|       #   extraComponents = [ |  | ||||||
|       #     "met" |  | ||||||
|       #     "radio_browser" |  | ||||||
|       #     "isal" |  | ||||||
|       #     "zha" |  | ||||||
|       #     "jellyfin" |  | ||||||
|       #     "webostv" |  | ||||||
|       #     "tailscale" |  | ||||||
|       #     "syncthing" |  | ||||||
|       #     "sonos" |  | ||||||
|       #     "analytics_insights" |  | ||||||
|       #     "unifi" |  | ||||||
|       #     "openweathermap" |  | ||||||
|       #   ]; |  | ||||||
|       #   config = { |  | ||||||
|       #     http = { |  | ||||||
|       #       server_port = 8082; |  | ||||||
|       #       use_x_forwarded_for = true; |  | ||||||
|       #       trusted_proxies = ["127.0.0.1" "::1"]; |  | ||||||
|       #       ip_ban_enabled = true; |  | ||||||
|       #       login_attempts_threshold = 10; |  | ||||||
|       #     }; |  | ||||||
|       #     # recorder.db_url = "postgresql://@/${db_user}"; |  | ||||||
|       #     "automation manual" = []; |  | ||||||
|       #     "automation ui" = "!include automations.yaml"; |  | ||||||
|       #   }; |  | ||||||
|       #   extraPackages = python3Packages: |  | ||||||
|       #     with python3Packages; [ |  | ||||||
|       #       hassil |  | ||||||
|       #       numpy |  | ||||||
|       #       gtts |  | ||||||
|       #     ]; |  | ||||||
|       # }; |  | ||||||
|       # host = { |  | ||||||
|       #   reverse_proxy.subdomains.${config.host.home-assistant.subdomain} = { |  | ||||||
|       #     target = "http://localhost:${toString config.services.home-assistant.config.http.server_port}"; |  | ||||||
| 
 | 
 | ||||||
|       #     websockets.enable = true; |       systemd.services.home-assistant = { | ||||||
|       #     forwardHeaders.enable = true; |         requires = [ | ||||||
| 
 |           config.systemd.services.postgresql.name | ||||||
|       #     extraConfig = '' |         ]; | ||||||
|       #       add_header Upgrade $http_upgrade; |       }; | ||||||
|       #       add_header Connection \"upgrade\"; |     }) | ||||||
| 
 |  | ||||||
|       #       proxy_buffering off; |  | ||||||
| 
 |  | ||||||
|       #       proxy_read_timeout 90; |  | ||||||
|       #     ''; |  | ||||||
|       #   }; |  | ||||||
|       # }; |  | ||||||
|     } |  | ||||||
|     (lib.mkIf config.host.impermanence.enable { |     (lib.mkIf config.host.impermanence.enable { | ||||||
|       # assertions = [ |       assertions = [ | ||||||
|       #   { |         { | ||||||
|       #     assertion = config.services.home-assistant.configDir == configDir; |           assertion = config.services.home-assistant.configDir == configDir; | ||||||
|       #     message = "home assistant config directory does not match persistence"; |           message = "home assistant config directory does not match persistence"; | ||||||
|       #   } |         } | ||||||
|       # ]; |       ]; | ||||||
|       # environment.persistence."/persist/system/root" = { |       environment.persistence."/persist/system/root" = { | ||||||
|       #   enable = true; |         enable = true; | ||||||
|       #   hideMounts = true; |         hideMounts = true; | ||||||
|       #   directories = [ |         directories = [ | ||||||
|       #     { |           { | ||||||
|       #       directory = configDir; |             directory = configDir; | ||||||
|       #       user = "hass"; |             user = "hass"; | ||||||
|       #       group = "hass"; |             group = "hass"; | ||||||
|       #     } |           } | ||||||
|       #   ]; |         ]; | ||||||
|       # }; |       }; | ||||||
|     }) |     }) | ||||||
|   ]); |   ]); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.host.podman = { |   options.host.podman = { | ||||||
|     enable = lib.mkEnableOption "should home-assistant be enabled on this computer"; |     enable = lib.mkEnableOption "should podman be enabled on this computer"; | ||||||
|     macvlan = { |     macvlan = { | ||||||
|       subnet = lib.mkOption { |       subnet = lib.mkOption { | ||||||
|         type = lib.types.str; |         type = lib.types.str; | ||||||
|  |  | ||||||
|  | @ -1,155 +0,0 @@ | ||||||
| { |  | ||||||
|   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; |  | ||||||
|           } |  | ||||||
|         ]; |  | ||||||
|       }; |  | ||||||
|     }) |  | ||||||
|   ]); |  | ||||||
| } |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue