{ config, lib, pkgs, ... }: with lib; let cfg = config.fudo.services.suanni; hostname = config.instance.hostname; isListener = hostname == cfg.event-listener.host; isObjectifier = hostname == cfg.objectifier.host; domain-name = config.fudo.hosts."${hostname}".domain; host-secrets = config.fudo.secrets.host-secrets."${hostname}"; suanni-mqtt-passwd = pkgs.lib.passwd.stablerandom-passwd-file "suanni-mqtt" config.instance.build-seed; in { options.fudo.services.suanni = with types; { enable = mkEnableOption "Enable Suan Ni Home Guardian."; mqtt-topic = mkOption { type = str; description = "MQTT topic on which to publish events."; default = "suanni/events/motion"; }; event-listener = { host = mkOption { type = str; description = "Hostname of Event Listener server."; }; port = mkOption { type = port; default = 5354; }; }; objectifier = { host = mkOption { type = str; description = "Hostname of objectifier server."; }; port = mkOption { type = port; default = 5121; }; }; synology = { host = mkOption { type = str; description = "Hostname of the Synology server."; }; port = mkOption { type = port; description = "Port on which to contact the Synology server."; }; username = mkOption { type = str; description = "Username as which to connect to the Synology server."; }; password-file = mkOption { type = str; description = "Path to file containing Synology user password."; }; }; }; config = mkIf cfg.enable { services = mkIf (isObjectifier || isListener) { nginx = { enable = true; recommendedOptimisation = true; recommendedProxySettings = true; recommendedGzipSettings = true; virtualHosts = { "event-listener.${domain-name}" = mkIf isListener { locations."/".proxyPass = "http://127.0.0.1:${toString cfg.event-listener.port}"; }; "objectifier.${domain-name}" = mkIf isObjectifier { locations."/".proxyPass = "http://127.0.0.1:${toString cfg.objectifier.port}"; }; }; }; objectifier = mkIf isObjectifier { enable = true; listen-addresses = [ "127.0.0.1" ]; port = cfg.objectifier.port; }; suanni.server = mkIf isListener { enable = true; verbose = true; event-listener.hostname = "127.0.0.1"; synology-client = { inherit (cfg.synology) host port username; password-file = host-secrets.suanni-synology-password.target-file; }; objectifier-client = { host = "objectifier.${domain-name}"; port = 80; }; mqtt-client = { inherit (config.fudo.services.mqtt.private) port; host = config.fudo.services.mqtt.mqtt-hostname; username = "suanni"; password-file = host-secrets.suanni-mqtt-password.target-file; topic = cfg.mqtt-topic; }; }; }; fudo = { secrets.host-secrets."${hostname}" = { suanni-synology-password = mkIf isListener { source-file = config.fudo.secrets.files.service-passwords."${hostname}".suanni-synology; target-file = "/run/suanni/synology.passwd"; }; suanni-mqtt-password = mkIf isListener { source-file = suanni-mqtt-passwd; target-file = "/run/suanni/mqtt.passwd"; }; }; services.mqtt = { enable = true; private = { enable = true; users.suanni = { password-file = suanni-mqtt-passwd; acl = [ "readwrite #" ]; }; }; }; zones."${domain-name}" = { aliases = { objectifier = cfg.objectifier.host; event-listener = "${cfg.event-listener.host}"; }; }; }; }; }