Cómo instalar Matrix
Matrix es un estandar abierto, que se puede usar para chat (y videollamadas) cifradas extremo-a-extremo, y es decentralizado. Puede haber muchos servidores y clientes usando el protocolo de Matrix, sincronizándose en tiempo real. Usa un servidor de casa para guardar la información de la cuenta y el historial chat. Si un servidor de Matrix no funciona, pueden usar otro.
Hoy vamos a instalar un servidor de Matrix usando conduwuit, y enlazarlo con Element, que es un cliente disponible en el web. Así vamos a poder usar nuestro servidor simplemente abriendo una página web. Y gracias a la naturaleza de Matrix, también pueden usar su servidor con cualquier cliente. También se puede instalar el servicio Coturn para agregar la función de llamadas a través de nuestro servidor.
Vamos a instalarlo en Debian, pero los comandos para otras distribuciones son igualitos.
Conduwuit
Conduwuit es un fork de Conduit, un servidor de Matrix escrito en Rust. Eso lo hace rápido y seguro. Conduwuit además incluye varias mejoras de seguridad, al usar la librería de C Musl, e incluir un allocator de memoria más seguro. También contiene más funcionalidad.
Para instalar Conduwuit, hay varias maneras, y varias versiones. Miremos la página de descargas
Hay dos que nos interesan:
x86_64-unknown-linux-musl.deb y static-x86_64-unknown-linux-musl. El primero nos interesa porque es un paquete .deb, o sea que sirve para Debian. Pero si vemos el tamaño, el estático es más grande. Según lo que entiendo, el allocator de memoria seguro y otras librerías está enlazado de forma estática, lo cual lo hace más grande. Nosotros queremos esa mejora de seguridad, pero también queremos la versión .deb, ya que se instala de una forma normal usando apt, y crea el archivo de configuración y manual etc etc.
Lo que podemos hacer es un truco: abrir el paquete .deb, y remplazar el binario con el nuevo static-musl.
wget "https://github.com/girlbossceo/conduwuit/releases/download/v0.4.6/x86_64-unknown-linux-musl.deb"
wget "https://github.com/girlbossceo/conduwuit/releases/download/v0.4.6/static-x86_64-unknown-linux-musl"
dpkg-deb -R x86_64-unknown-linux-musl.deb conduwuit-deb
cp static-x86_64-unknown-linux-musl conduwuit-deb/usr/sbin/conduwuit
cd conduwuit-deb
find . -type f -not -path "./DEBIAN/*" -exec md5sum {} + | sort -k 2 | sed 's/\.\/\(.*\)/\1/' > DEBIAN/md5sums
cd ..
dpkg-deb -b conduwuit-deb conduwuit.deb
Con estos comandos, descargamos la versión 0.4.6 de ambos (si hay una versión nueva, cambien el comando). Luego extraemos el paquete .deb a un directorio conduwuit-deb. Copiamos el binario estático a su nuevo lugar en conduwuit-deb/usr/sbin, y para que todo se verifique, remplazamos el hash con uno nuevo. Y por fin re-empacamos el directorio en un paquete .deb.
Ahora podemos instalar nuestro nuevo paquete .deb con un
sudo apt install ./conduwuit.deb
Aunque conduwuit pueda correr como cualquier usuario, es mejor crear un usuario específicamente para conduwuit.
sudo adduser --system conduwuit --group --disabled-login --no-create-home
Hay que poner las permisiones del directorio adecuadas:
sudo chown -R root:root /etc/conduwuit
sudo chmod -R 755 /etc/conduwuit
Y vamos a poner las permisiones del directorio de su base de datos (se instala allí por defecto. Claro, pueden modificar dónde se guarda la base de datos en el archivo de configuración, pero habrá que asegurarse que los permisos cuadran)
sudo mkdir -p /var/lib/conduwuit/
sudo chown -R conduwuit:conduwuit /var/lib/conduwuit/
sudo chmod 700 /var/lib/conduwuit/
Queremos modificar el archivo de configuración en /etc/conduwuit/conduwuit.toml y agregar nuestro dominio para matrix. Ese dominio va a ser dominio.com (y no matrix.dominio.com). Voy a explicar sobre eso un poco más adelante.
Si usamos runit, pueden usar el siguiente servicio run:
#!/bin/sh
exec 2>&1
NAME=${PWD##*/}
DAEMON="$(command -v $NAME)"
[ -x "$DAEMON" ] || exit
sv start socklog >/dev/null
exec chpst -u conduwuit:conduwuit env CONDUWUIT_CONFIG="/etc/conduwuit/conduwuit.toml" "$DAEMON"
Si no usan Runit, pueden activar el servicio de systemd:
sudo systemctl enable conduwuit
Dominios y proxy reverso
Matrix necesita el puerto 8448 esté abierto, y también usa por parte el puerto 443. Necesitan abrir el puerto 8448 en su router. El puerto 443 no lo podemos simplemente mandar a conduwuit, porque es posible que necesitemos este puerto para otros servicios. Por eso vamos a usar el proxy reverso de Nginx.
Nosotros queremos que nuestro servidor de matrix sea dominio.com, sin usar un sub-dominio (ej matrix.dominio.org), así que incluyamos lo siguiente en el archivo de Nginx que es responsable para el dominio (bien sea default_server o algo más).
location = /.well-known/matrix/client {
default_type application/json;
add_header access-control-allow-headers "Origin, X-Requested-With, Content-Type, Accept, Authorization";
add_header access-control-allow-methods "GET, POST, PUT, DELETE, OPTIONS";
add_header access-control-allow-origin "*";
return 200 '{ "m.homeserver": { "base_url": "https://matrix.dominio.com" } }';
}
location /.well-known/matrix/server {
return 200 '{"m.server": "matrix.dominio.com:443"}';
}
Al incluir eso, el cliente puede tener un usuario como usuario:dominio.com, en vez de usuario:matrix.dominio.com.
Y luego incluyamos lo siguiente en el archivo nginx para matrix.dominio.com
location / {
proxy_pass http://10.1.0.11:6167;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# WebSocket support
proxy_http_version 1.1;
proxy_buffering off;
proxy_connect_timeout 43200000;
proxy_read_timeout 30d;
proxy_send_timeout 30d;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Aquí hay que remplazar el IP con el IP de su máquina que corre matrix. Si el proxy reverso corre en la misma máquina, pueden usar 127.0.0.1.
Lo que yo hice fue enviar el puerto 8448 al puerto 443 interior (para simplificar un poco nginx). Mi archivo de nginx es lo siguiente:
server {
listen 443 ssl ;
listen [::]:443 ssl ;
http2 on;
server_name matrix.dominio.com;
merge_slashes off;
access_log off;
ssl_certificate /ruta/a/fullchain.pem;
ssl_certificate_key /ruta/a/privkey.pem;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1.3 ;
ssl_ciphers 'TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384';
ssl_ecdh_curve X448:secp521r1:secp384r1;
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
client_max_body_size 10G;
client_body_timeout 3600s;
client_body_buffer_size 512k;
fastcgi_buffers 64 4K;
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "none" always;
fastcgi_hide_header X-Powered-By;
location / {
proxy_pass http://10.1.0.11:6167;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# WebSocket support
proxy_http_version 1.1;
proxy_buffering off;
proxy_connect_timeout 43200000;
proxy_read_timeout 30d;
proxy_send_timeout 30d;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Registramos el dominio matrix.dominio.com, empezamos (y reiniciamos) los servicios de conduwuit y nginx. Podemos modificar la configuración de conduwuit (en /etc/conduwuit/conduwuit.toml) para incluir un token que se usa para registrar usuarios nuevos. Ahora usando un cliente de matrix, podemos registrarnos en nuestro servidor. Tengan cuidado que en el teléfono, muchos clientes no permiten registrarse. Element (no-X) y Schildichat permite registrar un usuario nuevo. Ya que lo han registrado, pueden usar su contraseña para login en otros clientes.
Element web
Si ya tenemos los clientes de matrix instalados (existen muchos, y les recomiendo Schildichat X para android, y Element desktop para Linux/windows/mac), entonces esto no es necesario. Sin embargo, unas veces es útil poder acceder a matrix con solo su navegador web, por lo cual vamos a configurar el sitio web de Element.
Aunque hayan muchos clientes para android/ios de matrix, la mayoría no funcionan, o funcionan muy lento, en el web. Lo mejor que he encontrado es Element y Schildichat (basado en Element, pero no muy actual).
Es bastante fácil instalar este sitio web:
cd /var/www
wget https://github.com/element-hq/element-web/releases/download/v1.11.82/element-v1.11.82.tar.gz
tar -xvf element-*.tar.gz
chown -R www-data:www-data element/
Nota: si queremos usar Schildichat u otro cliente web, remplazamos los comandos para descargar el adecuado.
Movemos el archivo de configuración de element:
mv config.json.example config.json
y lo modificamos para incluir nuestro dominio.com.
Si instalamos Element en una máquina (ej la de conduwuit) que está detrás de un proxy (otro Nginx), entonces podemos hacer un sitio web http siple. En nginx, creamos un archivo de sitio web parecido a lo siguiente:
server {
listen 80 ;
root /var/www/element;
index index.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
}
A lo contrario, si tienen su sitio web de element directo sin un proxy, pueden remplazar el listen 80
y server_name _;
y colocar parte del archivo de web del proxy reverso, just abajo.
Si están usando un proxy reverso, pueden usar esta configuración:
server {
listen 443 ssl ;
listen [::]:443 ssl ;
http2 on;
server_name element.dominio.com;
#access_log off;
ssl_certificate /root/certs/actual/fullchain.pem;
ssl_certificate_key /root/certs/actual/privkey.pem;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1.3 ;
ssl_ciphers 'TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384';
ssl_ecdh_curve X448:secp521r1:secp384r1;
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
client_max_body_size 10G;
client_body_timeout 3600s;
client_body_buffer_size 512k;
fastcgi_buffers 64 4K;
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Permissions-Policy "interest-cohort=()";
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options "noopen" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "none" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Content-Security-Policy "frame-ancestors 'self'" always;
fastcgi_hide_header X-Powered-By;
location / {
# redirect all HTTP traffic to localhost:8000
proxy_pass http://10.1.0.11:82;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# WebSocket support
proxy_http_version 1.1;
proxy_buffering off;
proxy_connect_timeout 43200000;
proxy_read_timeout 30d;
proxy_send_timeout 30d;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Es importante tener dos dominios distinctos: uno de matrix.dominio.com, y otro para element.dominio.com para prevenir unos ataques.
Con esto ya estamos listos.