at 18.03-beta 4.2 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.home-assistant; 7 8 configFile = pkgs.writeText "configuration.yaml" (builtins.toJSON cfg.config); 9 10 availableComponents = pkgs.home-assistant.availableComponents; 11 12 # Given component "parentConfig.platform", returns whether config.parentConfig 13 # is a list containing a set with set.platform == "platform". 14 # 15 # For example, the component sensor.luftdaten is used as follows: 16 # config.sensor = [ { 17 # platform = "luftdaten"; 18 # ... 19 # } ]; 20 useComponentPlatform = component: 21 let 22 path = splitString "." component; 23 parentConfig = attrByPath (init path) null cfg.config; 24 platform = last path; 25 in isList parentConfig && any 26 (item: item.platform or null == platform) 27 parentConfig; 28 29 # Returns whether component is used in config 30 useComponent = component: 31 hasAttrByPath (splitString "." component) cfg.config 32 || useComponentPlatform component; 33 34 # List of components used in config 35 extraComponents = filter useComponent availableComponents; 36 37 package = if cfg.autoExtraComponents 38 then (cfg.package.override { inherit extraComponents; }) 39 else cfg.package; 40 41in { 42 meta.maintainers = with maintainers; [ dotlambda ]; 43 44 options.services.home-assistant = { 45 enable = mkEnableOption "Home Assistant"; 46 47 configDir = mkOption { 48 default = "/var/lib/hass"; 49 type = types.path; 50 description = "The config directory, where your <filename>configuration.yaml</filename> is located."; 51 }; 52 53 config = mkOption { 54 default = null; 55 type = with types; nullOr attrs; 56 example = literalExample '' 57 { 58 homeassistant = { 59 name = "Home"; 60 time_zone = "UTC"; 61 }; 62 frontend = { }; 63 http = { }; 64 feedreader.urls = [ "https://nixos.org/blogs.xml" ]; 65 } 66 ''; 67 description = '' 68 Your <filename>configuration.yaml</filename> as a Nix attribute set. 69 Beware that setting this option will delete your previous <filename>configuration.yaml</filename>. 70 ''; 71 }; 72 73 package = mkOption { 74 default = pkgs.home-assistant; 75 defaultText = "pkgs.home-assistant"; 76 type = types.package; 77 example = literalExample '' 78 pkgs.home-assistant.override { 79 extraPackages = ps: with ps; [ colorlog ]; 80 } 81 ''; 82 description = '' 83 Home Assistant package to use. 84 Override <literal>extraPackages</literal> in order to add additional dependencies. 85 ''; 86 }; 87 88 autoExtraComponents = mkOption { 89 default = true; 90 type = types.bool; 91 description = '' 92 If set to <literal>true</literal>, the components used in <literal>config</literal> 93 are set as the specified package's <literal>extraComponents</literal>. 94 This in turn adds all packaged dependencies to the derivation. 95 You might still see import errors in your log. 96 In this case, you will need to package the necessary dependencies yourself 97 or ask for someone else to package them. 98 If a dependency is packaged but not automatically added to this list, 99 you might need to specify it in <literal>extraPackages</literal>. 100 ''; 101 }; 102 }; 103 104 config = mkIf cfg.enable { 105 systemd.services.home-assistant = { 106 description = "Home Assistant"; 107 wantedBy = [ "multi-user.target" ]; 108 after = [ "network.target" ]; 109 preStart = lib.optionalString (cfg.config != null) '' 110 rm -f ${cfg.configDir}/configuration.yaml 111 ln -s ${configFile} ${cfg.configDir}/configuration.yaml 112 ''; 113 serviceConfig = { 114 ExecStart = '' 115 ${package}/bin/hass --config "${cfg.configDir}" 116 ''; 117 User = "hass"; 118 Group = "hass"; 119 Restart = "on-failure"; 120 ProtectSystem = "strict"; 121 ReadWritePaths = "${cfg.configDir}"; 122 PrivateTmp = true; 123 }; 124 }; 125 126 users.extraUsers.hass = { 127 home = cfg.configDir; 128 createHome = true; 129 group = "hass"; 130 uid = config.ids.uids.hass; 131 }; 132 133 users.extraGroups.hass.gid = config.ids.gids.hass; 134 }; 135}