So installierst du das Mastodon Social Network mit Docker auf Rocky Linux 9

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 auf einem Server angemeldet sind, 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 diesem Lernprogramm lernst du, wie du deine Mastodon-Instanz auf einem Server mit Rocky Linux 9 mit Docker einrichtest. Docker erleichtert die Installation von Mastodon, da alle benötigten Pakete und Dienste in Containern enthalten sind.

Voraussetzungen

  • Ein Server mit Rocky Linux 9 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 dnf update
    
  • Installiere grundlegende Hilfspakete. Einige davon sind vielleicht schon installiert.
    $ sudo dnf install wget curl nano unzip yum-utils -y
    

Schritt 1 – Firewall konfigurieren

Der erste Schritt besteht darin, die Firewall zu konfigurieren. Rocky Linux verwendet die Firewalld Firewall. Überprüfe den Status der Firewall.

$ sudo firewall-cmd --state
running

Die Firewall arbeitet mit verschiedenen Zonen, wobei die öffentliche Zone die Standardzone ist, die wir verwenden werden. Liste alle Dienste und Ports auf, die auf der Firewall aktiv sind.

$ sudo firewall-cmd --permanent --list-services

Es sollte die folgende Ausgabe angezeigt werden.

cockpit dhcpv6-client ssh

Wiki.js braucht HTTP- und HTTPS-Ports, um zu funktionieren. Öffne sie.

$ sudo firewall-cmd --permanent --add-service=http
$ sudo firewall-cmd --permanent --add-service=https

Füge Masquerade hinzu, da die Anwendung andere Instanzen kontaktieren wird.

$ sudo firewall-cmd --permanent --add-masquerade

Lade die Firewall neu, um die Änderungen zu übernehmen.

$ sudo firewall-cmd --reload

Schritt 2 – Installiere Docker und Docker Compose

Rocky Linux wird mit einer älteren Version von Docker ausgeliefert. Um die neueste Version zu installieren, installierst du zunächst das offizielle Docker-Repository.

$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

Installiere die neueste Version von Docker.

$ sudo dnf install docker-ce docker-ce-cli containerd.io

Möglicherweise erhältst du die folgende Fehlermeldung, wenn du versuchst, Docker zu installieren.

ror: 
 Problem: problem with installed package buildah-1:1.26.2-1.el9_0.x86_64
  - package buildah-1:1.26.2-1.el9_0.x86_64 requires runc >= 1.0.0-26, but none of the providers can be installed
  - package containerd.io-1.6.9-3.1.el9.x86_64 conflicts with runc provided by runc-4:1.1.3-2.el9_0.x86_64
  - package containerd.io-1.6.9-3.1.el9.x86_64 obsoletes runc provided by runc-4:1.1.3-2.el9_0.x86_64
  - cannot install the best candidate for the job

Verwende den folgenden Befehl, wenn du die obige Fehlermeldung erhältst.

$ sudo dnf install docker-ce docker-ce-cli containerd.io docker-compose-plugin --allowerasing

Aktiviere den Docker-Daemon und starte ihn.

$ sudo systemctl enable docker --now

Überprüfe, ob er läuft.

? docker.service - Docker Application Container Engine
     Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
     Active: active (running) since Sat 2022-11-12 00:19:44 UTC; 6s ago
TriggeredBy: ? docker.socket
       Docs: https://docs.docker.com
   Main PID: 99263 (dockerd)
      Tasks: 8
     Memory: 28.1M
        CPU: 210ms
     CGroup: /system.slice/docker.service
             ??99263 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

Docker benötigt 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 wheel 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.

$ 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
$ sudo sysctl --load /etc/sysctl.d/90-max_map_count.conf

Konfiguriere SELinux, um Netzwerkverbindungen zuzulassen.

$ sudo setsebool -P httpd_can_network_connect 1

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.

version: '3'

services:
  postgresql:
    image: postgres:15-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.7
    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
    ulimits:
      memlock:
        soft: -1
        hard: -1
    healthcheck:
      test: ["CMD-SHELL", "nc -z elasticsearch 9200"]
    volumes:
      - elasticsearch:/usr/share/elasticsearch/data
    networks:
      - internal_network

  website:
    image: tootsuite/mastodon:v4.0.2
    env_file:
      - application.env
      - database.env
    command: bash -c "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.0.2
    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.0.2
    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.0.2
    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.0.2 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.x. Es gibt keine Hauptversion von Elasticsearch, der du auf der Docker Hub Seite folgen kannst, also musst du sie immer wieder manuell für die Sicherheitsupdates in Bezug auf Java aktualisieren.

Die Seite internal: true funktioniert nicht mit Firewalld, weshalb sie in der obigen Datei auskommentiert ist. Wenn dies jemals behoben wird, kannst du diese zusätzliche Einschränkung vielleicht wieder hinzufügen.

Anwendungsgeheimnisse erstellen

Der nächste Schritt ist die Erstellung von Anwendungsgeheimnissen.

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 die Bilder geladen werden müssen.

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

Du kannst dafür auch das Dienstprogramm openssl verwenden.

$ openssl rand -hex 64

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

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=AKIA3FIG4NVFNSC3AHXE
SMTP_PASSWORD=BHM4MVOjBmnGhSJ9lH3PAXKJ/9AiLWcUghG/kEN2kkFo
[email protected]

# secrets
SECRET_KEY_BASE=c09fa403575e0b431e54a2e228f20cd5a5fdfdbba0da80598959753b829a4e3c0266eedbac7e3cdf9f3345db36c56302c0e1bc5bfc8c5d516be59a2c41de7e37
OTP_SECRET=febb7dbb0d3308094083733fc923a430e52ccec767d48d7d2e0c577bfcb6863dbdfc920b1004b1f8c2967b9866bd7a0b4a15460f9fc7687aa4a42acf54e5a3d4

# Changing VAPID keys will break push notifications
VAPID_PRIVATE_KEY=13RgrfOY2tkwuUycylDPOkoHennkJ0ZAPV_fUwDy7-g=
VAPID_PUBLIC_KEY=BDAQuGwPbh1kbCV904adYXHvz9lLRaJHkiQkihRDPyBn3QmkAYbR21WHYoP8TkyG6dylG6IXpEVfLwdoW7fJVns=

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

Öffne die Datei database.env und bearbeite sie.

$ sudo nano database.env

Füge die folgenden Zeilen in die Datei ein.

# postgresql configuration
POSTGRES_USER=mastodon
POSTGRES_DB=mastodon
POSTGRES_PASSWORD=15ff12dcb93aa60680d2aadb4032ee
PGPASSWORD=15ff12dcb93aa60680d2aadb4032ee
PGPORT=5432
PGHOST=postgresql
PGUSER=mastodon

# pgbouncer configuration
#POOL_MODE=transaction
#ADMIN_USERS=postgres,mastodon
#DATABASE_URL="postgres://mastodon:[email protected]:5432/mastodon"

# elasticsearch
ES_JAVA_OPTS=-Xms512m -Xmx512m
ELASTIC_PASSWORD=13382e99f6b2d4dc7f3d66e4b9872d

# mastodon database configuration
#DB_HOST=pgbouncer
DB_HOST=postgresql
DB_USER=mastodon
DB_NAME=mastodon
DB_PASS=15ff12dcb93aa60680d2aadb4032ee
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=13382e99f6b2d4dc7f3d66e4b9872d

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.

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

Rufe die Datenschicht auf.

$ docker compose up -d postgresql redis redis-volatile

Überprüfe den Status der Container.

$ watch docker compose ps

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

Schritt 5 – Nginx installieren

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

Erstelle und öffne die Datei /etc/yum.repos.d/nginx.repo zur Erstellung des offiziellen Nginx-Repositorys.

$ sudo nano /etc/yum.repos.d/nginx.repo

Füge den folgenden Code in die Datei ein.

[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

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

Installiere den Nginx-Server.

$ sudo dnf install nginx

Überprüfe die Installation.

$ nginx -v
nginx version: nginx/1.22.1

Aktiviere und starte den Nginx-Server.

$ sudo systemctl enable nginx --now

Überprüfe den Status des Servers.

$ sudo systemctl status nginx
? nginx.service - nginx - high performance web server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
     Active: active (running) since Sun 2022-11-13 13:49:55 UTC; 1s ago
       Docs: http://nginx.org/en/docs/
    Process: 230797 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)
   Main PID: 230798 (nginx)
      Tasks: 3 (limit: 12355)
     Memory: 2.8M
        CPU: 13ms
     CGroup: /system.slice/nginx.service
             ??230798 "nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf"
             ??230799 "nginx: worker process"
             ??230800 "nginx: worker process"

Schritt 6 – SSL installieren

Das Certbot-Tool erstellt SSL-Zertifikate mithilfe der Let’s Encrypt API. Damit es funktioniert, benötigt es das EPEL-Repository.

$ sudo dnf install epel-release

Wir werden Snapd verwenden, um Certbot zu installieren. Installiere Snapd.

$ sudo dnf install snapd

Aktiviere und starte den Snap-Dienst.

$ sudo systemctl enable snapd --now

Installiere das Snap-Kernpaket.

$ sudo snap install core
$ sudo snap refresh core

Erstelle die notwendigen Links, damit Snapd funktioniert.

$ sudo ln -s /var/lib/snapd/snap /snap
$ echo 'export PATH=$PATH:/var/lib/snapd/snap/bin' | sudo tee -a /etc/profile.d/snapd.sh

Gib den folgenden Befehl ein, um Certbot zu installieren.

$ sudo snap install --classic certbot

Aktiviere Certbot, indem du den Symlink zu seiner ausführbaren Datei erstellst.

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

Erstelle das SSL-Zertifikat.

$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -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

Um zu überprüfen, ob die SSL-Erneuerung einwandfrei funktioniert, führe einen Probelauf des Prozesses durch.

$ sudo certbot renew --dry-run

Wenn du keine Fehler siehst, ist alles in Ordnung. 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 http2;
   server_name mastodon.example.com;
   
   access_log  /var/log/nginx/mastodon.access.log;
   error_log   /var/log/nginx/mastodon.error.log;

   http2_push_preload on; # Enable HTTP/2 Server Push

   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

Wenn du die folgende Fehlermeldung erhältst, liegt das höchstwahrscheinlich an SELinux-Einschränkungen.

nginx: [emerg] open() "/var/run/nginx.pid" failed (13: Permission denied)

Um den Fehler zu beheben, führe die folgenden Befehle aus.

$ sudo ausearch -c 'nginx' --raw | audit2allow -M my-nginx
$ sudo semodule -X 300 -i my-nginx.pp

Starte den Nginx-Dienst erneut.

$ sudo systemctl start 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 "[email protected]"

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

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 [email protected] --confirmed --role admin
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-web-1 /bin/bash

Führe den folgenden Befehl aus.

$ sed -E 's/indices.sum.+/2000/g' -i lib/mastodon/search_cli.rb

Beende die Container-Shell.

$ exit

Führe den Befehl Elasticsearch deploy erneut aus.

$ tootctl search deploy

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

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 2 Benutzer gibt und einer von ihnen (ich) als Administrator eingestellt ist. Das ist normalerweise nicht der Fall. Selbst wenn du ein Administratorkonto erstellst, wird es beim ersten Durchlauf nicht auf der Hauptseite angezeigt. Um das zu ändern, melde dich 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 Website-Einstellungen in der linken Seitenleiste.

Mastodon Admin User Information

Hier gibst du deinen Kontaktbenutzernamen und deine geschäftliche E-Mail-Adresse ein, die nun 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. Außerdem erfährst du, 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 Abfragestatistiken zu aktivieren, klickst du auf der obigen 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 dnf 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 alle Änderungen in der docker-compose.yml vor, wenn du willst.

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.

Das könnte dich auch interessieren …