···
1
+
{ config, lib, pkgs, ... }:
6
+
cfg = config.services.trafficserver;
7
+
user = config.users.users.trafficserver.name;
8
+
group = config.users.groups.trafficserver.name;
10
+
getManualUrl = name: "https://docs.trafficserver.apache.org/en/latest/admin-guide/files/${name}.en.html";
11
+
getConfPath = name: "${pkgs.trafficserver}/etc/trafficserver/${name}";
13
+
yaml = pkgs.formats.yaml { };
17
+
jsonFile = pkgs.runCommand "in.json"
19
+
nativeBuildInputs = [ pkgs.remarshal ];
21
+
yaml2json < "${f}" > "$out"
24
+
builtins.fromJSON (builtins.readFile jsonFile);
26
+
mkYamlConf = name: cfg:
27
+
if cfg != null then {
28
+
"trafficserver/${name}.yaml".source = yaml.generate "${name}.yaml" cfg;
30
+
"trafficserver/${name}.yaml".text = "";
33
+
mkRecordLines = path: value:
34
+
if isAttrs value then
35
+
lib.mapAttrsToList (n: v: mkRecordLines (path ++ [ n ]) v) value
36
+
else if isInt value then
37
+
"CONFIG ${concatStringsSep "." path} INT ${toString value}"
38
+
else if isFloat value then
39
+
"CONFIG ${concatStringsSep "." path} FLOAT ${toString value}"
41
+
"CONFIG ${concatStringsSep "." path} STRING ${toString value}";
43
+
mkRecordsConfig = cfg: concatStringsSep "\n" (flatten (mkRecordLines [ ] cfg));
44
+
mkPluginConfig = cfg: concatStringsSep "\n" (map (p: "${p.path} ${p.arg}") cfg);
47
+
options.services.trafficserver = {
48
+
enable = mkEnableOption "Apache Traffic Server";
53
+
example = "dest_domain=example.com suffix=js action=never-cache";
55
+
Caching rules that overrule the origin's caching policy.
57
+
Consult the <link xlink:href="${getManualUrl "cache.config"}">upstream
58
+
documentation</link> for more details.
62
+
hosting = mkOption {
65
+
example = "domain=example.com volume=1";
67
+
Partition the cache according to origin server or domain
69
+
Consult the <link xlink:href="${getManualUrl "hosting.config"}">
70
+
upstream documentation</link> for more details.
74
+
ipAllow = mkOption {
75
+
type = types.nullOr yaml.type;
76
+
default = fromYAML (getConfPath "ip_allow.yaml");
77
+
defaultText = "upstream defaults";
78
+
example = literalExample {
81
+
ip_addrs = "127.0.0.1";
87
+
Control client access to Traffic Server and Traffic Server connections
88
+
to upstream servers.
90
+
Consult the <link xlink:href="${getManualUrl "ip_allow.yaml"}">upstream
91
+
documentation</link> for more details.
95
+
logging = mkOption {
96
+
type = types.nullOr yaml.type;
97
+
default = fromYAML (getConfPath "logging.yaml");
98
+
defaultText = "upstream defaults";
99
+
example = literalExample { };
103
+
Consult the <link xlink:href="${getManualUrl "logging.yaml"}">upstream
104
+
documentation</link> for more details.
108
+
parent = mkOption {
109
+
type = types.lines;
112
+
dest_domain=. method=get parent="p1.example:8080; p2.example:8080" round_robin=true
115
+
Identify the parent proxies used in an cache hierarchy.
117
+
Consult the <link xlink:href="${getManualUrl "parent.config"}">upstream
118
+
documentation</link> for more details.
122
+
plugins = mkOption {
126
+
Controls run-time loadable plugins available to Traffic Server, as
127
+
well as their configuration.
129
+
Consult the <link xlink:href="${getManualUrl "plugin.config"}">upstream
130
+
documentation</link> for more details.
134
+
listOf (submodule {
135
+
options.path = mkOption {
137
+
example = "xdebug.so";
139
+
Path to plugin. The path can either be absolute, or relative to
140
+
the plugin directory.
143
+
options.arg = mkOption {
146
+
example = "--header=ATS-My-Debug";
147
+
description = "arguments to pass to the plugin";
152
+
records = mkOption {
154
+
let valueType = (attrsOf (oneOf [ int float str valueType ])) // {
155
+
description = "Traffic Server records value";
160
+
example = literalExample { proxy.config.proxy_name = "my_server"; };
162
+
List of configurable variables used by Traffic Server.
164
+
Consult the <link xlink:href="${getManualUrl "records.config"}">
165
+
upstream documentation</link> for more details.
170
+
type = types.lines;
172
+
example = "map http://from.example http://origin.example";
174
+
URL remapping rules used by Traffic Server.
176
+
Consult the <link xlink:href="${getManualUrl "remap.config"}">
177
+
upstream documentation</link> for more details.
181
+
splitDns = mkOption {
182
+
type = types.lines;
185
+
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"
186
+
dest_domain=!internal.corp.example named=255.255.255.253
189
+
Specify the DNS server that Traffic Server should use under specific
192
+
Consult the <link xlink:href="${getManualUrl "splitdns.config"}">
193
+
upstream documentation</link> for more details.
197
+
sslMulticert = mkOption {
198
+
type = types.lines;
200
+
example = "dest_ip=* ssl_cert_name=default.pem";
202
+
Configure SSL server certificates to terminate the SSL sessions.
204
+
Consult the <link xlink:href="${getManualUrl "ssl_multicert.config"}">
205
+
upstream documentation</link> for more details.
210
+
type = types.nullOr yaml.type;
212
+
example = literalExample {
214
+
fqdn = "no-http2.example.com";
219
+
Configure aspects of TLS connection handling for both inbound and
220
+
outbound connections.
222
+
Consult the <link xlink:href="${getManualUrl "sni.yaml"}">upstream
223
+
documentation</link> for more details.
227
+
storage = mkOption {
228
+
type = types.lines;
229
+
default = "/var/cache/trafficserver 256M";
230
+
example = "/dev/disk/by-id/XXXXX volume=1";
232
+
List all the storage that make up the Traffic Server cache.
234
+
Consult the <link xlink:href="${getManualUrl "storage.config"}">
235
+
upstream documentation</link> for more details.
239
+
strategies = mkOption {
240
+
type = types.nullOr yaml.type;
243
+
Specify the next hop proxies used in an cache hierarchy and the
244
+
algorithms used to select the next proxy.
246
+
Consult the <link xlink:href="${getManualUrl "strategies.yaml"}">
247
+
upstream documentation</link> for more details.
251
+
volume = mkOption {
252
+
type = types.nullOr yaml.type;
254
+
example = "volume=1 scheme=http size=20%";
256
+
Manage cache space more efficiently and restrict disk usage by
257
+
creating cache volumes of different sizes.
259
+
Consult the <link xlink:href="${getManualUrl "volume.config"}">
260
+
upstream documentation</link> for more details.
265
+
config = mkIf cfg.enable {
266
+
environment.etc = {
267
+
"trafficserver/cache.config".text = cfg.cache;
268
+
"trafficserver/hosting.config".text = cfg.hosting;
269
+
"trafficserver/parent.config".text = cfg.parent;
270
+
"trafficserver/plugin.config".text = mkPluginConfig cfg.plugins;
271
+
"trafficserver/records.config".text = mkRecordsConfig cfg.records;
272
+
"trafficserver/remap.config".text = cfg.remap;
273
+
"trafficserver/splitdns.config".text = cfg.splitDns;
274
+
"trafficserver/ssl_multicert.config".text = cfg.sslMulticert;
275
+
"trafficserver/storage.config".text = cfg.storage;
276
+
"trafficserver/volume.config".text = cfg.volume;
277
+
} // (mkYamlConf "ip_allow" cfg.ipAllow)
278
+
// (mkYamlConf "logging" cfg.logging)
279
+
// (mkYamlConf "sni" cfg.sni)
280
+
// (mkYamlConf "strategies" cfg.strategies);
282
+
environment.systemPackages = [ pkgs.trafficserver ];
283
+
systemd.packages = [ pkgs.trafficserver ];
285
+
# Traffic Server does privilege handling independently of systemd, and
286
+
# therefore should be started as root
287
+
systemd.services.trafficserver = {
289
+
wantedBy = [ "multi-user.target" ];
292
+
# These directories can't be created by systemd because:
294
+
# 1. Traffic Servers starts as root and switches to an unprivileged user
295
+
# afterwards. The runtime directories defined below are assumed to be
296
+
# owned by that user.
297
+
# 2. The bin/trafficserver script assumes these directories exist.
298
+
systemd.tmpfiles.rules = [
299
+
"d '/run/trafficserver' - ${user} ${group} - -"
300
+
"d '/var/cache/trafficserver' - ${user} ${group} - -"
301
+
"d '/var/lib/trafficserver' - ${user} ${group} - -"
302
+
"d '/var/log/trafficserver' - ${user} ${group} - -"
305
+
services.trafficserver = {
306
+
records.proxy.config.admin.user_id = user;
307
+
records.proxy.config.body_factory.template_sets_dir =
308
+
"${pkgs.trafficserver}/etc/trafficserver/body_factory";
311
+
users.users.trafficserver = {
312
+
description = "Apache Traffic Server";
313
+
isSystemUser = true;
316
+
users.groups.trafficserver = { };