0%

Servidor de Mastodon con Docker

Hoy vamos a aprender cómo tener nuestro propio servidor de mastodon con docker usando ubuntu 22.04.

Como ya intenté una vez por mastodon (pero no era el lugar la verdad), vamos a aprender a desplegar y construir el contenedor de mastodon en Docker.
Lo harémos siguiendo los siguientes pasos:

  1. Preparar el equipo
  2. Bajar repositorio de mastodon
  3. Cambiar permisos a carpetas
  4. Configurar el entorno
  5. Configurar nginx
  6. Elasticsearch (opcional)
  7. Fin

1. Preparar el equipo

El paso mas importante de todos para preparar el servidor necesitamos primero es hacer todo el proceso con este video de fondo. Si no no funciona.

Asumimos que tenemos un correo para el SMTP y un dominio (si no es así mal empezamos, cierra esta web y empieza por ahí)
Ahora necesitaríamos:

  • Instalar docker
  • Configurar las reglas de salida del cortafuegos
  • Instalar certbot

Al lio.

Instalar Docker

No os dejeis engañar por los cantos de sirena de instalar el servicio cuando instales ubuntu server. A la minima te dará problemas.
Seguimos los pasos que aparecen en la página oficial

Que son, añadir el repositorio

1
2
3
4
5
6
7
8
9
10
11
12
13
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Add the repository to Apt sources:
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

E instalarlo

1
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Configurar las reglas de salida del cortafuegos

Usaremos ufw, aka Uncomplicated Firewall (siempre me hago un lio con iptables)

1
2
3
4
5
6
# Activar cortafuegos
sudo ufw enable

# Añadir reglas http y https (puertos 80 y 443)
sudo ufw allow http
sudo ufw allow https
Instalar certbot

Si queremos que funcione nuestro servidor de mastodon tenemos que tener un certificado para que funcione el https. Así que primero, actualizamos el sistema e instalamos

1
2
3
4
# Actualizamos el sistema (aunque puede que lo hicieramos en el paso anterior, si es asi saltatelo)
sudo apt-get update
# E instalamos
sudo apt-get install certbot python3-certbot-apache

Por ultimo instalamos el certificado.
Nota: Si has sido muy rápido y has instalado nginx primero, lanza sudo “systemctl stop nginx” para pararlo, ya que imagino que estará tocando las narices en el puerto 80

1
sudo certbot certonly --standalone -d tu.dominio

(cambia “tu.dominio” por tu puto dominio, no me seas cabestro)

Y con eso ya tendriamos el certbot funcionando así como los puertos abiertos. Ya estamos listos para la acción.

2. Bajar el repositorio de mastodon

Este es el paso mas corto (mira que bien), en primer lugar necesitamos elegir el directorio donde vamos a instalar mastodon.

No ese no, ojo cuidao que por defecto todos los archivos de tus usuarios y los federados se van a almacenar ahí, busca una partición con espacio de sobra al menos 100GB para ir moviendote.

¿Ese? ¿seguro? bueeno, pues ahora, clonas el repositorio
¿que como? a ver que te lo tengo que dar todo hecho…

1
2
cd /tu/directorio/elegido
git clone https://github.com/mastodon/mastodon.git

¿Cómo? ¿que no tienes git? Bueno, si es el caso vete aqui que tampoco te lo tengo que dar todo todo hecho

Si tienes que modificar el limite de caracteres te recomiendo un post anterior, concretamente este

Y con eso ya estaríamos. No es estrictamente necesario construir la imagen de docker, ya que si no la construimos la bajará cuando lancemos el server, pero si modificamos algo que no sea .env.production o docker-compose.yml no nos olvidemos de lanzar

1
docker build . -t "ghcr.io/mastodon/mastodon:v4.2.0"

3. Cambiar permisos a carpetas

Algunas carpetas necesitan algunos permisos especiales para la imagen de docker, si da problemas podemos cambiar los permisos de la carpeta /public

1
sudo chown -R 991:991 public/*

Y si usamos elasticsearch

1
sudo chown -R 1000:1000 elasticsearch/*

4. Configurar el entorno

Aqui tenemos dos opciones, o crear nuestro .env.production desde 0, para lo cual copiaremos .env.production.sample a .env.production

Desde la carpeta donde tenemos el repositorio

1
cp .env.production.sample .env.production

y rellenamos la configuración que queramos, o bien lanzamos

1
docker-compose run --rm web bundle exec rake mastodon:setup

Lo cual lanzara el asistente de configuración de mastodon.

Teneis más información en (la web oficial de mastodon)[https://docs.joinmastodon.org/admin/config/]

NOTA: Muy importante cuando relleneis la configuración, la dirección del host de postgresql es “db”, la de redis es “redis” y la de elasticsearch es “es” sin mas.
Hay que tener en cuenta que los contenedores se reconocen entre si con esos aliases y es la dirección que necesitan para comunicarse

5. Configurar nginx

Ya va quedando menos, configuremos nginx.
Primero copiamos el archivo nginx que tenemos en el repositorio de mastodon a nuestro directorio de configuración de nginx.

1
sudo cp /tu/directorio/elegido/mastodon/dist/nginx.conf /etc/nginx/sites-available/mastodon

Y ahora editamos:

Si buscamos hay dos secciones donde pone “server_name”

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
listen [::]:80;
server_name example.com;
root /home/mastodon/live/public;
location /.well-known/acme-challenge/ { allow all; }
location / { return 301 https://$host$request_uri; }
}

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;

hay que sustituir donde pone example.com por “tu.dominio” (de nuevo, tu puto dominio, no me seas merluzo)

Luego, hay una parte comentada con los certificados

1
2
3
# Uncomment these lines once you acquire a certificate:
# ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

Descomentandola y añadiendo tu dominio en el path quedaría en nuestro ejemplo algo así

1
2
3
# Uncomment these lines once you acquire a certificate:
ssl_certificate /etc/letsencrypt/live/tu.dominio/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/tu.dominio/privkey.pem;

(no me hagas repetirte lo mismo)
Ojo cuidao que si no hemos instalado el certificado digital nos fallará nginx cuando lo lancemos

Ahora tenemos una serie de “locations” que son algo asi:

1
2
3
4
5
location = /sw.js {
add_header Cache-Control "public, max-age=604800, must-revalidate";
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
try_files $uri =404;
}

En todos ellos, al usar docker tenemos que sustituir el try_files $uri =404 por try_files $uri @proxy;
Quedando así

1
2
3
4
5
location = /sw.js {
add_header Cache-Control "public, max-age=604800, must-revalidate";
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
try_files $uri @proxy;
}

Y ya para terminar al final del todo, hay dos “location” que tienen proxy_pass estas reglas son las rutas hacia el servicio de streaming de mastodon y el de la web hay que sustituir donde pone “https://backend“ por nuestro backend quedando mas o menos así

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
location ^~ /api/v1/streaming {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Proxy "";

proxy_pass http://127.0.0.1:4000;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";

tcp_nodelay on;
}

location @proxy {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Proxy "";
proxy_pass_header Server;

proxy_pass http://127.0.0.1:3000;
proxy_force_ranges on;
proxy_buffering on;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

proxy_cache CACHE;
proxy_cache_valid 200 7d;
proxy_cache_valid 410 24h;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
add_header X-Cached $upstream_cache_status;

tcp_nodelay on;
}

Ya casi estamos

6. Elasticsearch (opcional)

Para añadir elasticsearch a la mezcla, en nuestro repositorio de mastodon tenemos un docker-compose.yml

En ese archivo veremos una seccion “es:” comentada, tiene que quedar así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
es:
restart: always
image: docker.elastic.co/elasticsearch/elasticsearch:7.17.4
environment:
- "ES_JAVA_OPTS=-Xms512m -Xmx512m -Des.enforce.bootstrap.checks=true"
- "xpack.license.self_generated.type=basic"
- "xpack.security.enabled=false"
- "xpack.watcher.enabled=false"
- "xpack.graph.enabled=false"
- "xpack.ml.enabled=false"
- "bootstrap.memory_lock=true"
- "cluster.name=es-mastodon"
- "discovery.type=single-node"
- "thread_pool.write.queue_size=1000"
networks:
- external_network
- internal_network
healthcheck:
test: ["CMD-SHELL", "curl --silent --fail localhost:9200/_cluster/health || exit 1"]
volumes:
- ./elasticsearch:/usr/share/elasticsearch/data
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
ports:
- '127.0.0.1:9200:9200'

Es muy posible que elasticsearch os falle porque necesita una configuración de memoria virtual extra, en ese caso podemos lanzar

1
sysctl -w vm.max_map_count=262144

Pero en el siguiente reinicio la configuración se irá. Para ello editamos el fichero /etc/sysctl.conf y añadimos al final

1
vm.max_map_count=262144

7. Fin

Bueno, ha sido un largo y extraño viaje. Una vez aquí ya podemos lanzar el servidor de mastodon “sin miedo”*

Desde la carpeta del repositorio:
Empezaremos migrando la base de datos (para construir las estructuras)

1
docker-compose run --rm web rake db:migrate

Y si queremos podemos construir los indices de elasticsearch (aunque van a estar vacíos la verdad) y solo si usamos elasticsearch

1
docker-compose run --rm web bin/tootctl search deploy

Y por último lanzamos los contenedores.

1
docker-compose up -d

Con esto ya deberias poder acceder “sin miedo”* a tu.dominio (ejem… que no me entere yo que sigues usandolo literal) y empezar a disfrutar de un nodo descentralizado.

En fin, ¡hasta luego! y gracias por el pescado.

*El miedo existe y existirá porque ni siquiera he validado la guía apropiadamente