diff --git a/hosts/aluminium/ports.nix b/hosts/aluminium/ports.nix index a259d6d..f1d126f 100644 --- a/hosts/aluminium/ports.nix +++ b/hosts/aluminium/ports.nix @@ -2,8 +2,12 @@ custom-utils.validatePortAttrset { asterisk-rtp = { udp.range = [ 10000 10200 ]; }; - unifi.tcp = 8443; doorbell-audiosocket.tcp = 9092; - doorbell-webrtc.tcp = 8889; doorbell-webrtc-ice.tcp = 8189; + doorbell-webrtc.tcp = 8889; + esphome.tcp = 6052; + home-assistant.tcp = 8123; + nginx-http.tcp = 80; + nginx-https.tcp = 443; + unifi.tcp = 8443; } diff --git a/hosts/aluminium/secrets.yaml b/hosts/aluminium/secrets.yaml index 01b9197..2ecd5a3 100644 --- a/hosts/aluminium/secrets.yaml +++ b/hosts/aluminium/secrets.yaml @@ -4,6 +4,7 @@ myintercom-doorbell-password: ENC[AES256_GCM,data:waUUvHQ9BZFePQ==,iv:ev21SNOwzd asterisk-pjsip: ENC[AES256_GCM,data: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,iv:bFKc8e+3rLAHje8UWwY2elof5xqceTTWX1f7nkE91nM=,tag:NWMiljj8urTDoka5bkF0jg==,type:str] asterisk-ari: ENC[AES256_GCM,data:HnY7d3BdScb0bmsBVlsTHAMv2k8tyyA/,iv:q+NsCHcGGOCe6gdAHbFfjKvO4dyWoW/xI5jtngJmdds=,tag:e8kuEsEokf5lAAgO/coxTQ==,type:str] asterisk-voicemail: ENC[AES256_GCM,data:uyXeBP+9WkfVot4Ot3vwv3OEZfoVDK2I+lvaPpGJTZp16YNtP+uxNiW2ynewQlORCTY59bP1jW3bQdT/ASGsErOrhInYSytTyfdZ51BF9+jz0TH6oWxsSuuawTrkC8jvJOpejt6XuGoYbbqlM/VL1xzgDkq3ztTxaHTfdTonQij2Q4cYddMRHWIEuBCK7FU2TlHAJeIFZvtE0MiyNNT3rEWSs1xcljTGfMjkoMd+FI1uZSQT4r0kAaPPkvCWcAGH6R+F0Ue++i9TuLhu+sDV+X6u3N/garDW74H0bOcLJysImtuPXh1aXuBkHQuC1Liss/IF4NDjtDDhpfc0eePR5MWv/Kj0q+VFJiUPY6XnWh6fG9I2yY22+I7eAAg/xWVZBXPWbFHRz8jm1owp4ln6/hcrJOw6Fzw8tZ6Jd9nciOeOmR1KtjEzklPP5kP1YQPtGio/LnOaAAhTHy16MbWf/Ey4S30+eHB+joD8OM93+YxxrdKNE6XXEcAhkdpHYecrvz4Co1fhY7ZoOnNvA8Juup/7PMyNEU/Fy4Pta34aT/j1s7de2vTpRNBeecWvgFA9Qd7Re/2XPqOAkpduxDniwsUdb52oL39MBoOCY8brmXn2J/mMDeOmoqvjRHsPZsajPTAqF/nqRB8VpwoZAKAx59DYBGgmHz7/7JRX9NXOAus1yLbMfVqDftk6+KTFQ9wCqei3jaI/K5AJrSEwlZG0BLoDefIGXT5f8bNNgSn865j2RP+FLa6W3/u5t+k=,iv:/phktIxMdDO5Nrum7hf3oLDmQO04lrkvFuHNw77aRks=,tag:7OUg0BG9X7nBHWiQNaSOEQ==,type:str] +esphome: ENC[AES256_GCM,data:2pFVokO8YTyKa1F7EePo6wIS3y6prL8SSkxypWZkHl3Ye6Qg0eqZ4du/iwLIXQpJoc6R3uU7D6eIQEVOGbwqYp6+F0CW17F89k9c/VLHQHRpWbA20GgLr7X4fZ8xdbp7HCLpVxRsdzDz8aoARfV8Cn6T7Uo80ah1rMDnTj10WI+Yu6xVqVwPNWrSk9NUGKMK32M2slk=,iv:Xla0c4d9rxn06upy7GTbWBQ8pzl+gLnIw+Rf6hqQlhk=,tag:S+clc2ctuOA6lsInSFm93Q==,type:str] sops: kms: [] gcp_kms: [] @@ -19,8 +20,8 @@ sops: NEtzRXY1Q1Njelc1YXNWVE9Jd2NnOFEKjOWHaxO5fF5l+c1Hv6QLBQajrvu1VimZ Hqk0GYrFpfpFtbhBRyrYgmNuX/qIRMHemdXcNKDYcj0WXgsdVqH7Qw== -----END AGE ENCRYPTED FILE----- - lastmodified: "2023-11-06T23:32:51Z" - mac: ENC[AES256_GCM,data:7lW6i4ULus4348NwnV/ovcWebspBcEBzYqLtl+8xFOfe3erIFnC3iRo0ibZJ8yishZpIUxoVu08yxQoa1qEriC57WETMaR+iGUPaY75tHraBJGY26Etk7Hy2QhQ7D+srBY+CogHhHAD8HUwT4/ZiPqKe1eQAvNg/6HWnjbQkG/Q=,iv:r43odkYgQsyK5uJJ5V98kTx7enP7TRuFoTnYfHmD/8o=,tag:hR+1zCniHs1l3qSkhQhtFw==,type:str] + lastmodified: "2024-03-17T20:41:27Z" + mac: ENC[AES256_GCM,data:f7RdcXpu9CGSZpIF8rwuIkn97EWRxJXxoC7KKbkZg4yxSxZJR/S5UXzEC56eY73IdBHap4op3l+cO7pT7p1rkspHQPH/5D225ihVQ8PQ29u2nlyyrrebB5tM1Mt+rJRlizBPxDDKySJYgdqZCWUwB8f5hQudpb0CGra7NfQreRg=,iv:vwpVqib7fyuV83FiyMT4BOeuqyrcspFyieQGWyZZzcU=,tag:zuJVSA2WqzSvM4MBWrdRlQ==,type:str] pgp: - created_at: "2024-01-31T01:19:14Z" enc: |- @@ -34,4 +35,4 @@ sops: -----END PGP MESSAGE----- fp: 3044E71E3DEFF49B586CF5809BF4FCCB90854DA9 unencrypted_suffix: _unencrypted - version: 3.7.3 + version: 3.8.1 diff --git a/hosts/aluminium/services/default.nix b/hosts/aluminium/services/default.nix index 9539fb7..7ce0f6e 100644 --- a/hosts/aluminium/services/default.nix +++ b/hosts/aluminium/services/default.nix @@ -4,6 +4,9 @@ ./dnsmasq.nix ./doorbell.nix ./dyndns.nix + ./esphome + ./home-assistant.nix + ./nginx.nix ./unifi-controller.nix ]; } diff --git a/hosts/aluminium/services/esphome/default.nix b/hosts/aluminium/services/esphome/default.nix new file mode 100644 index 0000000..b64c343 --- /dev/null +++ b/hosts/aluminium/services/esphome/default.nix @@ -0,0 +1,62 @@ +args@{ lib, pkgs, config, custom-utils, ... }: +let + ports = import ../../ports.nix args; + cfg = config.services.esphome; + cfgdir = pkgs.stdenvNoCC.mkDerivation { + name = "esphome-config"; + src = ./devices; + dontBuild = true; + installPhase = '' + mkdir $out + cp -r * $out + ''; + }; + esphomeParams = + if cfg.enableUnixSocket + then "--socket /run/esphome/esphome.sock" + else "--address ${cfg.address} --port ${toString cfg.port}"; +in +{ + sops.secrets.esphome = { + sopsFile = ../../secrets.yaml; + }; + + services.esphome = { + enable = true; + address = "127.0.0.1"; + port = ports.esphome.tcp; + package = pkgs.master.esphome; + }; + + systemd.services.esphome = { + environment = { + "PLATFORMIO_CORE_DIR" = lib.mkForce "/tmp/.platformio"; + }; + serviceConfig = { + BindPaths = [ + "/var/lib/esphome" + "/var/lib/private/esphome" + ]; + BindReadOnlyPaths = [ + "/nix/store" + "${cfgdir}" + ]; + DeviceAllow = [ + "char-ttyACM rw" + "char-ttyAMA rw" + "char-ttyUSB rw" + ]; + ExecStartPre = [ + "${pkgs.rsync}/bin/rsync -a --delete --exclude=.esphome --exclude=.platformio --exclude=.gitignore '${cfgdir}/' '/var/lib/esphome/'" + "${pkgs.coreutils}/bin/ln -snf '%d/secrets.yaml' '/var/lib/esphome/secrets.yaml'" + ]; + LoadCredential = "secrets.yaml:${config.sops.secrets.esphome.path}"; + PrivateTmp = true; + RootDirectory = "/run/esphome"; + RuntimeDirectory = "esphome"; + StateDirectory = "esphome"; + SupplementaryGroups = [ "dialout" ]; + WorkingDirectory = lib.mkForce "/tmp"; + }; + }; +} diff --git a/hosts/aluminium/services/esphome/devices/wasserbett.yaml b/hosts/aluminium/services/esphome/devices/wasserbett.yaml new file mode 100644 index 0000000..d40b52e --- /dev/null +++ b/hosts/aluminium/services/esphome/devices/wasserbett.yaml @@ -0,0 +1,63 @@ +esphome: + name: "waterbed" + friendly_name: "Wasserbett" + +esp8266: + board: d1_mini + framework: + version: recommended + +logger: + +api: + encryption: + key: !secret apikey_waterbed + +ota: + password: !secret otapass_waterbed + +wifi: + ssid: !secret wifi_ssid_kbh + password: !secret wifi_password_kbh + domain: .iot.kbh.jalr.de + enable_on_boot: true + fast_connect: true + +switch: + - platform: gpio + pin: + number: 13 + id: pump + icon: "mdi:electric-switch" + +dallas: + - pin: 12 + +sensor: + - platform: dallas + #address: 0xb7000802397ccc10 + index: 0 + name: "Temperatur" + id: temperature_waterbed + +climate: + - platform: thermostat + name: "Temperatur" + id: temperature + sensor: temperature_waterbed + heat_deadband: 0.2 + heat_overrun: 0.2 + min_heating_off_time: 300s + min_heating_run_time: 300s + min_idle_time: 30s + heat_action: + - switch.turn_on: pump + idle_action: + - switch.turn_off: pump + default_preset: heizen + on_boot_restore_from: memory + preset: + - name: heizen + default_target_temperature_low: 28.5 °C + - name: abwesend + default_target_temperature_low: 24 °C diff --git a/hosts/aluminium/services/home-assistant.nix b/hosts/aluminium/services/home-assistant.nix new file mode 100644 index 0000000..1a741d7 --- /dev/null +++ b/hosts/aluminium/services/home-assistant.nix @@ -0,0 +1,58 @@ +args@{ lib, pkgs, config, custom-utils, ... }: +let + ports = import ../ports.nix args; +in +{ + services.home-assistant = { + enable = true; + lovelaceConfig = { }; + extraComponents = [ + # See https://www.home-assistant.io/integrations + "esphome" + ]; + customComponents = [ + # https://github.com/a529987659852/GuntamaticBiostar + pkgs.home-assistant-custom-components.guntamatic + ]; + lovelaceConfigWritable = false; + configWritable = false; + config = { + http = { + server_host = [ "127.0.0.1" ]; + server_port = ports.home-assistant.tcp; + use_x_forwarded_for = true; + trusted_proxies = [ "127.0.0.1" ]; + }; + homeassistant = { + unit_system = "metric"; + time_zone = "Europe/Berlin"; + temperature_unit = "C"; + longitude = config.location.longitude; + latitude = config.location.latitude; + }; + default_config = { }; + "automation nix" = [ + ]; + "automation ui" = "!include automations.yaml"; + "scene nix" = [ + ]; + "scene ui" = "!include scenes.yaml"; + }; + }; + + systemd.tmpfiles.rules = [ + "f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass" + "f ${config.services.home-assistant.configDir}/scenes.yaml 0755 hass hass" + ]; + + services.nginx.virtualHosts."hass.kbh.jalr.de" = { + enableACME = true; + forceSSL = true; + kTLS = true; + locations."/" = { + proxyPass = "http://127.0.0.1:${toString ports.home-assistant.tcp}/"; + recommendedProxySettings = true; + proxyWebsockets = true; + }; + }; +} diff --git a/hosts/aluminium/services/nginx.nix b/hosts/aluminium/services/nginx.nix new file mode 100644 index 0000000..71bdff2 --- /dev/null +++ b/hosts/aluminium/services/nginx.nix @@ -0,0 +1,20 @@ +args@{ pkgs, custom-utils, ... }: + +let + ports = import ../ports.nix args; +in +{ + services.nginx = { + enable = true; + defaultHTTPListenPort = ports.nginx-http.tcp; + defaultSSLListenPort = ports.nginx-https.tcp; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + }; + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; +} diff --git a/pkgs/default.nix b/pkgs/default.nix index 1322ca8..5c352fe 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -31,5 +31,6 @@ in wofi-bluetooth = callPackage ./wofi-bluetooth/wofi-bluetooth.nix { }; home-assistant-custom-components = prev.recurseIntoAttrs { circadian_lighting = callPackage ./home-assistant-custom-components/circadian_lighting.nix { }; + guntamatic = callPackage ./home-assistant-custom-components/guntamatic.nix { }; }; } diff --git a/pkgs/home-assistant-custom-components/guntamatic.nix b/pkgs/home-assistant-custom-components/guntamatic.nix new file mode 100644 index 0000000..b7f86bb --- /dev/null +++ b/pkgs/home-assistant-custom-components/guntamatic.nix @@ -0,0 +1,19 @@ +{ lib +, fetchFromGitHub +, buildHomeAssistantComponent +}: + +buildHomeAssistantComponent rec { + owner = "a529987659852"; + domain = "GuntamaticBiostar"; + version = "0.2.8"; + + src = fetchFromGitHub { + owner = "a529987659852"; + repo = "GuntamaticBiostar"; + rev = "refs/tags/v${version}"; + hash = "sha256-edKt2LQzxaMXAIeJcBag85ksKPXOfgCENO4jBw9hkCQ="; + }; + + dontBuild = true; +}