grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / web-servers / agate.nix
blob76c1a94f3bf289dbb0071067832713ccf074f11f
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
6   cfg = config.services.agate;
7 in
9   options = {
10     services.agate = {
11       enable = mkEnableOption "Agate Server";
13       package = mkPackageOption pkgs "agate" { };
15       addresses = mkOption {
16         type = types.listOf types.str;
17         default = [ "0.0.0.0:1965" ];
18         description = ''
19           Addresses to listen on, IP:PORT, if you haven't disabled forwarding
20           only set IPv4.
21         '';
22       };
24       contentDir = mkOption {
25         default = "/var/lib/agate/content";
26         type = types.path;
27         description = "Root of the content directory.";
28       };
30       certificatesDir = mkOption {
31         default = "/var/lib/agate/certificates";
32         type = types.path;
33         description = "Root of the certificate directory.";
34       };
36       hostnames = mkOption {
37         default = [ ];
38         type = types.listOf types.str;
39         description = ''
40           Domain name of this Gemini server, enables checking hostname and port
41           in requests. (multiple occurrences means basic vhosts)
42         '';
43       };
45       language = mkOption {
46         default = null;
47         type = types.nullOr types.str;
48         description = "RFC 4646 Language code for text/gemini documents.";
49       };
51       onlyTls_1_3 = mkOption {
52         default = false;
53         type = types.bool;
54         description = "Only use TLSv1.3 (default also allows TLSv1.2).";
55       };
57       extraArgs = mkOption {
58         type = types.listOf types.str;
59         default = [ "" ];
60         example = [ "--log-ip" ];
61         description = "Extra arguments to use running agate.";
62       };
63     };
64   };
66   config = mkIf cfg.enable {
67     # available for generating certs by hand
68     # it can be a bit arduous with openssl
69     environment.systemPackages = [ cfg.package ];
71     systemd.services.agate = {
72       description = "Agate";
73       wantedBy = [ "multi-user.target" ];
74       wants = [ "network-online.target" ];
75       after = [ "network.target" "network-online.target" ];
77       script =
78         let
79           prefixKeyList = key: list: concatMap (v: [ key v ]) list;
80           addresses = prefixKeyList "--addr" cfg.addresses;
81           hostnames = prefixKeyList "--hostname" cfg.hostnames;
82         in
83         ''
84           exec ${cfg.package}/bin/agate ${
85             escapeShellArgs (
86               [
87                 "--content" "${cfg.contentDir}"
88                 "--certs" "${cfg.certificatesDir}"
89               ] ++
90               addresses ++
91               (optionals (cfg.hostnames != []) hostnames) ++
92               (optionals (cfg.language != null) [ "--lang" cfg.language ]) ++
93               (optionals cfg.onlyTls_1_3 [ "--only-tls13" ]) ++
94               (optionals (cfg.extraArgs != []) cfg.extraArgs)
95             )
96           }
97         '';
99       serviceConfig = {
100         Restart = "always";
101         RestartSec = "5s";
102         DynamicUser = true;
103         StateDirectory = "agate";
105         # Security options:
106         AmbientCapabilities = "";
107         CapabilityBoundingSet = "";
109         # ProtectClock= adds DeviceAllow=char-rtc r
110         DeviceAllow = "";
112         LockPersonality = true;
114         PrivateTmp = true;
115         PrivateDevices = true;
116         PrivateUsers = true;
118         ProtectClock = true;
119         ProtectControlGroups = true;
120         ProtectHostname = true;
121         ProtectKernelLogs = true;
122         ProtectKernelModules = true;
123         ProtectKernelTunables = true;
125         RestrictNamespaces = true;
126         RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
127         RestrictRealtime = true;
129         SystemCallArchitectures = "native";
130         SystemCallErrorNumber = "EPERM";
131         SystemCallFilter = [
132           "@system-service"
133           "~@cpu-emulation"
134           "~@debug"
135           "~@keyring"
136           "~@memlock"
137           "~@obsolete"
138           "~@privileged"
139           "~@setuid"
140         ];
141       };
142     };
143   };