1{ 2 config, 3 lib, 4 pkgs, 5 utils, 6 ... 7}: 8let 9 inherit (lib) 10 getExe 11 mkEnableOption 12 mkIf 13 mkOption 14 mkPackageOption 15 ; 16 17 cfg = config.services.evcc; 18 19 format = pkgs.formats.yaml { }; 20 configFile = format.generate "evcc.yml" cfg.settings; 21 22 package = pkgs.evcc; 23in 24 25{ 26 meta.maintainers = with lib.maintainers; [ hexa ]; 27 28 options.services.evcc = with lib.types; { 29 enable = mkEnableOption "EVCC, the extensible EV Charge Controller and Home Energy Management System"; 30 31 package = mkPackageOption pkgs "evcc" { }; 32 33 extraArgs = mkOption { 34 type = listOf str; 35 default = [ ]; 36 description = '' 37 Extra arguments to pass to the `evcc` executable. 38 ''; 39 }; 40 41 environmentFile = mkOption { 42 type = nullOr path; 43 default = null; 44 example = /run/keys/evcc; 45 description = '' 46 File with environment variables to pass into the runtime environment. 47 48 Useful to pass secrets into the configuration, that get applied using `envsubst`. 49 ''; 50 }; 51 52 settings = mkOption { 53 type = format.type; 54 description = '' 55 evcc configuration as a Nix attribute set. Supports substitution of secrets using `envsubst` from the `environmentFile`. 56 57 Check for possible options in the sample [evcc.dist.yaml](https://github.com/andig/evcc/blob/${package.version}/evcc.dist.yaml). 58 ''; 59 }; 60 }; 61 62 config = mkIf cfg.enable { 63 systemd.services.evcc = { 64 wants = [ "network-online.target" ]; 65 after = [ 66 "network-online.target" 67 "mosquitto.target" 68 ]; 69 wantedBy = [ 70 "multi-user.target" 71 ]; 72 environment.HOME = "/var/lib/evcc"; 73 path = with pkgs; [ 74 getent 75 ]; 76 serviceConfig = { 77 EnvironmentFile = lib.optionals (cfg.environmentFile != null) [ cfg.environmentFile ]; 78 ExecStartPre = utils.escapeSystemdExecArgs [ 79 (getExe pkgs.envsubst) 80 "-i" 81 configFile 82 "-o" 83 "/run/evcc/config.yaml" 84 ]; 85 ExecStart = utils.escapeSystemdExecArgs ( 86 [ 87 (getExe cfg.package) 88 "--config=/run/evcc/config.yaml" 89 ] 90 ++ cfg.extraArgs 91 ); 92 CapabilityBoundingSet = [ "" ]; 93 DeviceAllow = [ 94 "char-ttyUSB" 95 ]; 96 DevicePolicy = "closed"; 97 DynamicUser = true; 98 LockPersonality = true; 99 MemoryDenyWriteExecute = true; 100 PrivateTmp = true; 101 PrivateUsers = true; 102 ProcSubset = "pid"; 103 ProtectClock = true; 104 ProtectControlGroups = true; 105 ProtectHome = true; 106 ProtectHostname = true; 107 ProtectKernelLogs = true; 108 ProtectKernelModules = true; 109 ProtectKernelTunables = true; 110 ProtectProc = "invisible"; 111 Restart = "on-failure"; 112 RestrictAddressFamilies = [ 113 "AF_INET" 114 "AF_INET6" 115 "AF_UNIX" 116 "AF_NETLINK" 117 ]; 118 RestrictNamespaces = true; 119 RestrictRealtime = true; 120 RuntimeDirectory = "evcc"; 121 StateDirectory = "evcc"; 122 SystemCallArchitectures = "native"; 123 SystemCallFilter = [ 124 "@system-service" 125 "~@privileged" 126 ]; 127 UMask = "0077"; 128 User = "evcc"; 129 }; 130 }; 131 }; 132 133 meta.buildDocsInSandbox = false; 134}