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 options.services.traefik = {
53 enable = mkEnableOption (lib.mdDoc "Traefik web server");
55 staticConfigFile = mkOption {
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`)
65 staticConfigOptions = mkOption {
66 description = lib.mdDoc ''
67 Static configuration for Traefik.
70 default = { entryPoints.http.address = ":80"; };
72 entryPoints.web.address = ":8080";
73 entryPoints.http.address = ":80";
79 dynamicConfigFile = mkOption {
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`)
89 dynamicConfigOptions = mkOption {
90 description = lib.mdDoc ''
91 Dynamic configuration for Traefik.
96 http.routers.router1 = {
97 rule = "Host(`localhost`)";
101 http.services.service1.loadBalancer.servers =
102 [{ url = "http://localhost:8080"; }];
107 default = "/var/lib/traefik";
109 description = lib.mdDoc ''
110 Location for any persistent data traefik creates, ie. acme
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.
125 default = pkgs.traefik;
126 defaultText = literalExpression "pkgs.traefik";
127 type = types.package;
128 description = lib.mdDoc "Traefik package to use.";
132 config = mkIf cfg.enable {
133 systemd.tmpfiles.rules = [ "d '${cfg.dataDir}' 0700 traefik traefik - -" ];
135 systemd.services.traefik = {
136 description = "Traefik web server";
137 after = [ "network-online.target" ];
138 wantedBy = [ "multi-user.target" ];
139 startLimitIntervalSec = 86400;
143 "${cfg.package}/bin/traefik --configfile=${staticConfigFile}";
147 Restart = "on-failure";
148 AmbientCapabilities = "cap_net_bind_service";
149 CapabilityBoundingSet = "cap_net_bind_service";
150 NoNewPrivileges = true;
152 LimitNOFILE = 1048576;
154 PrivateDevices = true;
156 ProtectSystem = "full";
157 ReadWriteDirectories = cfg.dataDir;
161 users.users.traefik = {
168 users.groups.traefik = { };