tovotu

2. Februar 20200
Invidious auf einem Uberspace einrichten
Sprache:Crystal - OS:Uberspace

Wie so viele große moderne Webseiten ist auch YouTube vollgepackt mit JavaScript-Code, der Besucherinnen ausspäht, ausbremst, nervt, mit Werbung bombadiert und viel zu viele Ressourcen (Speicher, CPU) auf dem Client verbraucht. Außerdem ist so eine JavaScript-basierte Benutzeroberfläche oft noch nicht mal besonders komfortabel zu bedienen.

Glücklicherweise gibt es mit Invidious eine alternative Benutzeroberfläche für YouTube, die als Open-Source-Projekt entwickelt wird. In diesem Artikel stelle ich vor, wie man diese Proxy-artige Software auf einem Uberspace einrichtet und betreibt.

Leider ist die offizielle Installationsanleitung für Invidious ohne Root-Rechte nicht brauchbar. Da Accounts auf Uberspace einfache User-Accounts auf einem Multiuser-System sind, müssen wir alle Abhängigkeiten aus verschiedenen Quellen zusammensuchen und im Benutzerverzeichnis unterbringen.

Zuerst installieren wir PostgreSQL nach der Anleitung auf lab.uberspace.de. Anschließend beziehen wir eine CA-Zertifikat-Datei [1], die Invidious für die SSL-verschlüsselte Kommunikation mit den Google-Servern benötigen wird:

$ mkdir -p $HOME/etc/openssl/certs/
$ cd $HOME/etc/openssl/certs
$ wget http://curl.haxx.se/ca/cacert.pem

Dann setzen wir eine Umgebung für die Programmiersprache Crystal auf, in der Invidious geschrieben ist. Hierbei achten wir darauf, die jeweils aktuellste Release-Version aus dem offiziellen Repository (Version 0.35.0 zum Zeitpunkt der letzten Aktualisierung dieses Artikels) zu beziehen:

$ mkdir $HOME/build
$ cd $HOME/build
$ wget https://github.com/crystal-lang/crystal/releases/download/0.35.0/crystal-0.35.0-1-linux-x86_64.tar.gz
$ tar xvf crystal-0.35.0-1-linux-x86_64.tar.gz
$ mv crystal-0.35.0-1 $HOME/opt/crystal

Damit wir nicht alle weiteren Abhängigkeiten selber kompilieren müssen, setzen wir eine Anaconda-Umgebung auf und installieren dort vorkompilierte Pakete:

$ wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
$ bash Miniconda3-latest-Linux-x86_64.sh
$
$ # an dieser Stelle einmal ausloggen und wieder einloggen!
(base) $
(base) $ conda create -n invidious python=3.7
(base) $ conda activate invidious
(invidious) $ conda install -c conda-forge libunwind librsvg
(invidious) $ conda install pyyaml go openssl libevent cmake gxx_linux-64 gcc_linux-64
(invidious) $ mkdir -p $CONDA_PREFIX/etc/conda/activate.d/
(invidious) $ mkdir -p $CONDA_PREFIX/etc/conda/deactivate.d/
(invidious) $ cat > $CONDA_PREFIX/etc/conda/activate.d/set_vars.sh << EOF
export OLD_LD_LIBRARY_PATH=\${LD_LIBRARY_PATH}
export LD_LIBRARY_PATH=\$CONDA_PREFIX/lib:\${LD_LIBRARY_PATH}
export LD_LIBRARY_PATH=\$HOME/opt/crystal/lib:\${LD_LIBRARY_PATH}
 
export OLD_PATH=\${PATH}
export PATH=\$HOME/opt/crystal/bin/:\${PATH}
 
export OLD_PKG_CONFIG_PATH=\${PKG_CONFIG_PATH}
export PKG_CONFIG_PATH=\$CONDA_PREFIX/lib/pkgconfig:\${PKG_CONFIG_PATH}
 
export SSL_CERT_FILE=\$HOME/etc/openssl/certs/cacert.pem
EOF
(invidious) $ cat > $CONDA_PREFIX/etc/conda/deactivate.d/set_vars.sh << EOF
export LD_LIBRARY_PATH=\${OLD_LD_LIBRARY_PATH}
unset OLD_LD_LIBRARY_PATH
 
export PATH=\${OLD_PATH}
unset OLD_PATH
 
export PKG_CONFIG_PATH=\${OLD_PKG_CONFIG_PATH}
unset OLD_PKG_CONFIG_PATH
EOF
(invidious) $ conda deactivate
(base) $ conda activate invidious
(invidious) $

Die Bibliotheken lsquic und boringssl, die Invidious verwendet, um Kompatibilitätsprobleme mit der von YouTube verwendeten SSL-Verschlüsselung zu lösen, müssen wir leider selbst mit den folgenden Befehlen kompilieren:

(invidious) $ mkdir -p $HOME/build
(invidious) $ cd $HOME/build
(invidious) $ git clone https://boringssl.googlesource.com/boringssl
(invidious) $ cd boringssl
(invidious) $ git checkout bfe527fa35735e8e045cbfb42b012e13ca68f9cf
(invidious) $ export C_FLAGS="-DSO_RXQ_OVFL=40 -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS -I$CONDA_PREFIX/include -L$CONDA_PREFIX/lib"
(invidious) $ cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="$C_FLAGS" -DCMAKE_C_FLAGS="$C_FLAGS" .
(invidious) $ make ssl crypto
(invidious) $ cd $HOME/build
(invidious) $ git clone https://github.com/litespeedtech/lsquic
(invidious) $ cd lsquic
(invidious) $ git checkout v2.14.8
(invidious) $ git submodule update --init
(invidious) $ cmake -DCMAKE_BUILD_TYPE=Release -DBORINGSSL_DIR="$HOME/build/boringssl" -DCMAKE_C_FLAGS="$C_FLAGS" .
(invidious) $ make lsquic

Jetzt können wir endlich Invidious aus dem offiziellen Git-Repository beziehen und kompilieren:

(invidious) $ cd $HOME/opt
(invidious) $ git clone https://github.com/omarroth/invidious
(invidious) $ cd invidious
(invidious) $ shards install && shards update
(invidious) $ cp $HOME/build/boringssl/{ssl,crypto}/*.a $HOME/build/lsquic/src/liblsquic/*.a lib/lsquic/src/lsquic/ext/
(invidious) $ crystal build src/invidious.cr --threads 1 --progress --link-flags "-L$HOME/build/boringssl/ssl -L$HOME/build/boringssl/crypto -I$CONDA_PREFIX/include -L$CONDA_PREFIX/lib"

Bevor es losgehen kann, muss noch die PostgreSQL-Datenbank invidious mit dem Benutzer kemal (Passwort merken!) vorbereitet werden:

(invidious) $ cd $HOME/opt/invidious
(invidious) $ createuser -P kemal
(invidious) $ createdb -O kemal invidious
(invidious) $ psql invidious kemal < ./config/sql/channels.sql
(invidious) $ psql invidious kemal < ./config/sql/videos.sql
(invidious) $ psql invidious kemal < ./config/sql/channel_videos.sql
(invidious) $ psql invidious kemal < ./config/sql/users.sql
(invidious) $ psql invidious kemal < ./config/sql/session_ids.sql
(invidious) $ psql invidious kemal < ./config/sql/nonces.sql
(invidious) $ psql invidious kemal < ./config/sql/annotations.sql
(invidious) $ psql invidious kemal < ./config/sql/playlists.sql
(invidious) $ psql invidious kemal < ./config/sql/playlist_videos.sql

Das beim Anlegen von kemal gewählte Passwort tragen wir jetzt zusammen mit unserer Domain bzw. Subdomain in die Konfigurationsdatei config/config.yml im Invidious-Verzeichnis ein:

channel_threads: 1
feed_threads: 1
db:
  user: kemal
  password: <PostgreSQL-DB-Password>
  host: localhost
  port: 5432
  dbname: invidious
full_refresh: false
https_only: false
domain: <Domain>
login_enabled: false
registration_enabled: false

Die letzten zwei Zeilen sind optional und deaktivieren die Benutzeranmeldung und -registrierung.

Invidious soll im Produktivbetrieb als Hintergrundprozess laufen, was wir mit supervisord sicherstellen können. Dazu legen wir die Datei $HOME/etc/services.d/invidious.ini mit dem folgenden Inhalt an:

[program:invidious]
command=%(ENV_HOME)s/opt/invidious/invidious.sh
stdout_logfile=%(ENV_HOME)s/logs/invidious.out.log
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=0
stderr_logfile=%(ENV_HOME)s/logs/invidious.err.log
stderr_logfile_maxbytes=1MB
stderr_logfile_backups=0
autostart=yes
autorestart=yes
stopasgroup=true
stopsignal=QUIT

Wir rufen nicht direkt die Invidious-Binary auf, sondern ein Wrapper-Skript, das einige Umgebungsvariablen setzt. Dazu legen wir die Datei $HOME/opt/invidious/invidious.sh mit dem folgenden Inhalt an (wir denken daran, das Skript mit chmod +x ausführbar zu machen!):

#!/usr/bin/bash
 
source $HOME/miniconda3/etc/profile.d/conda.sh
conda activate invidious
 
cd $HOME/opt/invidious
./invidious

Schließlich können wir den Prozess mit supervisorctl reread starten und den Status mit supervisorctl status überprüfen.

Wenn alles gut gegangen ist, lauscht Invidious jetzt auf Port 3000. Damit das auch von draußen sichtbar ist, richten wir mit uberspace web backend set / --http --port 3000 einen entsprechenden Reverse-Proxy ein.

Invidious lässt sich übrigens besonders komfortabel in Kombination mit der Firefox-Erweiterung Invidition verwenden. Dort lässt sich auch die alternative Twitter-Oberfläche Nitter aktivieren, die ich in einem weiteren Artikel vorstelle.

  1. curl.haxx.se/docs/caextract.html