Simpler quarto-bot für Nextcloud

Ich nutze quarto unter anderem dafür, meine Briefe als PDF zu rendern. Damit dies auch auf dem Handy oder Tablet funktioniert, baue ich mir einen kleinen Bot, der einen Nextcloud-Ordner per Webdav mountent, nachschaut, ob eine .qmd-Datei im Verzeichnis liegt, und auf diese dann das Kommando quarto render DATEI ausführt. Der Webdav-Mountpunkt sowie der Bot ansich werden mit systemd gestartet.
quarto
ubuntuusers
Autor:in

Joe Slam

Veröffentlichungsdatum

23. September 2022

Mit quarto setze ich unter anderem auch meine (Geschäfts)Briefe als PDF-Datei. Hierfür habe ich mir ein paar Vorlagen gebastelt, siehe z.B. dieses Beispiel.

Das funktioniert soweit auf dem PC sehr gut. Am Handy oder am Tablet ist quarto mit nicht verfügbar, weshalb ich mir einen kleinen Bot programmiert habe, der einen Nextcloud-Ordner “überwacht” und die vorhandenen .qmd-Dateien zu PDFs rendert.

Der Bot

So kann ich “von überall”, z.B. am Handy, eine .qmd-Datei erzeugen, diese ins Nextcloud-Verzeichnis uploaden, 30 Sekunden warten, und die fertige PDF-Datei aus dem Nextcloud-Verzeichnis herunterladen.

Der Bot kann an jedem beliebigen Linux-PC mit Internetanschluss betrieben werden. Du musst “lediglich” sicherstellen, dass der Befehl

# muss fehlerfrei durchlaufen
quarto render Datei.qmd

korrekt auf dem Server ausgeführt wird. Der Bot führt ja letztendlich auch “nur” diesen Befehl aus.

Nextcloud

In Nextcloud habe ich in meinem Homeverzeichnis den Ornder quarto, und darunter den Ordner renderbot erstellt. In letzterem wird der Bot lauschen. Letztendlich ist es aber egal, welcher Ordner genau verwendet werden soll.

Mountpunkt

Auf dem Bot-PC erstelle ich mir das Verzeichis /media/Nextcloudquartobot.

# erstelle Verzeichnis
mkdir -p /media/Nextcloudquartobot

Hierhin mounten wir per WebDav unser Nextcloudverzeichnis. Die Dav-Adresse lautet:

# Webdav-Adresse
https://DEINE.NEXTCLOUD/remote.php/dav/files/USERNAME/pfad/zu/ordner

Wir mounten dieses Verzeichnis per systemd, daher müssen wir alles so einstellen, dass keine Passwortabfrage beim mounten erfolgt. Hierzu hinterlegen wir unsere Userdaten in der Datei /etc/davfs2/secrets :

# Passwörter hinzufügen
sudo nano /etc/davfs2/secrets

nach folgendem Schema:

# Schema
MOUNTPOINT  USERNAME "PASSWORD"

In meinem Falle also:

/media/Nextcloudquartobot  produnis "!SuperSecret#Password!"

Anschließend erstellen wir eine systemd.mount-Datei. Diese muss genau so heissen wie das Verzeichnis, in welches gemountet werden soll.

sudo nano /etc/systemd/system/media-Nextcloudquartobot.mount

Sie erhält folgenden Inhalt:

/etc/systemd/system/media-Nextcloudquartobot.mount
[Unit]
Description=WebDAV-Mount-Nextcloud-Quarto-Renderbot
After=network-online.target
Before=quarto-nextcloud-bot.service

[Mount]
Type=davfs
What=https://MEINE.NEXTCLOUD/remote.php/dav/files/USER/pfad/zu/ordner
Where=/media/Nextcloudquartobot
Options=noauto,user,uid=produnis,gid=produnis

[Install]
WantedBy=multi-user.target

In Zeile 4 habe ich bereits auf den noch zu erstellenden Bot-Service verwiesen. Die Mount-Unit soll immer vor dem Bot-Service starten.

In Zeile 8 müsst ihr eure Userdaten ergänzen

In Zeile 10 wird festgelegt, dass der User produnis den Mount durchführen soll, und nicht root. Hierdurch wird sichergestellt, dass ich auch alle Lese- und Schreibrechte erhalte.

Wir können das Verzeichnis nun per systemd mounten:

# mounten
sudo systemctl start media-Nextcloudquartobot.mount

#unmounten
sudo systemctl stop media-Nextcloudquartobot.mount

Bashscript

Die Aktion soll ein kleines Bashscript ausführen. Ich habe es quarto-nextcloud.sh genannt und wie folgt aufgebaut:

/etc/systemd/system/media-Nextcloudquartobot.mount
#!/bin/bash

while [[ true ]]; do
        if ls /media/Nextcloudquartobot/*.qmd 1> /dev/null 2>&1; then
                cd /media/Nextcloudquartobot

                for i in *.qmd; do
                    echo "Found file $i"
                        timestamp=$(date "+%Y-%m-%d--%H-%M-%S")
                        echo "Trying to run 'quarto render $i'..."
                        /sbin/quarto render "$i";
                        echo "Moving .qmd-file..."
                        mv "$i" "$i-$timestamp"
                done
        else
                echo "Nothing to do..."
        fi
        echo "Sleeping for 30 seconds."
        sleep 30
done

Dieses Script soll nun mit systemd gesteuert werden. Hierfür erstellen wir die Datei /etc/systemd/system/quarto-nextcloud-bot.service und geben ihr folgenden Inhalt:

/etc/systemd/system/quarto-nextcloud-bot.service
[Unit]
Description=quarto-Nextcloud-RenderBot
Wants=media-Nextcloudquartobot.mount

[Service]
Type=simple
Nice=19
IOSchedulingClass=idle
ExecStart=/bin/bash -c "PATH=$PATH exec /pfad/zu/quarto-nextcloud.sh"
User=produnis

[Install]
WantedBy=multi-user.target

In Zeile 3 legen wir fest, dass vor unserem Bot das Mountscript “media-Nextcloudquartobot.mount” ausgeführt werden soll. Sonst wäre ja der Nextcloudordner nicht da.

In Zeile 9 führen wir das Script aus und übergeben dabei den aktuellen $PATH.

In Zeile 10 sagen wir, dass das Script als User produnis ausgeführt werden soll.

Wir können das Script nun per systemd steuern:

sudo systemctl start quarto-nextcloud-bot.service
sudo systemctl stop quarto-nextcloud-bot.service
sudo systemctl enable quarto-nextcloud-bot.service

Sobald es läuft, können wir den Output mittels journalctl überwachen.

# journal laufend ausgeben
journalctl -u quarto-nextcloud-bot.service -f

So sehe ich, dass das Script läuft und sich langweilt:

Sep 23 17:40:19 SERVER bash[9086]: Sleeping for 30 seconds.
Sep 23 17:40:50 SERVER bash[9086]: Nothing to do...
Sep 23 17:40:50 SERVER bash[9086]: Sleeping for 30 seconds.
Sep 23 17:41:20 SERVER bash[9086]: Nothing to do...
Sep 23 17:41:20 SERVER bash[9086]: Sleeping for 30 seconds.

Sobald ich eine .qmd-Datei in das Nextcloudverzeichnis lege, fängt er an zu arbeiten:

Sep 23 17:42:52 SERVER bash[9086]: Found file Hinweise-zur-Klausuraufsicht.qmd
Sep 23 17:42:52 SERVER bash[9086]: Trying to run 'quarto render Hinweise-zur-Klausuraufsicht.qmd'...
Sep 23 17:42:55 SERVER bash[9360]: pandoc 
Sep 23 17:42:55 SERVER bash[9360]:   to: latex
Sep 23 17:42:55 SERVER bash[9360]:   output-file: Hinweise-zur-Klausuraufsicht.tex
Sep 23 17:42:55 SERVER bash[9360]: running xelatex - 1
Sep 23 17:42:58 SERVER bash[9360]: running xelatex - 2
Sep 23 17:43:01 SERVER bash[9360]:   This is XeTeX, Version 3.141592653-2.6-0.999994 (TeX Live 2022) (preloaded format=xelatex)
Sep 23 17:43:04 SERVER bash[9360]: Output created: Hinweise-zur-Klausuraufsicht.pdf
Sep 23 17:43:04 SERVER bash[9086]: Moving .qmd-file...
Sep 23 17:43:05 SERVER bash[9086]: Sleeping for 30 seconds.

Und die fertig gerenderte PDF-Datei ist im Nextcloudverzeichnis verfügbar.

Nutzung

Ich schmeiss also einfach eine qmd-Datei in den Nextcloudordner, und hole mir die PDF-Datei von dort zurück. Sollte ich Bilder einbinden (z.B. meine Unterschrift bei Briefen), oder Templates, müssen diese ebenfalls im Nextcloud-Ordner vorhanden sein, damit Quarto sie finden kann.

Nachtrag: matrix-Bot

Es gibt einen Bot für matrix, der ebenfalls .qmd-Dateien rendert und das PDF zurück in den matrix-Raum sendet, siehe https://github.com/rgomez90/matrix-bot.