| 
									
										
										
										
											2023-04-16 16:56:36 +02:00
										 |  |  | # home automation | 
					
						
							| 
									
										
										
										
											2024-07-28 21:08:02 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   config, | 
					
						
							|  |  |  |   lib, | 
					
						
							|  |  |  |   pkgs, | 
					
						
							|  |  |  |   ... | 
					
						
							|  |  |  | }: | 
					
						
							| 
									
										
										
										
											2023-04-16 16:56:36 +02:00
										 |  |  | let | 
					
						
							| 
									
										
										
										
											2023-11-26 16:28:59 +01:00
										 |  |  |   cfg = config.my.services.home-automation; | 
					
						
							| 
									
										
										
										
											2023-11-07 23:13:51 +01:00
										 |  |  |   inherit (config.networking) domain; | 
					
						
							| 
									
										
										
										
											2023-04-16 16:56:36 +02:00
										 |  |  | in | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-11-26 16:28:59 +01:00
										 |  |  |   options.my.services.home-automation = with lib; { | 
					
						
							| 
									
										
										
										
											2023-04-16 16:56:36 +02:00
										 |  |  |     enable = mkEnableOption "home-assistant server"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     package = lib.mkPackageOption pkgs "home-assistant" { }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     port = lib.mkOption { | 
					
						
							|  |  |  |       type = lib.types.port; | 
					
						
							|  |  |  |       default = 8123; | 
					
						
							|  |  |  |       description = lib.mdDoc ''
 | 
					
						
							|  |  |  |         Web interface port. | 
					
						
							|  |  |  |       '';
 | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     extraComponents = mkOption { | 
					
						
							|  |  |  |       type = types.listOf (types.enum cfg.package.availableComponents); | 
					
						
							|  |  |  |       example = literalExpression ''
 | 
					
						
							|  |  |  |         [ | 
					
						
							|  |  |  |           "analytics" | 
					
						
							|  |  |  |           "default_config" | 
					
						
							|  |  |  |           "esphome" | 
					
						
							|  |  |  |           "my" | 
					
						
							|  |  |  |           "wled" | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |       '';
 | 
					
						
							|  |  |  |       default = [ ]; | 
					
						
							|  |  |  |       description = mdDoc ''
 | 
					
						
							|  |  |  |           List | 
					
						
							|  |  |  |           of [ components ] | 
					
						
							|  |  |  |           (https://www.home-assistant.io/integrations/) | 
					
						
							|  |  |  |           that | 
					
						
							|  |  |  |           have | 
					
						
							|  |  |  |           their | 
					
						
							|  |  |  |           dependencies | 
					
						
							|  |  |  |           included in the package. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         The component name can be found in the URL, for example `https://www.home-assistant.io/integrations/ffmpeg/` would map to `ffmpeg`. | 
					
						
							|  |  |  |       '';
 | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     latitude = mkOption { | 
					
						
							|  |  |  |       type = types.nullOr (types.either types.float types.str); | 
					
						
							|  |  |  |       default = null; | 
					
						
							|  |  |  |       example = 52.3; | 
					
						
							|  |  |  |       description = mdDoc ''
 | 
					
						
							|  |  |  |         your location latitude. Impacts sunrise data. | 
					
						
							|  |  |  |       '';
 | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     longitude = mkOption { | 
					
						
							|  |  |  |       type = types.nullOr (types.either types.float types.str); | 
					
						
							|  |  |  |       default = null; | 
					
						
							|  |  |  |       example = 4.9; | 
					
						
							|  |  |  |       description = mdDoc ''
 | 
					
						
							|  |  |  |         your location longitude. Impacts sunrise data. | 
					
						
							|  |  |  |       '';
 | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     elevation = mkOption { | 
					
						
							|  |  |  |       type = types.nullOr (types.either types.float types.str); | 
					
						
							|  |  |  |       default = null; | 
					
						
							|  |  |  |       description = mdDoc ''
 | 
					
						
							|  |  |  |         your location elevation. Impacts sunrise data. | 
					
						
							|  |  |  |       '';
 | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     timezone = mkOption { | 
					
						
							|  |  |  |       type = types.str; | 
					
						
							|  |  |  |       default = "GMT"; | 
					
						
							|  |  |  |       description = mdDoc ''
 | 
					
						
							|  |  |  |         your timezone. | 
					
						
							|  |  |  |       '';
 | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   config = lib.mkIf cfg.enable { | 
					
						
							| 
									
										
										
										
											2023-11-26 16:27:53 +01:00
										 |  |  |     services = { | 
					
						
							|  |  |  |       home-assistant = { | 
					
						
							|  |  |  |         enable = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         inherit (cfg) package; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         config = { | 
					
						
							|  |  |  |           default_config = { }; | 
					
						
							|  |  |  |           homeassistant = { | 
					
						
							|  |  |  |             name = "Home"; | 
					
						
							|  |  |  |             inherit (cfg) latitude longitude elevation; | 
					
						
							|  |  |  |             unit_system = "metric"; | 
					
						
							|  |  |  |             time_zone = cfg.timezone; | 
					
						
							|  |  |  |             external_url = "https://automation.${domain}"; | 
					
						
							|  |  |  |             internal_url = "http://127.0.0.1:${toString cfg.port}"; | 
					
						
							|  |  |  |           }; | 
					
						
							|  |  |  |           http = { | 
					
						
							|  |  |  |             server_port = cfg.port; | 
					
						
							|  |  |  |             use_x_forwarded_for = true; | 
					
						
							|  |  |  |             trusted_proxies = [ | 
					
						
							|  |  |  |               "127.0.0.1" | 
					
						
							|  |  |  |               "::1" | 
					
						
							|  |  |  |             ]; | 
					
						
							|  |  |  |           }; | 
					
						
							|  |  |  |           prometheus.requires_auth = false; | 
					
						
							| 
									
										
										
										
											2023-04-16 16:56:36 +02:00
										 |  |  |         }; | 
					
						
							| 
									
										
										
										
											2023-11-26 16:27:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         extraComponents = [ | 
					
						
							|  |  |  |           "backup" | 
					
						
							| 
									
										
										
										
											2023-11-27 23:17:46 +01:00
										 |  |  |           "esphome" | 
					
						
							| 
									
										
										
										
											2023-11-29 20:22:40 +01:00
										 |  |  |           "shelly" | 
					
						
							| 
									
										
										
										
											2023-11-26 16:27:53 +01:00
										 |  |  |           "prometheus" | 
					
						
							|  |  |  |         ] ++ cfg.extraComponents; | 
					
						
							| 
									
										
										
										
											2023-04-16 16:56:36 +02:00
										 |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-26 16:27:53 +01:00
										 |  |  |       prometheus.scrapeConfigs = [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           job_name = "home-assistant"; | 
					
						
							|  |  |  |           metrics_path = "/api/prometheus"; | 
					
						
							|  |  |  |           static_configs = [ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               targets = [ "127.0.0.1:${toString cfg.port}" ]; | 
					
						
							|  |  |  |               labels = { | 
					
						
							|  |  |  |                 instance = config.networking.hostName; | 
					
						
							|  |  |  |               }; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           ]; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       ]; | 
					
						
							| 
									
										
										
										
											2023-04-16 16:56:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-26 16:27:53 +01:00
										 |  |  |       esphome.enable = true; | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2023-06-04 21:32:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-18 22:53:34 +02:00
										 |  |  |     my.services.prometheus.rules = { | 
					
						
							|  |  |  |       homeassistant = { | 
					
						
							|  |  |  |         condition = ''homeassistant_entity_available{domain="persistent_notification", entity!~"persistent_notification.http_login|persistent_notification.recorder_database_migration"} >= 0''; | 
					
						
							|  |  |  |         description = "homeassistant notification {{$labels.entity}} ({{$labels.friendly_name}}): {{$value}}"; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-16 16:56:36 +02:00
										 |  |  |     my.services.nginx.virtualHosts = [ | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2023-06-04 21:32:29 +02:00
										 |  |  |         subdomain = "automation"; | 
					
						
							| 
									
										
										
										
											2023-04-16 16:56:36 +02:00
										 |  |  |         inherit (cfg) port; | 
					
						
							| 
									
										
										
										
											2023-11-20 21:48:33 +01:00
										 |  |  |         extraConfig = { | 
					
						
							|  |  |  |           locations."/" = { | 
					
						
							|  |  |  |             proxyWebsockets = true; | 
					
						
							|  |  |  |             extraConfig = ''
 | 
					
						
							|  |  |  |               proxy_buffering off; | 
					
						
							|  |  |  |             '';
 | 
					
						
							|  |  |  |           }; | 
					
						
							|  |  |  |         }; | 
					
						
							| 
									
										
										
										
											2023-04-16 16:56:36 +02:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2023-11-26 16:27:53 +01:00
										 |  |  |       { | 
					
						
							|  |  |  |         subdomain = "esphome"; | 
					
						
							|  |  |  |         inherit (config.services.esphome) port; | 
					
						
							|  |  |  |         extraConfig = { | 
					
						
							|  |  |  |           locations."/" = { | 
					
						
							|  |  |  |             proxyWebsockets = true; | 
					
						
							|  |  |  |           }; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2023-04-16 16:56:36 +02:00
										 |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-26 16:27:53 +01:00
										 |  |  |     webapps.apps = { | 
					
						
							|  |  |  |       home-assistant = { | 
					
						
							|  |  |  |         dashboard = { | 
					
						
							|  |  |  |           name = "Home-Automation"; | 
					
						
							|  |  |  |           category = "infra"; | 
					
						
							|  |  |  |           icon = "house-signal"; | 
					
						
							|  |  |  |           url = "https://automation.${domain}"; | 
					
						
							|  |  |  |           method = "get"; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |       esphome = { | 
					
						
							|  |  |  |         dashboard = { | 
					
						
							|  |  |  |           name = "Home-Firmware"; | 
					
						
							|  |  |  |           category = "infra"; | 
					
						
							|  |  |  |           icon = "house-laptop"; | 
					
						
							|  |  |  |           url = "https://esphome.${domain}"; | 
					
						
							|  |  |  |           method = "get"; | 
					
						
							|  |  |  |         }; | 
					
						
							| 
									
										
										
										
											2023-04-16 16:56:36 +02:00
										 |  |  |       }; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | } |