Wie installiere ich Mastodon Social Network auf Debian 12

Mastodon ist ein freies, dezentrales und quelloffenes soziales Netzwerk. Es wurde als Alternative zu Twitter entwickelt. Genau wie bei Twitter können sich Menschen gegenseitig folgen und Nachrichten, Bilder und Videos posten. Aber anders als bei Twitter gibt es keinen zentralen Speicher oder eine Autorität für die Inhalte.

Stattdessen arbeitet Mastodon mit Tausenden von verschiedenen Servern, die von verschiedenen Mitgliedern der Community betrieben werden. Nutzer/innen, die sich auf einem Server angemeldet haben, können sich ganz einfach mit Nutzer/innen auf einem anderen Netzwerk verbinden und sich gegenseitig folgen.

Jeder kann seine eigene Instanz eines Mastodon-Servers installieren. In dieser Anleitung lernst du, wie du deine Mastodon-Instanz auf einem Server mit Debian 12 mit Docker einrichtest. Docker erleichtert die Installation von Mastodon, da alle benötigten Pakete und Dienste in Containern enthalten sind.

Voraussetzungen

  • Ein Server mit Debian 12 mit mindestens 2 CPU-Kernen und 2 GB Arbeitsspeicher. Du musst den Server entsprechend deinen Anforderungen aufrüsten.
  • Ein Nicht-Root-Benutzer mit sudo-Rechten.
  • Einen vollständig qualifizierten Domainnamen (FQDN), der auf deinen Server verweist. Für unsere Zwecke verwenden wir mastodon.example.com als Domänennamen.
  • Mastodon sendet E-Mail-Benachrichtigungen an die Benutzer. Wir empfehlen dir, einen Transaktions-E-Mail-Dienst eines Drittanbieters wie Mailgun, SendGrid, Amazon SES oder Sparkpost zu verwenden. Die Anweisungen in diesem Leitfaden beziehen sich auf Amazon SES.
  • Stelle sicher, dass alles auf dem neuesten Stand ist.
    $ sudo apt update
    
  • Installiere grundlegende Hilfspakete. Einige davon sind vielleicht schon installiert.
    $ sudo apt install curl wget nano software-properties-common dirmngr apt-transport-https ca-certificates lsb-release debian-archive-keyring gnupg2 ufw unzip -y
    

Schritt 1 – Firewall konfigurieren

Der erste Schritt besteht darin, die Firewall zu konfigurieren. Debian wird standardmäßig mit ufw (Uncomplicated Firewall) ausgeliefert.

Überprüfe, ob die Firewall läuft.

$ sudo ufw status

Du solltest die folgende Ausgabe erhalten.

Status: inactive

Erlaube den SSH-Port, damit die Firewall die aktuelle Verbindung nicht unterbricht, wenn du sie aktivierst.

$ sudo ufw allow OpenSSH

Lasse auch HTTP- und HTTPS-Ports zu.

$ sudo ufw allow http
$ sudo ufw allow https

Aktiviere die Firewall

$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

Überprüfe den Status der Firewall erneut.

$ sudo ufw status

Du solltest eine ähnliche Ausgabe sehen.

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443                        ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443 (v6)                   ALLOW       Anywhere (v6)

Schritt 2 – Installiere Docker und Docker Compose

Debian 12 wird mit einer älteren Version von Docker ausgeliefert. Um die neueste Version zu installieren, importiere zunächst den Docker GPG-Schlüssel.

$ sudo install -m 0755 -d /etc/apt/keyrings
$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ sudo chmod a+r /etc/apt/keyrings/docker.gpg

Erstelle die Docker-Repository-Datei.

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

Aktualisiere die Liste der System-Repositorys.

$ sudo apt update

Installiere die neueste Version von Docker.

$ sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Überprüfe, ob sie läuft.

$ sudo systemctl status docker
? docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; preset: enabled)
     Active: active (running) since Mon 2024-01-01 09:00:14 UTC; 17s ago
TriggeredBy: ? docker.socket
       Docs: https://docs.docker.com
   Main PID: 1839 (dockerd)
      Tasks: 9
     Memory: 27.6M
        CPU: 598ms
     CGroup: /system.slice/docker.service
             ??1839 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

Docker erfordert standardmäßig Root-Rechte. Wenn du vermeiden willst, dass du jedes Mal sudo verwendest, wenn du den Befehl docker ausführst, füge deinen Benutzernamen der Gruppe docker hinzu.

$ sudo usermod -aG docker $(whoami)

Um diese Änderung zu aktivieren, musst du dich vom Server abmelden und als derselbe Benutzer wieder anmelden oder den folgenden Befehl verwenden.

$ su - ${USER}

Bestätige, dass dein Benutzer der Docker-Gruppe hinzugefügt wurde.

$ groups
navjot sudo users docker

Schritt 3 – Vorbereitungen für die Installation

Das Standardlimit für die mmap-Anzahl ist für Elasticsearch sehr niedrig. Führe den folgenden Befehl aus, um den Standardwert zu überprüfen.

$ sudo sysctl vm.max_map_count

Du erhältst die folgende Ausgabe.

vm.max_map_count = 65530

Erhöhe den Wert mit den folgenden Befehlen.

$ echo "vm.max_map_count=262144" | sudo tee /etc/sysctl.d/90-max_map_count.conf
vm.max_map_count=262144
$ sudo sysctl --load /etc/sysctl.d/90-max_map_count.conf
vm.max_map_count=262144

Schritt 4 – Mastodon installieren

Verzeichnisse erstellen und Besitzverhältnisse festlegen

Erstelle Verzeichnisse für Mastodon und die zugehörigen Dienste.

$ sudo mkdir -p /opt/mastodon/database/{postgresql,pgbackups,redis,elasticsearch}
$ sudo mkdir -p /opt/mastodon/web/{public,system}
$ sudo mkdir -p /opt/mastodon/branding

Setze die richtigen Besitzverhältnisse für die Verzeichnisse Elasticsearch, web und backup.

$ sudo chown 991:991 /opt/mastodon/web/{public,system}
$ sudo chown 1000 /opt/mastodon/database/elasticsearch
$ sudo chown 70:70 /opt/mastodon/database/pgbackups

Wechsle in das Mastodon-Verzeichnis.

$ cd /opt/mastodon

Umgebungs- und Docker-Compose-Dateien erstellen

Erstelle Umgebungsdateien für die Anwendung und die Datenbank.

$ sudo touch application.env database.env

Erstelle und öffne die Docker compose Datei zur Bearbeitung.

$ sudo nano docker-compose.yml

Füge den folgenden Code in die Datei ein.

services:
  postgresql:
    image: postgres:16-alpine
    env_file: database.env
    restart: always
    shm_size: 512mb
    healthcheck:
      test: ['CMD', 'pg_isready', '-U', 'postgres']
    volumes:
      - postgresql:/var/lib/postgresql/data
      - pgbackups:/backups
    networks:
      - internal_network

  redis:
    image: redis:7-alpine
    restart: always
    healthcheck:
      test: ['CMD', 'redis-cli', 'ping']
    volumes:
      - redis:/data
    networks:
      - internal_network

  redis-volatile:
    image: redis:7-alpine
    restart: always
    healthcheck:
      test: ['CMD', 'redis-cli', 'ping']
    networks:
      - internal_network

  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.17.16
    restart: always
    env_file: database.env
    environment:
      - cluster.name=elasticsearch-mastodon
      - discovery.type=single-node
      - bootstrap.memory_lock=true
      - xpack.security.enabled=true
      - ingest.geoip.downloader.enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m -Des.enforce.bootstrap.checks=true"
      - xpack.license.self_generated.type=basic
      - xpack.watcher.enabled=false
      - xpack.graph.enabled=false
      - xpack.ml.enabled=false
      - thread_pool.write.queue_size=1000
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65536
        hard: 65536
    healthcheck:
      test: ["CMD-SHELL", "nc -z elasticsearch 9200"]
    volumes:
      - elasticsearch:/usr/share/elasticsearch/data
    networks:
      - internal_network
    ports:
      - '127.0.0.1:9200:9200'

  website:
    image: tootsuite/mastodon:v4.2.3
    env_file:
      - application.env
      - database.env
    command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000"
    restart: always
    depends_on:
      - postgresql
      - redis
      - redis-volatile
      - elasticsearch
    ports:
      - '127.0.0.1:3000:3000'
    networks:
      - internal_network
      - external_network
    healthcheck:
      test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:3000/health || exit 1']
    volumes:
      - uploads:/mastodon/public/system

  shell:
    image: tootsuite/mastodon:v4.2.3
    env_file:
      - application.env
      - database.env
    command: /bin/bash
    restart: "no"
    networks:
      - internal_network
      - external_network
    volumes:
      - uploads:/mastodon/public/system
      - static:/static

  streaming:
    image: tootsuite/mastodon:v4.2.3
    env_file:
      - application.env
      - database.env
    command: node ./streaming
    restart: always
    depends_on:
      - postgresql
      - redis
      - redis-volatile
      - elasticsearch
    ports:
      - '127.0.0.1:4000:4000'
    networks:
      - internal_network
      - external_network
    healthcheck:
      test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:4000/api/v1/streaming/health || exit 1']

  sidekiq:
    image: tootsuite/mastodon:v4.2.3
    env_file:
      - application.env
      - database.env
    command: bundle exec sidekiq
    restart: always
    depends_on:
      - postgresql
      - redis
      - redis-volatile
      - website
    networks:
      - internal_network
      - external_network
    healthcheck:
      test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 6' || false"]
    volumes:
      - uploads:/mastodon/public/system

networks:
  external_network:
  internal_network:
    internal: true

volumes:
  postgresql:
    driver_opts:
      type: none
      device: /opt/mastodon/database/postgresql
      o: bind
  pgbackups:
    driver_opts:
      type: none
      device: /opt/mastodon/database/pgbackups
      o: bind
  redis:
    driver_opts:
      type: none
      device: /opt/mastodon/database/redis
      o: bind
  elasticsearch:
    driver_opts:
      type: none
      device: /opt/mastodon/database/elasticsearch
      o: bind
  uploads:
    driver_opts:
      type: none
      device: /opt/mastodon/web/system
      o: bind
  static:
    driver_opts:
      type: none
      device: /opt/mastodon/web/public
      o: bind

Speichere die Datei, indem du Strg + X drückst und Y eingibst, wenn du dazu aufgefordert wirst.

Zum Zeitpunkt der Erstellung dieses Tutorials ist die neueste Version von Mastodon v4.2.3 verfügbar. Schau auf der Mastodon GitHub Releases Seite nach und passe die Version in der Docker Compose Datei entsprechend an. Wir verwenden auch die neuesten Versionen von PostgreSQL und Redis. Du kannst sie nach deinen Anforderungen anpassen. Wir verwenden im Moment Elasticsearch 7.17.16.

Anwendungsgeheimnisse erstellen

Der nächste Schritt ist die Erstellung der Anwendungsgeheimnisse.

Erstelle die Werte SECRET_KEY_BASE und OTP_SECRET, indem du den folgenden Befehl zweimal ausführst. Das erste Mal wird einige Zeit in Anspruch nehmen, da es die Images zieht.

$ docker compose run --rm shell bundle exec rake secret
349623c049e3b856f6848638146e459857862b908ed387bbef372a30d9bd7c604fc4de5338addc86bd369a99d38ef59bacfa28e02a1750f7094ea6ede05457b8

Du kannst dafür auch das Dienstprogramm openssl verwenden.

$ openssl rand -hex 64
ae01cf7d4dfae0182461a1345f1f2bf159658a27339ffafe7d356bef9ee8d4fa015ab2e72a608f236bd8e3f9b2af2dcb1d55ee5c8e43646959112c7da5582f4b

Erstelle die Werte VAPID_PRIVATE_KEY und VAPID_PUBLIC_KEY, indem du den folgenden Befehl ausführst.

$ docker compose run --rm shell bundle exec rake mastodon:webpush:generate_vapid_key

Du wirst eine ähnliche Ausgabe erhalten.

VAPID_PRIVATE_KEY=u2qsCs5JdmdmMLnUuU0sgmFGvZedteJz-lFB_xF4_ac=
VAPID_PUBLIC_KEY=BJXjE2hIXvFpo6dnHqyf1i-2PcP-cBoL95UCmhhxwlAgtFw_vnrYp4GBneR7_cmI9LZUYjHFh-TBAPSb9WTqH9A=

Verwende das Dienstprogramm openssl, um PostgreSQL- und Elasticsearch-Passwörter zu generieren.

$ openssl rand -hex 15
dd0bd7a95960623ed8e084a1fb7d5c
$ openssl rand -hex 15
0fb52834c991b5e296c647166185bc

Mastodon Umgebungsdateien

Öffne die Datei application.env zum Bearbeiten.

$ sudo nano application.env

Füge die folgenden Zeilen in die Datei ein.

# environment
RAILS_ENV=production
NODE_ENV=production

# domain
LOCAL_DOMAIN=mastodon.example.com

# redirect to the first profile
SINGLE_USER_MODE=false

# do not serve static files
RAILS_SERVE_STATIC_FILES=false

# concurrency
WEB_CONCURRENCY=2
MAX_THREADS=5

# pgbouncer
#PREPARED_STATEMENTS=false

# locale
DEFAULT_LOCALE=en

# email, not used
SMTP_SERVER=email-smtp.us-west-2.amazonaws.com
SMTP_PORT=587
SMTP_LOGIN=AKIA3FIG4NVFB343PZEI
SMTP_PASSWORD=AZX01WiA6JGbeZ2pwVXnyC9DhEa2nKcmXSu/zbLp
SMTP_FROM_ADDRESS=noreply@nspeaks.com

# secrets
SECRET_KEY_BASE=349623c049e3b856f6848638146e459857862b908ed387bbef372a30d9bd7c604fc4de5338addc86bd369a99d38ef59bacfa28e02a1750f7094ea6ede05457b8
OTP_SECRET=ae01cf7d4dfae0182461a1345f1f2bf159658a27339ffafe7d356bef9ee8d4fa015ab2e72a608f236bd8e3f9b2af2dcb1d55ee5c8e43646959112c7da5582f4b

# Changing VAPID keys will break push notifications
VAPID_PRIVATE_KEY=oNe_4BEL7Tpc3iV8eMtLegfLwrzA7ifitGJ2YOg3dUM=
VAPID_PUBLIC_KEY=BKBgmB90vIrJg6Ifq3cCHixalyPghJDkui9vm1wscxvAfNNoAQL0KinoxRTLDp0UFlGK_ahUG2n4W2n4x9AUAWM=

# IP and session retention
# -----------------------
# Make sure to modify the scheduling of ip_cleanup_scheduler in config/sidekiq.yml
# to be less than daily if you lower IP_RETENTION_PERIOD below two days (172800).
# -----------------------
IP_RETENTION_PERIOD=2592000
SESSION_RETENTION_PERIOD=2592000

Speichere die Datei, indem du Strg + X drückst und Y eingibst, wenn du dazu aufgefordert wirst.

Wir haben den Amazon SES-Versanddienst aktiviert. Wenn du ihn nicht brauchst, kannst du den Abschnitt löschen. Standardmäßig speichert Mastodon eine IP-Adresse für 1 Jahr, aber wir haben sie auf 30 Tage (2592000 Sekunden) geändert. Du kannst sie nach deinen Bedürfnissen ändern. Achte darauf, dass du sie länger als 2 Tage speicherst, sonst musst du ein bisschen mehr basteln, was den Rahmen dieses Tutorials sprengen würde.

Öffne die Datei database.env, um sie zu bearbeiten.

$ sudo nano database.env

Füge die folgenden Zeilen in die Datei ein.

# postgresql configuration
POSTGRES_USER=mastodon
POSTGRES_DB=mastodon
POSTGRES_PASSWORD=0fb52834c991b5e296c647166185bc
PGPASSWORD=0fb52834c991b5e296c647166185bc
PGPORT=5432
PGHOST=postgresql
PGUSER=mastodon

# pgbouncer configuration
#POOL_MODE=transaction
#ADMIN_USERS=postgres,mastodon
#DATABASE_URL="postgres://mastodon:0fb52834c991b5e296c647166185bc@postgresql:5432/mastodon"

# elasticsearch
ELASTIC_PASSWORD=dd0bd7a95960623ed8e084a1fb7d5c

# mastodon database configuration
#DB_HOST=pgbouncer
DB_HOST=postgresql
DB_USER=mastodon
DB_NAME=mastodon
DB_PASS=0fb52834c991b5e296c647166185bc
DB_PORT=5432

REDIS_HOST=redis
REDIS_PORT=6379

CACHE_REDIS_HOST=redis-volatile
CACHE_REDIS_PORT=6379

ES_ENABLED=true
ES_HOST=elasticsearch
ES_PORT=9200
ES_USER=elastic
ES_PASS=dd0bd7a95960623ed8e084a1fb7d5c

Speichere die Datei, indem du Strg + X drückst und Y eingibst, wenn du dazu aufgefordert wirst.

Mastodon vorbereiten

Bereite die statischen Dateien vor, damit sie von Nginx bedient werden können. Dieser Schritt wird einige Zeit in Anspruch nehmen, da Docker alle Images zum ersten Mal abruft.

$ docker compose run --rm shell bash -c "cp -r /opt/mastodon/public/* /static/"

Bringe die Datenschicht hoch.

$ docker compose up -d postgresql redis redis-volatile

Überprüfe den Status der Container.

$ watch docker compose ps

Docker Compose beobachten

Warte auf running (healthy), drücke dann Ctrl + C und initialisiere die Datenbank mit dem folgenden Befehl.

$ docker compose run --rm shell bundle exec rake db:setup

Wenn du die Fehlermeldung erhältst, dass die Datenbank mastodon bereits existiert, führe den folgenden Befehl aus.

$ docker compose run --rm shell bundle exec rake db:migrate

Schritt 5 – Nginx installieren

Debian 12 wird mit einer älteren Version von Nginx ausgeliefert. Um die neueste Version zu installieren, musst du das offizielle Nginx-Repository herunterladen.

Importiere den Signierschlüssel von Nginx.

$ curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
    | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

Füge das Repository für die Mainline-Version von Nginx hinzu.

$ echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/mainline/debian `lsb_release -cs` nginx" \
    | sudo tee /etc/apt/sources.list.d/nginx.list

Aktualisiere die System-Repositories.

$ sudo apt update

Installiere Nginx.

$ sudo apt install nginx

Überprüfe die Installation. Auf Debian-Systemen brauchst du sudo, um den folgenden Befehl auszuführen.

$ sudo nginx -v
nginx version: nginx/1.25.3

Starte den Nginx-Server.

$ sudo systemctl start nginx

Überprüfe den Status des Servers.

$ sudo systemctl status nginx
? nginx.service - nginx - high performance web server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
     Active: active (running) since Mon 2024-01-01 10:17:38 UTC; 4s ago
       Docs: https://nginx.org/en/docs/
    Process: 8972 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)
   Main PID: 8973 (nginx)
      Tasks: 3 (limit: 4637)
     Memory: 2.9M
        CPU: 17ms
     CGroup: /system.slice/nginx.service
             ??8973 "nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf"
             ??8974 "nginx: worker process"
             ??8975 "nginx: worker process"

Jan 01 10:17:38 mastodon systemd[1]: Starting nginx.service - nginx - high performance web server...
Jan 01 10:17:38 mastodon systemd[1]: Started nginx.service - nginx - high performance web server.

Schritt 6 – SSL installieren

Wir müssen Certbot installieren, um das SSL-Zertifikat zu erstellen. Du kannst Certbot entweder über das Repository von Debian installieren oder die neueste Version mit dem Snapd-Tool herunterladen. Wir werden die Snapd-Version verwenden.

Bei Debian 12 ist Snapd noch nicht installiert. Installiere das Snapd-Paket.

$ sudo apt install snapd

Führe die folgenden Befehle aus, um sicherzustellen, dass deine Version von Snapd auf dem neuesten Stand ist. Vergewissere dich, dass deine Version von Snapd auf dem neuesten Stand ist.

$ sudo snap install core
$ sudo snap refresh core

Installiere Certbot.

$ sudo snap install --classic certbot

Verwende den folgenden Befehl, um sicherzustellen, dass der Certbot-Befehl ausgeführt wird, indem du einen symbolischen Link zum Verzeichnis /usr/bin erstellst.

$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

Überprüfe die Installation.

$ certbot --version
certbot 2.8.0

Führe den folgenden Befehl aus, um ein SSL-Zertifikat zu erzeugen.

$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m name@example.com -d mastodon.example.com

Mit dem obigen Befehl wird ein Zertifikat in das Verzeichnis /etc/letsencrypt/live/mastodon.example.com auf deinem Server heruntergeladen.

Erstelle ein Diffie-Hellman-Gruppenzertifikat.

$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096

Überprüfe den Certbot Erneuerungszeitplanungsdienst.

$ systemctl list-timers

Du findest snap.certbot.renew.service als einen der Dienste, die für die Ausführung vorgesehen sind.

NEXT                        LEFT        LAST                        PASSED             UNIT                    ACTIVATES
-----------------------------------------------------------------------------------------------------------------------------------------
Mon 2024-01-01 20:03:52 UTC 9h left     Mon 2023-12-11 21:56:24 UTC 2 weeks 6 days ago apt-daily.timer         apt-daily.service
Mon 2024-01-01 21:06:00 UTC 10h left    -                           -                  snap.certbot.renew.timersnap.certbot.renew.service
Tue 2024-01-02 00:00:00 UTC 13h left    -                           -                  dpkg-db-backup.timer    dpkg-db-backup.service

Führe einen Probelauf des Prozesses durch, um zu prüfen, ob die SSL-Erneuerung einwandfrei funktioniert.

$ sudo certbot renew --dry-run

Wenn du keine Fehler siehst, bist du bereit. Dein Zertifikat wird automatisch erneuert.

Schritt 7 – Nginx konfigurieren

Öffne die Datei /etc/nginx/nginx.conf zum Bearbeiten.

$ sudo nano /etc/nginx/nginx.conf

Füge die folgende Zeile vor der Zeile include /etc/nginx/conf.d/*.conf; ein.

server_names_hash_bucket_size 64;

Speichere die Datei, indem du Strg + X drückst und Y eingibst, wenn du dazu aufgefordert wirst.

Erstelle und öffne die Datei /etc/nginx/conf.d/mastodon.conf zum Bearbeiten.

$ sudo nano /etc/nginx/conf.d/mastodon.conf

Füge den folgenden Code in die Datei ein.

map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}

upstream backend {
    server 127.0.0.1:3000 fail_timeout=0;
}

upstream streaming {
    server 127.0.0.1:4000 fail_timeout=0;
}

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHE:10m inactive=7d max_size=1g;

server {
  listen 80 default_server;
  server_name mastodon.example.com;
  location / { return 301 https://$host$request_uri; }
}

server {
   listen 443 ssl;
   server_name mastodon.example.com;
   
   access_log  /var/log/nginx/mastodon.access.log;
   error_log   /var/log/nginx/mastodon.error.log;

   http2 on; # Enable HTTP/2 - works only on Nginx 1.25.1+

   ssl_certificate /etc/letsencrypt/live/mastodon.example.com/fullchain.pem;
   ssl_certificate_key /etc/letsencrypt/live/mastodon.example.com/privkey.pem;
   ssl_trusted_certificate /etc/letsencrypt/live/mastodon.example.com/chain.pem;
   ssl_session_timeout 1d;

   # Enable TLS versions (TLSv1.3 is required upcoming HTTP/3 QUIC).
   ssl_protocols TLSv1.2 TLSv1.3;

   # Enable TLSv1.3's 0-RTT. Use $ssl_early_data when reverse proxying to
   # prevent replay attacks.
   #
   # @see: https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_early_data
   ssl_early_data on;

   ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384';
   ssl_prefer_server_ciphers on;
   ssl_session_cache shared:SSL:10m;
   ssl_session_tickets off;
   
   keepalive_timeout    70;
   sendfile             on;
   client_max_body_size 80m;

   # OCSP Stapling ---
   # fetch OCSP records from URL in ssl_certificate and cache them
   ssl_stapling on;
   ssl_stapling_verify on;
   ssl_dhparam /etc/ssl/certs/dhparam.pem;

   add_header X-Early-Data $tls1_3_early_data;
   
   root /opt/mastodon/web/public;
   
   gzip on;
   gzip_disable "msie6";
   gzip_vary on;
   gzip_proxied any;
   gzip_comp_level 6;
   gzip_buffers 16 8k;
   gzip_http_version 1.1;
   gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml image/x-icon;
   
   add_header Strict-Transport-Security "max-age=31536000" always;

  location / {
    try_files $uri @proxy;
  }

  location ~ ^/(system/accounts/avatars|system/media_attachments/files) {
    add_header Cache-Control "public, max-age=31536000, immutable";
    add_header Strict-Transport-Security "max-age=31536000" always;
    root /opt/mastodon/;
    try_files $uri @proxy;
  }

  location ~ ^/(emoji|packs) {
    add_header Cache-Control "public, max-age=31536000, immutable";
    add_header Strict-Transport-Security "max-age=31536000" always;
    try_files $uri @proxy;
  }

  location /sw.js {
    add_header Cache-Control "public, max-age=0";
    add_header Strict-Transport-Security "max-age=31536000" always;
    try_files $uri @proxy;
  }

  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://backend;
    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;
    add_header Strict-Transport-Security "max-age=31536000" always;

    tcp_nodelay on;
  }

  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://streaming;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }

  error_page 500 501 502 503 504 /500.html;
}

# This block is useful for debugging TLS v1.3. Please feel free to remove this
# and use the `$ssl_early_data` variable exposed by NGINX directly should you
# wish to do so.
map $ssl_early_data $tls1_3_early_data {
  "~." $ssl_early_data;
  default "";
}

Wenn du fertig bist, speichere die Datei, indem du Strg + X drückst und Y eingibst, wenn du dazu aufgefordert wirst.

Überprüfe die Syntax der Nginx-Konfigurationsdatei.

$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Starte den Nginx-Server neu.

$ sudo systemctl restart nginx

Schritt 8 – Mastodon starten

Tootctl CLI-Tool

Das Tootctl CLI-Tool wird verwendet, um administrative Aufgaben auf Mastodon durchzuführen. Wir müssen es auf der Host-Shell zugänglich machen.

Erstelle die Datei /usr/local/bin/tootctl und öffne sie zum Bearbeiten.

$ sudo nano /usr/local/bin/tootctl

Füge den folgenden Code in die Datei ein.

#!/bin/bash
docker compose -f /opt/mastodon/docker-compose.yml run --rm shell tootctl "$@"

Speichere die Datei, indem du Strg + X drückst und Y eingibst, wenn du dazu aufgefordert wirst.

Erteile der Datei die Berechtigung zur Ausführung.

$ sudo chmod +x /usr/local/bin/tootctl

Mastodon-Dienstdatei

Du kannst die Mastodon-Container mit dem Docker-Befehl compose starten, aber es ist einfacher, dies über eine systemd Unit-Datei zu tun.

Erstelle und öffne die Mastodon-Dienstdatei zum Bearbeiten.

$ sudo nano /etc/systemd/system/mastodon.service

Füge den folgenden Code in die Datei ein.

[Unit]
Description=Mastodon service
After=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes

WorkingDirectory=/opt/mastodon
ExecStart=/usr/bin/docker compose -f /opt/mastodon/docker-compose.yml up -d
ExecStop=/usr/bin/docker compose -f /opt/mastodon/docker-compose.yml down

[Install]
WantedBy=multi-user.target

Speichere die Datei, indem du Strg + X drückst und Y eingibst, wenn du dazu aufgefordert wirst.

Lade den Systemdaemon neu, um die Servicedatei zu starten.

$ sudo systemctl daemon-reload

Aktiviere und starte den Mastodon-Dienst.

$ sudo systemctl enable --now mastodon.service

Überprüfe den Status der Docker-Container.

$ watch docker compose -f /opt/mastodon/docker-compose.yml ps

Mastodon Docker Container Status

Sobald der Status der Container auf running (healthy) wechselt, verlasse den Bildschirm, indem du Strg + C drückst.

Erstelle den Benutzer admin für Mastodon und notiere dir das angegebene Passwort.

$ tootctl accounts create navjot --email name@example.com --confirmed --role Owner
OK
New password: 1338afbe1b4e06e823b6625da80cb537

Wenn du die Benutzerregistrierung schließen willst, verwende den folgenden Befehl.

$ tootctl settings registrations close

Um die Registrierungen wieder zu öffnen, gibst du den folgenden Befehl ein.

$ tootctl settings registrations open

Bevor du Elasticsearch-Indizes erstellen und befüllen kannst, musst du ein Toot erstellen. Sobald du ein Toot erstellt hast, gibst du den folgenden Befehl ein.

$ tootctl search deploy

Möglicherweise bekommst du die folgende Fehlermeldung.

/opt/mastodon/vendor/bundle/ruby/3.0.0/gems/ruby-progressbar-1.11.0/lib/ruby-progressbar/progress.rb:76:in `total=': You can't set the item's total value to less than the current progress. (ProgressBar::InvalidProgressError)
        from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/ruby-progressbar-1.11.0/lib/ruby-progressbar/base.rb:178:in `block in update_progress'
        from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/ruby-progressbar-1.11.0/lib/ruby-progressbar/output.rb:43:in `with_refresh'
        from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/ruby-progressbar-1.11.0/lib/ruby-progressbar/base.rb:177:in `update_progress'
        from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/ruby-progressbar-1.11.0/lib/ruby-progressbar/base.rb:101:in `total='
        from /opt/mastodon/lib/mastodon/search_cli.rb:67:in `deploy'
        from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/thor-1.2.1/lib/thor/command.rb:27:in `run'
        from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/thor-1.2.1/lib/thor/invocation.rb:127:in `invoke_command'
        from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/thor-1.2.1/lib/thor.rb:392:in `dispatch'
        from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/thor-1.2.1/lib/thor/invocation.rb:116:in `invoke'
        from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/thor-1.2.1/lib/thor.rb:243:in `block in subcommand'
        from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/thor-1.2.1/lib/thor/command.rb:27:in `run'
        from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/thor-1.2.1/lib/thor/invocation.rb:127:in `invoke_command'
        from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/thor-1.2.1/lib/thor.rb:392:in `dispatch'
        from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/thor-1.2.1/lib/thor/base.rb:485:in `start'
        from /opt/mastodon/bin/tootctl:8:in `<main>'

In diesem Fall musst du die Shell des Website-Containers aufrufen.

$ docker exec -it mastodon-website-1 /bin/bash

Führe den folgenden Befehl aus.

$ sed -E '/progress.total = /d' -i lib/mastodon/search_cli.rb

Beende die Container-Shell.

$ exit

Führe den Befehl Elasticsearch deploy erneut aus. Manchmal funktioniert der Befehl auch zu einem späteren Zeitpunkt. Dies ist ein laufendes Problem bei Mastodon, daher gibt es im Moment noch keine endgültige Lösung.

$ tootctl search deploy
Done! 1/?? |-=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=|  ETA: ??:??:?? (0 docs/s)
Indexed 1 records, de-indexed 0

Zusätzliche Hilfsdienste

Lass uns einen weiteren Dienst zum Entfernen heruntergeladener Mediendateien erstellen.

Erstelle und öffne den Mastodon-Medienentfernungsdienst zur Bearbeitung.

$ sudo nano /etc/systemd/system/mastodon-media-remove.service

Füge den folgenden Code in ihn ein.

[Unit]
Description=Mastodon - media remove service
Wants=mastodon-media-remove.timer

[Service]
Type=oneshot
StandardError=null
StandardOutput=null

WorkingDirectory=/opt/mastodon
ExecStart=/usr/bin/docker compose -f /opt/mastodon/docker-compose.yml run --rm shell tootctl media remove

[Install]
WantedBy=multi-user.target

Speichere die Datei, indem du Strg + X drückst und Y eingibst, wenn du dazu aufgefordert wirst.

Wenn du die Medienentfernung zeitlich planen möchtest, kannst du einen Timer-Dienst dafür einrichten.

$ sudo nano /etc/systemd/system/mastodon-media-remove.timer

Füge den folgenden Code ein.

[Unit]
Description=Schedule a media remove every week

[Timer]
Persistent=true
OnCalendar=Sat *-*-* 00:00:00
Unit=mastodon-media-remove.service

[Install]
WantedBy=timers.target

Speichere die Datei, indem du Strg + X drückst und Y eingibst, wenn du dazu aufgefordert wirst.

Du kannst einen weiteren Dienst einrichten, um die mit OpenGraph-Tags erstellten Rich-Vorschaukarten zu entfernen.

$ sudo nano /etc/systemd/system/mastodon-preview_cards-remove.service

Füge den folgenden Code ein.

[Unit]
Description=Mastodon - preview cards remove service
Wants=mastodon-preview_cards-remove.timer

[Service]
Type=oneshot
StandardError=null
StandardOutput=null

WorkingDirectory=/opt/mastodon
ExecStart=/usr/bin/docker compose -f /opt/mastodon/docker-compose.yml run --rm shell tootctl preview_cards remove

[Install]
WantedBy=multi-user.target

Speichere die Datei, indem du Strg + X drückst und Y eingibst, wenn du dazu aufgefordert wirst.

Richte den entsprechenden Timer-Dienst ein.

$ sudo nano /etc/systemd/system/mastodon-preview_cards-remove.timer

Füge den folgenden Code ein.

[Unit]
Description=Schedule a preview cards remove every week

[Timer]
Persistent=true
OnCalendar=Sat *-*-* 00:00:00
Unit=mastodon-preview_cards-remove.service

[Install]
WantedBy=timers.target

Speichere die Datei, indem du Strg + X drückst und Y eingibst, wenn du dazu aufgefordert wirst.

Lade den Systemdaemon neu.

$ sudo systemctl daemon-reload

Aktiviere und starte die Timer.

$ sudo systemctl enable --now mastodon-preview_cards-remove.timer
$ sudo systemctl enable --now mastodon-media-remove.timer

Liste alle Timer auf, um den Zeitplan der Mastodon-Dienste zu überprüfen.

$ systemctl list-timers
.....
Sat 2024-01-06 00:00:00 UTC 4 days left -                           -                  mastodon-media-remove.timer         mastodon-media-remove.service
Sat 2024-01-06 00:00:00 UTC 4 days left -                           -                  mastodon-preview_cards-remove.timer mastodon-preview_cards-remove.service

Zugriff auf Mastodon

Besuche die URL https://mastodon.example.com, um auf deine Instanz zuzugreifen, und du wirst eine ähnliche Seite sehen.

Mastodon Homepage

Im obigen Screenshot kannst du sehen, dass es 0 Benutzer gibt. Das liegt daran, dass wir uns noch nicht eingeloggt haben. Auch wenn du ein Administratorkonto erstellst, wird es beim ersten Durchlauf nicht auf der Hauptseite angezeigt. Melde dich dazu in deiner Instanz an und du gelangst auf die folgende Seite.

Mastodon TimeLine Seite

Klicke auf die Option Einstellungen in der rechten Seitenleiste, um zu den Einstellungen zu gelangen. Klicke auf die Option Administration im linken Menü, um auf das Mastodon Administrationspanel zuzugreifen.

Mastodon Verwaltungstafel

Klicke auf die Option Servereinstellungen in der linken Seitenleiste.

Mastodon Admin User Information

Hier gibst du deinen Kontaktbenutzernamen und deine geschäftliche E-Mail-Adresse ein, die dann auf der Startseite deines Servers angezeigt werden. Gib außerdem verschiedene andere Informationen ein, z.B. die Serverbeschreibung, das Logo und die Serverregeln, um deine Mastodon-Instanz anzupassen.

Schritt 9 – Mastodon-Wartung

Um die Leistung und die Logs deiner Mastodon-Instanz einzusehen, gehe zu https://mastodon.example.com/sidekiq/.

Hier kannst du eine Liste verschiedener Prozesse und geplanter Aufgaben im Zusammenhang mit deiner Mastodon-Instanz einsehen. Du kannst auch nach fehlgeschlagenen Aufgaben unter dem Abschnitt Dead or Retries suchen. Hier erfährst du auch, wie viel Speicherplatz deine Instanz verbraucht.

Mastodon Sidekiq Seite

Du kannst den Zustand der Datenbank deiner Instanz unter https://mastodon.example.com/pghero/ überprüfen.

Mastodon PgHero Seite

Du kannst deine Datenbank warten, SQL-Abfragen ausführen und ungenutzte Indizes entfernen. Um die Abfragestatistik zu aktivieren, klickst du auf der oben genannten Seite auf die Schaltfläche Aktivieren und du erhältst die folgenden Informationen.

Mastodon Query Stats Information

Wechsle zum Benutzer root.

$ sudo -i su

Wechsle in das Verzeichnis /opt/mastodon/database/postgresql.

$ cd /opt/mastodon/database/postgresql

Öffne die Datei postgresql.conf.

$ nano postgresql.conf

Suche die Zeile #shared_preload_libraries = '' # (change requires restart) und ersetze sie durch die folgende.

shared_preload_libraries = 'pg_stat_statements'

Füge die folgende Zeile am Ende der Datei ein.

pg_stat_statements.track = all

Speichere die Datei, indem du Strg + X drückst und Y eingibst, wenn du dazu aufgefordert wirst.

Starte die Mastodon-Container neu.

$ systemctl restart mastodon.service

Beende die Root-Shell.

$ exit

Wenn du auf der Seite mit dem Datenbankstatus nachschaust, kannst du sehen, ob es jetzt langsame Abfragen gibt.

Mastodon Slow Queries Check

Hinweis: Du kannst die PgHero- und Sidekiq-URLs auch über das Menü “ Einstellungen “ aufrufen.

Wenn deine Seite aus irgendeinem Grund nicht geladen wird, kannst du die von Docker generierten Logs überprüfen.

$ docker logs <container-name>

Schritt 10 – Mastodon sichern

Für das Backup von Mastodon verwenden wir das Drittanbieter-Tool Restic. Der erste Schritt zur Sicherung mit Restic besteht darin, alle Dateien und Verzeichnisse zur Repository-Liste hinzuzufügen.

Erstelle und öffne die Datei mit der Repository-Liste zum Bearbeiten.

$ sudo nano /opt/mastodon/backup-files

Füge die folgenden Zeilen in die Datei ein.

/etc/nginx
/etc/letsencrypt
/etc/systemd/system
/root
/opt/mastodon/database/pgbackups
/opt/mastodon/*.env
/opt/mastodon/docker-compose.yml
/opt/mastodon/branding
/opt/mastodon/database/redis
/opt/mastodon/web/system
/opt/mastodon/backup-files
/opt/mastodon/mastodon-backup

Speichere die Datei, indem du Strg + X drückst und Y eingibst, wenn du dazu aufgefordert wirst.

Installiere Restic.

$ sudo apt install restic

Erstelle ein Backup-Repository und erstelle das erste Backup. Wir sichern unsere Daten im S3-Dienst.

$ restic -r s3:https://$SERVER:$PORT/mybucket init
$ restic -r s3:https://$SERVER:$PORT/mybucket backup $(cat /opt/mastodon/backup-files) --exclude  /opt/mastodon/database/postgresql

Erstelle einen Mastodon Backup Service Timer und öffne ihn zur Bearbeitung.

$ sudo nano /etc/systemd/system/mastodon-backup.timer

Füge den folgenden Code in die Datei ein.

[Unit]
Description=Schedule a mastodon backup every hour

[Timer]
Persistent=true
OnCalendar=*:00:00
Unit=mastodon-backup.service

[Install]
WantedBy=timers.target

Speichere die Datei, indem du Strg + X drückst und Y eingibst, wenn du dazu aufgefordert wirst.

Erstelle eine Mastodon-Backup-Service-Datei und öffne sie zur Bearbeitung.

$ sudo nano /etc/systemd/system/mastodon-backup.service

Füge den folgenden Code in die Datei ein.

[Unit]
Description=Mastodon - backup service
# Without this, they can run at the same time and race to docker compose,
# double-creating networks and failing due to ambiguous network definition
# requiring `docker network prune` and restarting
After=mastodon.service

[Service]
Type=oneshot
StandardError=file:/var/log/mastodon-backup.err
StandardOutput=file:/var/log/mastodon-backup.log

WorkingDirectory=/opt/mastodon
ExecStart=/bin/bash /opt/mastodon/mastodon-backup

[Install]
WantedBy=multi-user.target

Speichere die Datei, indem du Strg + X drückst und Y eingibst, wenn du dazu aufgefordert wirst.

Als Nächstes erstellst du die Datei /opt/mastodon/mastodon-backup und öffnest sie zur Bearbeitung. Sie enthält die eigentlichen Backup-Befehle.

$ sudo nano /opt/mastodon/mastodon-backup

Füge den folgenden Code in die Datei ein.

#!/bin/bash

set -e

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
SERVER=
PORT=
RESTIC_PASSWORD_FILE=/root/restic-pasword

docker compose -f /opt/mastodon/docker-compose.yml run --rm postgresql sh -c "pg_dump -Fp  mastodon | gzip > /backups/dump.sql.gz"
restic -r s3:https://$SERVER:$PORT/mybucket --cache-dir=/root backup $(cat /opt/mastodon/backup-files) --exclude  /opt/mastodon/database/postgresql
restic -r s3:https://$SERVER:$PORT/mybucket --cache-dir=/root forget --prune --keep-hourly 24 --keep-daily 7 --keep-monthly 3

Speichere die Datei, indem du Strg + X drückst und Y eingibst, wenn du dazu aufgefordert wirst.

Gib dem Backup-Skript Ausführungsrechte.

$ sudo chmod +x /opt/mastodon/mastodon-backup

Lade den Service Daemon neu und starte den Backup-Dienst und den Timer.

$ sudo systemctl daemon-reload
$ sudo systemctl enable --now mastodon-backup.service
$ sudo systemctl enable --now mastodon-backup.timer

Überprüfe mit den folgenden Befehlen, ob stündliche Backups durchgeführt werden und ob sie zugänglich sind.

$ restic -r s3:https://$SERVER:$PORT/mybucket snapshots
$ restic -r s3:https://$SERVER:$PORT/mybucket mount /mnt

Schritt 11 – Upgrade von Mastodon

Das Upgrade von Mastodon erfordert mehrere Schritte. Wechsle zunächst in das Verzeichnis.

$ cd /opt/mastodon

Ziehe die neuesten Container-Images für Mastodon.

$ docker compose pull

Nimm Änderungen an der docker-compose.yml vor, wenn du möchtest.

Führe alle Datenbankmigrationen durch.

$ docker compose run --rm shell bundle exec rake db:migrate

Aktualisiere deine Kopien der statischen Dateien.

$ docker compose run --rm shell bash -c "cp -r /opt/mastodon/public/* /static/"

Starte die Mastodon-Container neu.

$ sudo systemctl restart mastodon.service

Die obigen Anweisungen sind allgemeine Update-Anweisungen. Überprüfe immer die GitHub-Releaseseite von Mastodon, um nach speziellen Update-Aufgaben und Befehlen zwischen den Versionen zu suchen, damit alles reibungslos funktioniert.

Fazit

Damit ist unsere Anleitung zur Installation von Mastodon Social Network mit Docker auf einem Debian 12 Server abgeschlossen. Wenn du noch Fragen hast, schreibe sie in die Kommentare unten.

Das könnte dich auch interessieren …