1{ pkgs, lib, config, ... }:
2
3with lib;
4
5let
6 cfg = config.services.thelounge;
7 dataDir = "/var/lib/thelounge";
8 configJsData = "module.exports = " + builtins.toJSON (
9 { inherit (cfg) public port; } // cfg.extraConfig
10 );
11 pluginManifest = {
12 dependencies = builtins.listToAttrs (builtins.map (pkg: { name = getName pkg; value = getVersion pkg; }) cfg.plugins);
13 };
14 plugins = pkgs.runCommandLocal "thelounge-plugins" { } ''
15 mkdir -p $out/node_modules
16 echo ${escapeShellArg (builtins.toJSON pluginManifest)} >> $out/package.json
17 ${concatMapStringsSep "\n" (pkg: ''
18 ln -s ${pkg}/lib/node_modules/${getName pkg} $out/node_modules/${getName pkg}
19 '') cfg.plugins}
20 '';
21in
22{
23 imports = [ (mkRemovedOptionModule [ "services" "thelounge" "private" ] "The option was renamed to `services.thelounge.public` to follow upstream changes.") ];
24
25 options.services.thelounge = {
26 enable = mkEnableOption (lib.mdDoc "The Lounge web IRC client");
27
28 public = mkOption {
29 type = types.bool;
30 default = false;
31 description = lib.mdDoc ''
32 Make your The Lounge instance public.
33 Setting this to `false` will require you to configure user
34 accounts by using the ({command}`thelounge`) command or by adding
35 entries in {file}`${dataDir}/users`. You might need to restart
36 The Lounge after making changes to the state directory.
37 '';
38 };
39
40 port = mkOption {
41 type = types.port;
42 default = 9000;
43 description = lib.mdDoc "TCP port to listen on for http connections.";
44 };
45
46 extraConfig = mkOption {
47 default = { };
48 type = types.attrs;
49 example = literalExpression ''{
50 reverseProxy = true;
51 defaults = {
52 name = "Your Network";
53 host = "localhost";
54 port = 6697;
55 };
56 }'';
57 description = lib.mdDoc ''
58 The Lounge's {file}`config.js` contents as attribute set (will be
59 converted to JSON to generate the configuration file).
60
61 The options defined here will be merged to the default configuration file.
62 Note: In case of duplicate configuration, options from {option}`extraConfig` have priority.
63
64 Documentation: <https://thelounge.chat/docs/server/configuration>
65 '';
66 };
67
68 plugins = mkOption {
69 default = [ ];
70 type = types.listOf types.package;
71 example = literalExpression "[ pkgs.theLoungePlugins.themes.solarized ]";
72 description = lib.mdDoc ''
73 The Lounge plugins to install. Plugins can be found in
74 `pkgs.theLoungePlugins.plugins` and `pkgs.theLoungePlugins.themes`.
75 '';
76 };
77 };
78
79 config = mkIf cfg.enable {
80 users.users.thelounge = {
81 description = "The Lounge service user";
82 group = "thelounge";
83 isSystemUser = true;
84 };
85
86 users.groups.thelounge = { };
87
88 systemd.services.thelounge = {
89 description = "The Lounge web IRC client";
90 wantedBy = [ "multi-user.target" ];
91 preStart = "ln -sf ${pkgs.writeText "config.js" configJsData} ${dataDir}/config.js";
92 environment.THELOUNGE_PACKAGES = mkIf (cfg.plugins != [ ]) "${plugins}";
93 serviceConfig = {
94 User = "thelounge";
95 StateDirectory = baseNameOf dataDir;
96 ExecStart = "${pkgs.thelounge}/bin/thelounge start";
97 };
98 };
99
100 environment.systemPackages = [ pkgs.thelounge ];
101 };
102
103 meta = {
104 maintainers = with lib.maintainers; [ winter ];
105 };
106}