Newsboat und Wallabag - Mehrere Smart Cards und unterschiedliche Betriebssystem verwenden
Newsboat kann über die API Artikel direkt an Wallabag senden. Dort können die Beiträge bequem und übersichtlich verwaltet, mit Tags versehen und im Webbrowser oder der Wallabag-Apps auf allen Endgeräten gelesen werden.
In diesem Beitrag werden mehrere Clients und Smartcards (YubiKey und Nitrokey (Affiliate Link )) verwendet, um interessante Artikel an die zentrale Wallabag-Instanz zum späteren lesen zu senden.
Dieser Beitrag baut auf Read it Later - Sende Artikel aus Newsboat direkt an Wallabag auf. Ein paar kleinere Anpassungen im Skript sind notwendig.
Ausgangssituation
Es werden mehrere Clients mit unterschiedlichen Betriebssystemen verwendet, u.a. macOS , Kubuntu und Qubes OS .
An diesen Clients werden mehrere Yubikeys und Nitrokey (Affiliate Link ) angeschlossen. Diese Smartcards haben jeweils unterschiedliche Seriennummern und werden mit verschiedenen GPG-Schlüssen verwendet.
Wichtige Konfigurationsdateien werden zwischen den einzelnen Clients über ein Git-Repository ausgetauscht und aktuell gehalten. Eine genaue Beschreibung des Setups ist in Newsboat Konfigurationsdateien in macOS und Linux verwenden zu finden. Dateien mit sensiblen Informationen, wie Zugangsdaten, werden mit GPG verschlüsselt.
Auf allen Clients wird der RSS Reader Newsboat verwendet. Die abonnierten Feeds werden über das Git-Repository verwaltet. Von jedem Client, aus jeder Newsboat-Instanz sollen interessante Artikel für das spätere Lesen an das zentrale Wallabag gesendet werden.
Syncthing - Alternative zu Git
Eine Alternative zu Git stellt Syncthing dar. Damit lassen sich Ordner und Dateien zwischen allen möglichen Geräten teilen. Für dieses Tool wird kein eigener Server benötigt.
Ich selbst verwende eine Hybrid-Lösung aus Git und Syncthing . Die Konfigurationsdateien werden über einen Git-Server verwaltet, da diese sich nicht so häufig ändern.
Die Token-Dateien werden über Syncthing übertragen, da der refresh_token sehr häufig gewechselt wird und dadurch sehr viele "unnötige" Änderungen in Git zu verwalten wären.
Das Problem
In meinem bisherigen Setup werden die Zugangsdaten zu Wallabag mit einem öffentlichen GPG-Schlüssel auf dem Client abgespeichert. Den Zugriff erhält Newsboat auf die Anmeldedaten nur, wenn die korrekte Smartcard angeschlossen ist. Das funktioniert wunderbar zuverlässig.
1. Problem: Smartcard ist nicht angeschlossen
Bei der Verwendung von mehreren Clients muss der richtige Yubikey / Nitrokey (Affiliate Link ) am Gerät angeschlossen sein. Wenn die Smartcard nun an einem anderen Client steckt, muss man umstecken. Das ist umständlich.
2. Wallabag verwendet OAuth
Wallabag verwendet OAuth und erstellt nach jeder erfolgreichen Anmeldung über die API einen sogenannten referesh_token, der im Skript in der automatisch in der verschlüsselten Passwortdatei hinterlegt wird.
Verwendet man nun die gleiche Passwortdatei auf unterschiedlichen Clients, stellt sich irgendwann die Frage: "Wo ist der richtige referesh_token abgelegt?
Ohne referesh_token keinen Zugriff auf Wallabag und kein Speichern des interessanten Artikels aus Newsboat.
Lösung
1. Lösung
Es werden einfach mehrere Yubikeys und Nitrokey (Affiliate Link ) verwendet.
-
Yubikey ist an Client 1 angeschlossen.
-
Nitrokey verbleibt an Client 2.
Die Smart Cards können aber auch gewechselt werden. Dann ist es jedoch erforderlich, dass man die Wallabag-Passwort-Datei per Git an alle Clients verteilt, sonst gibt es ein Problem mit dem referesh_token.
2. Lösung
Es werden zwei Passwortdateien mit unterschiedlichen Tokens erstellt. (Wallabag Token erstellen)
Jeder Smartcard wird eine Datei zugeordnet.
- Yubikey →
wallabag_token1.json.gpg - Nitrokey →
wallabag_token2.json.gpg
Das Skript erkennt auf Grundlage der Seriennummer der Smartcard, ob ein YubiKey oder ein Nitrokey angeschlossen ist. Dann wird die richtige Passwortdatei entschlüsselt und Newsboat kann den Artikel an Wallabag senden.
Installiere deinen eigenen Git-Server
Du kannst sehr einfach deinen eigenen Git-Server in einer Docker-Umgebung installieren.
In Gitea Installation via Docker auf einer Synology Disk Station wird das am Beispiel von Gitea beschrieben.
Du kannst aber auch Forgejo verwenden. (Empfehlung)
Gib mir gerne einen Kaffee ☕ aus 😀
Gib mir gerne einen Kaffee ☕ aus !
Wenn dir meine Beiträge gefallen und geholfen haben, dann kannst du mir gerne einen Kaffee ☕️ ausgeben.
bc1qfuz93hw2fhdvfuxf6mlxlk8zdadvnktppkzqzj
Weitere Möglichkeiten mich zu unterstützen findest du 👉 hier
Die Skripte
- Git - Newsboat-Konfigurations- und URL-Dateien
- Syncthing -
wallabag_token1.json.gpg&wallabag_token1.json.gpg
Der wichtige Abschnitt ist ab Zeile 33 anzupassen.
Die Seriennummer der Smartcard wird mit dem Befehl gpg --card-status abgefragt.
Die gpg_key_id_1 ist die Schlüssel-ID des eigenen GPG-Schlüssels.
Die restliche Einrichtung des Skripts bleibt gleich wie in Newsboat Konfigurationsdateien in macOS und Linux verwenden beschrieben.
#!/usr/bin/env bash
set -euo pipefail
export GPG_TTY=$(tty)
###################################
# ASYNCHRONER START (robust)
###################################
# Absoluten Pfad des Skripts ermitteln
SCRIPT_PATH="$(readlink -f "$0")"
if [[ "${ASYNC:-0}" -eq 0 ]]; then
ASYNC=1 bash "$SCRIPT_PATH" "$@" &
exit 0
fi
###################################
# Arguments
###################################
url="$1"
title="$2"
description="$3"
feed_title="$4"
date_time=$(date "+%Y-%m-%d")
###################################
# Bookmark files
###################################
bookmarks_folder="$HOME/Arbeitsordner/newsboat-bookmarks"
bookmarks_file_md="$HOME/Arbeitsordner/newsboat-bookmarks/bookmarks.md"
bookmarks_file_txt="$HOME/Arbeitsordner/newsboat-bookmarks/bookmarks.txt"
###################################
# Wallabag
###################################
wallabag_url="https://wallabag.exampel.com"
tags="newsboat,it"
###################################
# YubiKey / Nitrokey and GPG Configuration
###################################
# Command to get serial number of smart card
# gpg --card-status
# YubiKey 1
# Make sure serial key and gpg key match
serial_1="11111111"
gpg_key_id_1="GPG11111111"
# Nitrokey 1
# Make sure serial key and gpg key match
serial_2="222222222"
gpg_key_id_2="GPG222222222"
# Local Wallabag Token Files
#encrypted_file_1="$HOME/.newsboat/wallabag_token1.json.gpg"
#encrypted_file_2="$HOME/.newsboat/wallabag_token2.json.gpg"
# Syncthing - Wallabag Token Files via Syncthing
encrypted_file_1="$HOME/Sync/wallabag-via-synology/wallabag_token1.json.gpg"
encrypted_file_2="$HOME/Sync/wallabag-via-synology/wallabag_token2.json.gpg"
###################################
# Create folder and files if not present
###################################
# Sicherstellen, dass das Verzeichnis existiert
mkdir -p "$bookmarks_folder"
# Sicherstellen, dass die Dateien existieren
touch "$bookmarks_file_md"
touch "$bookmarks_file_txt"
###################################
# Newsboat Bookmarking
###################################
last_date=$(tail -n 1 "$bookmarks_file_md" 2>/dev/null | cut -d' ' -f2)
if [[ "$last_date" != "$date_time" ]]; then
echo "## Date: ${date_time}" >> "$bookmarks_file_md"
fi
echo "- ***${feed_title}***; [${title}](${url}); ${date_time}; 📝 ${description}" >> "$bookmarks_file_md"
if [[ "$last_date" != "$date_time" ]]; then
echo "Date: ${date_time}" >> "$bookmarks_file_txt"
fi
echo "- ${feed_title}; ${title}; ${url}; 📝 ${description}; ${date_time}" >> "$bookmarks_file_txt"
###################################
# Detect smartcard
###################################
card_serial=$(gpg --card-status 2>/dev/null | awk -F': ' '/Serial number/ {gsub(/ /,"",$2); print $2}')
if [[ -z "$card_serial" ]]; then
echo "Error: No smartcard detected."
exit 1
fi
echo "Detected card serial: $card_serial"
if [[ "$card_serial" == "$serial_1" ]]; then
gpg_key_id="$gpg_key_id_1"
encrypted_file="$encrypted_file_1"
elif [[ "$card_serial" == "$serial_2" ]]; then
gpg_key_id="$gpg_key_id_2"
encrypted_file="$encrypted_file_2"
else
echo "Error: Unknown YubiKey inserted."
exit 1
fi
###################################
# Wallabag Token Handling
###################################
backup_file="${encrypted_file}.bak"
cp "$encrypted_file" "$backup_file"
# Decrypt token file (loopback mode avoids GUI pinentry)
decrypted_data=$(gpg --decrypt "$encrypted_file" 2>/dev/null)
if [[ -z "$decrypted_data" ]]; then
echo "Error: Failed to decrypt token file."
exit 1
fi
# Extract values
access_token=$(echo "$decrypted_data" | jq -r .access_token)
refresh_token=$(echo "$decrypted_data" | jq -r .refresh_token)
client_id=$(echo "$decrypted_data" | jq -r .client_id)
client_secret=$(echo "$decrypted_data" | jq -r .client_secret)
wallabag_username=$(echo "$decrypted_data" | jq -r .username)
wallabag_password=$(echo "$decrypted_data" | jq -r .password)
###################################
# Check access token
###################################
response_body=$(mktemp)
response=$(curl -s -w "%{http_code}" -o "$response_body" \
-H "Authorization: Bearer $access_token" \
"$wallabag_url/api/user")
http_status="${response: -3}"
if [[ "$http_status" == "401" ]]; then
response=$(curl -s -X POST "$wallabag_url/oauth/v2/token" \
-d "grant_type=refresh_token" \
-d "client_id=$client_id" \
-d "client_secret=$client_secret" \
-d "refresh_token=$refresh_token")
if echo "$response" | jq -e '.access_token' >/dev/null 2>&1; then
access_token=$(echo "$response" | jq -r .access_token)
refresh_token=$(echo "$response" | jq -r .refresh_token)
else
response=$(curl -s -X POST "$wallabag_url/oauth/v2/token" \
-d "grant_type=password" \
-d "client_id=$client_id" \
-d "client_secret=$client_secret" \
-d "username=$wallabag_username" \
-d "password=$wallabag_password")
if echo "$response" | jq -e '.access_token' >/dev/null 2>&1; then
access_token=$(echo "$response" | jq -r .access_token)
refresh_token=$(echo "$response" | jq -r .refresh_token)
else
exit 1
fi
fi
updated_data=$(echo "$decrypted_data" | jq \
--arg access_token "$access_token" \
--arg refresh_token "$refresh_token" \
'.access_token = $access_token | .refresh_token = $refresh_token')
echo "$updated_data" | gpg --batch --yes --encrypt --recipient "$gpg_key_id" > "$encrypted_file"
fi
###################################
# Send article to Wallabag
###################################
curl -s -X POST "$wallabag_url/api/entries.json" \
-H "Authorization: Bearer $access_token" \
-H "Content-Type: application/json" \
-d '{
"url": "'"${url}"'",
"tags": "'"${tags}"'",
"starred": 1,
"archive": 0
}' >/dev/null
rm -f "$response_body"
exit 0
Das Skript ist noch ausführbar zu machen.
chmod +x bookmark.sh
Troubleshooting
Bricht das Skript gleich zu Beginn ab, dann sind die folgenden Punkte zu prüfen. Damit wird vielleicht eine lange Fehlersuche und ein Debuggin vermieden.
- Ist das Skript ausführbar?
- Ist der Ordner und die Dateien vorhanden?
bookmarks_folder,bookmarks_file_md,bookmarks_file_txt - Ist der korrekte
pinentry-Eintrag in der~/.gnupg/gpg-agent.confgesetzt.
Newsboat config
Die Newsboat-Konfigurationsdatei ist im Verzeichnis ~/.newsboat oder einer anderen Instanz ~/.newsboat-<instanz>/newsboat abzulegen.
Makros ausführen
Makros in Newsboat lassen sich mit der Tastenkombination ,+macro-kürzel.
Beispiele:
macro o open-in-browser; toggle-article-read "read" → ,o
macro c set browser "mpv --player-operation-mode=pseudo-gui -- %u &"; one; set browser firefox → ,c
auto-reload yes
reload-time 60
reload-threads 0
history-limit 60
cleanup-on-quit yes
prepopulate-query-feeds yes
show-read-feeds yes
text-width 80
articlelist-format "%4i %f %D %?T?|%-17T| ?%t"
always-display-description true
notify-screen yes
save-path "$HOME/arbeitsordner/"
### MACROS ###
macro k open; reload; quit -- "enter feed to reload it"
macro o open-in-browser; toggle-article-read "read"
# DOWNLOAD #
macro x set browser "~/.newsboat/yt-dlp-audio.sh %u &"; open-in-browser-noninteractively
macro y set browser "~/.newsboat/yt-dlp-video.sh %u &"; open-in-browser-noninteractively
# MACOS STREAM #
macro v set browser "~/.newsboat/yt-dlp-stream.sh %u &"; open-in-browser-noninteractively
# MACOS AND LINUX STREAM #
macro c set browser "mpv --player-operation-mode=pseudo-gui -- %u &"; one; set browser firefox
###BROWSER ###
#browser "open -g -a 'Firefox' %u"
#browser "open -g -a 'Mullvad\ Browser' %u"
# Use command on macOS and Linux
# Checks for operation system with "uname"
# depending on result
# Darwin = macOS --> open -g -a \"Mullvad\ Browser\" %u
# Linux = mullvad-browser %u
#browser "sh -c 'if [ \"$(uname)\" = \"Darwin\" ]; then open -g -a \"Mullvad\ Browser\" %u; else ~/.local/share/mullvad-browser/start-mullvad-browser.desktop %u; fi'"
browser "sh -c 'if [ \"$(uname)\" = \"Darwin\" ]; then open -g -a \"Mullvad\ Browser\" %u; else xdg-open %u; fi'"
### NEXTCLOUD ###
#urls-source "ocnews"
#ocnews-url "https://next.example.com/"
#ocnews-login "<benutzername>
#ocnews-passwordeval "gpg --decrypt ~/.newsboat/nextcloud-password.gpg"
### BOOKMARK SEND TO WALLABAG ###
bookmark-cmd "$HOME/.newsboat/bookmark.sh"
### COLORS ###
# Works on Linux
#include /usr/share/doc/newsboat/contrib/colorschemes/cyanism
color background white black
color listnormal cyan black
color listnormal_unread cyan black bold
color listfocus cyan black reverse
color listfocus_unread cyan black reverse bold
#color title color46 default reverse bold
color info white blue
#color hint-description magenta default
color article color229 default
#color end-of-text-marker color8 default
### Highlight URLs with regex ###
highlight article "^(Feed|Link):.*$" color46 default
highlight article "^(Title|Date|Author):.*$" color39 default bold
highlight article "https?://[^ ]+" color46 default underline
highlight article "\\[[0-9]+\\]" color63 default bold
highlight article "\\[image\\ [0-9]+\\]" color63 default bold
highlight feedlist "^─.*$" color61 color235 bold
### HEADLINES ###
highlight feedlist "---.*---" green default bold
highlight feedlist ".*0/0.." default default invis
Mit diesem Skript verwendet jeder Client einen eigenen Cache, die cache.db. Möchte man für alle Clients den gleichen Cache verwenden, kann diese ausgelagert werden.
Newsboat bietet die Option cache-file an. Es besteht damit die Mögklichkeit die cache.db über Syncthing zu verteilen.
cache.db <pfad-zu-cache.db-im-syncthing-ordner>
yt-dlp-audio.sh
Die Datei ist im Verzeichnis ~/.newsboat abzulegen. Das Skript ist anschließend ausführbar zu machen chmod +x.
#!/usr/bin/env bash
# Script to download audio via yt-dlp
# Triggered by a macro in Newsboat
###################################
# Wallabag Arguments (passed by Newsboat)
###################################
url="$1" # The URL of the video
title="$2" # The title of the article (optional, from Newsboat)
description="$3" # The description (optional, from Newsboat)
feed_title="$4" # Feed title (optional, from Newsboat)
date_time=$(date "+%Y-%m-%d") # Date and time of download
# Ensure cookies file exists
COOKIES_FILE="$HOME/.newsboat/www.youtube.com_cookies.txt"
if [ ! -f "$COOKIES_FILE" ]; then
echo "Cookies file $COOKIES_FILE not found. Please provide a valid cookies file."
exit 1
fi
# Output directory for audio
OUTPUT_DIR="$HOME/Downloads/audio"
mkdir -p "$OUTPUT_DIR"
cd "$OUTPUT_DIR"
# Run yt-dlp with the passed URL and options
yt-dlp --cookies "$COOKIES_FILE" -x --embed-thumbnail mp3 --audio-quality 0 "$url"
yt-dlp-video.sh
Die Datei ist im Verzeichnis ~/.newsboat abzulegen. Das Skript ist anschließend ausführbar zu machen chmod +x.
#!/usr/bin/env bash
# Script to download videos via yt-dlp
# Triggered by a macro in Newsboat
###################################
# Wallabag Arguments (passed by Newsboat)
###################################
url="$1" # The URL of the video
title="$2" # The title of the article (optional, from Newsboat)
description="$3" # The description (optional, from Newsboat)
feed_title="$4" # Feed title (optional, from Newsboat)
date_time=$(date "+%Y-%m-%d") # Date and time of download
# Output directory for audio
OUTPUT_DIR="$HOME/Downloads/video"
mkdir -p "$OUTPUT_DIR"
cd "$OUTPUT_DIR"
# Run yt-dlp with the passed URL and options
yt-dlp 'bestvieo[height<=480]+bestvideo/best[heigt<=480]' "$url"
yt-dlp-stream.sh
Die Datei ist im Verzeichnis ~/.newsboat abzulegen. Das Skript ist anschließend ausführbar zu machen chmod +x.
#!/usr/bin/env bash
# Script to stream yt-dlp
###################################
# Newsboat)
###################################
url="$1" # The URL of the video
title="$2" # The title of the article (optional, from Newsboat)
description="$3" # The description (optional, from Newsboat)
feed_title="$4" # Feed title (optional, from Newsboat)
date_time=$(date "+%Y-%m-%d") # Date and time of download
# Run yt-dlp with the passed URL and options
yt-dlp -o - "$url" | vlc -
Gib mir gerne einen Kaffee ☕ aus 😀
Gib mir gerne einen Kaffee ☕ aus !
Wenn dir meine Beiträge gefallen und geholfen haben, dann kannst du mir gerne einen Kaffee ☕️ ausgeben.
bc1qfuz93hw2fhdvfuxf6mlxlk8zdadvnktppkzqzj
Weitere Möglichkeiten mich zu unterstützen findest du 👉 hier
Follow Me
Source
Photo by Artak Petrosyan on Unsplash

