1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.traefik;
7 configFile =
8 if cfg.configFile == null then
9 pkgs.runCommand "config.toml" {
10 buildInputs = [ pkgs.remarshal ];
11 } ''
12 remarshal -if json -of toml \
13 < ${pkgs.writeText "config.json" (builtins.toJSON cfg.configOptions)} \
14 > $out
15 ''
16 else cfg.configFile;
17
18in {
19 options.services.traefik = {
20 enable = mkEnableOption "Traefik web server";
21
22 configFile = mkOption {
23 default = null;
24 example = literalExample "/path/to/config.toml";
25 type = types.nullOr types.path;
26 description = ''
27 Path to verbatim traefik.toml to use.
28 (Using that option has precedence over <literal>configOptions</literal>)
29 '';
30 };
31
32 configOptions = mkOption {
33 description = ''
34 Config for Traefik.
35 '';
36 type = types.attrs;
37 default = {
38 defaultEntryPoints = ["http"];
39 entryPoints.http.address = ":80";
40 };
41 example = {
42 defaultEntrypoints = [ "http" ];
43 web.address = ":8080";
44 entryPoints.http.address = ":80";
45
46 file = {};
47 frontends = {
48 frontend1 = {
49 backend = "backend1";
50 routes.test_1.rule = "Host:localhost";
51 };
52 };
53 backends.backend1 = {
54 servers.server1.url = "http://localhost:8000";
55 };
56 };
57 };
58
59 dataDir = mkOption {
60 default = "/var/lib/traefik";
61 type = types.path;
62 description = ''
63 Location for any persistent data traefik creates, ie. acme
64 '';
65 };
66
67 group = mkOption {
68 default = "traefik";
69 type = types.string;
70 example = "docker";
71 description = ''
72 Set the group that traefik runs under.
73 For the docker backend this needs to be set to <literal>docker</literal> instead.
74 '';
75 };
76
77 package = mkOption {
78 default = pkgs.traefik;
79 defaultText = "pkgs.traefik";
80 type = types.package;
81 description = "Traefik package to use.";
82 };
83 };
84
85 config = mkIf cfg.enable {
86 systemd.services.traefik = {
87 description = "Traefik web server";
88 after = [ "network-online.target" ];
89 wantedBy = [ "multi-user.target" ];
90 serviceConfig = {
91 PermissionsStartOnly = true;
92 ExecStart = ''${cfg.package.bin}/bin/traefik --configfile=${configFile}'';
93 ExecStartPre = [
94 ''${pkgs.coreutils}/bin/mkdir -p "${cfg.dataDir}"''
95 ''${pkgs.coreutils}/bin/chmod 700 "${cfg.dataDir}"''
96 ''${pkgs.coreutils}/bin/chown -R traefik:traefik "${cfg.dataDir}"''
97 ];
98 Type = "simple";
99 User = "traefik";
100 Group = cfg.group;
101 Restart = "on-failure";
102 StartLimitInterval = 86400;
103 StartLimitBurst = 5;
104 AmbientCapabilities = "cap_net_bind_service";
105 CapabilityBoundingSet = "cap_net_bind_service";
106 NoNewPrivileges = true;
107 LimitNPROC = 64;
108 LimitNOFILE = 1048576;
109 PrivateTmp = true;
110 PrivateDevices = true;
111 ProtectHome = true;
112 ProtectSystem = "full";
113 ReadWriteDirectories = cfg.dataDir;
114 };
115 };
116
117 users.users.traefik = {
118 group = "traefik";
119 home = cfg.dataDir;
120 createHome = true;
121 };
122
123 users.groups.traefik = {};
124 };
125}