aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2019-12-20 01:55:08 +0100
committerIsmaël Bouya <ismael.bouya@normalesup.org>2019-12-20 04:12:30 +0100
commit3f453c7d8f79dcf2fba94287ec286d55eceb99d1 (patch)
treee7a2531a08d7b8f514f2a1b8ec9914ca60623beb
parent8cf37c75c3c744717327344ff982a62d787c1dc7 (diff)
downloadNix-3f453c7d8f79dcf2fba94287ec286d55eceb99d1.tar.gz
Nix-3f453c7d8f79dcf2fba94287ec286d55eceb99d1.tar.zst
Nix-3f453c7d8f79dcf2fba94287ec286d55eceb99d1.zip
Add ejabberd service and website
-rw-r--r--modules/private/default.nix2
-rw-r--r--modules/private/ejabberd/default.nix93
-rw-r--r--modules/private/ejabberd/ejabberd.yml233
-rw-r--r--modules/private/system/eldiron.nix1
-rw-r--r--modules/private/websites/tools/im/default.nix37
-rw-r--r--modules/private/websites/tools/im/www/converse.html57
-rw-r--r--modules/private/websites/tools/im/www/index.html46
-rw-r--r--modules/private/websites/tools/tools/default.nix5
8 files changed, 473 insertions, 1 deletions
diff --git a/modules/private/default.nix b/modules/private/default.nix
index 57bad43..70d4b79 100644
--- a/modules/private/default.nix
+++ b/modules/private/default.nix
@@ -47,6 +47,7 @@ set = {
47 diasporaTool = ./websites/tools/diaspora; 47 diasporaTool = ./websites/tools/diaspora;
48 etherTool = ./websites/tools/ether; 48 etherTool = ./websites/tools/ether;
49 gitTool = ./websites/tools/git; 49 gitTool = ./websites/tools/git;
50 imTool = ./websites/tools/im;
50 mastodonTool = ./websites/tools/mastodon; 51 mastodonTool = ./websites/tools/mastodon;
51 mgoblinTool = ./websites/tools/mgoblin; 52 mgoblinTool = ./websites/tools/mgoblin;
52 peertubeTool = ./websites/tools/peertube; 53 peertubeTool = ./websites/tools/peertube;
@@ -64,6 +65,7 @@ set = {
64 dns = ./dns.nix; 65 dns = ./dns.nix;
65 ftp = ./ftp.nix; 66 ftp = ./ftp.nix;
66 mpd = ./mpd.nix; 67 mpd = ./mpd.nix;
68 ejabberd = ./ejabberd;
67 ssh = ./ssh; 69 ssh = ./ssh;
68 monitoring = ./monitoring; 70 monitoring = ./monitoring;
69 71
diff --git a/modules/private/ejabberd/default.nix b/modules/private/ejabberd/default.nix
new file mode 100644
index 0000000..5e717f4
--- /dev/null
+++ b/modules/private/ejabberd/default.nix
@@ -0,0 +1,93 @@
1{ lib, pkgs, config, ... }:
2let
3 cfg = config.myServices.ejabberd;
4in
5{
6 options.myServices = {
7 ejabberd.enable = lib.mkOption {
8 type = lib.types.bool;
9 default = false;
10 description = ''
11 Whether to enable ejabberd service.
12 '';
13 };
14 };
15
16 config = lib.mkIf cfg.enable {
17 security.acme.certs = {
18 "ejabberd" = config.myServices.certificates.certConfig // {
19 user = "ejabberd";
20 group = "ejabberd";
21 domain = "eldiron.immae.eu";
22 postRun = ''
23 systemctl restart ejabberd.service
24 '';
25 extraDomains = {
26 "immae.fr" = null;
27 "conference.immae.fr" = null;
28 "proxy.immae.fr" = null;
29 "pubsub.immae.fr" = null;
30 "upload.immae.fr" = null;
31 };
32 };
33 };
34 networking.firewall.allowedTCPPorts = [ 5222 5269 ];
35 myServices.websites.tools.im.enable = true;
36 systemd.services.ejabberd.postStop = ''
37 rm /var/log/ejabberd/erl_crash*.dump
38 '';
39 secrets.keys = [
40 {
41 dest = "ejabberd/psql.yml";
42 permissions = "0400";
43 user = "ejabberd";
44 group = "ejabberd";
45 text = ''
46 sql_type: pgsql
47 sql_server: "localhost"
48 sql_database: "${config.myEnv.jabber.postgresql.database}"
49 sql_username: "${config.myEnv.jabber.postgresql.user}"
50 sql_password: "${config.myEnv.jabber.postgresql.password}"
51 '';
52 }
53 {
54 dest = "ejabberd/host.yml";
55 permissions = "0400";
56 user = "ejabberd";
57 group = "ejabberd";
58 text = ''
59 host_config:
60 "immae.fr":
61 domain_certfile: "${config.security.acme.directory}/ejabberd/full.pem"
62 auth_method: [ldap]
63 ldap_servers: ["${config.myEnv.jabber.ldap.host}"]
64 ldap_encrypt: tls
65 ldap_rootdn: "${config.myEnv.jabber.ldap.dn}"
66 ldap_password: "${config.myEnv.jabber.ldap.password}"
67 ldap_base: "${config.myEnv.jabber.ldap.base}"
68 ldap_uids:
69 - "uid": "%u"
70 - "immaeXmppUid": "%u"
71 ldap_filter: "${config.myEnv.jabber.ldap.filter}"
72 '';
73 }
74 ];
75 users.users.ejabberd.extraGroups = [ "keys" ];
76 services.ejabberd = {
77 package = pkgs.ejabberd.override { withPgsql = true; };
78 imagemagick = true;
79 enable = true;
80 ctlConfig = ''
81 ERLANG_NODE=ejabberd@localhost
82 '';
83 configFile = pkgs.runCommand "ejabberd.yml" {
84 certificatePrivateKeyAndFullChain = "${config.security.acme.directory}/ejabberd/full.pem";
85 certificateCA = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
86 sql_config_file = config.secrets.fullPaths."ejabberd/psql.yml";
87 host_config_file = config.secrets.fullPaths."ejabberd/host.yml";
88 } ''
89 substituteAll ${./ejabberd.yml} $out
90 '';
91 };
92 };
93}
diff --git a/modules/private/ejabberd/ejabberd.yml b/modules/private/ejabberd/ejabberd.yml
new file mode 100644
index 0000000..0f678b6
--- /dev/null
+++ b/modules/private/ejabberd/ejabberd.yml
@@ -0,0 +1,233 @@
1###
2### ejabberd configuration file
3###
4### The parameters used in this configuration file are explained at
5###
6### https://docs.ejabberd.im/admin/configuration
7###
8### The configuration file is written in YAML.
9### *******************************************************
10### ******* !!! WARNING !!! *******
11### ******* YAML IS INDENTATION SENSITIVE *******
12### ******* MAKE SURE YOU INDENT SECTIONS CORRECTLY *******
13### *******************************************************
14### Refer to http://en.wikipedia.org/wiki/YAML for the brief description.
15### However, ejabberd treats different literals as different types:
16###
17### - unquoted or single-quoted strings. They are called "atoms".
18### Example: dog, 'Jupiter', '3.14159', YELLOW
19###
20### - numeric literals. Example: 3, -45.0, .0
21###
22### - quoted or folded strings.
23### Examples of quoted string: "Lizzard", "orange".
24### Example of folded string:
25### > Art thou not Romeo,
26### and a Montague?
27###
28
29hosts:
30 - "immae.fr"
31
32loglevel: 4
33log_rotate_size: 10485760
34log_rotate_date: ""
35log_rotate_count: 1
36log_rate_limit: 100
37
38certfiles:
39 - "@certificatePrivateKeyAndFullChain@"
40
41listen:
42 -
43 port: 5222
44 ip: "::"
45 module: ejabberd_c2s
46 max_stanza_size: 262144
47 shaper: c2s_shaper
48 access: c2s
49 starttls_required: true
50 -
51 port: 5269
52 ip: "::"
53 module: ejabberd_s2s_in
54 max_stanza_size: 524288
55 -
56 port: 5280
57 ip: "127.0.0.1"
58 module: ejabberd_http
59 request_handlers:
60 "/admin": ejabberd_web_admin
61 "/api": mod_http_api
62 "/bosh": mod_bosh
63 "/captcha": ejabberd_captcha
64 "/upload": mod_http_upload
65 "/ws": ejabberd_http_ws
66 tls: false
67
68s2s_use_starttls: optional
69s2s_cafile: "@certificateCA@"
70
71default_db: sql
72sql_type: pgsql
73include_config_file: @sql_config_file@
74include_config_file: @host_config_file@
75new_sql_schema: true
76
77acl:
78 admin:
79 - user: "ismael@immae.fr"
80 local:
81 user_regexp: ""
82 loopback:
83 ip:
84 - "127.0.0.0/8"
85 - "::1/128"
86 - "::FFFF:127.0.0.1/128"
87
88access_rules:
89 local:
90 - allow: local
91 c2s:
92 - deny: blocked
93 - allow
94 announce:
95 - allow: admin
96 configure:
97 - allow: admin
98 muc_admin:
99 - allow: admin
100 muc_create:
101 - allow: local
102 muc:
103 - allow
104 pubsub_createnode:
105 - allow: local
106 register:
107 - deny
108 trusted_network:
109 - allow: loopback
110
111api_permissions:
112 "console commands":
113 from:
114 - ejabberd_ctl
115 who: all
116 what: "*"
117 "admin access":
118 who:
119 - acl: admin
120 - oauth:
121 - scope: "ejabberd:admin"
122 - acl: admin
123 what:
124 - "*"
125 - "!stop"
126 - "!start"
127 "public commands":
128 who:
129 - ip:
130 - "0.0.0.0"
131 - "::"
132 what:
133 - "status"
134 - "connected_users_number"
135
136shaper:
137 normal: 1000
138 fast: 50000
139
140shaper_rules:
141 max_user_sessions: 10
142 max_user_offline_messages:
143 - 5000: admin
144 - 100
145 c2s_shaper:
146 - none: admin
147 - normal
148 s2s_shaper: fast
149
150modules:
151 mod_adhoc: {}
152 mod_admin_extra: {}
153 mod_announce:
154 access: announce
155 mod_avatar: {}
156 mod_blocking: {}
157 mod_bosh: {}
158 mod_caps: {}
159 mod_carboncopy: {}
160 mod_client_state: {}
161 mod_configure: {}
162 mod_disco: {}
163 mod_fail2ban: {}
164 mod_http_api: {}
165 mod_http_upload:
166 put_url: "https://im.immae.fr/upload"
167 custom_headers:
168 "Access-Control-Allow-Origin": "*"
169 "Access-Control-Allow-Methods": "OPTIONS, HEAD, GET, PUT, POST"
170 "Access-Control-Allow-Headers": "Content-Type"
171 mod_last: {}
172 mod_mam:
173 default: always
174 mod_muc:
175 access:
176 - allow
177 access_admin:
178 - allow: admin
179 access_create: muc_create
180 access_persistent: muc_create
181 default_room_options:
182 mam: true
183 mod_muc_admin: {}
184 mod_offline:
185 access_max_user_messages: max_user_offline_messages
186 mod_ping: {}
187 mod_privacy: {}
188 mod_private: {}
189 mod_proxy65:
190 access: local
191 max_connections: 5
192 mod_pubsub:
193 access_createnode: pubsub_createnode
194 plugins:
195 - "flat"
196 - "hometree"
197 - "pep"
198 force_node_config:
199 ## Change from "whitelist" to "open" to enable OMEMO support
200 ## See https://github.com/processone/ejabberd/issues/2425
201 "eu.siacs.conversations.axolotl.*":
202 access_model: open
203 ## Avoid buggy clients to make their bookmarks public
204 "storage:bookmarks":
205 access_model: whitelist
206 mod_push: {}
207 mod_push_keepalive: {}
208 mod_register:
209 ## Only accept registration requests from the "trusted"
210 ## network (see access_rules section above).
211 ## Think twice before enabling registration from any
212 ## address. See the Jabber SPAM Manifesto for details:
213 ## https://github.com/ge0rg/jabber-spam-fighting-manifesto
214 ip_access: trusted_network
215 access: register
216 mod_roster:
217 versioning: true
218 mod_s2s_dialback: {}
219 mod_shared_roster: {}
220 mod_stats: {}
221 mod_stream_mgmt:
222 resend_on_timeout: if_offline
223 mod_time: {}
224 mod_vcard: {}
225 mod_vcard_xupdate: {}
226 mod_version:
227 show_os: false
228
229### Local Variables:
230### mode: yaml
231### End:
232### vim: set filetype=yaml tabstop=8
233
diff --git a/modules/private/system/eldiron.nix b/modules/private/system/eldiron.nix
index 172e4be..e1186f5 100644
--- a/modules/private/system/eldiron.nix
+++ b/modules/private/system/eldiron.nix
@@ -34,6 +34,7 @@
34 myServices.certificates.enable = true; 34 myServices.certificates.enable = true;
35 myServices.websites.enable = true; 35 myServices.websites.enable = true;
36 myServices.mail.enable = true; 36 myServices.mail.enable = true;
37 myServices.ejabberd.enable = true;
37 services.pure-ftpd.enable = true; 38 services.pure-ftpd.enable = true;
38 services.duplyBackup.enable = true; 39 services.duplyBackup.enable = true;
39 40
diff --git a/modules/private/websites/tools/im/default.nix b/modules/private/websites/tools/im/default.nix
new file mode 100644
index 0000000..9744d8e
--- /dev/null
+++ b/modules/private/websites/tools/im/default.nix
@@ -0,0 +1,37 @@
1{ config, lib, ... }:
2let
3 cfg = config.myServices.websites.tools.im;
4in
5{
6 options.myServices.websites.tools.im = {
7 enable = lib.mkEnableOption "enable im website";
8 };
9
10 config = lib.mkIf cfg.enable {
11 services.websites.env.tools.vhostConfs.im = {
12 certName = "eldiron";
13 addToCerts = true;
14 hosts = ["im.immae.fr"];
15 root = ./www;
16 extraConfig = [
17 ''
18 Alias /converse ${./www}/converse.html
19 ProxyPreserveHost On
20 <Location "/bosh">
21 ProxyPass http://localhost:5280/bosh
22 ProxyPassReverse http://localhost:5280/bosh
23 </Location>
24 <Location "/ws">
25 ProxyPass ws://localhost:5280/ws
26 </Location>
27 ProxyPass /upload http://localhost:5280/upload
28 ProxyPassReverse /upload http://localhost:5280/upload
29 ProxyPass /admin http://localhost:5280/admin
30 ProxyPassReverse /admin http://localhost:5280/admin
31 ProxyPass /api http://localhost:5280/api
32 ProxyPassReverse /api http://localhost:5280/api
33 ''
34 ];
35 };
36 };
37}
diff --git a/modules/private/websites/tools/im/www/converse.html b/modules/private/websites/tools/im/www/converse.html
new file mode 100644
index 0000000..5835b6e
--- /dev/null
+++ b/modules/private/websites/tools/im/www/converse.html
@@ -0,0 +1,57 @@
1<!DOCTYPE html>
2<html lang="en">
3 <head>
4 <title>Converse</title>
5 <meta charset="utf-8">
6 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8 <meta name="description" content="Converse: An XMPP chat client which can be integrated into any website" />
9 <meta name="keywords" content="xmpp chat webchat converse.js Converse" />
10
11 <link type="text/css" rel="stylesheet" media="screen" href="https://cdn.conversejs.org/5.0.4/dist/converse.min.css" />
12 <style type="text/css">
13 #conversejs div.chat-msg__text pre {
14 background-color: #eee;
15 padding: 10px;
16 }
17 </style>
18 <script src="https://cdn.conversejs.org/3rdparty/libsignal-protocol.min.js"></script>
19 <script src="https://cdn.conversejs.org/5.0.4/dist/converse.min.js"></script>
20 <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
21 <script src="https://cdnjs.cloudflare.com/ajax/libs/markdown-it/10.0.0/markdown-it.min.js"></script>
22 <script>
23 var md = window.markdownit({
24 html: true,
25 });
26 converse.plugins.add('markdown', {
27 //initialize () {
28 // const { _converse } = this;
29 // _converse.api.listen.on('afterMessageBodyTransformed', (view, text) => {
30 // let newtext = text.replace(/<br\/>/g, '\n').replace(/```/g, "\n```\n");
31 // newtext = md.render(newtext).replace(/^<p>/, "").replace(/<\/p>\s*$/, "");
32 // view.model.save({'message': newtext}, {'silent': true });
33 // });
34 //}
35 overrides: {
36 MessageView: {
37 transformBodyText: async function(text) {
38 let newtext = await this.__super__.transformBodyText.apply(this, arguments);
39 newtext = newtext.replace(/<br\/>/g, '\n').replace(/```/g, "\n```\n");
40 return md.render(newtext).replace(/^<p>/, "").replace(/<\/p>\s*$/, "");
41 }
42 }
43 }
44 });
45 converse.initialize({
46 //bosh_service_url: 'https://im.immae.fr/bosh',
47 websocket_url: 'wss://im.immae.fr/ws',
48 view_mode: 'fullscreen',
49 show_controlbox_by_default: true,
50 whitelisted_plugins: ['markdown'],
51 });
52 </script>
53 </head>
54 <body>
55 </body>
56</html>
57
diff --git a/modules/private/websites/tools/im/www/index.html b/modules/private/websites/tools/im/www/index.html
new file mode 100644
index 0000000..15e09f2
--- /dev/null
+++ b/modules/private/websites/tools/im/www/index.html
@@ -0,0 +1,46 @@
1<!doctype html>
2<html lang="fr">
3 <head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Instant messaging configuration (Jabber/XMPP)</title>
7 <style type="text/css">
8 body {
9 padding-top: 1em;
10 padding-left: 5px;
11 padding-right: 5px;
12 text-align: left;
13 margin: auto;
14 font: 20px Helvetica, sans-serif;
15 color: #333;
16 height: 100%;
17 min-height: 100%;
18 }
19 article {
20 text-align: justify;
21 display: block;
22 max-width: 850px;
23 margin: 0 auto;
24 padding-top: 30px;
25 }
26 span.code {
27 font-family: monospace;
28 }
29 </style>
30 </head>
31 <body>
32 <p>
33 Pre-configured clients:
34 <ul>
35 <li><a href="converse">Converse client</a></li>
36 </ul>
37 </p>
38 <p>
39 Technical details:
40 <ul>
41 <li>HTTP-bind/BOSH access (XEP-0124 / XEP-0206): <span class="code">https://im.immae.fr/bosh</span></li>
42 <li>WS access (RFC 7395): <span class="code">wss://im.immae.fr/ws</span></li>
43 </ul>
44 </p>
45 </body>
46</html>
diff --git a/modules/private/websites/tools/tools/default.nix b/modules/private/websites/tools/tools/default.nix
index 5a0c196..02ff224 100644
--- a/modules/private/websites/tools/tools/default.nix
+++ b/modules/private/websites/tools/tools/default.nix
@@ -100,6 +100,7 @@ in {
100 extraConfig = [ 100 extraConfig = [
101 '' 101 ''
102 RedirectMatch 301 ^/roundcube(.*)$ https://mail.immae.eu/roundcube$1 102 RedirectMatch 301 ^/roundcube(.*)$ https://mail.immae.eu/roundcube$1
103 RedirectMatch 301 ^/jappix(.*)$ https://im.immae.fr/converse
103 104
104 <Directory "/var/lib/ftp/tools.immae.eu"> 105 <Directory "/var/lib/ftp/tools.immae.eu">
105 DirectoryIndex index.php index.htm index.html 106 DirectoryIndex index.php index.htm index.html
@@ -126,7 +127,7 @@ in {
126 services.websites.env.tools.vhostConfs.outils = { 127 services.websites.env.tools.vhostConfs.outils = {
127 certName = "eldiron"; 128 certName = "eldiron";
128 addToCerts = true; 129 addToCerts = true;
129 hosts = [ "outils.immae.eu" ]; 130 hosts = [ "outils.immae.eu" "outils.immae.fr" ];
130 root = null; 131 root = null;
131 extraConfig = [ 132 extraConfig = [
132 '' 133 ''
@@ -146,6 +147,8 @@ in {
146 147
147 RedirectMatch 301 ^/roundcube(.*)$ https://mail.immae.eu/roundcube$1 148 RedirectMatch 301 ^/roundcube(.*)$ https://mail.immae.eu/roundcube$1
148 149
150 RedirectMatch 301 ^/jappix(.*)$ https://im.immae.fr/converse
151
149 RedirectMatch 301 ^/(.*)$ https://tools.immae.eu/$1 152 RedirectMatch 301 ^/(.*)$ https://tools.immae.eu/$1
150 '' 153 ''
151 ]; 154 ];