From 78a024a924eea3db99fb9fc05520aff17d939655 Mon Sep 17 00:00:00 2001 From: Jake Hillion Date: Sun, 24 Dec 2023 22:09:53 +0000 Subject: [PATCH] add homeassistant --- .../default.nix | 16 ++- modules/backups/default.nix | 1 + modules/backups/homeassistant.nix | 34 +++++ modules/default.nix | 8 +- modules/locations.nix | 2 + modules/services/default.nix | 14 ++ modules/services/homeassistant.nix | 132 ++++++++++++++++++ modules/www/global.nix | 2 +- secrets/homeassistant/secrets.yaml.age | Bin 0 -> 2834 bytes secrets/restic/128G.age | 42 +++--- secrets/secrets.nix | 5 +- 11 files changed, 223 insertions(+), 33 deletions(-) create mode 100644 modules/backups/homeassistant.nix create mode 100644 modules/services/default.nix create mode 100644 modules/services/homeassistant.nix create mode 100644 secrets/homeassistant/secrets.yaml.age diff --git a/hosts/microserver.home.ts.hillion.co.uk/default.nix b/hosts/microserver.home.ts.hillion.co.uk/default.nix index eadd54e..5157d5e 100644 --- a/hosts/microserver.home.ts.hillion.co.uk/default.nix +++ b/hosts/microserver.home.ts.hillion.co.uk/default.nix @@ -13,6 +13,9 @@ networking.hostName = "microserver"; networking.domain = "home.ts.hillion.co.uk"; + ## Custom Services + custom.locations.autoServe = true; + # Networking ## Tailscale age.secrets."tailscale/microserver.home.ts.hillion.co.uk".file = ../../secrets/tailscale/microserver.home.ts.hillion.co.uk.age; @@ -40,9 +43,16 @@ services.iperf3.enable = true; services.iperf3.openFirewall = true; - networking.firewall.interfaces."tailscale0".allowedTCPPorts = [ - 1883 # MQTT server - ]; + networking.firewall.interfaces = { + "eth0" = { + allowedUDPPorts = [ + 5353 # HomeKit + ]; + allowedTCPPorts = [ + 21063 # HomeKit + ]; + }; + }; }; } diff --git a/modules/backups/default.nix b/modules/backups/default.nix index 9b90f7e..89a21b5 100644 --- a/modules/backups/default.nix +++ b/modules/backups/default.nix @@ -3,6 +3,7 @@ { imports = [ ./git.nix + ./homeassistant.nix ./matrix.nix ]; } diff --git a/modules/backups/homeassistant.nix b/modules/backups/homeassistant.nix new file mode 100644 index 0000000..8538b1f --- /dev/null +++ b/modules/backups/homeassistant.nix @@ -0,0 +1,34 @@ +{ config, pkgs, lib, ... }: + +let + cfg = config.custom.backups.homeassistant; +in +{ + options.custom.backups.homeassistant = { + enable = lib.mkEnableOption "homeassistant"; + }; + + config = lib.mkIf cfg.enable { + age.secrets."backups/homeassistant/restic/128G" = { + file = ../../secrets/restic/128G.age; + owner = "hass"; + group = "hass"; + }; + + services = { + restic.backups."homeassistant" = { + user = "hass"; + timerConfig = { + OnCalendar = "03:00"; + RandomizedDelaySec = "60m"; + }; + repository = "rest:http://restic.tywin.storage.ts.hillion.co.uk/128G"; + passwordFile = config.age.secrets."backups/homeassistant/restic/128G".path; + paths = [ + config.services.home-assistant.configDir + ]; + }; + }; + }; +} + diff --git a/modules/default.nix b/modules/default.nix index 2893faf..356e065 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -11,13 +11,7 @@ ./impermanence.nix ./locations.nix ./resilio.nix - ./services/downloads.nix - ./services/gitea.nix - ./services/mastodon/default.nix - ./services/matrix.nix - ./services/unifi.nix - ./services/version_tracker.nix - ./services/zigbee2mqtt.nix + ./services/default.nix ./storj.nix ./tailscale.nix ./users.nix diff --git a/modules/locations.nix b/modules/locations.nix index 46cc729..8cf5ff5 100644 --- a/modules/locations.nix +++ b/modules/locations.nix @@ -15,6 +15,7 @@ in services = { downloads = "tywin.storage.ts.hillion.co.uk"; gitea = "jorah.cx.ts.hillion.co.uk"; + homeassistant = "microserver.home.ts.hillion.co.uk"; mastodon = "vm.strangervm.ts.hillion.co.uk"; matrix = "jorah.cx.ts.hillion.co.uk"; unifi = "jorah.cx.ts.hillion.co.uk"; @@ -29,6 +30,7 @@ in config = lib.mkIf cfg.autoServe { custom.services.downloads.enable = cfg.locations.services.downloads == config.networking.fqdn; custom.services.gitea.enable = cfg.locations.services.gitea == config.networking.fqdn; + custom.services.homeassistant.enable = cfg.locations.services.homeassistant == config.networking.fqdn; custom.services.mastodon.enable = cfg.locations.services.mastodon == config.networking.fqdn; custom.services.matrix.enable = cfg.locations.services.matrix == config.networking.fqdn; custom.services.unifi.enable = cfg.locations.services.unifi == config.networking.fqdn; diff --git a/modules/services/default.nix b/modules/services/default.nix new file mode 100644 index 0000000..9c6d199 --- /dev/null +++ b/modules/services/default.nix @@ -0,0 +1,14 @@ +{ config, lib, ... }: + +{ + imports = [ + ./downloads.nix + ./gitea.nix + ./homeassistant.nix + ./mastodon/default.nix + ./matrix.nix + ./unifi.nix + ./version_tracker.nix + ./zigbee2mqtt.nix + ]; +} diff --git a/modules/services/homeassistant.nix b/modules/services/homeassistant.nix new file mode 100644 index 0000000..115a5e0 --- /dev/null +++ b/modules/services/homeassistant.nix @@ -0,0 +1,132 @@ +{ config, pkgs, lib, ... }: + +let + cfg = config.custom.services.homeassistant; +in +{ + options.custom.services.homeassistant = { + enable = lib.mkEnableOption "homeassistant"; + + backup = lib.mkOption { + default = true; + type = lib.types.bool; + }; + }; + + config = lib.mkIf cfg.enable { + custom = { + backups.homeassistant.enable = cfg.backup; + }; + + age.secrets."homeassistant/secrets.yaml" = { + file = ../../secrets/homeassistant/secrets.yaml.age; + path = "${config.services.home-assistant.configDir}/secrets.yaml"; + owner = "hass"; + group = "hass"; + }; + + services = { + postgresql = { + enable = true; + initialScript = pkgs.writeText "homeassistant-init.sql" '' + CREATE ROLE "hass" WITH LOGIN; + CREATE DATABASE "homeassistant" WITH OWNER "hass" ENCODING "utf8"; + ''; + }; + + home-assistant = { + enable = true; + + extraPackages = python3Packages: with python3Packages; [ + psycopg2 # postgresql support + ]; + extraComponents = [ + "default_config" + "esphome" + "flux" + "google_assistant" + "homekit" + "met" + "mobile_app" + "mqtt" + "otp" + "sun" + ]; + + config = { + default_config = { }; + + recorder = { + db_url = "postgresql://@/homeassistant"; + }; + + http = { + use_x_forwarded_for = true; + trusted_proxies = [ "100.96.143.138" ]; + }; + + google_assistant = { + project_id = "homeassistant-8de41"; + service_account = { + client_email = "!secret google_assistant_service_account_client_email"; + private_key = "!secret google_assistant_service_account_private_key"; + }; + }; + homekit = [{ + filter = { + include_domains = [ "light" ]; + }; + }]; + + switch = [ + { + platform = "flux"; + start_time = "07:00"; + stop_time = "23:59"; + mode = "mired"; + disable_brightness_adjust = true; + lights = [ + "light.bedroom_lamp" + "light.bedroom_light" + "light.cubby_light" + "light.desk_lamp" + "light.hallway_light" + "light.living_room_lamp" + "light.living_room_light" + "light.wardrobe_light" + ]; + } + ]; + + sensor = [ + { + # Time/Date (for automations) + platform = "time_date"; + display_options = [ + "date" + "date_time_iso" + ]; + } + + { + # Living Room Temperature + platform = "statistics"; + name = "Living Room temperature (rolling average)"; + entity_id = "sensor.living_room_environment_sensor_temperature"; + state_characteristic = "average_linear"; + unique_id = "e86198a8-88f4-4822-95cb-3ec7b2662395"; + max_age = { + minutes = 5; + }; + } + ]; + + # UI managed expansions + automation = "!include automations.yaml"; + script = "!include scripts.yaml"; + scene = "!include scenes.yaml"; + }; + }; + }; + }; +} diff --git a/modules/www/global.nix b/modules/www/global.nix index a8fe0ab..892c312 100644 --- a/modules/www/global.nix +++ b/modules/www/global.nix @@ -38,7 +38,7 @@ in file_server ''; "homeassistant.hillion.co.uk".extraConfig = '' - reverse_proxy http://homeassistant.homeassistant.ts.hillion.co.uk:8123 + reverse_proxy http://${locations.services.homeassistant}:8123 ''; "gitea.hillion.co.uk".extraConfig = '' reverse_proxy http://${locations.services.gitea}:3000 diff --git a/secrets/homeassistant/secrets.yaml.age b/secrets/homeassistant/secrets.yaml.age new file mode 100644 index 0000000000000000000000000000000000000000..a2a583f2b43d6e5e229c97941e94acd7435e99d6 GIT binary patch literal 2834 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 U^oE^$G@ ssh-rsa GxPFJQ -cHq8lMXJL5MiRad32l1zsSg16juWkbJeaAbhCNkoNS1AWZ0FMdDn1knFENWBmbQ5 -UQe4xkERwAzKhQqowP0/Ey9y47Vs5Z2MOdntLsnH0TiJ42uQWgocBHUPuWFA3iTD -a7Y1My+EsEWqKTtJUhwUPEmR473rsscQ87jRu/uyzDkCysERLfHh7vLyoxQJLjKY -ZBpn90Lvdw52QQGGgnJ2VvIa3tsWwCdKtdIHrucPOCzI2Kf0vgULlFancGFyE2bo -F+5ejQnGqfKhJAZABIgSGBdCGi3OeiQE+pwTiGPCNjWAre3+D+qgyONZO3yJMotw -ciryRD9A8dB+gURfmF2HlA +EZBFKBAzoSqlSaMvehEGiiCXaT7qhewJy1v6mr3NVCvQqTck6STzEBoalKDi3mIF +fLoX7oVMEh5bgOkKIYBiv00ueHe+osNCJtx/dHx9X462RXixrcbIqdPCD+XS0puZ +CxaohxNu+kSmbtZc9pZ8PETZ93dmCetSIwo1uQiGJChFBxNn7lm/fvOPvdN1821i +ougijCL+f8fG/fymXnnlULbAdyhUI+6Hx2WAP8v9796XQHBieKJJfRFVhbUGRKD9 +1AK66zZClZ1dD8SuZBtCnafrVm3Wjwys2aKgncKdrWuNoScWoZNiL4nS55w3PCEN +U2Jq6smqxjPdC/18xuBiNA -> ssh-rsa K9mW1w -ifetP5SszccWU8K/ZGJQ4Gj5qn3mis6pMUpm7Gzd8Bb04w6jVnSSvVW0V1VvW19a -y2CPB8f7hTmK+y5cKBNBxKUPs1lwH/ETe21paBRDfq5KBQQJJkJllHiG7Noc1F4D -2yIvwKTyM6scIrKOzypqpsQjKbEcQ/XVsWu1J+0ju1y0xj+KBrVtuQhDQSqCkpmi -IAFkgIZODLj7grqZEAcfOpcG30qcu3x92TcKvLDbN7OxQTbZRAG49T6x90NcllkD -Flp7Xda1eLey5hXbhv/pNs3C50S3fWGXZWytCaNvqKmCijwq80k0GI+YcfI2y3FD -Drj1b4IvUUEyWf0nxgJaKA --> ssh-ed25519 nWv9MA zpfBb+v7BQxbzWSpWHglqcGz/s+YnCR+OaXyf8LhSx0 -LLay86z80qxcbflUy0aJd1FmJwHCWGDAykq+PeUVKc0 --> ssh-ed25519 Qo6/7A s6Z/CG0rtblgo/LckP0UO00XE9ypU0pR8I9spFmGgAw -n6IPtqOp2+6l2dlbq5e0ly3I8tkCQkWQhUsSGGmqFJs --> G4>-grease i0nO3 wlKI -Ns995X91W6SrIpcnahbbI65GsjEDo4n7WOzOgmMN/Oc1NJdXAiUNEh3sSeFmoIeK -tf5G6zc1ysYS6ay31OCpvgpSZCAuXU5whbU2pP7W12uqDA ---- XQzGae+qe6NarNuMTg9U14bDEmXs4WgmtWIHj0oIEPs -\ҫV)Gmwhn:úe\ 5q OG \ No newline at end of file +wYSU6EnCqBEQL950d/suDPPmJmqiPWHX0GJuc37bYffJTCJIJKthk43FDOWrcgbD +vsfTjRkzRZY8H6ngTTlwIuECzoJDhLq4/4n69dOi2Uz8XZvD9y6lPE7qmqClMziZ +mtheoib/PVoV6OvPnCg+d52HfR2REuQNHxGhNucDOjmL+lcjYNqrVq1IHhZJ0WUh +4+8J5kA17yFtdnLuIcIPdVNZ1oI1Y5E6H+fiJhje5cnEJ7u/GQAFRLmdV36cZDzF +OaUap/nxyAIjga+zbGptHjvKvLfWL+5EA+H47es6xcpJfadBuq0+AfTlSvsQzrqj +15xCp6IeGXJeZCOF3NchWw +-> ssh-ed25519 nWv9MA k5cpWIDL6sNwqlr9dx3KBd8SXW4gwLZwjUPD1jqL4VM +xkDd8nnNoZNOPxIMt2iXvOVjUXxPcBpI0KD1I4p40p0 +-> ssh-ed25519 Qo6/7A 7eJXxyASGk0iZu7o81zoiIm33IILsL9I7ScDXARPXzw +L0WP9V9nkRUvLXVVWf6BWf2GR8xvEI0LkDDAYOmGqLE +-> ssh-ed25519 L5AKYA h7RKESPZ5k1wt67mErHvfWBpXY20mTVf/rMsvEcnb3s +xoHeghX8qvq2A9LYQpH+jna3Qr9tegIkTI/RhcZFXig +--- EwX1bjkJInYJEdM64ZNnt4UfwXAHcAz6ce+eBU9ORC0 + +@lf}40ur *'n%j=Ւ"÷;y \ No newline at end of file diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 06d9cb0..568751b 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -67,7 +67,7 @@ in "matrix/matrix.hillion.co.uk/registration_shared_secret.age".publicKeys = jake_users ++ [ ts.cx.jorah ]; # Backups Secrets - "restic/128G.age".publicKeys = jake_users ++ [ ts.storage.tywin ts.cx.jorah ]; + "restic/128G.age".publicKeys = jake_users ++ [ ts.storage.tywin ts.cx.jorah ts.home.microserver ]; "restic/1.6T.age".publicKeys = jake_users ++ [ ts.storage.tywin ts.home.router ]; "git/git_backups_ecdsa.age".publicKeys = jake_users ++ [ ts.storage.tywin ]; @@ -111,4 +111,7 @@ in "gitea/oauth_jwt_secret.age".publicKeys = jake_users ++ [ ts.cx.jorah ]; "gitea/security_secret_key.age".publicKeys = jake_users ++ [ ts.cx.jorah ]; "gitea/security_internal_token.age".publicKeys = jake_users ++ [ ts.cx.jorah ]; + + # HomeAssistant Secrets + "homeassistant/secrets.yaml.age".publicKeys = jake_users ++ [ ts.home.microserver ]; }