aboutsummaryrefslogtreecommitdiffstats
path: root/blog
diff options
context:
space:
mode:
authorLibravatar cel 🌸 <cel@blos.sm>2024-01-31 21:02:17 +0000
committerLibravatar cel 🌸 <cel@blos.sm>2024-01-31 21:02:17 +0000
commit7ccf135f287ccb6c12494275b2220aae63aa9126 (patch)
treee451be1fd0378ffd0049d31c4ed6472f839b0485 /blog
parentd1bfe2eb0ba8836d4eef4ca5dd6e20611dc3a8c0 (diff)
downloadblossom-7ccf135f287ccb6c12494275b2220aae63aa9126.tar.gz
blossom-7ccf135f287ccb6c12494275b2220aae63aa9126.tar.bz2
blossom-7ccf135f287ccb6c12494275b2220aae63aa9126.zip
rename articles folder to blog folder
Diffstat (limited to 'blog')
-rw-r--r--blog/ejabberd.md513
-rw-r--r--blog/rot.md28
2 files changed, 541 insertions, 0 deletions
diff --git a/blog/ejabberd.md b/blog/ejabberd.md
new file mode 100644
index 0000000..7831432
--- /dev/null
+++ b/blog/ejabberd.md
@@ -0,0 +1,513 @@
++++
+title = "cozy ejabberd xmpp chat server"
+published_at = "2023-09-16T21:07:40+0100"
+tags = ["tech", "sysadmin"]
++++
+
+today we are going to do the **ultimate** *cozy* ejabberd server guide. the only prerequisites for this guide are, one, having already set up some form of server, whether it be a vps, or an old laptop behind your fridge, it doesn't matter, because this isn't the email network, and two, ownership of a domain name, e.g. `blos.sm`.
+
+we shall begin with a single virtualhost[^1]. for example purposes, we will use `example.slay` (let's imagine this is a real tld because why not) as the domain. just replace all instances of `example.slay` with your own domain.
+
+[^1]: virtualhosts allow more than one xmpp service to be run on one server. for example, you could have one xmpp service with the domain `example.slay` and another xmpp service with the domain `example.flop`, both somewhat separated from each other as if they were run on different servers.
+
+<div>
+<div class="panel checklist">
+checklist!:
+<input type="checkbox" id="hide-checklist"><label for="hide-checklist">hide</label>
+
+- [ ] add dns records
+- [ ] open firewall ports
+- [ ] set up web server
+- [ ] get ssl certificates
+- [ ] install ejabberd
+- [ ] set up postgres database
+- [ ] write/edit configuration
+- [ ] start service
+- [ ] create admin user
+- [ ] change loglevel
+
+</div>
+
+## step 1: set up your dns records
+
+you will need dns A/AAAA records and srv records for each service on your xmpp server.
+
+you will need a records for:
+
+- `example.slay`
+- `muc.example.slay` (for group chats)
+- `upload.example.slay` (for http file upload)
+- `pubsub.example.slay` (for the pubsub node)
+- `proxy.example.slay` (for file transfer proxy)
+- `turn.example.slay` (for stun/turn)
+
+each pointing to the ip address of your server that is going to run ejabberd. the last two are technically optional, but i would recommend them.
+
+as well as srv records for each, pointing to a domain that resolves to your server, as so:
+
+(all records are in the form
+`_service._proto.name IN SRV priority weight port target`)
+
+```
+_xmpp-client._tcp IN SRV 5 0 5222 example.slay.
+_xmpps-client._tcp IN SRV 5 0 5223 example.slay.
+_xmpp-server._tcp IN SRV 5 0 5269 example.slay.
+_xmpps-server._tcp IN SRV 5 0 5270 example.slay.
+```
+
+and
+
+```
+_xmpp-client._tcp.muc IN SRV 5 0 5222 example.slay.
+_xmpps-client._tcp.muc IN SRV 5 0 5223 example.slay.
+_xmpp-server._tcp.muc IN SRV 5 0 5269 example.slay.
+_xmpps-server._tcp.muc IN SRV 5 0 5270 example.slay.
+```
+
+for each of the subdomains (starting with muc). exclude `turn.example.slay`.
+
+you will then have to add one last set of srv records for stun/turn.
+
+```
+_stun._udp IN SRV 5 0 3478 turn.example.slay.
+_stun._tcp IN SRV 5 0 3478 turn.example.slay.
+_stuns._tcp IN SRV 5 0 5349 turn.example.slay.
+
+_turn._udp IN SRV 5 0 3478 turn.example.slay.
+_turn._tcp IN SRV 5 0 3478 turn.example.slay.
+_turns._tcp IN SRV 5 0 5349 turn.example.slay.
+```
+
+extra info: as a result of these records, you could technically play around with hosting xmpp on a server other than the one at `example.slay` (i.e. if you were splitting services across servers on one domain) by using the srv delegation. further info can be found at [XEP-0368](https://xmpp.org/extensions/xep-0368.html).
+
+## step 2: open your firewall ports
+
+open ports:
+
+tcp: `80` `443` `5222` `5223` `5269` `5270` `3478` `5349` `49152-65535`
+
+udp: `3478` `49152-65535`
+
+`80` & `443` are for the web server, `5222`, `5223`, `5269` and `5270` are for xmpp, and the rest are for stun/turn.
+
+## step 3: set up your web server and get your ssl certificates
+
+you need to:
+
+- get (an) ssl certificate(s) for your domain, as well as several subdomains, all in all:
+ - `example.slay`
+ - `muc.example.slay`
+ - `upload.example.slay`
+ - `pubsub.example.slay`
+ - `proxy.example.slay`
+ - `turn.example.slay`
+- proxypass http://127.0.0.1:5443 through to:
+ - https://example.slay/xmpp
+ - https://example.slay/.well-known/host-meta
+ - https://example.slay/.well-known/host-meta.json
+
+ make sure that for /xmpp you have what is necessary to proxy websockets too. if you're using nginx, increase `client_max_body_size` for http uploads.
+- make sure the certificate files are readable and/or in a place that is readable by the `ejabberd` user
+
+you can technically avoid using something like nginx + certbot, and use the built-in [ejabberd acme module](https://docs.ejabberd.im/admin/configuration/basic/#acme), thereby skipping this, but i am assuming you may also want to host other web services on your system, in which case you would want to reverse proxy each http service to a single https web service.
+
+## step 4: install ejabberd
+
+now you should finally install the [system package](https://docs.ejabberd.im/admin/installation/#operating-system-packages). make sure that your build has postgresql support.
+
+make sure that the file `/etc/ejabberd/ejabberd.yml` exists, and of course, is readable by the user that runs ejabberd (almost definitely `ejabberd`), by, if necessary, copying over the example `ejabberd.yml` or `wget`/`curl`ing it from the [github repo](https://github.com/processone/ejabberd/blob/master/ejabberd.yml.example). if you are getting it from the repo, make sure the version corresponds to the version of ejabberd packaged by your os.
+
+## step 5: set up postgres database
+
+we will be creating a separate database for each virtualhost, as i feel this makes things clearer, and also it easier to migrate individual virtualhosts in the future. however, there is also now the ability to only have one, as described [here](https://docs.ejabberd.im/admin/configuration/database/#default-and-new-schemas).
+
+you should follow standard postgresql installation instructions for your OS. once this has been done, you should connect to your database as an admin and:
+
+1. create an ejabberd database user with `CREATE USER ejabberd WITH PASSWORD 'your_password';`. don't forget to change the password, and note it down.
+2. create a database for your virtualhost with `CREATE DATABASE ejabberd_example OWNER ejabberd;`. replace `example` with something corresponding to your virtualhost.
+3. quit psql, and import the database schema from github with the command `curl -s https://raw.githubusercontent.com/processone/ejabberd/master/sql/pg.sql | sudo -u ejabberd psql ejabberd_example` (once again replace `example`).
+
+## step 6: ejabberd configuration
+
+begin by replacing `localhost` under `hosts` with your virtualhost (e.g. `example.slay`), then list the certfiles you have obtained under `certfiles`.
+
+```
+hosts:
+ - example.slay
+
+certfiles:
+ - "/etc/ejabberd/certs/*/*"
+```
+
+now set `default_db: sql` at the root level of the yaml file. this should be followed by `host_config` and the database configuration for your virtualhost, as shown below. customise each value to your setup.
+
+```
+host_config:
+ example.slay:
+ sql_type: pgsql
+ sql_server: "localhost"
+ sql_port: 5432
+ sql_username: "ejabberd"
+ sql_password: "postgres_password"
+ sql_database: "ejabberd_example"
+ auth_method: sql
+ auth_password_format: scram
+```
+
+under `listen`, ensure all the correct services are enabled on each port, including tls s2s on port `5270` (not default):
+
+```
+listen:
+ -
+ port: 5222
+ module: ejabberd_c2s
+ max_stanza_size: 262144
+ shaper: c2s_shaper
+ access: c2s
+ starttls_required: true
+ -
+ port: 5223
+ tls: true
+ module: ejabberd_c2s
+ max_stanza_size: 262144
+ shaper: c2s_shaper
+ access: c2s
+ starttls_required: true
+ -
+ port: 5269
+ module: ejabberd_s2s_in
+ max_stanza_size: 524288
+ -
+ port: 5270
+ tls: true
+ module: ejabberd_s2s_in
+ max_stanza_size: 524288
+```
+
+we will also be enabling the http server and the stun/turn server modules. make sure you have set `turn_ipv4_address` and `ip` to your server's ipv4 address. tls will be off for the http server as we are reverse proxying it through our web server.
+
+```
+ -
+ port: 5443
+ module: ejabberd_http
+ request_handlers:
+ /xmpp/admin: ejabberd_web_admin
+ /xmpp/bosh: mod_bosh
+ /xmpp/upload: mod_http_upload
+ /xmpp/ws: ejabberd_http_ws
+ /.well-known/host-meta: mod_host_meta
+ /.well-known/host-meta.json: mod_host_meta
+ -
+ port: 3478
+ transport: udp
+ module: ejabberd_stun
+ use_turn: true
+ turn_min_port: 49152
+ turn_max_port: 65535
+ # The server's public IPv4 address:
+ turn_ipv4_address: 0.0.0.0
+ -
+ port: 5349
+ transport: tcp
+ module: ejabberd_stun
+ use_turn: true
+ tls: true
+ turn_min_port: 49152
+ turn_max_port: 65535
+ ip: 0.0.0.0
+ turn_ipv4_address: 0.0.0.0
+```
+
+now set `s2s_use_starttls: required` at the root.
+
+at this point you can set up some ACLs. `acls` are just the access control lists, you can also set up `access_rules` corresponding to your needs, which will be what are passed to module settings. you should at the minimum add an admin user. example:
+
+```
+acl:
+ admin:
+ user: admin@example.slay
+ flop:
+ - user: flop@example.slay
+ clown:
+ - user: clown@example.slay
+
+access_rules:
+ queens:
+ allow: flop
+ allow: clown
+```
+
+next, we will be adding some modules under `modules` and changing some settings.
+
+add abuse addresses under `mod_disco`. you can also add other contact addresses according to [XEP-0157](https://xmpp.org/extensions/xep-0157.html):
+
+```
+modules:
+# ...
+ mod_disco:
+ server_info:
+ -
+ modules: all
+ name: "abuse-addresses"
+ urls: ["mailto:abuse@example.slay"]
+```
+
+add `mod_host_meta`:
+
+```
+ mod_host_meta:
+ bosh_service_url: "https://@HOST@/xmpp/bosh"
+ websocket_url: "wss://@HOST@/xmpp/ws"
+```
+
+edit `mod_mam`, and change `assume_mam_usage` to `false` and `default` to `never` if you wish not to archive messages on the server:
+
+```
+ mod_mam:
+ db_type: sql
+ assume_mam_usage: never
+ default: never
+```
+
+add `mod_stun_disco` to advertise the stun service to clients, changing `0.0.0.0` and `example.slay` to your server's ip and hostname respectively:
+
+```
+ mod_stun_disco:
+ credentials_lifetime: 12h
+ services:
+ -
+ host: 0.0.0.0
+ port: 3478
+ type: stun
+ transport: udp
+ restricted: false
+ -
+ host: 0.0.0.0
+ port: 3478
+ type: turn
+ transport: udp
+ restricted: true
+ -
+ host: turn.example.slay
+ port: 5349
+ type: stuns
+ transport: tcp
+ restricted: false
+ -
+ host: turn.example.slay
+ port: 5349
+ type: turns
+ transport: tcp
+ restricted: true
+```
+
+now it is time to enable MUCs (multi-user chatrooms), file proxy, http upload, and pubsub.
+
+### mucs:
+
+make sure that you set the host to your muc subdomain, otherwise it will attempt to use `conference.example.slay`. you can also set `mam: false` in `default_room_options` to disable server-side message archiving by default.
+
+```
+ mod_muc:
+ host: muc.example.slay
+ access:
+ - allow
+ access_admin:
+ - allow: admin
+ access_create: muc_create
+ access_persistent: muc_create
+ access_mam:
+ - allow
+ default_room_options:
+ mam: false
+```
+
+### file proxy:
+
+```
+ mod_proxy65:
+ access: local
+ max_connections: 5
+```
+
+### http file upload:
+
+```
+ mod_http_upload:
+ put_url: https://@HOST@/xmpp/upload
+ docroot: /var/www/ejabberdupload
+ max_size: 1073741824
+ custom_headers:
+ "Access-Control-Allow-Origin": "https://@HOST@"
+ "Access-Control-Allow-Methods": "GET,HEAD,PUT,OPTIONS"
+ "Access-Control-Allow-Headers": "Content-Type"
+```
+
+create the folder for the `docroot`, and make sure it is owned by the `ejabberd` user. you can also change `max_size` (the max upload size) to whatever you prefer.
+
+### pubsub:
+
+```
+ mod_pubsub:
+ access_createnode: pubsub_createnode
+ plugins:
+ - flat
+ - pep
+ force_node_config:
+ ## Avoid buggy clients to make their bookmarks public
+ storage:bookmarks:
+ access_model: whitelist
+```
+
+## step 7: start server and create admin user
+
+start the ejabberd server!
+
+use `sudo -u ejabberd ejabberdctl register admin example.slay password` to register `admin@example.slay` with the password `password`.
+
+there is a compliance tester at [compliance.conversations.im](https://compliance.conversations.im) if you wish to test your server. once you are done and believe everything has been set up correctly, you can optionally change the [`loglevel`](https://docs.ejabberd.im/admin/configuration/toplevel/#loglevel) at the root of the config.
+
+there will be an admin page accessible at [https://example.slay/xmpp/admin](https://example.slay/xmpp/admin).
+
+</div>
+
+<hr>
+
+# extra goodies!
+
+## web client
+
+you can set up conversejs using [`mod_conversejs`](https://docs.ejabberd.im/admin/configuration/modules/#mod-conversejs). you will also need to possibly update your web server config to proxy the new endpoint, as so:
+
+```
+listen:
+ -
+ port: 5443
+ module: ejabberd_http
+ request_handlers:
+ /xmpp/bosh: mod_bosh
+ /xmpp/ws: ejabberd_http_ws
+ /chat: mod_conversejs
+
+modules:
+ mod_conversejs:
+ websocket_url: "ws://@HOST@/xmpp/ws"
+ bosh_service_url: "https://@HOST@/xmpp/bosh"
+```
+
+## further virtualhosts?
+
+for further virtualhosts you should create a new database for each, and add them to the database part of the config. e.g.:
+
+```
+host_config:
+ example.slay:
+ sql_type: pgsql
+ sql_server: "localhost"
+ sql_port: 5432
+ sql_username: "ejabberd"
+ sql_password: "postgres_password"
+ sql_database: "ejabberd_slay"
+ auth_method: sql
+ auth_password_format: scram
+ example.flop:
+ sql_type: pgsql
+ sql_server: "localhost"
+ sql_port: 5432
+ sql_username: "ejabberd"
+ sql_password: "postgres_password"
+ sql_database: "ejabberd_flop"
+ auth_method: sql
+ auth_password_format: scram
+```
+
+there cannot be conflicts between declarations in the config file, so if you have `mod_muc`, `mod_proxy65`, `mod_http_upload` and `mod_pubsub` declared under `modules` at the root, they (as well as other configuration differences between virtualhosts) must be deleted and replicated for each virtualhost under `append_host_config` at the root. example as so:
+
+```
+append_host_config:
+ example.flop:
+ modules:
+ mod_muc:
+ host: muc.example.flop
+ access_create: flops
+ access_persistent: flops
+ access:
+ - allow
+ access_admin:
+ - allow: admin
+ default_room_options:
+ mam: false
+ mod_proxy65:
+ access: flops
+ max_connections: 5
+ mod_http_upload:
+ access: flops
+ put_url: https://@HOST@/xmpp/upload
+ docroot: /var/www/ejabberdupload
+ max_size: 1073741824
+ custom_headers:
+ "Access-Control-Allow-Origin": "https://@HOST@"
+ "Access-Control-Allow-Methods": "GET,HEAD,PUT,OPTIONS"
+ "Access-Control-Allow-Headers": "Content-Type"
+ mod_pubsub:
+ access_createnode: flops
+ plugins:
+ - flat
+ - pep
+ force_node_config:
+ ## Avoid buggy clients to make their bookmarks public
+ storage:bookmarks:
+ access_model: whitelist
+ example.flop:
+ modules:
+ mod_muc:
+ hosts:
+ - muc.example.flop
+ access_create: local
+ access_persistent: local
+ access:
+ - allow
+ access_admin:
+ - allow: admin
+ default_room_options:
+ mam: false
+ mod_proxy65:
+ access: local
+ max_connections: 5
+ mod_http_upload:
+ put_url: https://@HOST@/xmpp/upload
+ docroot: /var/www/ejabberdupload
+ max_size: 1073741824
+ custom_headers:
+ "Access-Control-Allow-Origin": "https://@HOST@"
+ "Access-Control-Allow-Methods": "GET,HEAD,PUT,OPTIONS"
+ "Access-Control-Allow-Headers": "Content-Type"
+ mod_pubsub:
+ access_createnode: pubsub_createnode
+ plugins:
+ - flat
+ - pep
+ force_node_config:
+ ## Avoid buggy clients to make their bookmarks public
+ storage:bookmarks:
+ access_model: whitelist
+```
+
+as you can see above, you may also want to disable access to certain services per virtualhost using ACLs, in order to e.g. prevent users on `example.slay` from creating MUCs on `muc.example.flop`.
+
+## separate turn server (coturn)
+
+in this case, change `mod_stun_disco` to this, and don't enable the `listen` opts for stun/turn. generate an auth secret and share it with your turn server instance.
+
+```
+ mod_stun_disco:
+ secret: "auth_secret"
+ services:
+ -
+ host: turn.example.slay
+ type: stun
+ -
+ host: turn.example.slay
+ type: turn
+```
+
diff --git a/blog/rot.md b/blog/rot.md
new file mode 100644
index 0000000..a4e1068
--- /dev/null
+++ b/blog/rot.md
@@ -0,0 +1,28 @@
++++
+title = "rot"
+published_at = "2022-04-27T09:48:30+0100"
+tags = ["thoughts"]
++++
+
+i want to write something about rot. why not? i think it's become my favourite word over the last few months. it's so versatile.
+
+what is rot? the oxford english dictionary defines rot as well i tried to look it up and i hit a paywall. this is a good representation of rot. it is pure decay. it is horrid yet undeniable. there is no way to tell at a glance at what point it became rot, and whatever it used to be, was surely destined for this end. perhaps it was always rotted to begin with. there is no way of knowing, only that now, at this time, it is surely rot.
+
+rot in my opinion represents a state of post-cringe, a state of absurdism. how is rot post-cringe? it is something so bad that when you experience it it no longer triggers your cringe response, you simply accept it for what it is. this is most definitely absurd. there is no more meaning to it but rot. there is no interpretation, there is no saving it from this state, it is past the point of no return.
+
+how can we solve rot? in my opinion there is therefore only one solution: abandonment of that which is rotted. rot is not worth saving, there is no way to salvage it, we must start anew with something better, even if it shall most likely reach the same end.
+
+the worst kind of rot is that which pretends to not be completely rot, which is propped up by some as being salvageable, or in some cases, perfectly acceptable and maybe even a net positive. some examples of this include:
+
+- capitalism
+- power structures
+- money
+- ariana grande
+- neoliberalism
+- software
+
+it is undeniable these are rotted to the core.
+
+i hope this aids in you understanding this term. maybe now you see rot in a different light, and that it could help you in making sense of the world.
+
+— cel