1{ config, lib, options, pkgs, ... }: let
2 cfg = config.services.ergochat;
3in {
4 options = {
5 services.ergochat = {
6
7 enable = lib.mkEnableOption (lib.mdDoc "Ergo IRC daemon");
8
9 openFilesLimit = lib.mkOption {
10 type = lib.types.int;
11 default = 1024;
12 description = lib.mdDoc ''
13 Maximum number of open files. Limits the clients and server connections.
14 '';
15 };
16
17 configFile = lib.mkOption {
18 type = lib.types.path;
19 default = (pkgs.formats.yaml {}).generate "ergo.conf" cfg.settings;
20 defaultText = lib.literalMD "generated config file from `settings`";
21 description = lib.mdDoc ''
22 Path to configuration file.
23 Setting this will skip any configuration done via `settings`
24 '';
25 };
26
27 settings = lib.mkOption {
28 type = (pkgs.formats.yaml {}).type;
29 description = lib.mdDoc ''
30 Ergo IRC daemon configuration file.
31 https://raw.githubusercontent.com/ergochat/ergo/master/default.yaml
32 '';
33 default = {
34 network = {
35 name = "testnetwork";
36 };
37 server = {
38 name = "example.com";
39 listeners = {
40 ":6667" = {};
41 };
42 casemapping = "permissive";
43 enforce-utf = true;
44 lookup-hostnames = false;
45 ip-cloaking = {
46 enabled = false;
47 };
48 forward-confirm-hostnames = false;
49 check-ident = false;
50 relaymsg = {
51 enabled = false;
52 };
53 max-sendq = "1M";
54 ip-limits = {
55 count = false;
56 throttle = false;
57 };
58 };
59 datastore = {
60 autoupgrade = true;
61 # this points to the StateDirectory of the systemd service
62 path = "/var/lib/ergo/ircd.db";
63 };
64 accounts = {
65 authentication-enabled = true;
66 registration = {
67 enabled = true;
68 allow-before-connect = true;
69 throttling = {
70 enabled = true;
71 duration = "10m";
72 max-attempts = 30;
73 };
74 bcrypt-cost = 4;
75 email-verification.enabled = false;
76 };
77 multiclient = {
78 enabled = true;
79 allowed-by-default = true;
80 always-on = "opt-out";
81 auto-away = "opt-out";
82 };
83 };
84 channels = {
85 default-modes = "+ntC";
86 registration = {
87 enabled = true;
88 };
89 };
90 limits = {
91 nicklen = 32;
92 identlen = 20;
93 channellen = 64;
94 awaylen = 390;
95 kicklen = 390;
96 topiclen = 390;
97 };
98 history = {
99 enabled = true;
100 channel-length = 2048;
101 client-length = 256;
102 autoresize-window = "3d";
103 autoreplay-on-join = 0;
104 chathistory-maxmessages = 100;
105 znc-maxmessages = 2048;
106 restrictions = {
107 expire-time = "1w";
108 query-cutoff = "none";
109 grace-period = "1h";
110 };
111 retention = {
112 allow-individual-delete = false;
113 enable-account-indexing = false;
114 };
115 tagmsg-storage = {
116 default = false;
117 whitelist = [
118 "+draft/react"
119 "+react"
120 ];
121 };
122 };
123 };
124 };
125
126 };
127 };
128 config = lib.mkIf cfg.enable {
129
130 environment.etc."ergo.yaml".source = cfg.configFile;
131
132 # merge configured values with default values
133 services.ergochat.settings =
134 lib.mapAttrsRecursive (_: lib.mkDefault) options.services.ergochat.settings.default;
135
136 systemd.services.ergochat = {
137 description = "Ergo IRC daemon";
138 wantedBy = [ "multi-user.target" ];
139 # reload is not applying the changed config. further investigation is needed
140 # at some point this should be enabled, since we don't want to restart for
141 # every config change
142 # reloadIfChanged = true;
143 restartTriggers = [ cfg.configFile ];
144 serviceConfig = {
145 ExecStart = "${pkgs.ergochat}/bin/ergo run --conf /etc/ergo.yaml";
146 ExecReload = "${pkgs.util-linux}/bin/kill -HUP $MAINPID";
147 DynamicUser = true;
148 StateDirectory = "ergo";
149 LimitNOFILE = toString cfg.openFilesLimit;
150 };
151 };
152
153 };
154 meta.maintainers = with lib.maintainers; [ lassulus tv ];
155}