nixos/preload: init
[NixPkgs.git] / nixos / modules / services / search / typesense.nix
blobc158d04fea23884c32f18c99876fb81f5eb80ee7
1 { config, lib, pkgs, ... }: let
2   inherit
3     (lib)
4     concatMapStringsSep
5     generators
6     mdDoc
7     mkEnableOption
8     mkIf
9     mkOption
10     mkPackageOption
11     optionalString
12     types
13     ;
15   cfg = config.services.typesense;
16   settingsFormatIni = pkgs.formats.ini {
17     listToValue = concatMapStringsSep " " (generators.mkValueStringDefault { });
18     mkKeyValue = generators.mkKeyValueDefault
19       {
20         mkValueString = v:
21           if v == null then ""
22           else generators.mkValueStringDefault { } v;
23       }
24       "=";
25   };
26   configFile = settingsFormatIni.generate "typesense.ini" cfg.settings;
27 in {
28   options.services.typesense = {
29     enable = mkEnableOption "typesense";
30     package = mkPackageOption pkgs "typesense" {};
32     apiKeyFile = mkOption {
33       type = types.path;
34       description = ''
35         Sets the admin api key for typesense. Always use this option
36         instead of {option}`settings.server.api-key` to prevent the key
37         from being written to the world-readable nix store.
38       '';
39     };
41     settings = mkOption {
42       description = mdDoc "Typesense configuration. Refer to [the documentation](https://typesense.org/docs/0.24.1/api/server-configuration.html) for supported values.";
43       default = {};
44       type = types.submodule {
45         freeformType = settingsFormatIni.type;
46         options.server = {
47           data-dir = mkOption {
48             type = types.str;
49             default = "/var/lib/typesense";
50             description = mdDoc "Path to the directory where data will be stored on disk.";
51           };
53           api-address = mkOption {
54             type = types.str;
55             description = mdDoc "Address to which Typesense API service binds.";
56           };
58           api-port = mkOption {
59             type = types.port;
60             default = 8108;
61             description = mdDoc "Port on which the Typesense API service listens.";
62           };
63         };
64       };
65     };
66   };
68   config = mkIf cfg.enable {
69     systemd.services.typesense = {
70       description = "Typesense search engine";
71       wantedBy = [ "multi-user.target" ];
72       after = [ "network.target" ];
74       script = ''
75         export TYPESENSE_API_KEY=$(cat ${cfg.apiKeyFile})
76         exec ${cfg.package}/bin/typesense-server --config ${configFile}
77       '';
79       serviceConfig = {
80         Restart = "on-failure";
81         DynamicUser = true;
82         User = "typesense";
83         Group = "typesense";
85         StateDirectory = "typesense";
86         StateDirectoryMode = "0750";
88         # Hardening
89         CapabilityBoundingSet = "";
90         LockPersonality = true;
91         # MemoryDenyWriteExecute = true; needed since 0.25.1
92         NoNewPrivileges = true;
93         PrivateUsers = true;
94         PrivateTmp = true;
95         PrivateDevices = true;
96         PrivateMounts = true;
97         ProtectClock = true;
98         ProtectControlGroups = true;
99         ProtectHome = true;
100         ProtectHostname = true;
101         ProtectKernelLogs = true;
102         ProtectKernelModules = true;
103         ProtectKernelTunables = true;
104         ProtectProc = "invisible";
105         ProcSubset = "pid";
106         ProtectSystem = "strict";
107         RemoveIPC = true;
108         RestrictAddressFamilies = [
109           "AF_INET"
110           "AF_INET6"
111           "AF_UNIX"
112         ];
113         RestrictNamespaces = true;
114         RestrictRealtime = true;
115         RestrictSUIDSGID = true;
116         SystemCallArchitectures = "native";
117         SystemCallFilter = [
118           "@system-service"
119           "~@privileged"
120         ];
121         UMask = "0077";
122       };
123     };
124   };