at 21.11-pre 6.6 kB view raw
1{ options, config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 runDir = "/run/searx"; 7 8 cfg = config.services.searx; 9 10 settingsFile = pkgs.writeText "settings.yml" 11 (builtins.toJSON cfg.settings); 12 13 generateConfig = '' 14 cd ${runDir} 15 16 # write NixOS settings as JSON 17 ( 18 umask 077 19 cp --no-preserve=mode ${settingsFile} settings.yml 20 ) 21 22 # substitute environment variables 23 env -0 | while IFS='=' read -r -d ''' n v; do 24 sed "s#@$n@#$v#g" -i settings.yml 25 done 26 ''; 27 28 settingType = with types; (oneOf 29 [ bool int float str 30 (listOf settingType) 31 (attrsOf settingType) 32 ]) // { description = "JSON value"; }; 33 34in 35 36{ 37 38 imports = [ 39 (mkRenamedOptionModule 40 [ "services" "searx" "configFile" ] 41 [ "services" "searx" "settingsFile" ]) 42 ]; 43 44 ###### interface 45 46 options = { 47 48 services.searx = { 49 50 enable = mkOption { 51 type = types.bool; 52 default = false; 53 relatedPackages = [ "searx" ]; 54 description = "Whether to enable Searx, the meta search engine."; 55 }; 56 57 environmentFile = mkOption { 58 type = types.nullOr types.path; 59 default = null; 60 description = '' 61 Environment file (see <literal>systemd.exec(5)</literal> 62 "EnvironmentFile=" section for the syntax) to define variables for 63 Searx. This option can be used to safely include secret keys into the 64 Searx configuration. 65 ''; 66 }; 67 68 settings = mkOption { 69 type = types.attrsOf settingType; 70 default = { }; 71 example = literalExample '' 72 { server.port = 8080; 73 server.bind_address = "0.0.0.0"; 74 server.secret_key = "@SEARX_SECRET_KEY@"; 75 76 engines = lib.singleton 77 { name = "wolframalpha"; 78 shortcut = "wa"; 79 api_key = "@WOLFRAM_API_KEY@"; 80 engine = "wolframalpha_api"; 81 }; 82 } 83 ''; 84 description = '' 85 Searx settings. These will be merged with (taking precedence over) 86 the default configuration. It's also possible to refer to 87 environment variables 88 (defined in <xref linkend="opt-services.searx.environmentFile"/>) 89 using the syntax <literal>@VARIABLE_NAME@</literal>. 90 <note> 91 <para> 92 For available settings, see the Searx 93 <link xlink:href="https://searx.github.io/searx/admin/settings.html">docs</link>. 94 </para> 95 </note> 96 ''; 97 }; 98 99 settingsFile = mkOption { 100 type = types.path; 101 default = "${runDir}/settings.yml"; 102 description = '' 103 The path of the Searx server settings.yml file. If no file is 104 specified, a default file is used (default config file has debug mode 105 enabled). Note: setting this options overrides 106 <xref linkend="opt-services.searx.settings"/>. 107 <warning> 108 <para> 109 This file, along with any secret key it contains, will be copied 110 into the world-readable Nix store. 111 </para> 112 </warning> 113 ''; 114 }; 115 116 package = mkOption { 117 type = types.package; 118 default = pkgs.searx; 119 defaultText = "pkgs.searx"; 120 description = "searx package to use."; 121 }; 122 123 runInUwsgi = mkOption { 124 type = types.bool; 125 default = false; 126 description = '' 127 Whether to run searx in uWSGI as a "vassal", instead of using its 128 built-in HTTP server. This is the recommended mode for public or 129 large instances, but is unecessary for LAN or local-only use. 130 <warning> 131 <para> 132 The built-in HTTP server logs all queries by default. 133 </para> 134 </warning> 135 ''; 136 }; 137 138 uwsgiConfig = mkOption { 139 type = options.services.uwsgi.instance.type; 140 default = { http = ":8080"; }; 141 example = literalExample '' 142 { 143 disable-logging = true; 144 http = ":8080"; # serve via HTTP... 145 socket = "/run/searx/searx.sock"; # ...or UNIX socket 146 } 147 ''; 148 description = '' 149 Additional configuration of the uWSGI vassal running searx. It 150 should notably specify on which interfaces and ports the vassal 151 should listen. 152 ''; 153 }; 154 155 }; 156 157 }; 158 159 160 ###### implementation 161 162 config = mkIf cfg.enable { 163 environment.systemPackages = [ cfg.package ]; 164 165 users.users.searx = 166 { description = "Searx daemon user"; 167 group = "searx"; 168 isSystemUser = true; 169 }; 170 171 users.groups.searx = { }; 172 173 systemd.services.searx-init = { 174 description = "Initialise Searx settings"; 175 serviceConfig = { 176 Type = "oneshot"; 177 RemainAfterExit = true; 178 User = "searx"; 179 RuntimeDirectory = "searx"; 180 RuntimeDirectoryMode = "750"; 181 } // optionalAttrs (cfg.environmentFile != null) 182 { EnvironmentFile = builtins.toPath cfg.environmentFile; }; 183 script = generateConfig; 184 }; 185 186 systemd.services.searx = mkIf (!cfg.runInUwsgi) { 187 description = "Searx server, the meta search engine."; 188 wantedBy = [ "network.target" "multi-user.target" ]; 189 requires = [ "searx-init.service" ]; 190 after = [ "searx-init.service" ]; 191 serviceConfig = { 192 User = "searx"; 193 Group = "searx"; 194 ExecStart = "${cfg.package}/bin/searx-run"; 195 } // optionalAttrs (cfg.environmentFile != null) 196 { EnvironmentFile = builtins.toPath cfg.environmentFile; }; 197 environment.SEARX_SETTINGS_PATH = cfg.settingsFile; 198 }; 199 200 systemd.services.uwsgi = mkIf (cfg.runInUwsgi) 201 { requires = [ "searx-init.service" ]; 202 after = [ "searx-init.service" ]; 203 }; 204 205 services.searx.settings = { 206 # merge NixOS settings with defaults settings.yml 207 use_default_settings = mkDefault true; 208 }; 209 210 services.uwsgi = mkIf (cfg.runInUwsgi) { 211 enable = true; 212 plugins = [ "python3" ]; 213 214 instance.type = "emperor"; 215 instance.vassals.searx = { 216 type = "normal"; 217 strict = true; 218 immediate-uid = "searx"; 219 immediate-gid = "searx"; 220 lazy-apps = true; 221 enable-threads = true; 222 module = "searx.webapp"; 223 env = [ "SEARX_SETTINGS_PATH=${cfg.settingsFile}" ]; 224 pythonPackages = self: [ cfg.package ]; 225 } // cfg.uwsgiConfig; 226 }; 227 228 }; 229 230 meta.maintainers = with maintainers; [ rnhmjoj ]; 231 232}