1let
2 cert =
3 pkgs:
4 pkgs.runCommand "selfSignedCerts" { buildInputs = [ pkgs.openssl ]; } ''
5 openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -nodes -subj '/CN=example.com/CN=muc.example.com/CN=matrix.example.com' -addext "subjectAltName = DNS:example.com,DNS:muc.example.com,DNS:matrix.example.com" -days 36500
6 mkdir -p $out
7 cp key.pem cert.pem $out
8 '';
9in
10{ pkgs, ... }:
11{
12 name = "ejabberd";
13 meta = with pkgs.lib.maintainers; {
14 maintainers = [ ];
15 };
16 nodes = {
17 client-a =
18 { nodes, pkgs, ... }:
19 {
20 security.pki.certificateFiles = [ "${cert pkgs}/cert.pem" ];
21 networking.extraHosts = ''
22 ${nodes.server.networking.primaryIPAddress} example.com
23 '';
24
25 imports = [ ./go-sendxmpp-listen.nix ];
26 };
27
28 client-b =
29 { nodes, pkgs, ... }:
30 {
31 security.pki.certificateFiles = [ "${cert pkgs}/cert.pem" ];
32 networking.extraHosts = ''
33 ${nodes.server.networking.primaryIPAddress} example.com
34 '';
35
36 environment.systemPackages = [
37 (pkgs.callPackage ./xmpp-sendmessage.nix {
38 connectTo = nodes.server.networking.primaryIPAddress;
39 })
40 ];
41 };
42
43 server =
44 { config, pkgs, ... }:
45 {
46 security.pki.certificateFiles = [ "${cert pkgs}/cert.pem" ];
47 networking.extraHosts = ''
48 ${config.networking.primaryIPAddress} example.com
49 ${config.networking.primaryIPAddress} matrix.example.com
50 '';
51
52 services.ejabberd = {
53 enable = true;
54 configFile = "/etc/ejabberd.yml";
55 };
56
57 systemd.services.ejabberd.serviceConfig.TimeoutStartSec = "15min";
58 environment.etc."ejabberd.yml" = {
59 user = "ejabberd";
60 mode = "0600";
61 text = ''
62 loglevel: 3
63
64 hosts:
65 - "example.com"
66
67 listen:
68 -
69 port: 5222
70 module: ejabberd_c2s
71 zlib: false
72 max_stanza_size: 65536
73 shaper: c2s_shaper
74 access: c2s
75 starttls: true
76 -
77 port: 5269
78 ip: "::"
79 module: ejabberd_s2s_in
80 -
81 port: 8448
82 module: ejabberd_http
83 tls: true
84 request_handlers:
85 "/_matrix": mod_matrix_gw
86 -
87 port: 5347
88 ip: "127.0.0.1"
89 module: ejabberd_service
90 access: local
91 shaper: fast
92 -
93 port: 5444
94 module: ejabberd_http
95 request_handlers:
96 "/upload": mod_http_upload
97
98 certfiles:
99 - ${cert pkgs}/key.pem
100 - ${cert pkgs}/cert.pem
101
102 ## Disabling digest-md5 SASL authentication. digest-md5 requires plain-text
103 ## password storage (see auth_password_format option).
104 disable_sasl_mechanisms: "digest-md5"
105
106 ## Outgoing S2S options
107 ## Preferred address families (which to try first) and connect timeout
108 ## in seconds.
109 outgoing_s2s_families:
110 - ipv4
111 - ipv6
112
113 ## auth_method: Method used to authenticate the users.
114 ## The default method is the internal.
115 ## If you want to use a different method,
116 ## comment this line and enable the correct ones.
117 auth_method: internal
118
119 ## Store the plain passwords or hashed for SCRAM:
120 ## auth_password_format: plain
121 auth_password_format: scram
122
123 ###' TRAFFIC SHAPERS
124 shaper:
125 # in B/s
126 normal: 1000000
127 fast: 50000000
128
129 ## This option specifies the maximum number of elements in the queue
130 ## of the FSM. Refer to the documentation for details.
131 max_fsm_queue: 1000
132
133 ###' ACCESS CONTROL LISTS
134 acl:
135 ## The 'admin' ACL grants administrative privileges to XMPP accounts.
136 ## You can put here as many accounts as you want.
137 admin:
138 user:
139 - "root": "example.com"
140
141 ## Local users: don't modify this.
142 local:
143 user_regexp: ""
144
145 ## Loopback network
146 loopback:
147 ip:
148 - "127.0.0.0/8"
149 - "::1/128"
150 - "::FFFF:127.0.0.1/128"
151
152 ###' SHAPER RULES
153 shaper_rules:
154 ## Maximum number of simultaneous sessions allowed for a single user:
155 max_user_sessions: 10
156 ## Maximum number of offline messages that users can have:
157 max_user_offline_messages:
158 - 5000: admin
159 - 1024
160 ## For C2S connections, all users except admins use the "normal" shaper
161 c2s_shaper:
162 - none: admin
163 - normal
164 ## All S2S connections use the "fast" shaper
165 s2s_shaper: fast
166
167 ###' ACCESS RULES
168 access_rules:
169 ## This rule allows access only for local users:
170 local:
171 - allow: local
172 ## Only non-blocked users can use c2s connections:
173 c2s:
174 - deny: blocked
175 - allow
176 ## Only admins can send announcement messages:
177 announce:
178 - allow: admin
179 ## Only admins can use the configuration interface:
180 configure:
181 - allow: admin
182 ## Only accounts of the local ejabberd server can create rooms:
183 muc_create:
184 - allow: local
185 ## Only accounts on the local ejabberd server can create Pubsub nodes:
186 pubsub_createnode:
187 - allow: local
188 ## In-band registration allows registration of any possible username.
189 ## To disable in-band registration, replace 'allow' with 'deny'.
190 register:
191 - allow
192 ## Only allow to register from localhost
193 trusted_network:
194 - allow: loopback
195
196 ## ===============
197 ## API PERMISSIONS
198 ## ===============
199 ##
200 ## This section allows you to define who and using what method
201 ## can execute commands offered by ejabberd.
202 ##
203 ## By default "console commands" section allow executing all commands
204 ## issued using ejabberdctl command, and "admin access" section allows
205 ## users in admin acl that connect from 127.0.0.1 to execute all
206 ## commands except start and stop with any available access method
207 ## (ejabberdctl, http-api, xmlrpc depending what is enabled on server).
208 ##
209 ## If you remove "console commands" there will be one added by
210 ## default allowing executing all commands, but if you just change
211 ## permissions in it, version from config file will be used instead
212 ## of default one.
213 ##
214 api_permissions:
215 "console commands":
216 from:
217 - ejabberd_ctl
218 who: all
219 what: "*"
220
221 language: "en"
222
223 ###' MODULES
224 ## Modules enabled in all ejabberd virtual hosts.
225 modules:
226 mod_adhoc: {}
227 mod_announce: # recommends mod_adhoc
228 access: announce
229 mod_blocking: {} # requires mod_privacy
230 mod_caps: {}
231 mod_carboncopy: {}
232 mod_client_state: {}
233 mod_configure: {} # requires mod_adhoc
234 ## mod_delegation: {} # for xep0356
235 mod_disco: {}
236 #mod_irc:
237 # host: "irc.@HOST@"
238 # default_encoding: "utf-8"
239 ## mod_bosh: {}
240 ## mod_http_fileserver:
241 ## docroot: "/var/www"
242 ## accesslog: "/var/log/ejabberd/access.log"
243 mod_http_upload:
244 thumbnail: false # otherwise needs the identify command from ImageMagick installed
245 put_url: "http://@HOST@:5444/upload"
246 ## # docroot: "@HOME@/upload"
247 #mod_http_upload_quota:
248 # max_days: 14
249 mod_last: {}
250 ## XEP-0313: Message Archive Management
251 ## You might want to setup a SQL backend for MAM because the mnesia database is
252 ## limited to 2GB which might be exceeded on large servers
253 mod_mam: {}
254 mod_muc:
255 host: "muc.@HOST@"
256 access:
257 - allow
258 access_admin:
259 - allow: admin
260 access_create: muc_create
261 access_persistent: muc_create
262 mod_muc_admin: {}
263 mod_muc_log: {}
264 mod_offline:
265 access_max_user_messages: max_user_offline_messages
266 mod_ping: {}
267 ## mod_pres_counter:
268 ## count: 5
269 ## interval: 60
270 mod_privacy: {}
271 mod_private: {}
272 mod_roster:
273 versioning: true
274 mod_shared_roster: {}
275 mod_stats: {}
276 mod_time: {}
277 mod_vcard:
278 search: false
279 mod_vcard_xupdate: {}
280 ## Convert all avatars posted by Android clients from WebP to JPEG
281 mod_avatar: {}
282 # convert:
283 # webp: jpeg
284 mod_version: {}
285 mod_stream_mgmt: {}
286 ## The module for S2S dialback (XEP-0220). Please note that you cannot
287 ## rely solely on dialback if you want to federate with other servers,
288 ## because a lot of servers have dialback disabled and instead rely on
289 ## PKIX authentication. Make sure you have proper certificates installed
290 ## and check your accessibility at https://check.messaging.one/
291 mod_s2s_dialback: {}
292 mod_pubsub:
293 plugins:
294 - "pep"
295 mod_push: {}
296 mod_matrix_gw:
297 key_name: key1
298 key: MATRIX_SECRET
299 '';
300 };
301
302 systemd.services.ejabberd.serviceConfig.EnvironmentFile = pkgs.writeText "ejabberd.env" ''
303 EJABBERD_MACRO_MATRIX_SECRET=SU4mu/j8b8A1i1EdyxIcKlFlrp+eSRBIlZwGyHP7Mfo=
304 '';
305 networking.firewall.enable = false;
306 };
307 };
308
309 testScript =
310 { nodes, ... }:
311 ''
312 ejabberd_prefix = "su ejabberd -s $(which ejabberdctl) "
313
314 server.wait_for_unit("ejabberd.service")
315
316 assert "status: started" in server.succeed(ejabberd_prefix + "status")
317
318 server.succeed("curl https://matrix.example.com:8448/_matrix/key/v2/server")
319
320 server.succeed(
321 ejabberd_prefix + "register azurediamond example.com hunter2",
322 ejabberd_prefix + "register cthon98 example.com nothunter2",
323 )
324 server.fail(ejabberd_prefix + "register asdf wrong.domain")
325
326 for machine in client_a, client_b:
327 machine.systemctl("start network-online.target")
328 machine.wait_for_unit("network-online.target")
329
330 client_a.wait_for_unit("go-sendxmpp-listen")
331 client_b.succeed("send-message")
332
333 client_a.wait_until_succeeds(
334 "journalctl -o cat -u go-sendxmpp-listen.service | grep 'cthon98@example.com: Hello, this is dog.'"
335 )
336
337 server.succeed(
338 ejabberd_prefix + "unregister cthon98 example.com",
339 ejabberd_prefix + "unregister azurediamond example.com",
340 )
341 '';
342}