1 { config, lib, pkgs, ... }:
6 cfg = config.services.traefik;
7 jsonValue = with types;
9 valueType = nullOr (oneOf [
14 (lazyAttrsOf valueType)
17 description = "JSON value";
18 emptyValue.value = { };
21 dynamicConfigFile = if cfg.dynamicConfigFile == null then
22 pkgs.runCommand "config.toml" {
23 buildInputs = [ pkgs.remarshal ];
24 preferLocalBuild = true;
26 remarshal -if json -of toml \
28 pkgs.writeText "dynamic_config.json"
29 (builtins.toJSON cfg.dynamicConfigOptions)
34 cfg.dynamicConfigFile;
35 staticConfigFile = if cfg.staticConfigFile == null then
36 pkgs.runCommand "config.toml" {
37 buildInputs = [ pkgs.yj ];
38 preferLocalBuild = true;
42 pkgs.writeText "static_config.json" (builtins.toJSON
43 (recursiveUpdate cfg.staticConfigOptions {
44 providers.file.filename = "${dynamicConfigFile}";
52 finalStaticConfigFile =
53 if cfg.environmentFiles == []
55 else "/run/traefik/config.toml";
57 options.services.traefik = {
58 enable = mkEnableOption "Traefik web server";
60 staticConfigFile = mkOption {
62 example = literalExpression "/path/to/static_config.toml";
63 type = types.nullOr types.path;
65 Path to traefik's static configuration to use.
66 (Using that option has precedence over `staticConfigOptions` and `dynamicConfigOptions`)
70 staticConfigOptions = mkOption {
72 Static configuration for Traefik.
75 default = { entryPoints.http.address = ":80"; };
77 entryPoints.web.address = ":8080";
78 entryPoints.http.address = ":80";
84 dynamicConfigFile = mkOption {
86 example = literalExpression "/path/to/dynamic_config.toml";
87 type = types.nullOr types.path;
89 Path to traefik's dynamic configuration to use.
90 (Using that option has precedence over `dynamicConfigOptions`)
94 dynamicConfigOptions = mkOption {
96 Dynamic configuration for Traefik.
101 http.routers.router1 = {
102 rule = "Host(`localhost`)";
103 service = "service1";
106 http.services.service1.loadBalancer.servers =
107 [{ url = "http://localhost:8080"; }];
112 default = "/var/lib/traefik";
115 Location for any persistent data traefik creates, ie. acme
124 Set the group that traefik runs under.
125 For the docker backend this needs to be set to `docker` instead.
129 package = mkPackageOption pkgs "traefik" { };
131 environmentFiles = mkOption {
133 type = types.listOf types.path;
134 example = [ "/run/secrets/traefik.env" ];
136 Files to load as environment file. Environment variables from this file
137 will be substituted into the static configuration file using envsubst.
142 config = mkIf cfg.enable {
143 systemd.tmpfiles.rules = [ "d '${cfg.dataDir}' 0700 traefik traefik - -" ];
145 systemd.services.traefik = {
146 description = "Traefik web server";
147 wants = [ "network-online.target" ];
148 after = [ "network-online.target" ];
149 wantedBy = [ "multi-user.target" ];
150 startLimitIntervalSec = 86400;
153 EnvironmentFile = cfg.environmentFiles;
154 ExecStartPre = lib.optional (cfg.environmentFiles != [])
155 (pkgs.writeShellScript "pre-start" ''
157 ${pkgs.envsubst}/bin/envsubst -i "${staticConfigFile}" > "${finalStaticConfigFile}"
159 ExecStart = "${cfg.package}/bin/traefik --configfile=${finalStaticConfigFile}";
163 Restart = "on-failure";
164 AmbientCapabilities = "cap_net_bind_service";
165 CapabilityBoundingSet = "cap_net_bind_service";
166 NoNewPrivileges = true;
168 LimitNOFILE = 1048576;
170 PrivateDevices = true;
172 ProtectSystem = "full";
173 ReadWritePaths = [ cfg.dataDir ];
174 RuntimeDirectory = "traefik";
178 users.users.traefik = {
185 users.groups.traefik = { };