···15151616 settingsFile = pkgs.writeText "settings.yml" (builtins.toJSON cfg.settings);
17171818- limiterSettingsFile = (pkgs.formats.toml { }).generate "limiter.toml" cfg.limiterSettings;
1918 faviconsSettingsFile = (pkgs.formats.toml { }).generate "favicons.toml" cfg.faviconsSettings;
1919+ limiterSettingsFile = (pkgs.formats.toml { }).generate "limiter.toml" cfg.limiterSettings;
20202121 generateConfig = ''
2222 cd ${runDir}
···4646 // {
4747 description = "JSON value";
4848 };
4949-5049in
5151-5250{
5353-5454- imports = [
5555- (mkRenamedOptionModule [ "services" "searx" "configFile" ] [ "services" "searx" "settingsFile" ])
5656- ];
5757-5851 options = {
5952 services.searx = {
6053 enable = mkOption {
···6457 description = "Whether to enable Searx, the meta search engine.";
6558 };
66596060+ domain = mkOption {
6161+ type = types.str;
6262+ description = ''
6363+ The domain under which searxng will be served.
6464+ Right now this is only used with the configureNginx option.
6565+ '';
6666+ };
6767+6768 environmentFile = mkOption {
6869 type = types.nullOr types.path;
6970 default = null;
7071 description = ''
7171- Environment file (see {manpage}`systemd.exec(5)`
7272- "EnvironmentFile=" section for the syntax) to define variables for
7373- Searx. This option can be used to safely include secret keys into the
7474- Searx configuration.
7272+ Environment file (see {manpage}`systemd.exec(5)` "EnvironmentFile=" section for the syntax) to define variables for Searx.
7373+ This option can be used to safely include secret keys into the Searx configuration.
7574 '';
7675 };
7776···7978 type = types.bool;
8079 default = false;
8180 description = ''
8282- Configure a local Redis server for SearXNG. This is required if you
8383- want to enable the rate limiter and bot protection of SearXNG.
8181+ Configure a local Redis server for SearXNG.
8282+ This is required if you want to enable the rate limiter and bot protection of SearXNG.
8483 '';
8584 };
86858786 settings = mkOption {
8888- type = types.attrsOf settingType;
8787+ type = types.submodule {
8888+ freeformType = settingType;
8989+ imports = [
9090+ (mkRenamedOptionModule [ "redis" ] [ "valkey" ])
9191+ ];
9292+ };
8993 default = { };
9094 example = literalExpression ''
9191- { server.port = 8080;
9595+ {
9696+ server.port = 8080;
9297 server.bind_address = "0.0.0.0";
9398 server.secret_key = "@SEARX_SECRET_KEY@";
94999595- engines = lib.singleton
9696- { name = "wolframalpha";
9797- shortcut = "wa";
9898- api_key = "@WOLFRAM_API_KEY@";
9999- engine = "wolframalpha_api";
100100- };
100100+ engines = lib.singleton {
101101+ name = "wolframalpha";
102102+ shortcut = "wa";
103103+ api_key = "@WOLFRAM_API_KEY@";
104104+ engine = "wolframalpha_api";
105105+ };
101106 }
102107 '';
103108 description = ''
104104- Searx settings. These will be merged with (taking precedence over)
105105- the default configuration. It's also possible to refer to
106106- environment variables
107107- (defined in [](#opt-services.searx.environmentFile))
108108- using the syntax `@VARIABLE_NAME@`.
109109+ Searx settings.
110110+ These will be merged with (taking precedence over) the default configuration.
111111+ It's also possible to refer to environment variables (defined in [](#opt-services.searx.environmentFile)) using the syntax `@VARIABLE_NAME@`.
109112110113 ::: {.note}
111111- For available settings, see the Searx
112112- [docs](https://searx.github.io/searx/admin/settings.html).
114114+ For available settings, see the Searx [docs](https://docs.searxng.org/admin/settings/index.html).
113115 :::
114116 '';
115117 };
···118120 type = types.path;
119121 default = "${runDir}/settings.yml";
120122 description = ''
121121- The path of the Searx server settings.yml file. If no file is
122122- specified, a default file is used (default config file has debug mode
123123- enabled). Note: setting this options overrides
124124- [](#opt-services.searx.settings).
123123+ The path of the Searx server settings.yml file.
124124+ If no file is specified, a default file is used (default config file has debug mode enabled).
125125126126- ::: {.warning}
127127- This file, along with any secret key it contains, will be copied
128128- into the world-readable Nix store.
126126+ ::: {.note}
127127+ Setting this options overrides [](#opt-services.searx.settings).
129128 :::
130130- '';
131131- };
132129133133- limiterSettings = mkOption {
134134- type = types.attrsOf settingType;
135135- default = { };
136136- example = literalExpression ''
137137- {
138138- real_ip = {
139139- x_for = 1;
140140- ipv4_prefix = 32;
141141- ipv6_prefix = 56;
142142- }
143143- botdetection.ip_lists.block_ip = [
144144- # "93.184.216.34" # example.org
145145- ];
146146- }
147147- '';
148148- description = ''
149149- Limiter settings for SearXNG.
150150-151151- ::: {.note}
152152- For available settings, see the SearXNG
153153- [schema file](https://github.com/searxng/searxng/blob/master/searx/limiter.toml).
130130+ ::: {.warning}
131131+ This file, along with any secret key it contains, will be copied into the world-readable Nix store.
154132 :::
155133 '';
156134 };
···163141 favicons = {
164142 cfg_schema = 1;
165143 cache = {
166166- db_url = "/run/searx/faviconcache.db";
144144+ db_url = "/var/cache/searx/faviconcache.db";
167145 HOLD_TIME = 5184000;
168146 LIMIT_TOTAL_BYTES = 2147483648;
169147 BLOB_MAX_BYTES = 40960;
···183161 '';
184162 };
185163164164+ limiterSettings = mkOption {
165165+ type = types.attrsOf settingType;
166166+ default = { };
167167+ example = literalExpression ''
168168+ {
169169+ real_ip = {
170170+ x_for = 1;
171171+ ipv4_prefix = 32;
172172+ ipv6_prefix = 56;
173173+ }
174174+ botdetection.ip_lists.block_ip = [
175175+ # "93.184.216.34" # example.org
176176+ ];
177177+ }
178178+ '';
179179+ description = ''
180180+ Limiter settings for SearXNG.
181181+182182+ ::: {.note}
183183+ For available settings, see the SearXNG [schema file](https://github.com/searxng/searxng/blob/master/searx/limiter.toml).
184184+ :::
185185+ '';
186186+ };
187187+186188 package = mkPackageOption pkgs "searxng" { };
187189188188- runInUwsgi = mkOption {
190190+ configureUwsgi = mkOption {
189191 type = types.bool;
190192 default = false;
191193 description = ''
···199201 '';
200202 };
201203204204+ configureNginx = mkOption {
205205+ type = types.bool;
206206+ default = false;
207207+ description = ''
208208+ Whether to configure nginx as an frontend to uwsgi.
209209+ '';
210210+ };
211211+202212 uwsgiConfig = mkOption {
203203- type = options.services.uwsgi.instance.type;
213213+ inherit (options.services.uwsgi.instance) type;
204214 default = {
205215 http = ":8080";
206216 };
···218228 should listen.
219229 '';
220230 };
221221-222231 };
223223-224232 };
225233226226- config = mkIf cfg.enable {
227227- environment.systemPackages = [ cfg.package ];
234234+ imports = [
235235+ (mkRenamedOptionModule [ "services" "searx" "configFile" ] [ "services" "searx" "settingsFile" ])
236236+ (mkRenamedOptionModule [ "services" "searx" "runInUwsgi" ] [ "services" "searx" "configureUwsgi" ])
237237+ ];
228238229229- users.users.searx = {
230230- description = "Searx daemon user";
231231- group = "searx";
232232- isSystemUser = true;
239239+ config = mkIf cfg.enable {
240240+ environment = {
241241+ etc = {
242242+ "searxng/favicons.toml" = lib.mkIf (cfg.faviconsSettings != { }) {
243243+ source = faviconsSettingsFile;
244244+ };
245245+ "searxng/limiter.toml" = lib.mkIf (cfg.limiterSettings != { }) {
246246+ source = limiterSettingsFile;
247247+ };
248248+ };
249249+ systemPackages = [ cfg.package ];
233250 };
234251235235- users.groups.searx = { };
236236-237237- systemd.services.searx-init = {
238238- description = "Initialise Searx settings";
239239- serviceConfig =
240240- {
241241- Type = "oneshot";
242242- RemainAfterExit = true;
243243- User = "searx";
244244- RuntimeDirectory = "searx";
245245- RuntimeDirectoryMode = "750";
246246- }
247247- // optionalAttrs (cfg.environmentFile != null) {
248248- EnvironmentFile = builtins.toPath cfg.environmentFile;
252252+ services = {
253253+ nginx = lib.mkIf cfg.configureNginx {
254254+ enable = true;
255255+ virtualHosts."${cfg.domain}".locations = {
256256+ "/" = {
257257+ recommendedProxySettings = true;
258258+ recommendedUwsgiSettings = true;
259259+ uwsgiPass = "unix:${config.services.uwsgi.instance.vassals.searx.socket}";
260260+ extraConfig = # nginx
261261+ ''
262262+ uwsgi_param HTTP_HOST $host;
263263+ uwsgi_param HTTP_CONNECTION $http_connection;
264264+ uwsgi_param HTTP_X_SCHEME $scheme;
265265+ uwsgi_param HTTP_X_SCRIPT_NAME ""; # NOTE: When we ever make the path configurable, this must be set to anything not "/"!
266266+ uwsgi_param HTTP_X_REAL_IP $remote_addr;
267267+ uwsgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for;
268268+ '';
269269+ };
270270+ "/static/".alias = lib.mkDefault "${cfg.package}/share/static/";
249271 };
250250- script = generateConfig;
251251- };
272272+ };
273273+274274+ redis.servers.searx = lib.mkIf cfg.redisCreateLocally {
275275+ enable = true;
276276+ user = "searx";
277277+ port = 0;
278278+ };
252279253253- systemd.services.searx = mkIf (!cfg.runInUwsgi) {
254254- description = "Searx server, the meta search engine.";
255255- wantedBy = [ "multi-user.target" ];
256256- requires = [ "searx-init.service" ];
257257- after = [
258258- "searx-init.service"
259259- "network.target"
260260- ];
261261- serviceConfig =
262262- {
263263- User = "searx";
264264- Group = "searx";
265265- ExecStart = lib.getExe cfg.package;
266266- }
267267- // optionalAttrs (cfg.environmentFile != null) {
268268- EnvironmentFile = builtins.toPath cfg.environmentFile;
280280+ searx = {
281281+ configureUwsgi = lib.mkIf cfg.configureNginx true;
282282+ settings = {
283283+ # merge NixOS settings with defaults settings.yml
284284+ use_default_settings = mkDefault true;
285285+ server.base_url = lib.mkIf cfg.configureNginx "http${
286286+ lib.optionalString (lib.any lib.id (
287287+ with config.services.nginx.virtualHosts."${cfg.domain}";
288288+ [
289289+ onlySSL
290290+ addSSL
291291+ forceSSL
292292+ ]
293293+ )) "s"
294294+ }://${cfg.domain}/";
295295+ ui.static_use_hash = true;
296296+ valkey.url = lib.mkIf cfg.redisCreateLocally "unix://${config.services.redis.servers.searx.unixSocket}";
269297 };
270270- environment = {
271271- SEARX_SETTINGS_PATH = cfg.settingsFile;
272272- SEARXNG_SETTINGS_PATH = cfg.settingsFile;
273298 };
274274- };
275299276276- systemd.services.uwsgi = mkIf cfg.runInUwsgi {
277277- requires = [ "searx-init.service" ];
278278- after = [ "searx-init.service" ];
300300+ uwsgi = mkIf cfg.configureUwsgi {
301301+ enable = true;
302302+ plugins = [ "python3" ];
303303+ instance.type = "emperor";
304304+ instance.vassals.searx =
305305+ {
306306+ type = "normal";
307307+ strict = true;
308308+ immediate-uid = "searx";
309309+ immediate-gid = "searx";
310310+ lazy-apps = true;
311311+ enable-threads = true;
312312+ module = "searx.webapp";
313313+ env = [
314314+ "SEARXNG_SETTINGS_PATH=${cfg.settingsFile}"
315315+ ];
316316+ buffer-size = 32768;
317317+ pythonPackages = _: [ cfg.package ];
318318+ }
319319+ // lib.optionalAttrs cfg.configureNginx {
320320+ socket = "/run/searx/uwsgi.sock";
321321+ chmod-socket = "660";
322322+ }
323323+ // cfg.uwsgiConfig;
324324+ };
279325 };
280326281281- services.searx.settings = {
282282- # merge NixOS settings with defaults settings.yml
283283- use_default_settings = mkDefault true;
284284- redis.url = lib.mkIf cfg.redisCreateLocally "unix://${config.services.redis.servers.searx.unixSocket}";
285285- };
327327+ systemd.services = {
328328+ nginx = lib.mkIf cfg.configureNginx {
329329+ serviceConfig.SupplementaryGroups = [ "searx" ];
330330+ };
286331287287- services.uwsgi = mkIf cfg.runInUwsgi {
288288- enable = true;
289289- plugins = [ "python3" ];
332332+ searx-init = {
333333+ description = "Initialise Searx settings";
334334+ serviceConfig =
335335+ {
336336+ Type = "oneshot";
337337+ RemainAfterExit = true;
338338+ User = "searx";
339339+ RuntimeDirectory = "searx";
340340+ RuntimeDirectoryMode = "750";
341341+ RuntimeDirectoryPreserve = "yes";
342342+ }
343343+ // optionalAttrs (cfg.environmentFile != null) {
344344+ EnvironmentFile = cfg.environmentFile;
345345+ };
346346+ script = generateConfig;
347347+ };
290348291291- instance.type = "emperor";
292292- instance.vassals.searx = {
293293- type = "normal";
294294- strict = true;
295295- immediate-uid = "searx";
296296- immediate-gid = "searx";
297297- lazy-apps = true;
298298- enable-threads = true;
299299- module = "searx.webapp";
300300- env = [
301301- # TODO: drop this as it is only required for searx
302302- "SEARX_SETTINGS_PATH=${cfg.settingsFile}"
303303- # searxng compatibility https://github.com/searxng/searxng/issues/1519
304304- "SEARXNG_SETTINGS_PATH=${cfg.settingsFile}"
349349+ searx = mkIf (!cfg.configureUwsgi) {
350350+ description = "Searx server, the meta search engine.";
351351+ wantedBy = [ "multi-user.target" ];
352352+ requires = [ "searx-init.service" ];
353353+ after = [
354354+ "searx-init.service"
355355+ "network.target"
305356 ];
306306- buffer-size = 32768;
307307- pythonPackages = self: [ cfg.package ];
308308- } // cfg.uwsgiConfig;
309309- };
357357+ serviceConfig =
358358+ {
359359+ User = "searx";
360360+ Group = "searx";
361361+ ExecStart = lib.getExe cfg.package;
362362+ }
363363+ // optionalAttrs (cfg.environmentFile != null) {
364364+ EnvironmentFile = cfg.environmentFile;
365365+ };
366366+ environment = {
367367+ SEARXNG_SETTINGS_PATH = cfg.settingsFile;
368368+ };
369369+ };
310370311311- services.redis.servers.searx = lib.mkIf cfg.redisCreateLocally {
312312- enable = true;
313313- user = "searx";
314314- port = 0;
371371+ uwsgi = mkIf cfg.configureUwsgi {
372372+ requires = [ "searx-init.service" ];
373373+ after = [ "searx-init.service" ];
374374+ restartTriggers = [
375375+ cfg.package
376376+ cfg.settingsFile
377377+ ] ++ lib.optional (cfg.environmentFile != null) cfg.environmentFile;
378378+ };
315379 };
316380317317- environment.etc = {
318318- "searxng/limiter.toml" = lib.mkIf (cfg.limiterSettings != { }) {
319319- source = limiterSettingsFile;
320320- };
321321- "searxng/favicons.toml" = lib.mkIf (cfg.faviconsSettings != { }) {
322322- source = faviconsSettingsFile;
381381+ users = {
382382+ groups.searx = { };
383383+ users.searx = {
384384+ description = "Searx daemon user";
385385+ group = "searx";
386386+ isSystemUser = true;
323387 };
324388 };
325389 };
326390327391 meta.maintainers = with maintainers; [
328328- rnhmjoj
392392+ SuperSandro2000
329393 _999eagle
330394 ];
331395}
+9
nixos/modules/system/boot/systemd.nix
···832832 minsize = "1M";
833833 };
834834 };
835835+836836+ # run0 is supposed to authenticate the user via polkit and then run a command. Without this next
837837+ # part, run0 would fail to run the command even if authentication is successful and the user has
838838+ # permission to run the command. This next part is only enabled if polkit is enabled because the
839839+ # error that we’re trying to avoid can’t possibly happen if polkit isn’t enabled. When polkit isn’t
840840+ # enabled, run0 will fail before it even tries to run the command.
841841+ security.pam.services = mkIf config.security.polkit.enable {
842842+ systemd-run0 = { };
843843+ };
835844 };
836845837846 # FIXME: Remove these eventually.
···3636 checkFlags = [
3737 # Network errors for all of these tests
3838 # "error reading DNS system conf: No such file or directory (os error 2)" } }
3939- "--skip=archive::wayback::tests::wayback_suggestion"
4040- "--skip=archive::wayback::tests::wayback_suggestion_unknown_url"
3939+ "--skip=archive::wayback::tests::wayback_suggestion_real_unknown"
4140 "--skip=archive::wayback::tests::wayback_api_no_breaking_changes"
4241 "--skip=cli::test_dont_dump_data_uris_by_default"
4342 "--skip=cli::test_dump_data_uris_in_verbose_mode"
···2020 "12.5" = "12.5.1";
2121 "12.6" = "12.6.3";
2222 "12.8" = "12.8.1";
2323+ "12.9" = "12.9.1";
2324 };
24252526 # Check if the current CUDA version is supported.
···183183 self_attribute_name = "nix_2_24";
184184 };
185185186186- nix_2_26 = commonMeson {
187187- version = "2.26.4";
188188- hash = "sha256-WmGMiwwC9RLomNtpDeRoe5bqBAH84A6pLcqi1MbcQi4=";
189189- self_attribute_name = "nix_2_26";
190190- };
191191-192186 nix_2_28 = commonMeson {
193187 version = "2.28.4";
194188 hash = "sha256-V1tPrBkPteqF8VWUgpotNFYJ2Xm6WmB3aMPexuEHl9I=";
···271265 )
272266 // {
273267 nixComponents_2_27 = throw "nixComponents_2_27 has been removed. use nixComponents_git.";
268268+ nix_2_26 = throw "nix_2_26 has been removed. use nix_2_28.";
274269 nix_2_27 = throw "nix_2_27 has been removed. use nix_2_28.";
275270 nix_2_25 = throw "nix_2_25 has been removed. use nix_2_28.";
276271
+1
pkgs/top-level/aliases.nix
···17481748 rl_json = tclPackages.rl_json; # Added 2025-05-03
17491749 rockbox_utility = rockbox-utility; # Added 2022-03-17
17501750 rocmPackages_5 = throw "ROCm 5 has been removed in favor of newer versions"; # Added 2025-02-18
17511751+ root5 = throw "root5 has been removed from nixpkgs because it's a legacy version"; # Added 2025-07-17
17511752 rnix-hashes = throw "'rnix-hashes' has been removed due to lack of upstream maintenance"; # Added 2025-01-25
17521753 rpiboot-unstable = throw "'rpiboot-unstable' has been renamed to/replaced by 'rpiboot'"; # Converted to throw 2024-10-17
17531754 rr-unstable = rr; # Added 2022-09-17