Mastodon auf dem Raspberry Pi hosten
Gestern kam die Frage von jemandem, der offensichtlich Bock auf eine eigene Mastodon-Instanz hat, ob das auf einem Raspberry Pi geht. Er hat einfach die Schnauze voll von Twitter & Co., will sich aber auch auf keiner bestehenden Mastodon-Instanz anmelden, bei der er völlig dem Betreiber ausgeliefert ist und jederzeit abgeschossen werden könnte.
Einen V-Server mieten? Keine Chance, will er nicht. Stattdessen wollte er wissen, ob das Ganze auf einem Raspberry Pi zu Hause machbar ist. Da ich selbst keines dieser Netzwerke nutze, also auch keine Erfahrungen damit habe, dachte ich mir, probiere ich es einfach mal aus und dokumentiere das Ganze hier, damit er alles Schritt für Schritt nachlesen kann.
Was du brauchst
- Raspberry Pi 4 mit mindestens 4 GB RAM (2 GB geht nur mit Swap-Tricks, Performance leidet)
- SSD empfohlen, SD-Karte geht, aber nur hochwertige z. B. Samsung Pro Endurance; überwache Gesundheit mit
smartctloderfsck - Domain/Subdomain, die auf deine öffentliche IP zeigt
- Routerzugang für Portforwarding (80 und 443)
- SSH-Zugang und Basiskenntnisse für Terminalbefehle
Optional, aber stark empfohlen:
- DynDNS (z. B. duckdns) für wechselnde IP
- SSH-Key für sicheren Zugriff
- Backup-Speicher extern (Festplatte/NAS/Cloud)
Schritt 1: Raspberry Pi OS Lite installieren
-
- Raspberry Pi OS Lite auf SD-Karte oder SSD schreiben (Raspberry Pi Imager).
- Pi starten, per SSH einloggen:
ssh pi@raspberrypi.local - Alles updaten und Grundpakete installieren:
sudo apt update sudo apt upgrade -y sudo apt install -y git curl wget ca-certificates unzip nano ufw fail2ban - Nach Kernel-Updates
reboot:
sudo reboot
- Swap erhöhen bei 2 GB RAM (optional):
sudo dphys-swapfile swapoff sudo sed -i 's/CONF_SWAPSIZE=.*/CONF_SWAPSIZE=2048/' /etc/dphys-swapfile sudo dphys-swapfile setup sudo dphys-swapfile swapon - Statische IP einstellen (Beispiel für
/etc/dhcpcd.conf):interface eth0 static ip_address=192.168.1.100/24 static routers=192.168.1.1 static domain_name_servers=1.1.1.1 8.8.8.8
Schritt 2: Docker & Docker Compose installieren
- Docker installieren:
curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh sudo usermod -aG docker $USERHinweis: danach abmelden und wieder anmelden oder SSH neu starten.
- Docker Compose Plugin installieren:
sudo apt install -y docker-compose-plugin - Prüfen:
docker --version docker compose version docker infoFalls
docker infomeckert:sudo systemctl restart docker
Schritt 3: Mastodon-Verzeichnis & Code klonen
- Verzeichnis erstellen:
sudo mkdir -p /srv/mastodon sudo chown $USER:$USER /srv/mastodon cd /srv/mastodon - Mastodon-Code klonen und stabile Version nutzen:
git clone https://github.com/mastodon/mastodon.git . git checkout v4.3.0
Schritt 4: Docker Compose Datei erstellen
docker-compose.yml anlegen:
nano docker-compose.yml
Inhalt:
version: '3.3'
services:
db:
image: postgres:16
environment:
POSTGRES_USER: mastodon
POSTGRES_PASSWORD: mastodon
POSTGRES_DB: mastodon
volumes:
- ./postgres:/var/lib/postgresql/data
restart: always
redis:
image: redis:7
command: redis-server --save 60 1 --loglevel warning
volumes:
- ./redis:/data
restart: always
web:
build: .
env_file: .env.production
command: bundle exec puma -C config/puma.rb
ports:
- "3000:3000"
depends_on:
- db
- redis
volumes:
- ./public/system:/mastodon/public/system
restart: always
streaming:
build: .
env_file: .env.production
command: node ./streaming/index.js
ports:
- "4000:4000"
depends_on:
- db
- redis
restart: always
sidekiq:
build: .
env_file: .env.production
command: bundle exec sidekiq
depends_on:
- db
- redis
volumes:
- ./public/system:/mastodon/public/system
restart: always
Schritt 5: .env.production anlegen & konfigurieren
- Datei kopieren:
cp .env.production.sample .env.production nano .env.production - Wichtige Anpassungen:
LOCAL_DOMAIN=deinedomain.de WEB_DOMAIN=deinedomain.de DB_HOST=db DB_USER=mastodon DB_NAME=mastodon DB_PASS=supergeheim REDIS_HOST=redis SMTP_SERVER=smtp.deinmailanbieter.example SMTP_PORT=587 SMTP_LOGIN=deinlogin SMTP_PASSWORD=deinapppasswort SMTP_FROM_ADDRESS=no-reply@deinedomain.de - Keys generieren:
docker compose run --rm web rake secret docker compose run --rm web rake mastodon:webpush:generate_vapid_key - Datei schützen:
chmod 600 .env.productionHinweis: Keys niemals öffentlich speichern; Passwort-Manager oder verschlüsselte Datei verwenden.
- SMTP-Hinweis: Bei Gmail App-Passwort nutzen oder „Unsichere Apps“ aktivieren.
Schritt 6: Mastodon bauen & Setup
- Build starten:
docker compose build sudo chown -R 991:991 public - Setup ausführen (Admin anlegen, DB-Tabellen erstellen):
docker compose run --rm web bundle exec rake mastodon:setup - Container starten:
docker compose up -dTipp: Build dauert auf Pi 4 gerne 1–2 Stunden. Kaffee holen.
Schritt 7: Reverse Proxy & HTTPS (Caddy)
- Caddy installieren:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo apt-key add - curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list sudo apt update sudo apt install -y caddy - Caddyfile erstellen:
sudo nano /etc/caddy/CaddyfileBeispielinhalt:
deinedomain.de { reverse_proxy localhost:3000 @notls { protocol http } redir @notls https://{host}{uri} limit_rps 100 } - Reload:
sudo systemctl reload caddy - Router: Ports 80 & 443 (IPv4 und IPv6) weiterleiten.
Schritt 8: Firewall & Sicherheit
- UFW konfigurieren:
sudo ufw allow 2222/tcp sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw enable - Fail2Ban aktivieren:
sudo systemctl enable fail2ban sudo systemctl start fail2ban - Beispiel Jail für Mastodon-Logs:
[mastodon] enabled = true filter = mastodon logpath = /srv/mastodon/log/*.log maxretry = 3 bantime = 1h
Schritt 9: Backups
- Datenbank komprimiert sichern:
docker compose exec db pg_dump -U mastodon mastodon | gzip > /srv/mastodon/backups/backup-$(date +%F).sql.gz - Medien sichern:
tar czf /srv/mastodon/backups/media_backup_$(date +%F).tar.gz public/system - Cronjob für tägliche Backups:
crontab -e 0 3 * * * docker compose exec db pg_dump -U mastodon mastodon | gzip > /srv/mastodon/backups/backup-$(date +\%F).sql.gz - Offsite-Backup mit rclone:
rclone copy /srv/mastodon/backups remote:backups/mastodon/
Schritt 10: Updates & Wartung
cd /srv/mastodon
git pull
docker compose build
docker compose run --rm web bundle exec rails db:migrate
docker compose up -d
docker system prune -f
Hinweis: Docker-Prune nur ausführen, wenn alle Container laufen. Downtime kurz, ggf. Nutzer vorher informieren.
Schritt 11: Häufige Fehler
- Styles fehlen → Domain in
.env.productionprüfen - Build-Abbruch → RAM, evtl.
docker compose build --no-cacheoder auf stärkerem Rechner bauen - Logs wachsen → Logrotation:
/srv/mastodon/log/*.log { daily missingok rotate 7 compress delaycompress notifempty create 644 mastodon mastodon } - Mailversand → SMTP prüfen, App-Passwort nötig
Schritt 12: Sicherheit & Monitoring
- HTTPS erzwingen (Admin)
- Rate-Limiting in Caddy (siehe oben)
- Monitoring mit netdata:
bash <(curl -Ss https://my-netdata.io/kickstart.sh) # Zugriff lokal: http://deine-ip:19999
Schritt 13: Fediverse-Kompatibilität
curl https://deinedomain.de/nodeinfo/2.0
curl https://deinedomain.de/.well-known/webfinger?resource=acct:admin@deinedomain.de
Wenn das nicht klappt: Domain, HTTPS-Zertifikat, Port 443 prüfen.
Schritt 14: Rechtliches
- Impressum Pflicht, Beispiel:
<p>Verantwortlich für diese Instanz:<br> Max Mustermann<br> Musterstraße 1<br> 12345 Musterstadt<br> E-Mail: admin@deinedomain.de</p> - DSGVO beachten
- Urheberrecht bei Medieninhalten beachten
Schritt 15: Erste Schritte nach Installation
- Als Admin einloggen →
/admin - HTTPS erzwingen
- Registrierung aktivieren (falls erwünscht)
- Mailversand testen:
docker compose logs web | grep 'SMTP' - Freunde einladen und eigene Social-Media-Blase starten
Piehnat
Für ‚ne Nummer kleiner würde ich GoToSocial empfehlen. Das Ding ist deutlch ressourcenschonender.
Habe ich versucht, aber um es mit seinen Worten auszudrücken „Wenn schon, dann will ich den vollen Funktionsumfang, keine abgespeckte Version mit Einschränkungen“. Machste nix.
Dann ist das so 😉