Mastodon auf URL ungleich Domäne

Wer Mastodon Server so wie ich auf Server der nicht wie Domäne heißt betreibt (Server: social.galluner.fun, Domäne für User: gallauner.fun, also z.B. @roman@gallauner.fun – also WEB_DOMAIN != LOCAL_DOMAIN) aber auch nicht gleich die Domäne 1:1 auf Mastodon weiterleiten will weil vielleicht für andere Webseite benutzt funktionieren für mich bisher folgende Weiterleitungen (natürlich inklusive allem was im Originalrequest in der URI hinten dran stand):

# für federation
/.well-known/*
# für following von anderen Instanzen
/authorize_interaction

Bin mir ziemlich sicher dass da noch was dazu kommt 🙂

WordPress Preview Cards in Mastodon

Mein aktuelles Theme hat in Mastodon Preview Cards ohne Bild und Text erzeugt, Lösung ist dass Mastodon keine rich oEmbeds erlaubt daher im WordPress Thema in function.php gemäß Anleitung auf link only umgebaut.

Codeteil der in function.php vom Theme einzubauen ist (irgendwo):

/* Return link instead of rich oembed data */
function filter_oembed_response_data($data) {
  if ($data['type'] === 'rich') {
    $data['type'] = 'link';
    unset($data['html']);
  }
  /* While we're at it, remove single quotes html entities */
  $data["title"] = str_replace("’","'", $data["title"]);

  return $data;
}
add_filter('oembed_response_data', 'filter_oembed_response_data', 11, 4);

Quelle: https://www.colino.net/wordpress/en/archives/2022/11/27/wordpress-fix-thumbnail-on-mastodons-preview-cards/

Single User Mastodon mit rootless Podman auf Debian

Voraussetzungen:

  • Server mit Zugang von und zum Internetz 🙂
  • public DNS Record (A/CNAME) für Webserver
  • Podman 4.x mit netavark als Network Backend, siehe auch hier.

Mastodon von Github clonen

git clone https://github.com/tootsuite/mastodon

Änderungen im docker-compose.yml:

  • Da Podman nicht per Default auf docker.io nach den Images sucht im docker-compose.yml postgres und redis Image auf docker.io/postgres:.. bzw. docker.io/redis:… ändern.
  • Optional: web/redis/db/etc. sind etwas generisch wenn man mehrere Dienste hinter dem folgenden Caddy verstecken will – daher Container- und Netzwerknamen mit mastodon_ prefixieren

Images ziehen, da wir Caddy dann in anderem Deployment starten und die Netzwerke sonst vom Namen her unterschiedlich wären (podman-compose nimmt per Default Verzeichnisnamen als Prefix was man über die Angabe eines Projekts übersteuern kann, im Beispiel “ext”):

podman-compose -p ext pull

Mastodon Setup starten:

podman-compose -p ext run mastodon_web bundle exec rake mastodon:setup

Die Fragen:

  • Domäne ist der Name mit dem die Instanz aufscheinen soll – muss NICHT der Webservername sein wie ich ursprünglich angenommen habe. Also z.B. whatever.at wenn Webserver social.whatever.at heissen soll. Die Fediverse Usernamen sind dann @whoever@whatever.at.
  • Single User Mode: No – stellen wir später um nachdem wir interaktiv ersten Account angelegt haben (auch über tootctl möglich dann könnte man hier schon Yes verwenden)
  • Postgres/Redis: Bis auf Rechnername (wenn wie oben mit mastodon_ prefixiert) ohne Änderung übernehmen.
  • Attachments werden nicht in einer Cloud gespeichert.
  • Mailing nicht über localhost – passende SMTP Settings angeben.
  • An dieser Stelle werden die Settings ausgegeben – in Datei .env.production speichern.
  • DB erstellen lassen
  • KEINEN Admin erstellen, Setup läuft hier sonst in einen Fehler

Alle laufenden Container entfernen.

In .env.production einbauen damit Webserver nicht gleich Instanzname sein muss:

WEB_DOMAIN=social.whatever.at

Das Ganze starten:

podman-compose -p ext up -d

Damit man Attachments oder auch z.B. Avatarbilder raufladen kann muss man Security von einem Folder noch ändern (die Start ID in /etc/subuid für den podman ausführenden User + 990 – absolut keine Ahnung warum 990 wenn die UID des mastodon Users im Container 991 ist 🙂 ):

chown -R 100990:100990 ./public/system

An dieser Stelle haben wir auf 127.0.0.1:3000 Webserver und auf 127.0.0.1:4000 API Server laufen, mit Caddy in einem zweiten podman-compose Deployment bringen wir das samt Lets Encrypt ins Internetz.

docker-compose.yml (unter der Annahme dass Container+Netze mit mastodon_ prefixiert wurden):

version: '3'
services:
 caddy:
   image: docker.io/caddy:latest
   container_name: caddy
   ports:
     - 80:80
     - 443:443
   volumes:
     - ./Caddyfile:/etc/caddy/Caddyfile
     - ./caddy-data/certs:/data
   restart: always
   depends_on:
     - mastodon_web
     - mastodon_streaming
   networks:
     - mastodon_external_network
     - mastodon_internal_network

networks:
 mastodon_external_network:
 mastodon_internal_network:
   internal: true

Caddyfile:

https://social.whatever.at {
  handle /api/v1/streaming*    {
     reverse_proxy mastodon_streaming:4000
  }

  handle    {
     reverse_proxy mastodon_web:3000
  }
}

Verzeichnis caddy-data erzeugen und schon kanns losgehen, wichtig gleiches Projekt wegen Netzwerknamen:

podman-compose -p ext up -d

An dieser Stelle sollte (sofern Caddy Zertifikat lösen konnte) https://social.whatever.at aufrubar sein – Account erstellen und aktivieren (Aktivierungslink via Mail), danach zum Admin machen (wiederum – unter der Annahme dass Projekt “ext” verwendet und Container/Netzwerke mit “mastodon_” prefixiert wurden):

podman exec -it ext_mastodon_web_1 /bin/bash

Im Container dann (Annahme neuer Account = whoever, casing bei Admin wichtig):

tootctl account modify whoever -- role=Admin

Danach die Instanz stoppen (web bleibt gerne hängen) und in .env.production auf Single User Mode ändern:

SINGLE_USER_MODE=true

Danach wie wieder starten. Fertig 😀

Provider ohne IPv6 prefix delegation: NAT66

Solange A1 am VDSL Modem keine IPv6 Prefix Delegation zulässt (es werden nur /64 Adressen geliefert) muss man für halbnativen IPv6 Zugriff (und vorhersagbare/die Möglichkeit von statischen lokalen Adressen) in die Trickkiste greifen und NAT66 von den lokalen ULAs (fd::/8) auf die öffentliche GUA am Modem konfigurieren. Hier am Beispiel OpenWrt (alles LuCI, Stand 23.05.2):

Network/Interfaces/Global network options: Check ob “IPv6 ULA-Prefix” vorhanden ist (der ausgewürfelte /48 prefix für die lokalen fd:: Adressen)

Network/Interfaces/Interfaces/Interface der Wahl/DHCP Server/IPv6 Settings: RA-Service auf “server mode” (DHCP Server und NDP Proxy bleibt disabled)

Darauf erscheint Zusatztab “IPv6 RA Settings”: “Default Router” auf “on available prefix”

Ist das angewendet gibts unter Network/Interfaces/Interfaces/Interfache der Wahl/General Settings neue Felder für die IPv6 Adresse (nur das Default Interface “lan” erhält eine Adresse mit dem ULA Prefix und fdxx:xxxx:xxxx::1/60, dort ist dann naturgemäß nichts zu tun) – dort dann passende IPv6 Adresse eintragen (z.B. VLAN hinter dem /48 Teil der vorgegeben ist für /60 Netz – im Beispiel VLAN 20):

Network/Interfaces/Interfaces/wan6/Advanced Settings/IPv6 source routing disablen

Network/Firewall/Zones/der Zeile mit wan => REJECT (die mit Masquerading=enabled)/Advanced Settings/IPv6 Masquerading enablen

Damit hat man all das mühsam nachgebaut was mit IPv6 eigentlich der Vergangenheit angehören hätte sollen…. 🙁

Das alles ist im OpenWrt Wiki beschrieben:

# Enable IPv6 masquerading aka NAT66 on the WAN zone.
# ---------------------------------------------------
uci set firewall.@zone[1].masq6="1"
uci commit firewall
service firewall restart

# Announce IPv6 default route for the ULA prefix.
# (replace ".lan." with your interface to change)
# -----------------------------------------------
uci set dhcp.lan.ra_default="1"
uci commit dhcp
service odhcpd restart

# Disable IPv6 source filter on the upstream interface.
# -----------------------------------------------------
uci set network.wan6.sourcefilter="0"
uci commit network
service network restart

Debian Dependency ignorieren

Problem: Custom .DEB mit einer Dependency die in Debian nicht enthalten ist oder die Dependency ist falsch weil eine höhere Version der Dependency benötigt wird aber nicht in Debian enthalten ist
[TP-Link Omada Controller DEB mit JRE 17 verlangt JSVC >=1.0.8 aber 1.1.x ist tatsächlich notwendig, siehe hier]

Lösung (grauslich aber es wirkt): /var/lib/dpkg/status editieren und beim entsprechenden Paket (welches z.B. bei apt upgrade dann die fehlende Dependency einfordert und –fix-broken vorschlägt was zwar apt glücklich machen würde aber Omada bricht) bei “Depends:” die irrgeleitete Dependency entfernen.

tp-link Omada Controller auf Raspberry Pi installieren

In Anlehnung an die Anleitung hier die Kommandos (Raspberry 4 mit 4 GB RAM, unter 2 eher schmerzhaft, Debian 11):

sudo apt update && sudo apt upgrade
#--------------- MONGODB -------------------
wget https://repo.mongodb.org/apt/ubuntu/dists/focal/mongodb-org/4.4/multiverse/binary-arm64/mongodb-org-server_4.4.18_arm64.deb

sudo dpkg -i mongodb-org-server_4.4.18_arm64.deb

sudo systemctl daemon-reload
sudo systemctl enable mongod
sudo systemctl start mongod

#--------------- JAVA (JDK) ----------------
sudo apt install openjdk-17-jdk-headless

#--------------- JSVC BUILD ----------------
sudo apt install autoconf make gcc
wget https://dlcdn.apache.org/commons/daemon/source/commons-daemon-1.3.4-src.tar.gz
tar xvfz commons-daemon-1.3.4-src.tar.gz
cd src/native/unix
sh support/buildconf.sh
./configure --with-java=/usr/lib/jvm/java-17-openjdk-arm64
make
sudo cp jsvc /usr/bin/

#---------------- OMADA -------------------
#Liste: https://www.tp-link.com/de/support/download/omada-software-controller/
wget https://static.tp-link.com/upload/software/2024/202401/20240112/Omada_SDN_Controller_v5.13.23_linux_x64.deb

sudo dpkg -i --ignore-depends=jsvc Omada_SDN_Controller_v5.13.23_linux_x64.deb

Das letzte dpkg -i sollte den Controller auch gleich starten (Zugriff über Port 8088). Sonst mit sudo tpeap start/stop/status/version steuerbar.

Software, Logs und Configs unter /opt/tplink/EAPController.

ffmpeg Fenster oder single Desktop aufzeichnen

Weil mir die Sucherei jedes mal auf die Nerven geht:

ffmpeg -f gdigrab -framerate 30 -i title="Fenstertitel" -b:v 3M -pix_fmt yuv420p video.mp4

Der einfachste Weg die verfügbaren Fenstertitel kann man über das EXE mit folgender Commandline rausfinden (hier am Beispiel Chrome):

tasklist /v /fi "imagename eq chrome.exe" /fo list|findstr "Window"
(oder "Fenster" auf deutschem System)

Problematisch wirds bei Firmen die meinen irgendwelche in CMD nicht vernünftig übertragbare Zeichen im Fenstertitel haben zu müssen, oder Microsoft? ODER???

Bei Multimonitor kann man das Video um die nicht gewünschten Teile erleichtern, Syntax ist

videobreite:videohöhe:xstart:ystart

bei einem Setup mit 3 1920×1200 Monitoren wäre der volle mittlere Monitor also:

ffmpeg -f gdigrab -framerate 30 -i desktop -vf crop=1920:1200:1920:0 -b:v 3M -pix_fmt yuv420p video.mp4

Cross podman-compose Namensauflösung

Annahme: Zwei Verzeichnisse mit docker-compose.yaml die mit podman-compose ins Leben gerufen werden.

Defaultverhalten: Selbst bei Angabe von “networks:” im docker-compose.yaml sehen sich die zwei Deployments nicht weil sie in zwei Podman Netzwerken erzeugt werden. Die Netzwerke werden immer mit dem Verzeichnisnamen prefixiert (podman network ls).

Ziel: Container aus Deployment A sollen Container aus Deployment B namensmäßig auflösen und auch netzwerkmäßig erreichen können.

Lösung: Identen Projektnamen beim Aufruf von podman-compose für beide Deployments angeben

podman-compose -p meinprojekt up -d

❗ Sollten networks: im yaml verwendet werden müssen die Container die miteinander kommunizieren sollen natürlich auch im gleichen Network sein – der Projektname ist nur der Prefix des Netzwerks.

Debian + fail2ban = Have not found any log file for sshd jail

Gemäß Issue ist das ein Problem von allen systemd-basierten Distros die nur mehr in journald loggen – in /etc/fail2ban/jail.local in Sektion [DEFAULT] das Setting backend auf systemd setzen:

# /etc/fail2ban/jail.local 
# (gemäß Doku von /etc/fail2ban/jail.conf kopiert)

[DEFAULT]
backend = systemd

[sshd]
enabled = true

Damit das funktioniert muss man noch folgendes Paket installieren:

sudo apt install python3-systemd

Wie man im Issue auch nachlesen kann bringt das natürlich alle Jails um die in Logfiles suchen wollen 😐

Inter-Container Kommunikation mit rootless podman auf Debian

Notwendige Pakete für podman

podman
slirp4netns
uidmap
podman-compose

Danach am besten Reboot weil sonst a) die subuids/subguids von uidmap und b) die netns Geschichten von slirp4netns nicht greifen und podman-compose auf die Nase fliegt mit “podman failed to mount runtime directory for rootless netns” failed.

Aber – damit können zwei Container noch nicht miteinander kommunizieren. Podman benutzt dann per default CNI als Netzwerkmethode und das überall beschriebene Paket “podman-plugins” gibts auf Debian offenbar nicht (erlebt auf bookworm), das notwendige Paket mit dem plugin “dnsname” (landet dann auf /usr/lib/cni/) heißt

golang-github-containernetworking-plugin-dnsname

Das installiert eben das dnsname CNI plugin und auch dnsmasq-base damit Inter-Container DNS Lookups darüber geführt werden können.

Das alleine hilft aber noch nicht weil das Default Netzwerk “podman” (podman network ls) hat DNS lookups nicht enabled (podman network inspect podman – Property “dns_enabled” steht auf false).

Erzeugt man aber nach der Installation vom DNSNAME plugin ein Netzwerk hat dieses dns_enabled=true, entweder auf der commandline

podman create network whatevernet
podman run whatever:latest --net whatevernet

oder im compose file als network:

networks:
   whatevernet:


services:
   whatever:
      image: whatever:latest
      networks:
         - whatevernet

UPDATE

Keine Ahnung warum mein podman mit CNI als Netzwerkbackend installiert wurde aber seit 4.0 sollte eigentlich netavark Default sein – welches das alles out of the box kann. Umstellung:

  • podman system reset
    (Reboot um Reste zu entfernen)
  • sudo cp /usr/share/containers.conf /etc/containers/
  • unter [network] Eintrag network_backend entkommentieren und auf “netavark” setzen
  • sudo apt install netavark
  • sudo apt install aavark
  • podman info | grep networkBackend
    (sollte netavark sein)