Schlagwort-Archiv: Mastodon

Mastodon-Backups

Vor über 10 Jahren habe ich mal darüber berichtet, wie ich diverse Web-Dienste bei mir lokal sichere. Davon ist fast nichts mehr, wie es war: Viele Dienste wurden umgebaut, manche haben sich verabschiedet, und generell läuft das alle nicht mehr auf einem Raspberry Pi, sondern als virtuelle Maschine auf meinem Proxmox-Server (das wäre mal ein Thema für sich…).

Nicht geändert hat sich mein Wunsch, Daten bei mir lokal gesichert zu haben; das gilt auch für meinen Mastodon-Account (@dasaweb). Ich habe meine Mastodon-Aktivität zum Jahresanfang wieder intensiviert, und es gefällt mir. Mein Account wird zwar auf der Instanz https://wue.social/ von Ralf gehostet, und Ralf kann man auf jeden Fall vertrauen was die Datensicherheit angeht. Aber ihr wisst ja, wie das ist mit dem Vertrauen und der Kontrolle. Außerdem braucht man ja auch was zum basteln, und wenn sich so ein Gedanke erst mal vestgesetzt hat…

Nach etwas Recherche bin ich bei Mastodon-Archive hängen geblieben und habe das erst mal per pip installiert:

sudo apt update
pip install mastodon-archive

Damit habe ich mir dann ein Backup-Script gebaut, welches Beiträge, Follow-Listen, Medien etc. zieht und die Beiträge noch in verschiedenen Formaten speichert:

#!/usr/bin/env bash
export PATH="/usr/local/bin:/usr/bin:/bin:/home/daniel/.local/bin"
set -Eeuo pipefail

# Einfaches Backup-Script basiernd auf "mastodon-archive" https://github.com/kensanata/mastodon-archive
# 
# - optional: quiet-run fuer Crontab via -q/--quiet
# - nur Fehler gehen auf STDERR raus
# - Token/Secret-Dateien bleiben im ZIP enthalten

QUIET=0

usage() {
  cat <<'EOT'
Usage: backup-mastodon.sh [OPTION]

Optionen:
  -q, --quiet     Minimaler Output (fuer Crontab)
  -v, --verbose   Voller Output (Default)
  -h, --help      Diese Hilfe anzeigen
EOT
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    -q|--quiet)
      QUIET=1
      ;;
    -v|--verbose)
      QUIET=0
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "❌ Fehler: Unbekannte Option: $1" >&2
      usage >&2
      exit 2
      ;;
  esac
  shift
done

log() {
  if (( QUIET == 0 )); then
    echo "$@"
  fi
}


ACCOUNT="dasaweb@wue.social"
BACKUP_BASE_DIR="$HOME/backups/mastodon"
TOOTS_PER_PAGE="2000"

USER_PART="${ACCOUNT%@*}"
INSTANCE_PART="${ACCOUNT#*@}"
STAMP="$(date +%Y-%m-%d_%H%M%S)"
WORKDIR="$BACKUP_BASE_DIR/workingdir"
ZIPFILE="$BACKUP_BASE_DIR/mastodon-${STAMP}.zip"

mkdir -p "$WORKDIR"
cd "$WORKDIR"

if ! command -v mastodon-archive >/dev/null 2>&1; then
  echo "❌ Fehler: mastodon-archive ist nicht im PATH." >&2
  exit 1
fi

if ! command -v zip >/dev/null 2>&1; then
  echo "❌ Fehler: zip ist nicht installiert." >&2
  exit 1
fi

ma() {
  if (( QUIET == 1 )); then
    mastodon-archive --quiet "$@"
  else
    mastodon-archive "$@"
  fi
}

log "📦 Starte Mastodon-Backup fuer $ACCOUNT"

log "🗂️ Aktualisiere Archiv"
ma archive \
  --with-mentions \
  --with-followers \
  --with-following \
  --with-mutes \
  --with-blocks \
  "$ACCOUNT"

log "🖼️ Lade Medien"
# Medien von eigenen Toots:
ma media --suppress-errors "$ACCOUNT"
# Medien von Toots, die ich gebookmarkt habe:
ma media --collection bookmarks --suppress-errors "$ACCOUNT"
# Medien von Toots, die ich geliked habe:
# ma media --collection favourites --suppress-errors "$ACCOUNT"

log "📝 Erzeuge Text-Exporte"
ma text "$ACCOUNT" > "$WORKDIR/${INSTANCE_PART}.user.${USER_PART}.statuses.txt"
ma text --reverse "$ACCOUNT" > "$WORKDIR/${INSTANCE_PART}.user.${USER_PART}.statuses.reverse.txt"
ma text --collection favourites "$ACCOUNT" > "$WORKDIR/${INSTANCE_PART}.user.${USER_PART}.favourites.txt"
ma text --collection favourites --reverse "$ACCOUNT" > "$WORKDIR/${INSTANCE_PART}.user.${USER_PART}.favourites.reverse.txt"
ma text --collection bookmarks "$ACCOUNT" > "$WORKDIR/${INSTANCE_PART}.user.${USER_PART}.bookmarks.txt"
ma text --collection bookmarks --reverse "$ACCOUNT" > "$WORKDIR/${INSTANCE_PART}.user.${USER_PART}.bookmarks.reverse.txt"
ma text --collection mentions "$ACCOUNT" > "$WORKDIR/${INSTANCE_PART}.user.${USER_PART}.mentions.txt"
ma text --collection mentions --reverse "$ACCOUNT" > "$WORKDIR/${INSTANCE_PART}.user.${USER_PART}.mentions.reverse.txt"

log "🌐 Erzeuge HTML"
ma html --toots-per-page "$TOOTS_PER_PAGE" "$ACCOUNT"
ma html --collection favourites --toots-per-page "$TOOTS_PER_PAGE" "$ACCOUNT"

log "📊 Erzeuge Report"
{
  echo "# report ($(date --iso-8601=seconds))"
  ma report --all --top -1 "$ACCOUNT"
} > "$WORKDIR/${INSTANCE_PART}.user.${USER_PART}.report.txt"

log "👥 Versuche Zusatzlisten"
for cmd in allowlist followers following mutuals; do
  if ma "$cmd" "$ACCOUNT" > "$WORKDIR/${INSTANCE_PART}.user.${USER_PART}.${cmd}.txt" 2>/dev/null; then
    :
  else
    rm -f "$WORKDIR/${INSTANCE_PART}.user.${USER_PART}.${cmd}.txt"
  fi
done

cat > "$WORKDIR/README-backup.txt" <<EOT
📦 Mastodon-Backup
Account: $ACCOUNT
Erstellt: $(date --iso-8601=seconds)
Quelle: mastodon-archive

Enthalten:
- JSON-Archiv(e)
- heruntergeladene Medien für statuses/favourites/bookmarks
- Text-Exporte (normal + reverse)
- HTML-Exporte
- Report
- ggf. Zusatzlisten
- Token-/Secret-Dateien
EOT

log "🗜️ Packe ZIP: $ZIPFILE"
(
  cd "$BACKUP_BASE_DIR"
  zip -qr "$ZIPFILE" "$WORKDIR"
)

log "✅ Fertig: $ZIPFILE"

Man sieht dem Script an, dass ich mir dabei habe helfen lassen, denn so schön wäre ein selbstgebautes Script (bei mir) nicht geworden.

Beim ersten Lauf des Scripts muss man sich autorisieren. Man bekomme eine URL gezeigt, die man im Browser aufruft und damit Credentials erhält, die auch nur Leserechte haben:

Die Credentials werden dann lokal gespeichert. Ein Durchlauf des Scripts sieht in etwas so aus:

daniel@netzbackup:~/skripte$ ./backup-mastodon.sh

📦 Starte Mastodon-Backup fuer dasaweb@wue.social
🗂️ Aktualisiere Archiv
Registering app
This app needs access to your Mastodon account.
Visit the following URL and authorize the app:
https://wue.social/oauth/authorize?client_id=.............................................................................................................&response_type=code&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&scope=read&force_login=False&state=None&lang=None
Then paste the access token here:
_0...................................ciI
Get user info
Get all statuses (this may take a while)
Get favourites (this may take a while)
Get bookmarks (this may take a while)
Get notifications and look for mentions (this may take a while)
Get followers (this may take a while)
Get following (this may take a while)
Get mutes (this may take a while)
Get blocks (this may take a while)
Skipping notes
Saving 307 statuses, 436 favourites, 1 bookmarks, 143 mentions, 88 followers, 182 following, 0 mutes, 0 blocks, 0 notes
🖼️ Lade Medien
123 urls in your backup (39 are previews)
123 to download
Downloading |################################| 123/123
3 urls in your backup (0 are previews)
0 to download

📝 Erzeuge Text-Exporte
🌐 Erzeuge HTML
Loading existing archive: wue.social.user.dasaweb.json
Writing wue.social.user.dasaweb.statuses.0.html
Loading existing archive: wue.social.user.dasaweb.json
Writing wue.social.user.dasaweb.favourites.0.html
📊 Erzeuge Report
👥 Versuche Zusatzlisten
🗜️ Packe ZIP: /home/daniel/backup/Mastodon/mastodon-2026-04-02_001551.zip
✅ Fertig: /home/daniel/backup/Mastodon/mastodon-2026-04-02_001551.zip

Jetzt kann das Script in die Crontab gepackt werden:

0 1 * * 2,6 ~/skripte/backup-mastodon.sh --quiet

Jeder Run aktualisiert inkrementell das Arbeitsverzeichnis und zippt das Ergebnis. Fertig.

DALL·E 2022-12-21 15.46.15 - a blue bird fighting with a mastodon

Fediverse / ActivityPub / Mastodon / Pixelfed / …

Viel wird in diesen Tagen geschrieben über Twitter und den ganzen Elon Musk-Irrsinn, viel wird diskutiert über die problematischen Seiten zentraler Kommunikationsinfrastruktur in den Händen von mächtigen Privatpersonen. Da ist es nicht nötig, dass ich – ganz im Sinne von “Es wurde bereits alles gesagt, aber noch nicht von jedem” – hier das Thema inhaltlich nochmal vertiefe. Mit diesem Post will ich vor allem meine (zugegeben noch sehr überschaubaren) Fediverse-Links sammeln, die für die Leute interessant sind, die sich für mich interessieren. Here we go:

  • @dasaweb@wue.social Das ist der Link zu meinem Mastodon-Profil. Ich war vorher auf der beliebten Instanz mastodon.social, an der es an sich auch nichts auszusetzen gibt; allerdings ist mir die Idee der Dezentralität wichtig, daher bin ich unlängst zu wue.social gewechselt. Eine kleine und lokale Instanz, bei der die lokale Timeline dann auch wirklich eine geographische und keine inhaltliche Lokalität abbildet. Die “lokale Timeline” ist die Sammlung der Inhalte, die Leute auf genau dieser Instanz auch posten. Außerdem wird die Instanz von Ralf gehostet, und Vertrauen zum Hoster ist immer eine gute Sache, siehe die aktuellen Twitter-Debatten… Im Moment ist die Instanz noch so überschaubar, dass Moderation kaum nötig und die Finanzierung auch privat machbar ist. Ralfs gute Gedanken dazu findet man in einem Post von ihm auf dem Würzblog.
  • @dasaweb@pixelfed.de Mein Pixelfed-Account. Pixelfed funktioniert wie Instagram, nur eben dezentralisiert und natürlich über das ActivityPub-Protokoll, genau wie Mastodon und alles andere im Fediverse auch. Zugegeben, hier ist noch gar nichts los, bisher habe ich dort nur zwei Testfotos und bin nicht vernetzt. Aber vielleicht werde ich meine Liebe zu Fotos dort wieder ausleben, Instagram ist für mich aktuell leider nur noch eine Plattform für Stories. In der Diskussion um Twitter und Mastodon verstehe ich, dass Mastodon konzeptionell hier und da Schwierigkeiten hat; bei Instagram vs. Pixelfed sehe ich die tatsächlich viel weniger, denn da geht es (jedenfalls in meinem Nutzungsverhalten) doch viel mehr um ein persönliches Netzwerk und weniger um globale Debatten. Wir werden sehen.
  • @dasaweb@dasaweb.de Unter diesem Link kann man den Inhalten dieses Blogs hier im Fediverse folgen. Einfach @dasaweb in die Suche z.B. bei Mastodon eingeben und folgen. Möglich ist das durch die ActivityPub-Erweiterung von Matthias Pfefferle für WordPress. Feine Sache. Generell mag ich die Idee, vorhandene Plattformen ActivityPub-fähig zu machen.

Nachdem jetzt so häufig die Begriffe “Fediverse” und “ActivityPub” gefallen sind verlinke ich dazu doch noch ein kurzes Video, falls das jemandem gar nichts sagt. Ist schon etwas älter, was ich ganz gut finde, weil es dadurch nicht von den aktuellen Debatten überlagert ist:

Ich bin gespannt, wie das alles weiter geht. Mein Optimismus, dass Fediverse-Angebote bisherige Social-Media-Diensten den Rang ablaufen werden hält sich in Grenzen. Aber ich bedauere das, weil ich der Meinung bin, dass die nicht zu leugnenden aktuellen Nachteile (Bsp.: keine globale Suche bei Mastodon) keine Rolle spielen sollten gegenüber den Problemen, die wir uns gesellschaftlich und politisch in den letzten Jahren mit Diensten wie Facebook und Twitter eingehandelt haben. Das größte Problem für einen Wandel scheint mir die Trägheit der Masse zu sein, und dagegen kann ich als Physiker nun wahrlich nichts sagen…