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 0000000..a2a583f Binary files /dev/null and b/secrets/homeassistant/secrets.yaml.age differ diff --git a/secrets/restic/128G.age b/secrets/restic/128G.age index 534b28a..8c7ec30 100644 --- a/secrets/restic/128G.age +++ b/secrets/restic/128G.age @@ -1,24 +1,24 @@ age-encryption.org/v1 -> 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 ]; }