diff --git a/esphome/bedroom-sensor.nix b/esphome/bedroom-sensor.nix index 3f355bea..4b2e9b82 100644 --- a/esphome/bedroom-sensor.nix +++ b/esphome/bedroom-sensor.nix @@ -1,10 +1,11 @@ -{ config, ... }: { +{ config, target, ... }: { + esphome = { + platform = "esp8266"; + board = "d1_mini"; + }; api = { password = "!secret api_password"; }; - esp8266 = { - board = "d1_mini"; - }; wifi = { ssid = "Gensokyo"; password = "!secret wifi_password"; @@ -24,7 +25,7 @@ sensor = [ { platform = "dht"; - model = "dht22"; + model = "DHT22"; update_interval = "60s"; pin = "D0"; temperature = { diff --git a/modules/esphome/deploy.nix b/modules/esphome/deploy.nix new file mode 100644 index 00000000..56330afa --- /dev/null +++ b/modules/esphome/deploy.nix @@ -0,0 +1,86 @@ +{ tf, target, name, meta, config, lib, ... }: + +/* + This module: + * aliases .system.build.toplevel to .deploy.system for ease of use. + * marries meta config to NixOS configs for each host. + * provides in-scope TF config in NixOS and home-manager, instead of only as a part of meta config. +*/ + +with lib; + +let + cfg = config.deploy; + unmergedValues = types.mkOptionType { + name = "unmergedValues"; + merge = loc: defs: map (def: def.value) defs; + }; +in +{ + options.deploy.tf = mkOption { + type = types.submodule { + inherit (unmerged) freeformType; + + options = { + triggers = mkOption { + type = types.attrsOf types.unspecified; + default = { }; + }; + import = mkOption { + type = types.attrsOf types.unspecified; + default = [ ]; + }; + imports = mkOption { + type = types.listOf types.str; + description = "Other targets to depend on"; + default = [ ]; + }; + attrs = mkOption { + type = types.listOf types.str; + default = [ ]; + }; + out.set = mkOption { type = types.unspecified; }; + }; + }; + }; + + config = let + functionlessConfig = lib.removeAttrs config ["out" "_module" "platform" "deploy"]; + mutatedConfig = functionlessConfig // (optionalAttrs (config.platform != {}) { + ${functionlessConfig.esphome.platform} = config.platform; + }); + jsonConfig = builtins.toJSON mutatedConfig; + closureConfig = pkgs.writeText "${functionlessConfig.esphome.name}.json" jsonConfig; + closure-upload = pkgs.writeShellScriptBin "${functionlessConfig.esphome.name}-upload" '' + ''; + in { + deploy.tf = { + attrs = [ "import" "imports" "out" "attrs" "triggers" ]; + import = genAttrs cfg.tf.imports (target: meta.deploy.targets.${target}.tf); + out.set = removeAttrs cfg.tf cfg.tf.attrs; + triggers = { + compile = { + system = config.out; + }; + }; + resources = { + "${name}-upload" = { + provider = "null"; + type = "resource"; + inputs.triggers = cfg.tf.triggers.compile; + provisioners = [ + { + type = "local-exec"; + local-exec.command = '' + ${pkgs.esphome}/bin/esphome upload ${closureConfig} + ''; + } + ]; + }; + }; + }; + + _module.args.tf = mapNullable (target: target.tf) target; + }; +} + diff --git a/modules/esphome/genesis.nix b/modules/esphome/genesis.nix index efe70297..c981aecd 100644 --- a/modules/esphome/genesis.nix +++ b/modules/esphome/genesis.nix @@ -1,2 +1,10 @@ -{ config, ... }: { -} +{ name, config, meta, pkgs, lib, ... }: with lib; +{ + options = { + } // genAttrs [ "esphome" "api" "platform" "wifi" "i2c" "logger" "ota" "sensor" ] (key: + mkOption { + type = types.unspecified; + default = {}; + } + ); + } diff --git a/modules/meta/deploy.nix b/modules/meta/deploy.nix index 1689efc2..6682fcb5 100644 --- a/modules/meta/deploy.nix +++ b/modules/meta/deploy.nix @@ -127,7 +127,8 @@ in }; }; continue.envVar = "TF_NIX_CONTINUE_${replaceStrings [ "-" ] [ "_" ] config.name}"; - }) ++ map (nodeName: mapAttrs (_: mkMerge) meta.network.nodes.nixos.${nodeName}.deploy.tf.out.set) config.nodeNames); + }) ++ map (nodeName: mapAttrs (_: mkMerge) meta.network.nodes.nixos.${nodeName}.deploy.tf.out.set) config.nodeNames + ++ (optionals (config.name == "home") (mapAttrsToList (node: config: (mapAttrs (_: mkMerge) config.deploy.tf.out.set)) meta.network.nodes.esphome))); }); in mkOption { diff --git a/modules/meta/network.nix b/modules/meta/network.nix index f721b72f..5832149b 100644 --- a/modules/meta/network.nix +++ b/modules/meta/network.nix @@ -49,32 +49,13 @@ with lib; default = { }; }; }; - union = mkOption { + nodes.all = mkOption { type = types.attrsOf types.unspecified; default = config.network.nodes.nixos // config.network.nodes.darwin // config.network.nodes.esphome; }; nodes.esphome = let - esphomeModule = { name, config, meta, lib, ... }: with lib; - let - settings = config.settings; - closureConfig = pkgs.writeText "${settings.esphome.name}.json" builtins.toJSON settings; - closure = pkgs.runCommand "${settings.esphome.name}" {} '' - ${pkgs.esphome}/bin/esphome compile ${closureConfig} - mv .esphome/build/${settings.esphome.name}/.pioenvs/${settings.esphome.name}/firmware.bin $out - ''; - in { - options.out = mkOption { - type = types.unspecified; - default = closure; - }; - options.settings = mkOption { - type = types.unspecified; - }; - }; esphomeType = types.submoduleWith { - modules = [ - esphomeModule - ] ++ config.network.esphome.extraModules; + modules = [ { _module.args.pkgs = pkgs; } ] ++ config.network.esphome.extraModules; inherit (config.network.esphome) specialArgs; }; in mkOption { @@ -158,8 +139,10 @@ with lib; config.network = { esphome = { extraModules = [ + meta.modules.esphome ]; specialArgs = { + target = config.deploy.targets.home; inherit (config.network) nodes; inherit inputs meta; }; @@ -186,7 +169,7 @@ with lib; ]; specialArgs = { inherit (config.network) nodes; - inherit inputs meta; + inherit inputs meta pkgs; }; }; }; diff --git a/nixos/network.nix b/nixos/network.nix index ab99730d..09c9af31 100644 --- a/nixos/network.nix +++ b/nixos/network.nix @@ -289,20 +289,6 @@ acme = let home = meta.deploy.targets.home.tf; in { - enable = true; - account = { - emailAddress = "kat@inskip.me"; - accountKeyPem = home.resources.acme_private_key.importAttr "private_key_pem"; - }; - challenge = { - defaultProvider = "rfc2136"; - configs.rfc2136 = { - RFC2136_NAMESERVER = tf.variables.katdns-address.ref; - RFC2136_TSIG_KEY = tf.variables.katdns-name.ref; - RFC2136_TSIG_SECRET = tf.variables.katdns-key.ref; - RFC2136_TSIG_ALGORITHM = "hmac-sha512"; - }; - }; certs = let nvP = network: settings: nameValuePair settings.uqdn { keyType = "4096"; diff --git a/outputs.nix b/outputs.nix index 54ba7a69..523747ac 100644 --- a/outputs.nix +++ b/outputs.nix @@ -80,6 +80,7 @@ }; "modules/darwin".functor.enable = true; "modules/system".functor.enable = true; + "modules/esphome".functor.enable = true; "modules/meta".functor.enable = true; "nixos/systems".functor.enable = false; "darwin/systems".functor.enable = false; @@ -125,11 +126,9 @@ esphomeNodes = (map (node: { network.nodes.esphome.${node} = { - settings = { - imports = config.lib.kw.esphomeImport node; - esphome = { - name = node; - }; + imports = config.lib.kw.esphomeImport node; + esphome = { + name = node; }; }; }) diff --git a/tf b/tf index 856827e2..19085b06 160000 --- a/tf +++ b/tf @@ -1 +1 @@ -Subproject commit 856827e23fd7f1ef1d07dea9c5be26c0a0f7dee8 +Subproject commit 19085b061685d726090c2b5fdc3afe536ad43dd7 diff --git a/tf.nix b/tf.nix index fa1ad35b..93b57460 100644 --- a/tf.nix +++ b/tf.nix @@ -18,6 +18,22 @@ type = "string"; sensitive = true; }; + acme = { + enable = true; + account = { + emailAddress = "kat@inskip.me"; + accountKeyPem = home.resources.acme_private_key.importAttr "private_key_pem"; + }; + challenge = { + defaultProvider = "rfc2136"; + configs.rfc2136 = { + RFC2136_NAMESERVER = tf.variables.katdns-address.ref; + RFC2136_TSIG_KEY = tf.variables.katdns-name.ref; + RFC2136_TSIG_SECRET = tf.variables.katdns-key.ref; + RFC2136_TSIG_ALGORITHM = "hmac-sha512"; + }; + }; + }; providers.katdns = { type = "dns";