···141141142142- `services.clamsmtp` is unmaintained and was removed from Nixpkgs.
143143144144+- `prosody` gained a config check option named `services.prosody.checkConfig` which runs `prosodyctl check config` and is turned on by default.
145145+144146- `services.dependency-track` removed its configuration of the JVM heap size. This lets the JVM choose its maximum heap size automatically, which should work much better in practice for most users. For deployments on systems with little RAM, it may now be necessary to manually configure a maximum heap size using {option}`services.dependency-track.javaArgs`.
145147146148- `services.dnscrypt-proxy2` gains a `package` option to specify dnscrypt-proxy package to use.
+340-353
nixos/modules/services/networking/prosody.nix
···99let
1010 cfg = config.services.prosody;
11111212- sslOpts =
1313- { ... }:
1414- {
1212+ sslOpts = _: {
1313+ options = {
1414+ key = mkOption {
1515+ type = types.path;
1616+ description = "Path to the key file.";
1717+ };
15181616- options = {
1919+ # TODO: rename to certificate to match the prosody config
2020+ cert = mkOption {
2121+ type = types.path;
2222+ description = "Path to the certificate file.";
2323+ };
17241818- key = mkOption {
1919- type = types.path;
2020- description = "Path to the key file.";
2121- };
2222-2323- # TODO: rename to certificate to match the prosody config
2424- cert = mkOption {
2525- type = types.path;
2626- description = "Path to the certificate file.";
2727- };
2828-2929- extraOptions = mkOption {
3030- type = types.attrs;
3131- default = { };
3232- description = "Extra SSL configuration options.";
3333- };
3434-2525+ extraOptions = mkOption {
2626+ type = types.attrs;
2727+ default = { };
2828+ description = "Extra SSL configuration options.";
3529 };
3630 };
3131+ };
37323833 discoOpts = {
3934 options = {
···301296 };
302297 '';
303298304304- mucOpts =
305305- { ... }:
306306- {
307307- options = {
308308- domain = mkOption {
309309- type = types.str;
310310- description = "Domain name of the MUC";
311311- };
312312- name = mkOption {
313313- type = types.str;
314314- description = "The name to return in service discovery responses for the MUC service itself";
315315- default = "Prosody Chatrooms";
316316- };
317317- restrictRoomCreation = mkOption {
318318- type = types.enum [
319319- true
320320- false
321321- "admin"
322322- "local"
323323- ];
324324- default = false;
325325- description = "Restrict room creation to server admins";
326326- };
327327- maxHistoryMessages = mkOption {
328328- type = types.int;
329329- default = 20;
330330- description = "Specifies a limit on what each room can be configured to keep";
331331- };
332332- roomLocking = mkOption {
333333- type = types.bool;
334334- default = true;
335335- description = ''
336336- Enables room locking, which means that a room must be
337337- configured before it can be used. Locked rooms are invisible
338338- and cannot be entered by anyone but the creator
339339- '';
340340- };
341341- roomLockTimeout = mkOption {
342342- type = types.int;
343343- default = 300;
344344- description = ''
345345- Timeout after which the room is destroyed or unlocked if not
346346- configured, in seconds
347347- '';
348348- };
349349- tombstones = mkOption {
350350- type = types.bool;
351351- default = true;
352352- description = ''
353353- When a room is destroyed, it leaves behind a tombstone which
354354- prevents the room being entered or recreated. It also allows
355355- anyone who was not in the room at the time it was destroyed
356356- to learn about it, and to update their bookmarks. Tombstones
357357- prevents the case where someone could recreate a previously
358358- semi-anonymous room in order to learn the real JIDs of those
359359- who often join there.
360360- '';
361361- };
362362- tombstoneExpiry = mkOption {
363363- type = types.int;
364364- default = 2678400;
365365- description = ''
366366- This settings controls how long a tombstone is considered
367367- valid. It defaults to 31 days. After this time, the room in
368368- question can be created again.
369369- '';
370370- };
371371- allowners_muc = mkOption {
372372- type = types.bool;
373373- default = false;
374374- description = ''
375375- Add module allowners, any user in chat is able to
376376- kick other. Usefull in jitsi-meet to kick ghosts.
377377- '';
378378- };
379379- vcard_muc = mkOption {
380380- type = types.bool;
381381- default = true;
382382- description = "Adds the ability to set vCard for Multi User Chat rooms";
383383- };
299299+ mucOpts = _: {
300300+ options = {
301301+ domain = mkOption {
302302+ type = types.str;
303303+ description = "Domain name of the MUC";
304304+ };
305305+ name = mkOption {
306306+ type = types.str;
307307+ description = "The name to return in service discovery responses for the MUC service itself";
308308+ default = "Prosody Chatrooms";
309309+ };
310310+ restrictRoomCreation = mkOption {
311311+ type = types.enum [
312312+ true
313313+ false
314314+ "admin"
315315+ "local"
316316+ ];
317317+ default = false;
318318+ description = "Restrict room creation to server admins";
319319+ };
320320+ maxHistoryMessages = mkOption {
321321+ type = types.int;
322322+ default = 20;
323323+ description = "Specifies a limit on what each room can be configured to keep";
324324+ };
325325+ roomLocking = mkOption {
326326+ type = types.bool;
327327+ default = true;
328328+ description = ''
329329+ Enables room locking, which means that a room must be
330330+ configured before it can be used. Locked rooms are invisible
331331+ and cannot be entered by anyone but the creator
332332+ '';
333333+ };
334334+ roomLockTimeout = mkOption {
335335+ type = types.int;
336336+ default = 300;
337337+ description = ''
338338+ Timeout after which the room is destroyed or unlocked if not
339339+ configured, in seconds
340340+ '';
341341+ };
342342+ tombstones = mkOption {
343343+ type = types.bool;
344344+ default = true;
345345+ description = ''
346346+ When a room is destroyed, it leaves behind a tombstone which
347347+ prevents the room being entered or recreated. It also allows
348348+ anyone who was not in the room at the time it was destroyed
349349+ to learn about it, and to update their bookmarks. Tombstones
350350+ prevents the case where someone could recreate a previously
351351+ semi-anonymous room in order to learn the real JIDs of those
352352+ who often join there.
353353+ '';
354354+ };
355355+ tombstoneExpiry = mkOption {
356356+ type = types.int;
357357+ default = 2678400;
358358+ description = ''
359359+ This settings controls how long a tombstone is considered
360360+ valid. It defaults to 31 days. After this time, the room in
361361+ question can be created again.
362362+ '';
363363+ };
364364+ allowners_muc = mkOption {
365365+ type = types.bool;
366366+ default = false;
367367+ description = ''
368368+ Add module allowners, any user in chat is able to
369369+ kick other. Useful in jitsi-meet to kick ghosts.
370370+ '';
371371+ };
372372+ vcard_muc = mkOption {
373373+ type = types.bool;
374374+ default = true;
375375+ description = "Adds the ability to set vCard for Multi User Chat rooms";
376376+ };
384377385385- # Extra parameters. Defaulting to prosody default values.
386386- # Adding them explicitly to make them visible from the options
387387- # documentation.
388388- #
389389- # See https://prosody.im/doc/modules/mod_muc for more details.
390390- roomDefaultPublic = mkOption {
391391- type = types.bool;
392392- default = true;
393393- description = "If set, the MUC rooms will be public by default.";
394394- };
395395- roomDefaultMembersOnly = mkOption {
396396- type = types.bool;
397397- default = false;
398398- description = "If set, the MUC rooms will only be accessible to the members by default.";
399399- };
400400- roomDefaultModerated = mkOption {
401401- type = types.bool;
402402- default = false;
403403- description = "If set, the MUC rooms will be moderated by default.";
404404- };
405405- roomDefaultPublicJids = mkOption {
406406- type = types.bool;
407407- default = false;
408408- description = "If set, the MUC rooms will display the public JIDs by default.";
409409- };
410410- roomDefaultChangeSubject = mkOption {
411411- type = types.bool;
412412- default = false;
413413- description = "If set, the rooms will display the public JIDs by default.";
414414- };
415415- roomDefaultHistoryLength = mkOption {
416416- type = types.int;
417417- default = 20;
418418- description = "Number of history message sent to participants by default.";
419419- };
420420- roomDefaultLanguage = mkOption {
421421- type = types.str;
422422- default = "en";
423423- description = "Default room language.";
424424- };
425425- extraConfig = mkOption {
426426- type = types.lines;
427427- default = "";
428428- description = "Additional MUC specific configuration";
429429- };
378378+ # Extra parameters. Defaulting to prosody default values.
379379+ # Adding them explicitly to make them visible from the options
380380+ # documentation.
381381+ #
382382+ # See https://prosody.im/doc/modules/mod_muc for more details.
383383+ roomDefaultPublic = mkOption {
384384+ type = types.bool;
385385+ default = true;
386386+ description = "If set, the MUC rooms will be public by default.";
387387+ };
388388+ roomDefaultMembersOnly = mkOption {
389389+ type = types.bool;
390390+ default = false;
391391+ description = "If set, the MUC rooms will only be accessible to the members by default.";
392392+ };
393393+ roomDefaultModerated = mkOption {
394394+ type = types.bool;
395395+ default = false;
396396+ description = "If set, the MUC rooms will be moderated by default.";
397397+ };
398398+ roomDefaultPublicJids = mkOption {
399399+ type = types.bool;
400400+ default = false;
401401+ description = "If set, the MUC rooms will display the public JIDs by default.";
402402+ };
403403+ roomDefaultChangeSubject = mkOption {
404404+ type = types.bool;
405405+ default = false;
406406+ description = "If set, the rooms will display the public JIDs by default.";
407407+ };
408408+ roomDefaultHistoryLength = mkOption {
409409+ type = types.int;
410410+ default = 20;
411411+ description = "Number of history message sent to participants by default.";
412412+ };
413413+ roomDefaultLanguage = mkOption {
414414+ type = types.str;
415415+ default = "en";
416416+ description = "Default room language.";
417417+ };
418418+ extraConfig = mkOption {
419419+ type = types.lines;
420420+ default = "";
421421+ description = "Additional MUC specific configuration";
430422 };
431423 };
424424+ };
432425433433- uploadHttpOpts =
434434- { ... }:
435435- {
436436- options = {
437437- domain = mkOption {
438438- type = types.nullOr types.str;
439439- description = "Domain name for the http-upload service";
440440- };
441441- uploadFileSizeLimit = mkOption {
442442- type = types.str;
443443- default = "50 * 1024 * 1024";
444444- description = "Maximum file size, in bytes. Defaults to 50MB.";
445445- };
446446- uploadExpireAfter = mkOption {
447447- type = types.str;
448448- default = "60 * 60 * 24 * 7";
449449- description = "Max age of a file before it gets deleted, in seconds.";
450450- };
451451- userQuota = mkOption {
452452- type = types.nullOr types.int;
453453- default = null;
454454- example = 1234;
455455- description = ''
456456- Maximum size of all uploaded files per user, in bytes. There
457457- will be no quota if this option is set to null.
458458- '';
459459- };
460460- httpUploadPath = mkOption {
461461- type = types.str;
462462- description = ''
463463- Directory where the uploaded files will be stored when the http_upload module is used.
464464- By default, uploaded files are put in a sub-directory of the default Prosody storage path (usually /var/lib/prosody).
465465- '';
466466- default = "/var/lib/prosody";
467467- };
426426+ uploadHttpOpts = _: {
427427+ options = {
428428+ domain = mkOption {
429429+ type = types.nullOr types.str;
430430+ description = "Domain name for the http-upload service";
431431+ };
432432+ uploadFileSizeLimit = mkOption {
433433+ type = types.str;
434434+ default = "50 * 1024 * 1024";
435435+ description = "Maximum file size, in bytes. Defaults to 50MB.";
436436+ };
437437+ uploadExpireAfter = mkOption {
438438+ type = types.str;
439439+ default = "60 * 60 * 24 * 7";
440440+ description = "Max age of a file before it gets deleted, in seconds.";
441441+ };
442442+ userQuota = mkOption {
443443+ type = types.nullOr types.int;
444444+ default = null;
445445+ example = 1234;
446446+ description = ''
447447+ Maximum size of all uploaded files per user, in bytes. There
448448+ will be no quota if this option is set to null.
449449+ '';
450450+ };
451451+ httpUploadPath = mkOption {
452452+ type = types.str;
453453+ description = ''
454454+ Directory where the uploaded files will be stored when the http_upload module is used.
455455+ By default, uploaded files are put in a sub-directory of the default Prosody storage path (usually /var/lib/prosody).
456456+ '';
457457+ default = "/var/lib/prosody";
468458 };
469459 };
460460+ };
470461471471- httpFileShareOpts =
472472- { ... }:
473473- {
474474- freeformType =
475475- with types;
476476- let
477477- atom = oneOf [
478478- int
479479- bool
480480- str
481481- (listOf atom)
482482- ];
483483- in
484484- attrsOf (nullOr atom)
485485- // {
486486- description = "int, bool, string or list of them";
487487- };
488488- options.domain = mkOption {
489489- type = with types; nullOr str;
490490- description = "Domain name for a http_file_share service.";
462462+ httpFileShareOpts = _: {
463463+ freeformType =
464464+ with types;
465465+ let
466466+ atom = oneOf [
467467+ int
468468+ bool
469469+ str
470470+ (listOf atom)
471471+ ];
472472+ in
473473+ attrsOf (nullOr atom)
474474+ // {
475475+ description = "int, bool, string or list of them";
491476 };
477477+ options.domain = mkOption {
478478+ type = with types; nullOr str;
479479+ description = "Domain name for a http_file_share service.";
492480 };
481481+ };
493482494494- vHostOpts =
495495- { ... }:
496496- {
483483+ vHostOpts = _: {
484484+ options = {
485485+ # TODO: require attribute
486486+ domain = mkOption {
487487+ type = types.str;
488488+ description = "Domain name";
489489+ };
490490+491491+ enabled = mkOption {
492492+ type = types.bool;
493493+ default = false;
494494+ description = "Whether to enable the virtual host";
495495+ };
496496+497497+ ssl = mkOption {
498498+ type = types.nullOr (types.submodule sslOpts);
499499+ default = null;
500500+ description = "Paths to SSL files";
501501+ };
497502498498- options = {
503503+ extraConfig = mkOption {
504504+ type = types.lines;
505505+ default = "";
506506+ description = "Additional virtual host specific configuration";
507507+ };
508508+ };
509509+ };
499510500500- # TODO: require attribute
501501- domain = mkOption {
502502- type = types.str;
503503- description = "Domain name";
511511+ configFile =
512512+ let
513513+ httpDiscoItems =
514514+ optional (cfg.uploadHttp != null) {
515515+ url = cfg.uploadHttp.domain;
516516+ description = "HTTP upload endpoint";
517517+ }
518518+ ++ optional (cfg.httpFileShare != null) {
519519+ url = cfg.httpFileShare.domain;
520520+ description = "HTTP file share endpoint";
504521 };
522522+ mucDiscoItems = builtins.foldl' (
523523+ acc: muc:
524524+ [
525525+ {
526526+ url = muc.domain;
527527+ description = "${muc.domain} MUC endpoint";
528528+ }
529529+ ]
530530+ ++ acc
531531+ ) [ ] cfg.muc;
532532+ discoItems = cfg.disco_items ++ httpDiscoItems ++ mucDiscoItems;
533533+ in
534534+ pkgs.writeText "prosody.cfg.lua" ''
535535+ pidfile = "/run/prosody/prosody.pid"
536536+537537+ log = ${cfg.log}
538538+539539+ data_path = "${cfg.dataDir}"
540540+ plugin_paths = {
541541+ ${lib.concatStringsSep ", " (map (n: "\"${n}\"") cfg.extraPluginPaths)}
542542+ }
505543506506- enabled = mkOption {
507507- type = types.bool;
508508- default = false;
509509- description = "Whether to enable the virtual host";
510510- };
544544+ ${optionalString (cfg.ssl != null) (createSSLOptsStr cfg.ssl)}
511545512512- ssl = mkOption {
513513- type = types.nullOr (types.submodule sslOpts);
514514- default = null;
515515- description = "Paths to SSL files";
516516- };
546546+ admins = ${toLua cfg.admins}
517547518518- extraConfig = mkOption {
519519- type = types.lines;
520520- default = "";
521521- description = "Additional virtual host specific configuration";
522522- };
548548+ modules_enabled = {
523549550550+ ${lib.concatStringsSep "\n " (
551551+ lib.mapAttrsToList (name: val: optionalString val "${toLua name};") cfg.modules
552552+ )}
553553+ ${lib.concatStringsSep "\n" (map (x: "${toLua x};") cfg.package.communityModules)}
554554+ ${lib.concatStringsSep "\n" (map (x: "${toLua x};") cfg.extraModules)}
524555 };
525556526526- };
557557+ disco_items = {
558558+ ${lib.concatStringsSep "\n" (builtins.map (x: ''{ "${x.url}", "${x.description}"};'') discoItems)}
559559+ };
527560528528-in
561561+ allow_registration = ${toLua cfg.allowRegistration}
529562530530-{
563563+ c2s_require_encryption = ${toLua cfg.c2sRequireEncryption}
531564532532- ###### interface
565565+ s2s_require_encryption = ${toLua cfg.s2sRequireEncryption}
566566+ s2s_secure_auth = ${toLua cfg.s2sSecureAuth}
567567+ s2s_insecure_domains = ${toLua cfg.s2sInsecureDomains}
568568+ s2s_secure_domains = ${toLua cfg.s2sSecureDomains}
533569534534- options = {
570570+ authentication = ${toLua cfg.authentication}
571571+572572+ http_interfaces = ${toLua cfg.httpInterfaces}
573573+ https_interfaces = ${toLua cfg.httpsInterfaces}
574574+575575+ http_ports = ${toLua cfg.httpPorts}
576576+ https_ports = ${toLua cfg.httpsPorts}
535577536536- services.prosody = {
578578+ ${cfg.extraConfig}
537579580580+ ${lib.concatMapStrings (muc: ''
581581+ Component ${toLua muc.domain} "muc"
582582+ modules_enabled = { "muc_mam"; ${optionalString muc.vcard_muc ''"vcard_muc";''} ${optionalString muc.allowners_muc ''"muc_allowners";''} }
583583+ name = ${toLua muc.name}
584584+ restrict_room_creation = ${toLua muc.restrictRoomCreation}
585585+ max_history_messages = ${toLua muc.maxHistoryMessages}
586586+ muc_room_locking = ${toLua muc.roomLocking}
587587+ muc_room_lock_timeout = ${toLua muc.roomLockTimeout}
588588+ muc_tombstones = ${toLua muc.tombstones}
589589+ muc_tombstone_expiry = ${toLua muc.tombstoneExpiry}
590590+ muc_room_default_public = ${toLua muc.roomDefaultPublic}
591591+ muc_room_default_members_only = ${toLua muc.roomDefaultMembersOnly}
592592+ muc_room_default_moderated = ${toLua muc.roomDefaultModerated}
593593+ muc_room_default_public_jids = ${toLua muc.roomDefaultPublicJids}
594594+ muc_room_default_change_subject = ${toLua muc.roomDefaultChangeSubject}
595595+ muc_room_default_history_length = ${toLua muc.roomDefaultHistoryLength}
596596+ muc_room_default_language = ${toLua muc.roomDefaultLanguage}
597597+ ${muc.extraConfig}
598598+ '') cfg.muc}
599599+600600+ ${lib.optionalString (cfg.uploadHttp != null) ''
601601+ Component ${toLua cfg.uploadHttp.domain} "http_upload"
602602+ http_upload_file_size_limit = ${cfg.uploadHttp.uploadFileSizeLimit}
603603+ http_upload_expire_after = ${cfg.uploadHttp.uploadExpireAfter}
604604+ ${lib.optionalString (
605605+ cfg.uploadHttp.userQuota != null
606606+ ) "http_upload_quota = ${toLua cfg.uploadHttp.userQuota}"}
607607+ http_upload_path = ${toLua cfg.uploadHttp.httpUploadPath}
608608+ ''}
609609+610610+ ${lib.optionalString (cfg.httpFileShare != null) ''
611611+ Component ${toLua cfg.httpFileShare.domain} "http_file_share"
612612+ ${settingsToLua " http_file_share_" (cfg.httpFileShare // { domain = null; })}
613613+ ''}
614614+615615+ ${lib.concatStringsSep "\n" (
616616+ lib.mapAttrsToList (n: v: ''
617617+ VirtualHost "${v.domain}"
618618+ enabled = ${boolToString v.enabled};
619619+ ${optionalString (v.ssl != null) (createSSLOptsStr v.ssl)}
620620+ ${v.extraConfig}
621621+ '') cfg.virtualHosts
622622+ )}
623623+ '';
624624+625625+in
626626+{
627627+ options = {
628628+ services.prosody = {
538629 enable = mkOption {
539630 type = types.bool;
540631 default = false;
541632 description = "Whether to enable the prosody server";
633633+ };
634634+635635+ checkConfig = mkOption {
636636+ type = types.bool;
637637+ default = true;
638638+ example = false;
639639+ description = "Check the configuration file with `prosodyctl check config`";
542640 };
543641544642 xmppComplianceSuite = mkOption {
···818916 }
819917 '';
820918 };
821821-822919 };
823920 };
824921825825- ###### implementation
826826-827922 config = mkIf cfg.enable {
828828-829923 assertions =
830924 let
831925 genericErrMsg = ''
···860954861955 environment.systemPackages = [ cfg.package ];
862956863863- environment.etc."prosody/prosody.cfg.lua".text =
864864- let
865865- httpDiscoItems =
866866- optional (cfg.uploadHttp != null) {
867867- url = cfg.uploadHttp.domain;
868868- description = "HTTP upload endpoint";
957957+ environment.etc."prosody/prosody.cfg.lua".source =
958958+ if cfg.checkConfig then
959959+ pkgs.runCommandLocal "prosody.cfg.lua-checked"
960960+ {
961961+ nativeBuildInputs = [ cfg.package ];
869962 }
870870- ++ optional (cfg.httpFileShare != null) {
871871- url = cfg.httpFileShare.domain;
872872- description = "HTTP file share endpoint";
873873- };
874874- mucDiscoItems = builtins.foldl' (
875875- acc: muc:
876876- [
877877- {
878878- url = muc.domain;
879879- description = "${muc.domain} MUC endpoint";
880880- }
881881- ]
882882- ++ acc
883883- ) [ ] cfg.muc;
884884- discoItems = cfg.disco_items ++ httpDiscoItems ++ mucDiscoItems;
885885- in
886886- ''
887887-888888- pidfile = "/run/prosody/prosody.pid"
889889-890890- log = ${cfg.log}
891891-892892- data_path = "${cfg.dataDir}"
893893- plugin_paths = {
894894- ${lib.concatStringsSep ", " (map (n: "\"${n}\"") cfg.extraPluginPaths)}
895895- }
896896-897897- ${optionalString (cfg.ssl != null) (createSSLOptsStr cfg.ssl)}
898898-899899- admins = ${toLua cfg.admins}
900900-901901- modules_enabled = {
902902-903903- ${lib.concatStringsSep "\n " (
904904- lib.mapAttrsToList (name: val: optionalString val "${toLua name};") cfg.modules
905905- )}
906906- ${lib.concatStringsSep "\n" (map (x: "${toLua x};") cfg.package.communityModules)}
907907- ${lib.concatStringsSep "\n" (map (x: "${toLua x};") cfg.extraModules)}
908908- };
909909-910910- disco_items = {
911911- ${lib.concatStringsSep "\n" (builtins.map (x: ''{ "${x.url}", "${x.description}"};'') discoItems)}
912912- };
913913-914914- allow_registration = ${toLua cfg.allowRegistration}
915915-916916- c2s_require_encryption = ${toLua cfg.c2sRequireEncryption}
917917-918918- s2s_require_encryption = ${toLua cfg.s2sRequireEncryption}
919919-920920- s2s_secure_auth = ${toLua cfg.s2sSecureAuth}
921921-922922- s2s_insecure_domains = ${toLua cfg.s2sInsecureDomains}
923923-924924- s2s_secure_domains = ${toLua cfg.s2sSecureDomains}
925925-926926- authentication = ${toLua cfg.authentication}
927927-928928- http_interfaces = ${toLua cfg.httpInterfaces}
929929-930930- https_interfaces = ${toLua cfg.httpsInterfaces}
931931-932932- http_ports = ${toLua cfg.httpPorts}
933933-934934- https_ports = ${toLua cfg.httpsPorts}
935935-936936- ${cfg.extraConfig}
937937-938938- ${lib.concatMapStrings (muc: ''
939939- Component ${toLua muc.domain} "muc"
940940- modules_enabled = { "muc_mam"; ${optionalString muc.vcard_muc ''"vcard_muc";''} ${optionalString muc.allowners_muc ''"muc_allowners";''} }
941941- name = ${toLua muc.name}
942942- restrict_room_creation = ${toLua muc.restrictRoomCreation}
943943- max_history_messages = ${toLua muc.maxHistoryMessages}
944944- muc_room_locking = ${toLua muc.roomLocking}
945945- muc_room_lock_timeout = ${toLua muc.roomLockTimeout}
946946- muc_tombstones = ${toLua muc.tombstones}
947947- muc_tombstone_expiry = ${toLua muc.tombstoneExpiry}
948948- muc_room_default_public = ${toLua muc.roomDefaultPublic}
949949- muc_room_default_members_only = ${toLua muc.roomDefaultMembersOnly}
950950- muc_room_default_moderated = ${toLua muc.roomDefaultModerated}
951951- muc_room_default_public_jids = ${toLua muc.roomDefaultPublicJids}
952952- muc_room_default_change_subject = ${toLua muc.roomDefaultChangeSubject}
953953- muc_room_default_history_length = ${toLua muc.roomDefaultHistoryLength}
954954- muc_room_default_language = ${toLua muc.roomDefaultLanguage}
955955- ${muc.extraConfig}
956956- '') cfg.muc}
957957-958958- ${lib.optionalString (cfg.uploadHttp != null) ''
959959- Component ${toLua cfg.uploadHttp.domain} "http_upload"
960960- http_upload_file_size_limit = ${cfg.uploadHttp.uploadFileSizeLimit}
961961- http_upload_expire_after = ${cfg.uploadHttp.uploadExpireAfter}
962962- ${lib.optionalString (
963963- cfg.uploadHttp.userQuota != null
964964- ) "http_upload_quota = ${toLua cfg.uploadHttp.userQuota}"}
965965- http_upload_path = ${toLua cfg.uploadHttp.httpUploadPath}
966966- ''}
967967-968968- ${lib.optionalString (cfg.httpFileShare != null) ''
969969- Component ${toLua cfg.httpFileShare.domain} "http_file_share"
970970- ${settingsToLua " http_file_share_" (cfg.httpFileShare // { domain = null; })}
971971- ''}
972972-973973- ${lib.concatStringsSep "\n" (
974974- lib.mapAttrsToList (n: v: ''
975975- VirtualHost "${v.domain}"
976976- enabled = ${boolToString v.enabled};
977977- ${optionalString (v.ssl != null) (createSSLOptsStr v.ssl)}
978978- ${v.extraConfig}
979979- '') cfg.virtualHosts
980980- )}
981981- '';
963963+ ''
964964+ cp ${configFile} prosody.cfg.lua
965965+ prosodyctl --config ./prosody.cfg.lua check config
966966+ touch $out
967967+ ''
968968+ else
969969+ configFile;
982970983971 users.users.prosody = mkIf (cfg.user == "prosody") {
984972 uid = config.ids.uids.prosody;
···10251013 })
10261014 ];
10271015 };
10281028-10291016 };
1030101710311018 meta.doc = ./prosody.md;