diff --git a/candle-sensor b/candle-sensor new file mode 100644 index 0000000..4f6b364 --- /dev/null +++ b/candle-sensor @@ -0,0 +1,12 @@ +it does not work if the sensor is underneath + +i could build a device which you can put on the table and looks to the candles +it has 80cm of recognizing a flame. + +it would use the following components +Adafruit ESP32 Feather V2 +ANGEEK KY-026 Flame Sensor Module +2000 - 3000 mah LiPo + +battery life would be 20 Days, cost would be around 35€ just plain devices cost without work time +3d printed housing would be needed diff --git a/modules/cloonar-assistant/networking/default.nix b/modules/cloonar-assistant/networking/default.nix index 94eff10..a317a1c 100644 --- a/modules/cloonar-assistant/networking/default.nix +++ b/modules/cloonar-assistant/networking/default.nix @@ -1,9 +1,8 @@ { ... }: { imports = [ ./interfaces.nix - ./dhcp.nix ./firewall.nix - ./unbound.nix + ./dnsmasq.nix # New dnsmasq configuration ./wireguard.nix ]; } diff --git a/modules/cloonar-assistant/networking/dhcp.nix b/modules/cloonar-assistant/networking/dhcp.nix deleted file mode 100644 index 164acd0..0000000 --- a/modules/cloonar-assistant/networking/dhcp.nix +++ /dev/null @@ -1,187 +0,0 @@ -{ config, lib, ... }: -{ - services.kea.dhcp4 = lib.mkIf config.cloonar-assistant.firewall.enable { - enable = true; - settings = { - interfaces-config = { - interfaces = [ - "lan" - "server" - "infrastructure" - "multimedia" - "smart" - "guest" - ]; - }; - lease-database = { - name = "/var/lib/kea/dhcp4.leases"; - persist = true; - type = "memfile"; - }; - rebind-timer = 2000; - renew-timer = 1000; - subnet4 = [ - { - id = 96; - pools = [ - { - pool = "${config.cloonar-assistant.networkPrefix}.96.100 - ${config.cloonar-assistant.networkPrefix}.96.240"; - } - ]; - subnet = "${config.cloonar-assistant.networkPrefix}.96.0/24"; - interface = "lan"; - option-data = [ - { - name = "routers"; - data = "${config.cloonar-assistant.networkPrefix}.96.1"; - } - { - name = "domain-name"; - data = config.cloonar-assistant.domain; - } - { - name = "domain-search"; - data = config.cloonar-assistant.domain; - } - { - name = "domain-name-servers"; - data = "${config.cloonar-assistant.networkPrefix}.96.1"; - } - ]; - reservations = [ - ]; - } - { - id = 97; - pools = [ - { - pool = "${config.cloonar-assistant.networkPrefix}.97.100 - ${config.cloonar-assistant.networkPrefix}.97.240"; - } - ]; - subnet = "${config.cloonar-assistant.networkPrefix}.97.0/24"; - interface = "server"; - option-data = [ - { - name = "routers"; - data = "${config.cloonar-assistant.networkPrefix}.97.1"; - } - { - name = "domain-name"; - data = config.cloonar-assistant.domain; - } - { - name = "domain-name-servers"; - data = "${config.cloonar-assistant.networkPrefix}.97.1"; - } - ]; - reservations = [ - ]; - } - { - id = 101; - pools = [ - { - pool = "${config.cloonar-assistant.networkPrefix}.101.100 - ${config.cloonar-assistant.networkPrefix}.101.240"; - } - ]; - subnet = "${config.cloonar-assistant.networkPrefix}.101.0/24"; - interface = "infrastructure"; - option-data = [ - { - name = "routers"; - data = "${config.cloonar-assistant.networkPrefix}.101.1"; - } - { - name = "domain-name"; - data = config.cloonar-assistant.domain; - } - { - name = "domain-name-servers"; - data = "${config.cloonar-assistant.networkPrefix}.101.1"; - } - { - name = "capwap-ac-v4"; - code = 138; - data = "${config.cloonar-assistant.networkPrefix}.97.2"; - } - ]; - reservations = [ - ]; - } - { - id = 99; - pools = [ - { - pool = "${config.cloonar-assistant.networkPrefix}.99.100 - ${config.cloonar-assistant.networkPrefix}.99.240"; - } - ]; - subnet = "${config.cloonar-assistant.networkPrefix}.99.0/24"; - interface = "multimedia"; - option-data = [ - { - name = "routers"; - data = "${config.cloonar-assistant.networkPrefix}.99.1"; - } - { - name = "domain-name"; - data = config.cloonar-assistant.domain; - } - { - name = "domain-name-servers"; - data = "${config.cloonar-assistant.networkPrefix}.99.1"; - } - ]; - reservations = [ - ]; - } - { - id = 254; - pools = [ - { - pool = "${config.cloonar-assistant.networkPrefix}.254.10 - ${config.cloonar-assistant.networkPrefix}.254.254"; - } - ]; - subnet = "${config.cloonar-assistant.networkPrefix}.254.0/24"; - interface = "guest"; - option-data = [ - { - name = "routers"; - data = "${config.cloonar-assistant.networkPrefix}.254.1"; - } - { - name = "domain-name-servers"; - data = "9.9.9.9"; - } - ]; - } - { - id = 100; - pools = [ - { - pool = "${config.cloonar-assistant.networkPrefix}.100.100 - ${config.cloonar-assistant.networkPrefix}.100.240"; - } - ]; - subnet = "${config.cloonar-assistant.networkPrefix}.100.0/24"; - interface = "smart"; - option-data = [ - { - name = "routers"; - data = "${config.cloonar-assistant.networkPrefix}.100.1"; - } - { - name = "domain-name"; - data = config.cloonar-assistant.domain; - } - { - name = "domain-name-servers"; - data = "${config.cloonar-assistant.networkPrefix}.100.1"; - } - ]; - reservations = [ - ]; - } - ]; - valid-lifetime = 4000; - }; - }; -} diff --git a/modules/cloonar-assistant/networking/dnsmasq.nix b/modules/cloonar-assistant/networking/dnsmasq.nix new file mode 100644 index 0000000..9ae354f --- /dev/null +++ b/modules/cloonar-assistant/networking/dnsmasq.nix @@ -0,0 +1,98 @@ +{ config, lib, ... }: + +{ + # Disable systemd-resolved (same as current unbound.nix) + services.resolved.enable = false; + + # Main dnsmasq service with preserved conditional enablement + services.dnsmasq = lib.mkIf config.cloonar-assistant.firewall.enable { + enable = true; + resolveLocalQueries = false; # We handle DNS manually + + settings = { + # Interface binding + interface = [ + "lan" + "server" + "infrastructure" + "multimedia" + "smart" + "guest" + ]; + + # DHCP ranges per VLAN + dhcp-range = [ + "${config.cloonar-assistant.networkPrefix}.96.100,${config.cloonar-assistant.networkPrefix}.96.240,24h" + "${config.cloonar-assistant.networkPrefix}.97.100,${config.cloonar-assistant.networkPrefix}.97.240,24h" + "${config.cloonar-assistant.networkPrefix}.101.100,${config.cloonar-assistant.networkPrefix}.101.240,24h" + "${config.cloonar-assistant.networkPrefix}.99.100,${config.cloonar-assistant.networkPrefix}.99.240,24h" + "${config.cloonar-assistant.networkPrefix}.100.100,${config.cloonar-assistant.networkPrefix}.100.240,24h" + "${config.cloonar-assistant.networkPrefix}.254.10,${config.cloonar-assistant.networkPrefix}.254.254,24h" + ]; + + # DHCP options with VLAN tagging + dhcp-option = [ + # LAN VLAN (.96) + "tag:lan,option:router,${config.cloonar-assistant.networkPrefix}.96.1" + "tag:lan,option:dns-server,${config.cloonar-assistant.networkPrefix}.96.1" + "tag:lan,option:domain-name,${config.cloonar-assistant.domain}" + + # Server VLAN (.97) + "tag:server,option:router,${config.cloonar-assistant.networkPrefix}.97.1" + "tag:server,option:dns-server,${config.cloonar-assistant.networkPrefix}.97.1" + "tag:server,option:domain-name,${config.cloonar-assistant.domain}" + + # Infrastructure VLAN (.101) with CAPWAP option + "tag:infrastructure,option:router,${config.cloonar-assistant.networkPrefix}.101.1" + "tag:infrastructure,option:dns-server,${config.cloonar-assistant.networkPrefix}.101.1" + "tag:infrastructure,option:domain-name,${config.cloonar-assistant.domain}" + "tag:infrastructure,138,${config.cloonar-assistant.networkPrefix}.97.2" # CAPWAP + + # Multimedia VLAN (.99) + "tag:multimedia,option:router,${config.cloonar-assistant.networkPrefix}.99.1" + "tag:multimedia,option:dns-server,${config.cloonar-assistant.networkPrefix}.99.1" + "tag:multimedia,option:domain-name,${config.cloonar-assistant.domain}" + + # Smart VLAN (.100) + "tag:smart,option:router,${config.cloonar-assistant.networkPrefix}.100.1" + "tag:smart,option:dns-server,${config.cloonar-assistant.networkPrefix}.100.1" + "tag:smart,option:domain-name,${config.cloonar-assistant.domain}" + + # Guest VLAN (.254) - DNS isolation + "tag:guest,option:router,${config.cloonar-assistant.networkPrefix}.254.1" + "tag:guest,option:dns-server,9.9.9.9" # External DNS only + ]; + + # Static DNS records + address = [ + "/fw.${config.cloonar-assistant.domain}/${config.cloonar-assistant.networkPrefix}.97.1" + "/fw/${config.cloonar-assistant.networkPrefix}.97.1" + "/home-assistant.${config.cloonar-assistant.domain}/${config.cloonar-assistant.networkPrefix}.97.20" + "/mopidy.${config.cloonar-assistant.domain}/${config.cloonar-assistant.networkPrefix}.97.21" + "/snapcast.${config.cloonar-assistant.domain}/${config.cloonar-assistant.networkPrefix}.97.21" + "/localhost/127.0.0.1" + "/localhost.${config.cloonar-assistant.domain}/127.0.0.1" + ]; + + # Domain configuration + domain = "${config.cloonar-assistant.domain}"; + expand-hosts = true; + + # Upstream DNS servers (plain DNS, no DoT support in dnsmasq) + server = [ + "9.9.9.9" + "149.112.112.11" + ]; + + # Performance and security + cache-size = 1000; + neg-ttl = 60; + domain-needed = true; # Don't forward plain names + bogus-priv = true; # Don't forward RFC1918 reverse lookups + bind-interfaces = true; # Only bind to specified interfaces + }; + }; + + # Firewall configuration (preserve existing) + networking.firewall.allowedUDPPorts = [ 53 5353 ]; +} \ No newline at end of file diff --git a/modules/cloonar-assistant/networking/unbound.nix b/modules/cloonar-assistant/networking/unbound.nix deleted file mode 100644 index 4745b26..0000000 --- a/modules/cloonar-assistant/networking/unbound.nix +++ /dev/null @@ -1,138 +0,0 @@ -{ config, lib, pkgs, ... }: -let - cfg = { - remote-control.control-enable = true; - server = { - interface = [ "0.0.0.0" "::0" ]; - interface-automatic = "yes"; - access-control = [ - "127.0.0.0/8 allow" - "${config.cloonar-assistant.networkPrefix}.96.0/24 allow" - "${config.cloonar-assistant.networkPrefix}.97.0/24 allow" - "${config.cloonar-assistant.networkPrefix}.98.0/24 allow" - "${config.cloonar-assistant.networkPrefix}.99.0/24 allow" - "${config.cloonar-assistant.networkPrefix}.101.0/24 allow" - "0.0.0.0/0 allow" - ]; - tls-cert-bundle = "/etc/ssl/certs/ca-certificates.crt"; - local-zone = "\"${config.cloonar-assistant.domain}\" transparent"; - local-data = [ - "\"localhost A 127.0.0.1\"" - "\"localhost.${config.cloonar-assistant.domain} A 127.0.0.1\"" - "\"localhost AAAA ::1\"" - "\"localhost.${config.cloonar-assistant.domain} AAAA ::1\"" - "\"fw.${config.cloonar-assistant.domain} A ${config.cloonar-assistant.networkPrefix}.97.1\"" - "\"fw A ${config.cloonar-assistant.networkPrefix}.97.1\"" - - "\"mopidy.${config.cloonar-assistant.domain} IN A ${config.cloonar-assistant.networkPrefix}.97.21\"" - "\"snapcast.${config.cloonar-assistant.domain} IN A ${config.cloonar-assistant.networkPrefix}.97.21\"" - "\"home-assistant.${config.cloonar-assistant.domain} IN A ${config.cloonar-assistant.networkPrefix}.97.20\"" - ]; - local-data-ptr = [ - "\"127.0.0.1 localhost\"" - "\"::1 localhost\"" - "\"${config.cloonar-assistant.networkPrefix}.97.1 fw.${config.cloonar-assistant.domain}\"" - "\"${config.cloonar-assistant.networkPrefix}.97.20 home-assistant.${config.cloonar-assistant.domain}\"" - "\"${config.cloonar-assistant.networkPrefix}.97.21 snapcast.${config.cloonar-assistant.domain}\"" - ]; - # ssl-upstream = "yes"; - }; - forward-zone = [ - { - name = "."; - forward-tls-upstream = "yes"; - forward-first = "no"; - forward-addr = [ - "9.9.9.9@853#dns9.quad9.net" - "149.112.112.11@853#dns11.quad9.net" - ]; - } - ]; - }; -in { - users.users.unbound = { - group = "unbound"; - isSystemUser = true; - extraGroups = [ "ssl-users" ]; - }; - users.groups.unbound = { }; - - services.resolved.enable = false; - - services.unbound = { - enable = true; - settings = cfg; - }; - - systemd.services.unbound-sync = lib.mkIf config.cloonar-assistant.firewall.enable { - enable = true; - path = with pkgs; [ unbound inotify-tools ]; - script = '' - function readFile() { - if [[ "''\$2" == "A" ]] ; then - cat "''\$1" | tail -n +2 | while IFS=, read -r address hwaddr client_id valid_lifetime expire subnet_id fqdn_fwd fqdn_rev hostname state user_context - do - echo "''\${address},''\${hostname}" - done - else - cat "''\$1" | tail -n +2 | while IFS=, read -r address duid valid_lifetime expire subnet_id pref_lifetime lease_type iaid prefix_len fqdn_fwd fqdn_rev hostname hwaddr state user_context hwtype hwaddr_source - do - echo "''\${address},''\${hostname}" - done - fi - } - - function readFileUnique() { - readFile "''\$1" ''\$2 | uniq | while IFS=, read -r address hostname - do - if echo "''\${1}" | grep -Eq '.*\.(${config.cloonar-assistant.domain})'; then - echo ''\${hostname} ''\$2 ''\${address} - unbound-control local_data ''\${hostname} ''\$2 ''\${address} > /dev/null 2>&1 - if [[ "''\$2" == "A" ]] ; then - echo ''\${address} | while IFS=. read -r ip0 ip1 ip2 ip3 - do - unbound-control local_data ''\${ip3}.''\${ip2}.''\${ip1}.''\${ip0}.ip4.arpa. PTR ''\${hostname} > /dev/null 2>&1 - unbound-control local_data ''\${ip3}.''\${ip2}.''\${ip1}.''\${ip0}.in-addr.arpa. PTR ''\${hostname} > /dev/null 2>&1 - done - fi - else - if [[ "''\$2" == "A" ]] ; then - echo ''\${address} | while IFS=. read -r ip0 ip1 ip2 ip3 - do - if [[ "''\${hostname}" != "" ]]; then - domain=${config.cloonar-assistant.domain} - if [[ "''\${hostname}" != *. ]]; then - unbound-control local_data ''\${hostname}.''\${domain} ''\$2 ''\${address} > /dev/null 2>&1 - else - unbound-control local_data ''\${hostname}''\${domain} ''\$2 ''\${address} > /dev/null 2>&1 - fi - - fi - unbound-control local_data ''\${ip3}.''\${ip2}.''\${ip1}.''\${ip0}.ip4.arpa. PTR ''\${hostname} > /dev/null 2>&1 - unbound-control local_data ''\${ip3}.''\${ip2}.''\${ip1}.''\${ip0}.in-addr.arpa. PTR ''\${hostname} > /dev/null 2>&1 - done - fi - fi - done - } - - function syncFile() { - # readFileUnique "''\$1" "''\$2" - while true; do - readFileUnique "''\$1" "''\$2" - sleep 10 - done - } - - syncFile "/var/lib/kea/dhcp4.leases" A & - # syncFile "/var/lib/kea/dhcp6.leases" AAAA & - wait - ''; - wants = [ "network-online.target" "unbound.service" ]; - after = [ "network-online.target" "unbound.service" ]; - partOf = [ "unbound.service" ]; - wantedBy = [ "multi-user.target" ]; - }; - - networking.firewall.allowedUDPPorts = [ 53 5353 ]; -}