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 "The Lounge web IRC client";
27
28 package = mkPackageOption pkgs "thelounge" { };
29
30 public = mkOption {
31 type = types.bool;
32 default = false;
33 description = ''
34 Make your The Lounge instance public.
35 Setting this to `false` will require you to configure user
36 accounts by using the ({command}`thelounge`) command or by adding
37 entries in {file}`${dataDir}/users`. You might need to restart
38 The Lounge after making changes to the state directory.
39 '';
40 };
41
42 port = mkOption {
43 type = types.port;
44 default = 9000;
45 description = "TCP port to listen on for http connections.";
46 };
47
48 extraConfig = mkOption {
49 default = { };
50 type = types.attrs;
51 example = literalExpression ''
52 {
53 reverseProxy = true;
54 defaults = {
55 name = "Your Network";
56 host = "localhost";
57 port = 6697;
58 };
59 }
60 '';
61 description = ''
62 The Lounge's {file}`config.js` contents as attribute set (will be
63 converted to JSON to generate the configuration file).
64
65 The options defined here will be merged to the default configuration file.
66 Note: In case of duplicate configuration, options from {option}`extraConfig` have priority.
67
68 Documentation: <https://thelounge.chat/docs/server/configuration>
69 '';
70 };
71
72 plugins = mkOption {
73 default = [ ];
74 type = types.listOf types.package;
75 example = literalExpression "[ pkgs.theLoungePlugins.themes.solarized ]";
76 description = ''
77 The Lounge plugins to install. Plugins can be found in
78 `pkgs.theLoungePlugins.plugins` and `pkgs.theLoungePlugins.themes`.
79 '';
80 };
81 };
82
83 config = mkIf cfg.enable {
84 users.users.thelounge = {
85 description = "The Lounge service user";
86 group = "thelounge";
87 isSystemUser = true;
88 };
89
90 users.groups.thelounge = { };
91
92 systemd.services.thelounge = {
93 description = "The Lounge web IRC client";
94 wantedBy = [ "multi-user.target" ];
95 preStart = "ln -sf ${pkgs.writeText "config.js" configJsData} ${dataDir}/config.js";
96 environment.THELOUNGE_PACKAGES = mkIf (cfg.plugins != [ ]) "${plugins}";
97 serviceConfig = {
98 User = "thelounge";
99 StateDirectory = baseNameOf dataDir;
100 ExecStart = "${getExe cfg.package} start";
101 };
102 };
103
104 environment.systemPackages = [ cfg.package ];
105 };
106
107 meta = {
108 maintainers = with lib.maintainers; [ winter ];
109 };
110}