Featured image of post Eigene Webseite ins Fediverse bringen – Blog automatisch über GoToSocial veröffentlichen

Eigene Webseite ins Fediverse bringen – Blog automatisch über GoToSocial veröffentlichen

Schritt-für-Schritt-Anleitung: Eigene Webseite mit GoToSocial ins Fediverse bringen und Blogbeiträge automatisch über RSS auf Mastodon & Co. veröffentlichen.

Eigene Webseite ins Fediverse bringen

Was ist das Ziel?

In diesem Tutorial zeige ich, wie du deine Webseite direkt mit dem Fediverse verbindest, sodass neue Blogbeiträge automatisch auf Mastodon und anderen föderierten Diensten erscheinen.

Das Ziel:

  • eigener Blog bleibt die Hauptplattform
  • neue Beiträge werden automatisch im Fediverse veröffentlicht
  • Leser können dem Blog direkt folgen
  • keine Abhängigkeit von Facebook, X oder anderen Plattformen

Was ist das Fediverse?

Vereinfacht gesagt ist das Fediverse ein dezentrales soziales Netzwerk.

Statt einer einzelnen Plattform gibt es viele unabhängige Server, die miteinander kommunizieren können.

Mastodon ist dabei nur eine von vielen Plattformen.

Man kann sich das vorstellen wie E-Mail:

Jemand mit einer Gmail-Adresse kann einer Person bei Posteo schreiben.

Im Fediverse funktioniert das ähnlich.

Ein Nutzer auf Mastodon kann Accounts auf anderen Servern abonnieren, kommentieren und teilen.

Voraussetzungen

Folgendes solltest du bereits haben:

  • Domain
  • VPS oder Server
  • Debian oder Ubuntu
  • Docker + Docker Compose
  • nginx Reverse Proxy
  • HTTPS via Let’s Encrypt
  • RSS-Feed deiner Webseite

In meinem Fall:

  • Hugo Webseite
  • Debian VPS
  • nginx Reverse Proxy
  • GoToSocial als Single-User-Instanz

Was du bereits können solltest

Dieses Tutorial richtet sich eher an technisch interessierte Nutzer und Selbsthoster. Du musst kein Administrator sein, aber ein paar Grundlagen helfen enorm.

Folgende Dinge solltest du grob beherrschen:

  • per SSH auf einen Server verbinden
  • grundlegende Linux-Befehle ausführen
  • Dateien mit einem Editor wie nano bearbeiten
  • DNS-Einträge beim Domainanbieter setzen
  • nginx-Konfigurationen anpassen
  • Docker und Docker Compose starten
  • HTTPS-Zertifikate via Let’s Encrypt erstellen

Falls dir einzelne Punkte noch nichts sagen: Kein Problem. Du kannst das Tutorial trotzdem nachvollziehen – eventuell musst du einzelne Begriffe zwischendurch kurz nachschlagen.

Subdomain vorbereiten

Ich habe eine eigene Subdomain verwendet:

social.deinedomain.tld

Beim DNS-Anbieter einen A Record auf den VPS setzen, sofern das notwendig ist. Bei mir ist das der Fall, da diese Webseite hier nicht auf einem VPS, sondern bei einem Webhoster gelagert ist. Haben wir den DNS Eintrag gemacht, prüfen wir, obs auch greift: dig social.deinedomain.tld

Das Ergenis sollte ungefär so aussehen:

1
2
3
4
5
6
7
8
; <<>> DiG <<>> social.deinedomain.tld
;; ->>HEADER<<- opcode: QUERY, status: NOERROR

;; QUESTION SECTION:
;social.deinedomain.tld.   IN   A

;; ANSWER SECTION:
social.deinedomain.tld. 3600 IN A 203.0.113.42

Wichtig ist, dass im ANSWER SECTION die IP-Adresse deines Servers erscheint.

GoToSocial installieren

Verzeichnisse anlegen:

1
2
3
mkdir -p ~/fediblog/gotosocial
cd ~/fediblog/gotosocial
mkdir config data

docker-compose.yml erstellen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
services:
  gotosocial:
    image: superseriousbusiness/gotosocial:latest
    container_name: gotosocial
    restart: unless-stopped

    ports:
      - "127.0.0.1:3000:8080"

    volumes:
      - ./data:/gotosocial/storage
      - ./config:/gotosocial/config

    environment:
      GTS_HOST: social.deinedomain.tld
      GTS_ACCOUNT_DOMAIN: social.deinedomain.tld
      GTS_PROTOCOL: https

      GTS_TRUSTED_PROXIES: 127.0.0.1/32,172.16.0.0/12

      GTS_DB_TYPE: sqlite
      GTS_DB_ADDRESS: /gotosocial/storage/gotosocial.db

      GTS_STORAGE_BACKEND: local
      GTS_STORAGE_LOCAL_BASE_PATH: /gotosocial/storage

      GTS_WEB_ASSET_BASE_DIR: /gotosocial/web/assets

      GTS_LETSENCRYPT_ENABLED: "false"

      GTS_INSTANCE_TITLE: "Mein Blog"
      GTS_INSTANCE_DESCRIPTION: "Mein Blog im Fediverse"

      TZ: Europe/Berlin

Starten: docker compose up -d und auch Prüfen obs läuft: docker ps.

nginx Reverse Proxy

Wir legen folgende Datei an: nano /etc/nginx/sites-available/social-blog und klatschen da das hier rein:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
server {
    server_name social.deinedomain.tld;

    location / {
        proxy_pass http://127.0.0.1:3000;

        proxy_http_version 1.1;

        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 Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Dann muss das ganze auch noch aktiviert werden:

1
2
3
sudo ln -s /etc/nginx/sites-available/social-blog /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

HTTPS via Certbot

Natürlich bestehen wir auch hier auf https, daher holen wir uns bei letsencrypt noch ein kostenloses ssl Zertifikat:

sudo certbot --nginx -d social.deinedomain.tld

Benutzer anlegen

1
2
3
4
5
6
docker exec -it gotosocial sh

/gotosocial/gotosocial admin account create \
--username blog \
--email deine@mail.de \
--password DEINPASSWORT

Adminrechte brauchen wir auch, denn ohne gehts nicht. Den Grund sehen wir später noch.

1
2
/gotosocial/gotosocial admin account promote \
--username blog
📌 Achtung!

Hier kann es noch eine Stolperfalle geben! Und zwar, das der Account versteckt ist.

Bei mir wurde der Account so erstellt:

1
2
locked = 1
discoverable = 0

Allerdings funktionierte dadurch Föderation nicht richtig. Denn das Fediverse ist ein Föderiertes Netzwerk und diese Funktion wollen wir ja haben, damit dann auch jede Instanz, jeder User im Fediverse unseren Blog sehen und folgen kann.

Also müssen wir folgendes prüfen: sqlite3 ~/fediblog/gotosocial/data/gotosocial.db. Dann: SELECT username, locked, discoverable FROM accounts;

Sollte da dann das rauskommen, was bei mir stand, dann müssen wir das korrigieren:

1
2
3
4
UPDATE accounts
SET locked = 0,
    discoverable = 1
WHERE username = 'blog';

Danach starten wir das ganze einmal neu: docker restart gotosocial.

OAuth App erstellen

Goto Social funktioniert und ist über deine Domain social.deinedomain.tld erreichbar.

Also wechseln wir in den Browser und geben dort dann https://social.deinedomain.tld in die Adresszeile ein.

Einloggen mit den erstellten Benutzerdaten (email Adresse und Passwort), dann auf Settings -> Application. Dort öffnet sich dann ein Menü, wo wir auf New Application gehen um eine neue “App” zu erstellen.

Den Namen der App sucht euch selber aus. Application website (optional) ist, wie man sieht, optional.

Was wir wollen ist unter Redirect URIs (optional, newline-separated entries) einzutragen. Es steht schon oben in der Erklärung aber hier noch mal: urn:ietf:wg:oauth:2.0:oob.

Nicht die eigene URL verwenden. Das war bei mir eine der größten Fehlerquellen.

Das Grundgerüst haben wir damit schon fertig. Nun kommt das “Fine tuning”. 😄

RSS automatisch posten

Legen wir mal wieder ein Verzeichnis an. Hatten wir ja schon lange nicht mehr 😁. Ich schreibe hier mal den ganzen nächsten Schritt auf:

1
2
3
4
mkdir ~/fediblog/rss-bot
cd ~/fediblog/rss-bot
python3 -m venv venv
source venv/bin/activate
📝 Hinweis

Unter Debian-basierten Distributionen wie Debian, Ubuntu oder LMDE muss gegebenenfalls zuerst das Paket python3-venv installiert werden: sudo apt install python3-venv Dann kann man ein Python Virtual Environment anlegen:

1
2
python3 -m venv venv
source venv/bin/activate

Wenn das erledigt ist, installieren wir mal wieder was:

pip install feedparser requests

RSS automatisch ins Fediverse posten

Nachdem die GoToSocial-Instanz läuft, fehlt nur noch die Automatisierung.

Ziel ist:

Sobald ein neuer Blogbeitrag erscheint, wird dieser automatisch im Fediverse veröffentlicht.

Da Hugo bereits einen RSS-Feed erzeugt (index.xml), können wir diesen einfach auslesen und neue Beiträge automatisch posten.

Python Virtual Environment anlegen

Zuerst erstellen wir ein separates Python-Environment.

Verzeichnis anlegen:

1
2
mkdir -p ~/fediblog/rss-bot
cd ~/fediblog/rss-bot

Virtuelle Umgebung erstellen:

1
2
python3 -m venv venv
source venv/bin/activate

Hinweis:

Unter Debian-basierten Distributionen wie Debian, Ubuntu oder LMDE muss gegebenenfalls zuerst folgendes Paket installiert werden:

sudo apt install python3-venv

Benötigte Python-Pakete installieren:

pip install feedparser requests

Access Token sicher hinterlegen

Statt den Access Token direkt in das Python-Script einzutragen, nutzen wir eine Umgebungsvariable.

Das ist sauberer und sicherer – besonders, wenn das Script später öffentlich dokumentiert oder versioniert wird.

Datei öffnen:

nano ~/.bashrc

Ganz unten ergänzen:

export GTS_ACCESS_TOKEN="DEIN_ACCESS_TOKEN"

Shell neu laden:

source ~/.bashrc

Prüfen:

echo $GTS_ACCESS_TOKEN

Wenn der Token angezeigt wird, funktioniert alles.

Python Script erstellen

Datei anlegen:

nano rss_to_gts.py

Folgenden Inhalt einfügen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import feedparser
import requests
import json
import os
import re

RSS_URL = "https://deinedomain.tld/index.xml"
MASTODON_URL = "https://social.deinedomain.tld"

ACCESS_TOKEN = os.getenv("GTS_ACCESS_TOKEN")

STATE_FILE = "last_post.json"


def load_last():
    if os.path.exists(STATE_FILE):
        with open(STATE_FILE, "r") as f:
            return json.load(f).get("id")
    return None


def save_last(post_id):
    with open(STATE_FILE, "w") as f:
        json.dump({"id": post_id}, f)


def clean_html(text):
    """Entfernt HTML aus RSS Summary"""
    return re.sub(r"<.*?>", "", text)


feed = feedparser.parse(RSS_URL)

if not feed.entries:
    print("Keine RSS Einträge gefunden.")
    exit()

latest = feed.entries[0]
latest_id = latest.get("id", latest.link)

last_id = load_last()

if latest_id == last_id:
    print("Kein neuer Beitrag.")
    exit()

title = latest.title
link = latest.link
summary = clean_html(latest.get("summary", ""))

# Summary kürzen
summary = summary[:300]

tags = []
if "tags" in latest:
    tags = [f"#{t.term.replace(' ', '')}" for t in latest.tags]

hashtags = " ".join(tags)

post = f"""Neuer Beitrag auf meinem Blog

{title}

{summary}

{link}

{hashtags}
"""

response = requests.post(
    f"{MASTODON_URL}/api/v1/statuses",
    headers={
        "Authorization": f"Bearer {ACCESS_TOKEN}"
    },
    data={
        "status": post,
        "visibility": "public"
    }
)

if response.status_code == 200:
    print("Beitrag veröffentlicht.")
    save_last(latest_id)
else:
    print(response.text)

Wie funktioniert das Script?

Das Script macht Folgendes:

  1. RSS-Feed deiner Webseite abrufen
  2. neuesten Beitrag ermitteln
  3. prüfen, ob dieser bereits gepostet wurde
  4. HTML aus der Summary entfernen
  5. Beitrag automatisch veröffentlichen
  6. ID lokal speichern, um Doppelposts zu verhindern

Die Datei:

last_post.json

merkt sich den zuletzt veröffentlichten Beitrag.

Dadurch werden keine doppelten Posts erstellt.

Hugo Summary bewusst nutzen

Ein kleiner Praxistipp:

Das Script nutzt:

summary = ""

aus deinem Hugo Frontmatter.

Pflege diesen Wert bewusst.

Warum?

Die Summary wird später dein Vorschautext im Fediverse.

Eine gute Summary führt meist zu deutlich mehr Interaktionen als automatisch abgeschnittener Text.

Beispiel:

summary = "So bringst du deine Webseite ins Fediverse und veröffentlichst neue Beiträge automatisch über GoToSocial."

Script testen

Manuell starten:

python rss_to_gts.py

Mögliche Ausgabe:

Beitrag veröffentlicht.

Oder:

Kein neuer Beitrag.

Automatisch per Cronjob ausführen

Cronjob öffnen:

crontab -e

Eintrag ergänzen:

*/10 * * * * cd /home/USER/fediblog/rss-bot && /home/USER/fediblog/rss-bot/venv/bin/python rss_to_gts.py >> bot.log 2>&1

Dadurch wird der RSS-Feed alle 10 Minuten geprüft.

Neue Beiträge erscheinen anschließend automatisch im Fediverse.

Letze Schritte

Solangsam nähern wir uns dem Ende dieses Tutorials. Solltest Du bis hier alles ohne Probleme am laufen haben, dann hast Du jetzt deinen Blog via Active Pub ins Fediverse eingebunden. Deine Seite kann nun von allen Instanzen auf Mastodon gesehen werden und jeder User kann Ihr folgen.

Zum Schluss testen wir jedoch noch einmal die Föderation, in dem wir die Seite https://social.deinedomain.tld/@blog öffnen und auf Mastodon über die Suchfunktion @blog@social.deinedomain.tld suchen.

Wenn neue Beiträge erscheinen, funktioniert die Föderation.

Fazit

Mit einer kleinen GoToSocial-Instanz lässt sich die eigene Webseite direkt ins Fediverse integrieren.

Neue Beiträge erscheinen automatisch im Fediverse und Leser können dem Blog direkt folgen – unabhängig davon, welche Plattform sie nutzen.

Für mich ist das aber nicht nur eine technische Spielerei, sondern auch ein Schritt in Richtung digitale Souveränität.

Statt Inhalte ausschließlich auf zentralen Plattformen wie Facebook, Instagram oder X zu veröffentlichen, behält man die Kontrolle über die eigene Infrastruktur, die eigenen Inhalte und die eigene Reichweite.

Das bedeutet konkret:

  • eigene Domain statt Plattformabhängigkeit
  • offene Standards statt proprietärer Systeme
  • keine algorithmische Reichweitensteuerung
  • keine erzwungene Profilbildung für Werbezwecke
  • weniger Tracking und Datensammlung

Natürlich ist das Fediverse kein vollkommen anonymer Raum und Föderation bedeutet immer auch Datenaustausch zwischen Instanzen. Der entscheidende Unterschied ist jedoch:

Man kann selbst entscheiden, wem man vertraut, welche Software man nutzt und wo die eigenen Daten liegen.

Gerade für Blogs rund um Open Source, Linux, Datenschutz oder digitale Souveränität ist das eine spannende Alternative zu klassischen sozialen Netzwerken.

Und vielleicht ist genau das die eigentliche Stärke:

Die eigene Webseite bleibt der Mittelpunkt – soziale Netzwerke werden nur noch zum Verteilen der Inhalte genutzt, statt zur einzigen Plattform zu werden.