at 23.11-pre 4.6 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; 51in { 52 options.services.traefik = { 53 enable = mkEnableOption (lib.mdDoc "Traefik web server"); 54 55 staticConfigFile = mkOption { 56 default = null; 57 example = literalExpression "/path/to/static_config.toml"; 58 type = types.nullOr types.path; 59 description = lib.mdDoc '' 60 Path to traefik's static configuration to use. 61 (Using that option has precedence over `staticConfigOptions` and `dynamicConfigOptions`) 62 ''; 63 }; 64 65 staticConfigOptions = mkOption { 66 description = lib.mdDoc '' 67 Static configuration for Traefik. 68 ''; 69 type = jsonValue; 70 default = { entryPoints.http.address = ":80"; }; 71 example = { 72 entryPoints.web.address = ":8080"; 73 entryPoints.http.address = ":80"; 74 75 api = { }; 76 }; 77 }; 78 79 dynamicConfigFile = mkOption { 80 default = null; 81 example = literalExpression "/path/to/dynamic_config.toml"; 82 type = types.nullOr types.path; 83 description = lib.mdDoc '' 84 Path to traefik's dynamic configuration to use. 85 (Using that option has precedence over `dynamicConfigOptions`) 86 ''; 87 }; 88 89 dynamicConfigOptions = mkOption { 90 description = lib.mdDoc '' 91 Dynamic configuration for Traefik. 92 ''; 93 type = jsonValue; 94 default = { }; 95 example = { 96 http.routers.router1 = { 97 rule = "Host(`localhost`)"; 98 service = "service1"; 99 }; 100 101 http.services.service1.loadBalancer.servers = 102 [{ url = "http://localhost:8080"; }]; 103 }; 104 }; 105 106 dataDir = mkOption { 107 default = "/var/lib/traefik"; 108 type = types.path; 109 description = lib.mdDoc '' 110 Location for any persistent data traefik creates, ie. acme 111 ''; 112 }; 113 114 group = mkOption { 115 default = "traefik"; 116 type = types.str; 117 example = "docker"; 118 description = lib.mdDoc '' 119 Set the group that traefik runs under. 120 For the docker backend this needs to be set to `docker` instead. 121 ''; 122 }; 123 124 package = mkOption { 125 default = pkgs.traefik; 126 defaultText = literalExpression "pkgs.traefik"; 127 type = types.package; 128 description = lib.mdDoc "Traefik package to use."; 129 }; 130 }; 131 132 config = mkIf cfg.enable { 133 systemd.tmpfiles.rules = [ "d '${cfg.dataDir}' 0700 traefik traefik - -" ]; 134 135 systemd.services.traefik = { 136 description = "Traefik web server"; 137 after = [ "network-online.target" ]; 138 wantedBy = [ "multi-user.target" ]; 139 startLimitIntervalSec = 86400; 140 startLimitBurst = 5; 141 serviceConfig = { 142 ExecStart = 143 "${cfg.package}/bin/traefik --configfile=${staticConfigFile}"; 144 Type = "simple"; 145 User = "traefik"; 146 Group = cfg.group; 147 Restart = "on-failure"; 148 AmbientCapabilities = "cap_net_bind_service"; 149 CapabilityBoundingSet = "cap_net_bind_service"; 150 NoNewPrivileges = true; 151 LimitNPROC = 64; 152 LimitNOFILE = 1048576; 153 PrivateTmp = true; 154 PrivateDevices = true; 155 ProtectHome = true; 156 ProtectSystem = "full"; 157 ReadWriteDirectories = cfg.dataDir; 158 }; 159 }; 160 161 users.users.traefik = { 162 group = "traefik"; 163 home = cfg.dataDir; 164 createHome = true; 165 isSystemUser = true; 166 }; 167 168 users.groups.traefik = { }; 169 }; 170}