Am 7. Oktober 2026 war ich neugierig. Nicht, weil ich unbedingt noch einen Dienst brauchte, sondern weil ich wissen wollte, wie sich ein eigener ActivityPub-Server anfühlt. Warum nicht? Ich will wissen, wie das abläuft. Einen Tag später war NEBUVERSE öffentlich erreichbar – auf demselben Debian-Server, der längst meine Website und andere Projekte versorgt.

Ich wollte keinen zweiten Infrastruktur-Zoo
Worldnode ist kein leerer Test-VPS. Die Maschine läuft mit Debian 13, nginx und mehreren anderen Aufgaben. Vor der Installation haben wir deshalb CPU, RAM und SSD geprüft: rund 4 vCPU, 23,3 GiB RAM und 110 GiB Speicher standen insgesamt zur Verfügung. Mich interessierte vor allem, ob der zusätzliche Dienst für den bestehenden Server überschaubar bleibt. Und ich wollte keine Docker-Installation.
Ich habe mir Mastodon, Akkoma, Snac2 und GoToSocial angesehen. Mastodon ist umfangreich und bringt ein gewachsenes Ökosystem mit, braucht aber einen größeren Dienstestack. Akkoma reizte mich durch seine Möglichkeiten; Snac2 durch seinen Minimalismus. GoToSocial gewann, weil es meine Anforderungen mit einem überschaubaren nativen Dienst, SQLite und meinem vorhandenen nginx erfüllt.
„Läuft! … Aber warum sehe ich hier nichts?“
Die Installation selbst war erstaunlich unspektakulär: Domain, HTTPS, Datenbank, Dienststart, Benutzerkonto. Beim ersten öffentlichen Beitrag wurde es richtig spannend. Jemand von einer anderen Instanz konnte mich finden und begrüßen. Das war der Moment, in dem aus meinem kleinen Server ein Teil des Fediverse wurde.
Nur wirkte die föderierte Timeline anfangs ziemlich leer. Ich war direkt nach dem Start in der Oberfläche unterwegs und hatte Relay Pushes und Relay Subscriptions erst einmal vergessen. Die Instanz funktionierte trotzdem: Anderen Accounts folgen und Beiträge austauschen geht auch ohne Relay. Aber ein neuer, kaum vernetzter Server kennt eben nicht automatisch alles, was irgendwo veröffentlicht wird.
Heute verwende ich für beide Richtungen https://relay.infosec.exchange/actor. Für die Subscription habe ich Themenfilter ausgewählt: #Linux, #OpenSource, #Homelab, #SelfHosting, #RetroComputing und #DOOM. Das ist meine persönliche Auswahl, kein allgemeiner Pflichtschritt.
Warum zwei Relay-Richtungen?
Ein Relay ist kein globales Nachrichtenarchiv. Wechsle die Richtung und verfolge, was bei einer Verbindung tatsächlich geschieht.
Subscription: Das Relay kann passende öffentliche Beiträge an meine Instanz zustellen.
Die Darstellung ist schematisch. Freigabe durch den Relay-Betreiber und die jeweiligen Filterbedingungen bleiben entscheidend. Keine Daten werden gesendet.
So sieht mein tatsächlicher Aufbau aus
Internet / andere Fediverse-Instanzen
│ HTTPS · ActivityPub
▼
social.dennishilk.com → nginx :443
│ Proxy an localhost
▼
127.0.0.1:8080
│
GoToSocial / systemd
├── SQLite: /var/lib/gotosocial/sqlite.db
└── Medien: /var/lib/gotosocial/storage
@nebu@dennishilk.com
│ WebFinger über dennishilk.com
└── verweist auf social.dennishilk.com
Die Trennung aus host: social.dennishilk.com und account-domain: dennishilk.com ist Absicht: Ich wollte den kurzen Handle @nebu@dennishilk.com behalten. Das ist die kleine Besonderheit, bei der man vor dem ersten öffentlichen Start nachdenken sollte. Spätere Änderungen an der föderierten Identität können andere Instanzen verwirren oder bestehende Beziehungen beschädigen.
Nachbauen: Mein Debian-13-Weg ohne Docker
Die folgende Checkliste entspricht dem Aufbau auf Worldnode. Sie ist als nachvollziehbarer Ablauf mit exemplarischen, sicheren Konfigurationsausschnitten gedacht – nicht als blind ausführbares Skript, das fremde bestehende nginx-Konfigurationen überschreibt. Für eine Neuinstallation zuerst die offizielle Bare-Metal-Anleitung und die Hinweise zur getrennten Account-Domain lesen.
- Vor dem Start entscheiden: DNS, öffentlichen Host, Account-Domain, E-Mail-Versand, Anmelderegeln und Backups planen. Bei mir zeigt der DNS-A-Record
social.dennishilk.comauf Worldnode. Registrierungen sind geschlossen. - Release statt Container: Für den ersten Aufbau haben wir das offizielle Linux-amd64-Release 0.22.1 mit WASM geladen, seine SHA256-Prüfsumme abgeglichen und das Archiv nach
/opt/gotosocialentpackt. Release-Datei und Prüfsumme immer aus derselben offiziellen Veröffentlichung beziehen; niemals eine Prüfsumme aus einem Blogbeitrag übernehmen. Aktuelle Releases und unterstützte Architekturen. - Dienst separieren: Ein eigener Systembenutzer
gotosocialverwaltet den Prozess. Die Konfiguration liegt unter/etc/gotosocial/config.yaml, die persistenten Daten unter/var/lib/gotosocial. Zugriffsrechte entsprechend einschränken; Konfigurationsdateien können geheime Werte enthalten. - SQLite und localhost: Für eine persönliche Instanz verwende ich SQLite und lokal gespeicherte Medien. nginx übernimmt die öffentliche HTTPS-Verbindung; der GoToSocial-Prozess selbst lauscht nur auf Loopback.
# Ausschnitt aus meinem bestätigten Pfad-/Domain-Konzept
host: "social.dennishilk.com"
account-domain: "dennishilk.com"
protocol: "https"
bind-address: "127.0.0.1"
port: 8080
letsencrypt-enabled: false
db-type: "sqlite"
db-address: "/var/lib/gotosocial/sqlite.db"
storage-backend: "local"
storage-local-base-path: "/var/lib/gotosocial/storage"
- systemd statt Handstart: Unser Service-Template kam aus dem GoToSocial-Release und wurde angepasst; anschließend haben wir es mit
systemd-analyze verifykontrolliert. Der auf Worldnode aktuell bestätigte Start sieht so aus:
# relevante Einträge aus gotosocial.service
[Service]
User=gotosocial
Group=gotosocial
WorkingDirectory=/opt/gotosocial
ExecStart=/opt/gotosocial/gotosocial --config-path /etc/gotosocial/config.yaml server start
# nach geprüfter Einrichtung
sudo systemctl enable --now gotosocial.service
sudo journalctl -u gotosocial.service -n 50 --no-pager
- nginx + TLS: Im Virtual Host für
social.dennishilk.comwird HTTPS durch nginx/Let's Encrypt abgewickelt und anhttp://127.0.0.1:8080weitergegeben. Der Host-Header ist wichtig für korrekt erzeugte URLs und Föderationssignaturen. Wir habennginx -tund den HTTPS-Endpunkt getestet. Offizielle nginx-Anleitung. - WebFinger für den kurzen Handle: Auf
dennishilk.comleiten drei exakte Well-known-Endpunkte auf den Social-Host um; Query-Parameter müssen erhalten bleiben. Nicht die komplette Website und nicht die/api/-Pfade umleiten.
# Im bestehenden HTTPS-server{} für dennishilk.com
location = /.well-known/webfinger {
return 301 https://social.dennishilk.com$request_uri;
}
location = /.well-known/host-meta {
return 301 https://social.dennishilk.com$request_uri;
}
location = /.well-known/nodeinfo {
return 301 https://social.dennishilk.com$request_uri;
}
# nginx prüfen, dann kontrolliert neu laden
sudo nginx -t
sudo systemctl reload nginx
- Benutzer erstellen und kontrollieren: Erst GoToSocial mindestens einmal starten, damit es die Datenbank initialisieren kann. Dann über den CLI-Befehl
admin account createden Benutzer anlegen und mitadmin account promoteadministrieren. Passwörter nicht in Blogbeiträgen, Befehlsverläufen oder Screenshots veröffentlichen; die offizielle CLI-Dokumentation erklärt die Parameter. Bei uns haben WebFinger und öffentliche Profilauflösung schließlich funktioniert.
# Diagnose ohne Zugangsdaten
systemctl status gotosocial.service --no-pager
curl -I https://social.dennishilk.com/
curl -i 'https://dennishilk.com/.well-known/webfinger?resource=acct:nebu@dennishilk.com'
# Achtung: bei -i kann zuerst ein HTTP-Redirect erscheinen
# dessen Ziel und JSON-Antwort prüfen.
Kein Copy-and-paste für einen bestehenden Webserver: Ob die nginx-Snippets zu deiner Installation passen, hängt von den vorhandenen Server-Blöcken, Zertifikaten und Weiterleitungen ab. Meine Beispielwerte sind bewusst öffentlich, aber keine vollständige private Produktionskonfiguration.
Ein Server ohne mitgelieferte Timeline-App?
GoToSocial bietet eine eigene Instanz- und Einstellungsoberfläche, aber nicht denselben vollständigen integrierten Webclient wie Mastodon. Ich nutze im Browser Elk als Mastodon-kompatiblen Client. Den Elk-Dienst hoste ich nicht selbst. Eine externe Web-App ist ein eigener Vertrauenspunkt; bei der Autorisierung prüfe ich, welcher Anwendung ich welche Rechte gebe.
Was kostet der Spaß Worldnode tatsächlich?
Statt Herstellerangaben zu zitieren, habe ich auf dem laufenden Server gemessen. ps zeigte ungefähr 2,1 % über die bisherige Prozesslaufzeit gemittelte CPU-Nutzung, nicht die CPU-Spitze dieses Moments. Über /proc/<pid>/status kamen aktuelle RSS- und bisherige Peak-Werte:
Messzeitpunkt: 11. Oktober 2026. Das ist nur der Prozess, nicht nginx, das Betriebssystem oder der Dateisystemcache. Und es beweist nicht, dass jede größere Instanz mit denselben Werten auskommt.
Über meinen selbstgebauten Site Traffic Observer lasse ich außerdem die Speichernutzung beobachten. Die öffentliche Telemetrie stammt aus einem lokalen Python-Sammler mit systemd-Timer, nicht aus GoToSocial-Zugangsdaten. Der Snapshot vom 11. Oktober zeigte 1,74 GiB Medien, rund 28,55 MiB SQLite, zusammen 1,77 GiB, sowie rund 70,14 GiB freien Platz. Warnschwellen: 5 GiB Nutzung oder weniger als 10 GiB frei. Föderation bringt eben auch Speicherbedarf mit.
Backups: Erst testen, dann behaupten
Am 8. Oktober lag bereits eine kleine manuelle Sicherung unter /var/backups/gotosocial/: SQLite, Storage und die Konfiguration für GoToSocial, systemd, nginx und die Domainweiterleitungen. Am 11. Oktober haben wir das auf ein verschlüsseltes Restic-Repository erweitert. Der neue Dienst läuft als nebuverse-backup.service, ausgelöst durch nebuverse-backup.timer täglich um 03:30 Uhr Worldnode-Systemzeit.
Das Skript unter /usr/local/sbin/nebuverse-backup erstellt mit Pythons SQLite-Backup-API einen konsistenten Live-Snapshot, prüft ihn mit PRAGMA quick_check, sichert Daten, Medien, Konfiguration, nginx, Zertifikate und die Backup-Automatisierung selbst. Danach bereinigt es den unverschlüsselten Zwischenstand. Die Aufbewahrung ist auf 7 tägliche, 4 wöchentliche und 6 monatliche Wiederherstellungspunkte ausgelegt.
Grenzen des Tests: Das ist ein erfolgreicher Datenbank-Restore und eine Restic-Integritätsprüfung, kein vollständiger Neuaufbau der Instanz. Die neue Restic-Gruppierungsoption --group-by host,tags ist im Skript syntaktisch geprüft; ein produktiver automatischer Lauf unter dieser letzten Änderung stand beim Schreiben noch aus. Den Verschlüsselungsschlüssel habe ich separat verwahrt. Das Repository möchte ich zusätzlich einmal pro Woche selbst auf mein NAS kopieren – diese externe Kopie war bei Veröffentlichung noch nicht als abgeschlossen bestätigt. Die lokalen Backups liegen auf derselben virtuellen Platte wie die Daten, also sind sie kein Ersatz für ein externes Backup.
Was ich aus NEBUVERSE mitnehme
Ich habe jetzt mein eigenes kleines Stück Fediverse. Nicht weil es die bequemste Lösung ist, sondern weil ich verstehen wollte, was hinter einem Profil, einer Zustellung und einer Föderation steckt. Ein funktionierender Server ist ein gutes Gefühl. Die erste Antwort aus einer fremden Instanz war noch besser.
Was bleibt, ist Verantwortung: Updates, Zertifikate, Abuse- und Moderationsentscheidungen, Speicher, Sicherung und Restore. Aber die Ressourcen auf Worldnode wirken bislang überschaubar. Und wenn ich heute meine Timeline öffne, weiß ich zumindest wesentlich genauer, warum dort etwas erscheint.
Dokumentation und Nachprüfbarkeit
GoToSocial Bare Metal · nginx Reverse Proxy · Split-Domain & WebFinger · Relay Subscriptions · Relay Pushes · Restic · mein öffentlicher Telemetrie-Code. Meine eigenen Messungen und Screenshots stammen vom 8. bis 11. Oktober 2026; die Dokumentationslinks können sich später ändern.