python313Packages.traits: fix build (#373698)
[NixPkgs.git] / nixos / modules / services / web-servers / trafficserver / default.nix
blobf6a98b1ebe2f035cebf0f800745415efbb4cb3e9
2   config,
3   lib,
4   pkgs,
5   ...
6 }:
8 with lib;
10 let
11   cfg = config.services.trafficserver;
12   user = config.users.users.trafficserver.name;
13   group = config.users.groups.trafficserver.name;
15   getManualUrl =
16     name: "https://docs.trafficserver.apache.org/en/latest/admin-guide/files/${name}.en.html";
18   yaml = pkgs.formats.yaml { };
20   mkYamlConf =
21     name: cfg:
22     if cfg != null then
23       {
24         "trafficserver/${name}.yaml".source = yaml.generate "${name}.yaml" cfg;
25       }
26     else
27       {
28         "trafficserver/${name}.yaml".text = "";
29       };
31   mkRecordLines =
32     path: value:
33     if isAttrs value then
34       lib.mapAttrsToList (n: v: mkRecordLines (path ++ [ n ]) v) value
35     else if isInt value then
36       "CONFIG ${concatStringsSep "." path} INT ${toString value}"
37     else if isFloat value then
38       "CONFIG ${concatStringsSep "." path} FLOAT ${toString value}"
39     else
40       "CONFIG ${concatStringsSep "." path} STRING ${toString value}";
42   mkRecordsConfig = cfg: concatStringsSep "\n" (flatten (mkRecordLines [ ] cfg));
43   mkPluginConfig = cfg: concatStringsSep "\n" (map (p: "${p.path} ${p.arg}") cfg);
46   options.services.trafficserver = {
47     enable = mkEnableOption "Apache Traffic Server";
49     cache = mkOption {
50       type = types.lines;
51       default = "";
52       example = "dest_domain=example.com suffix=js action=never-cache";
53       description = ''
54         Caching rules that overrule the origin's caching policy.
56         Consult the [upstream
57         documentation](${getManualUrl "cache.config"}) for more details.
58       '';
59     };
61     hosting = mkOption {
62       type = types.lines;
63       default = "";
64       example = "domain=example.com volume=1";
65       description = ''
66         Partition the cache according to origin server or domain
68         Consult the [
69         upstream documentation](${getManualUrl "hosting.config"}) for more details.
70       '';
71     };
73     ipAllow = mkOption {
74       type = types.nullOr yaml.type;
75       default = lib.importJSON ./ip_allow.json;
76       defaultText = literalMD "upstream defaults";
77       example = literalExpression ''
78         {
79           ip_allow = [{
80             apply = "in";
81             ip_addrs = "127.0.0.1";
82             action = "allow";
83             methods = "ALL";
84           }];
85         }
86       '';
87       description = ''
88         Control client access to Traffic Server and Traffic Server connections
89         to upstream servers.
91         Consult the [upstream
92         documentation](${getManualUrl "ip_allow.yaml"}) for more details.
93       '';
94     };
96     logging = mkOption {
97       type = types.nullOr yaml.type;
98       default = lib.importJSON ./logging.json;
99       defaultText = literalMD "upstream defaults";
100       example = { };
101       description = ''
102         Configure logs.
104         Consult the [upstream
105         documentation](${getManualUrl "logging.yaml"}) for more details.
106       '';
107     };
109     parent = mkOption {
110       type = types.lines;
111       default = "";
112       example = ''
113         dest_domain=. method=get parent="p1.example:8080; p2.example:8080" round_robin=true
114       '';
115       description = ''
116         Identify the parent proxies used in an cache hierarchy.
118         Consult the [upstream
119         documentation](${getManualUrl "parent.config"}) for more details.
120       '';
121     };
123     plugins = mkOption {
124       default = [ ];
126       description = ''
127         Controls run-time loadable plugins available to Traffic Server, as
128         well as their configuration.
130         Consult the [upstream
131         documentation](${getManualUrl "plugin.config"}) for more details.
132       '';
134       type =
135         with types;
136         listOf (submodule {
137           options.path = mkOption {
138             type = str;
139             example = "xdebug.so";
140             description = ''
141               Path to plugin. The path can either be absolute, or relative to
142               the plugin directory.
143             '';
144           };
145           options.arg = mkOption {
146             type = str;
147             default = "";
148             example = "--header=ATS-My-Debug";
149             description = "arguments to pass to the plugin";
150           };
151         });
152     };
154     records = mkOption {
155       type =
156         with types;
157         let
158           valueType =
159             (attrsOf (oneOf [
160               int
161               float
162               str
163               valueType
164             ]))
165             // {
166               description = "Traffic Server records value";
167             };
168         in
169         valueType;
170       default = { };
171       example = {
172         proxy.config.proxy_name = "my_server";
173       };
174       description = ''
175         List of configurable variables used by Traffic Server.
177         Consult the [
178         upstream documentation](${getManualUrl "records.config"}) for more details.
179       '';
180     };
182     remap = mkOption {
183       type = types.lines;
184       default = "";
185       example = "map http://from.example http://origin.example";
186       description = ''
187         URL remapping rules used by Traffic Server.
189         Consult the [
190         upstream documentation](${getManualUrl "remap.config"}) for more details.
191       '';
192     };
194     splitDns = mkOption {
195       type = types.lines;
196       default = "";
197       example = ''
198         dest_domain=internal.corp.example named="255.255.255.255:212 255.255.255.254" def_domain=corp.example search_list="corp.example corp1.example"
199         dest_domain=!internal.corp.example named=255.255.255.253
200       '';
201       description = ''
202         Specify the DNS server that Traffic Server should use under specific
203         conditions.
205         Consult the [
206         upstream documentation](${getManualUrl "splitdns.config"}) for more details.
207       '';
208     };
210     sslMulticert = mkOption {
211       type = types.lines;
212       default = "";
213       example = "dest_ip=* ssl_cert_name=default.pem";
214       description = ''
215         Configure SSL server certificates to terminate the SSL sessions.
217         Consult the [
218         upstream documentation](${getManualUrl "ssl_multicert.config"}) for more details.
219       '';
220     };
222     sni = mkOption {
223       type = types.nullOr yaml.type;
224       default = null;
225       example = literalExpression ''
226         {
227           sni = [{
228             fqdn = "no-http2.example.com";
229             https = "off";
230           }];
231         }
232       '';
233       description = ''
234         Configure aspects of TLS connection handling for both inbound and
235         outbound connections.
237         Consult the [upstream
238         documentation](${getManualUrl "sni.yaml"}) for more details.
239       '';
240     };
242     storage = mkOption {
243       type = types.lines;
244       default = "/var/cache/trafficserver 256M";
245       example = "/dev/disk/by-id/XXXXX volume=1";
246       description = ''
247         List all the storage that make up the Traffic Server cache.
249         Consult the [
250         upstream documentation](${getManualUrl "storage.config"}) for more details.
251       '';
252     };
254     strategies = mkOption {
255       type = types.nullOr yaml.type;
256       default = null;
257       description = ''
258         Specify the next hop proxies used in an cache hierarchy and the
259         algorithms used to select the next proxy.
261         Consult the [
262         upstream documentation](${getManualUrl "strategies.yaml"}) for more details.
263       '';
264     };
266     volume = mkOption {
267       type = types.nullOr yaml.type;
268       default = "";
269       example = "volume=1 scheme=http size=20%";
270       description = ''
271         Manage cache space more efficiently and restrict disk usage by
272         creating cache volumes of different sizes.
274         Consult the [
275         upstream documentation](${getManualUrl "volume.config"}) for more details.
276       '';
277     };
278   };
280   config = mkIf cfg.enable {
281     environment.etc =
282       {
283         "trafficserver/cache.config".text = cfg.cache;
284         "trafficserver/hosting.config".text = cfg.hosting;
285         "trafficserver/parent.config".text = cfg.parent;
286         "trafficserver/plugin.config".text = mkPluginConfig cfg.plugins;
287         "trafficserver/records.config".text = mkRecordsConfig cfg.records;
288         "trafficserver/remap.config".text = cfg.remap;
289         "trafficserver/splitdns.config".text = cfg.splitDns;
290         "trafficserver/ssl_multicert.config".text = cfg.sslMulticert;
291         "trafficserver/storage.config".text = cfg.storage;
292         "trafficserver/volume.config".text = cfg.volume;
293       }
294       // (mkYamlConf "ip_allow" cfg.ipAllow)
295       // (mkYamlConf "logging" cfg.logging)
296       // (mkYamlConf "sni" cfg.sni)
297       // (mkYamlConf "strategies" cfg.strategies);
299     environment.systemPackages = [ pkgs.trafficserver ];
300     systemd.packages = [ pkgs.trafficserver ];
302     # Traffic Server does privilege handling independently of systemd, and
303     # therefore should be started as root
304     systemd.services.trafficserver = {
305       enable = true;
306       wantedBy = [ "multi-user.target" ];
307     };
309     # These directories can't be created by systemd because:
310     #
311     #   1. Traffic Servers starts as root and switches to an unprivileged user
312     #      afterwards. The runtime directories defined below are assumed to be
313     #      owned by that user.
314     #   2. The bin/trafficserver script assumes these directories exist.
315     systemd.tmpfiles.rules = [
316       "d '/run/trafficserver' - ${user} ${group} - -"
317       "d '/var/cache/trafficserver' - ${user} ${group} - -"
318       "d '/var/lib/trafficserver' - ${user} ${group} - -"
319       "d '/var/log/trafficserver' - ${user} ${group} - -"
320     ];
322     services.trafficserver = {
323       records.proxy.config.admin.user_id = user;
324       records.proxy.config.body_factory.template_sets_dir =
325         "${pkgs.trafficserver}/etc/trafficserver/body_factory";
326     };
328     users.users.trafficserver = {
329       description = "Apache Traffic Server";
330       isSystemUser = true;
331       inherit group;
332     };
333     users.groups.trafficserver = { };
334   };