1 { config, lib, pkgs, ... }:
6 cfg = config.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" ];
19 Addresses to listen on, IP:PORT, if you haven't disabled forwarding
24 contentDir = mkOption {
25 default = "/var/lib/agate/content";
27 description = "Root of the content directory.";
30 certificatesDir = mkOption {
31 default = "/var/lib/agate/certificates";
33 description = "Root of the certificate directory.";
36 hostnames = mkOption {
38 type = types.listOf types.str;
40 Domain name of this Gemini server, enables checking hostname and port
41 in requests. (multiple occurrences means basic vhosts)
47 type = types.nullOr types.str;
48 description = "RFC 4646 Language code for text/gemini documents.";
51 onlyTls_1_3 = mkOption {
54 description = "Only use TLSv1.3 (default also allows TLSv1.2).";
57 extraArgs = mkOption {
58 type = types.listOf types.str;
60 example = [ "--log-ip" ];
61 description = "Extra arguments to use running agate.";
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" ];
79 prefixKeyList = key: list: concatMap (v: [ key v ]) list;
80 addresses = prefixKeyList "--addr" cfg.addresses;
81 hostnames = prefixKeyList "--hostname" cfg.hostnames;
84 exec ${cfg.package}/bin/agate ${
87 "--content" "${cfg.contentDir}"
88 "--certs" "${cfg.certificatesDir}"
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)
103 StateDirectory = "agate";
106 AmbientCapabilities = "";
107 CapabilityBoundingSet = "";
109 # ProtectClock= adds DeviceAllow=char-rtc r
112 LockPersonality = true;
115 PrivateDevices = 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";