at 23.11-beta 5.4 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.traefik; 7 jsonValue = with types; 8 let 9 valueType = nullOr (oneOf [ 10 bool 11 int 12 float 13 str 14 (lazyAttrsOf valueType) 15 (listOf valueType) 16 ]) // { 17 description = "JSON value"; 18 emptyValue.value = { }; 19 }; 20 in valueType; 21 dynamicConfigFile = if cfg.dynamicConfigFile == null then 22 pkgs.runCommand "config.toml" { 23 buildInputs = [ pkgs.remarshal ]; 24 preferLocalBuild = true; 25 } '' 26 remarshal -if json -of toml \ 27 < ${ 28 pkgs.writeText "dynamic_config.json" 29 (builtins.toJSON cfg.dynamicConfigOptions) 30 } \ 31 > $out 32 '' 33 else 34 cfg.dynamicConfigFile; 35 staticConfigFile = if cfg.staticConfigFile == null then 36 pkgs.runCommand "config.toml" { 37 buildInputs = [ pkgs.yj ]; 38 preferLocalBuild = true; 39 } '' 40 yj -jt -i \ 41 < ${ 42 pkgs.writeText "static_config.json" (builtins.toJSON 43 (recursiveUpdate cfg.staticConfigOptions { 44 providers.file.filename = "${dynamicConfigFile}"; 45 })) 46 } \ 47 > $out 48 '' 49 else 50 cfg.staticConfigFile; 51 52 finalStaticConfigFile = 53 if cfg.environmentFiles == [] 54 then staticConfigFile 55 else "/run/traefik/config.toml"; 56in { 57 options.services.traefik = { 58 enable = mkEnableOption (lib.mdDoc "Traefik web server"); 59 60 staticConfigFile = mkOption { 61 default = null; 62 example = literalExpression "/path/to/static_config.toml"; 63 type = types.nullOr types.path; 64 description = lib.mdDoc '' 65 Path to traefik's static configuration to use. 66 (Using that option has precedence over `staticConfigOptions` and `dynamicConfigOptions`) 67 ''; 68 }; 69 70 staticConfigOptions = mkOption { 71 description = lib.mdDoc '' 72 Static configuration for Traefik. 73 ''; 74 type = jsonValue; 75 default = { entryPoints.http.address = ":80"; }; 76 example = { 77 entryPoints.web.address = ":8080"; 78 entryPoints.http.address = ":80"; 79 80 api = { }; 81 }; 82 }; 83 84 dynamicConfigFile = mkOption { 85 default = null; 86 example = literalExpression "/path/to/dynamic_config.toml"; 87 type = types.nullOr types.path; 88 description = lib.mdDoc '' 89 Path to traefik's dynamic configuration to use. 90 (Using that option has precedence over `dynamicConfigOptions`) 91 ''; 92 }; 93 94 dynamicConfigOptions = mkOption { 95 description = lib.mdDoc '' 96 Dynamic configuration for Traefik. 97 ''; 98 type = jsonValue; 99 default = { }; 100 example = { 101 http.routers.router1 = { 102 rule = "Host(`localhost`)"; 103 service = "service1"; 104 }; 105 106 http.services.service1.loadBalancer.servers = 107 [{ url = "http://localhost:8080"; }]; 108 }; 109 }; 110 111 dataDir = mkOption { 112 default = "/var/lib/traefik"; 113 type = types.path; 114 description = lib.mdDoc '' 115 Location for any persistent data traefik creates, ie. acme 116 ''; 117 }; 118 119 group = mkOption { 120 default = "traefik"; 121 type = types.str; 122 example = "docker"; 123 description = lib.mdDoc '' 124 Set the group that traefik runs under. 125 For the docker backend this needs to be set to `docker` instead. 126 ''; 127 }; 128 129 package = mkOption { 130 default = pkgs.traefik; 131 defaultText = literalExpression "pkgs.traefik"; 132 type = types.package; 133 description = lib.mdDoc "Traefik package to use."; 134 }; 135 136 environmentFiles = mkOption { 137 default = []; 138 type = types.listOf types.path; 139 example = [ "/run/secrets/traefik.env" ]; 140 description = lib.mdDoc '' 141 Files to load as environment file. Environment variables from this file 142 will be substituted into the static configuration file using envsubst. 143 ''; 144 }; 145 }; 146 147 config = mkIf cfg.enable { 148 systemd.tmpfiles.rules = [ "d '${cfg.dataDir}' 0700 traefik traefik - -" ]; 149 150 systemd.services.traefik = { 151 description = "Traefik web server"; 152 after = [ "network-online.target" ]; 153 wantedBy = [ "multi-user.target" ]; 154 startLimitIntervalSec = 86400; 155 startLimitBurst = 5; 156 serviceConfig = { 157 EnvironmentFile = cfg.environmentFiles; 158 ExecStartPre = lib.optional (cfg.environmentFiles != []) 159 (pkgs.writeShellScript "pre-start" '' 160 umask 077 161 ${pkgs.envsubst}/bin/envsubst -i "${staticConfigFile}" > "${finalStaticConfigFile}" 162 ''); 163 ExecStart = "${cfg.package}/bin/traefik --configfile=${finalStaticConfigFile}"; 164 Type = "simple"; 165 User = "traefik"; 166 Group = cfg.group; 167 Restart = "on-failure"; 168 AmbientCapabilities = "cap_net_bind_service"; 169 CapabilityBoundingSet = "cap_net_bind_service"; 170 NoNewPrivileges = true; 171 LimitNPROC = 64; 172 LimitNOFILE = 1048576; 173 PrivateTmp = true; 174 PrivateDevices = true; 175 ProtectHome = true; 176 ProtectSystem = "full"; 177 ReadWriteDirectories = cfg.dataDir; 178 RuntimeDirectory = "traefik"; 179 }; 180 }; 181 182 users.users.traefik = { 183 group = "traefik"; 184 home = cfg.dataDir; 185 createHome = true; 186 isSystemUser = true; 187 }; 188 189 users.groups.traefik = { }; 190 }; 191}