Offlineimap mit Zugangsdaten im GNOME-Keyring durch systemd-Timer starten
Ich habe die Erfahrung gemacht, dass offlineimap
sehr viel Arbeitsspeicher verbraucht, wenn man es permanent laufen
lässt. Das Problem lässt sich umgehen, lässt man es stattdessen durch
einen systemd
-Timer (oder Cronjob) aufrufen.
Der systemd
-Timer hat ein kleines nettes Detail
als Vorzug gegenüber einem Cronjob: Man kann ihn immer erst dann
starten, wenn die Unit, also in dem Fall
offlineimap
schon eine definierte Zeit lang
inaktiv ist. Im Fall von offlineimap
heißt das
also, dass man auch bei längeren Synchronisationsvorgängen über eine
langsame Verbindung nicht in Gefahr läuft, dass ein zweiter Prozess
gestartet werden soll, wenn der erste noch dabei ist, Mails
herunterzuladen und die Datenbank zu verändern. Das gewählte Intervall
beginnt erst, wenn die Ausführung der Unit abgeschlossen ist.
Haken: Kennworte aus einem Kennwortspeicher
Kennworte, vor allem die für Mail-Konten, im Klartext irgendwo zu
speichern ist nie eine gute Idee. Besser ist da schon die Verwendung von
z.B. KeePass oder des Schlüsselsrings der Desktopumgebung. Hat man, etwa
direkt beim Login in die Desktopumgebung, den Schlüsselring entsperrt,
kann man über secret-tool
ein Kennwort aus dem
Schlüsselring anfordern. Das funktioniert aber nicht, wenn ein
Prozess nicht in Abhängigkeit der grafischen Oberfläche und der dort
laufenden Sitzung gestartet wurde. Es fehlt die dazugehörige
Umgebungsvariable, welche den Pfad zum DBUS-Sitzungsbus angibt, über
den die Kommunikation mit dem Schlüsselring läuft. Periodische
Ausführung von Programmen wie offlineimap
scheitern also, wenn sie über systemd
gestartet
werden, weil dann kein Bezug zur grafischen Oberfläche besteht.
Workaround
ein klein wenig unsicherer
Zuerst zur Sicherheit: Ich verwende also einen Workaround, der ein klein
wenig unsicherer ist, da ich die Verwendung meiner DBUS-Sitzung von der
grafischen Oberfläche entkopple. Gleichzeitig vermeide ich aber so auch,
dass ich das Kennwort im Klartext irgendwo hinterlegen muss. Während
mein Rechner also läuft, kann mein DBUS von allen Prozessen verwendet
werden, die als mein Nutzer laufen. Ohne den noch zu beschreibenden
Workaround wäre das (erstmal) nur möglich, wenn ein Einbruch etwa durch
eine Sicherheitslücke aus dem Desktop-Kontext käme, also in einem unter
der grafischen Oberfläche gestarteten Anwendungsprogramm (ob
mutt
auf der Konsole oder Firefox spielt dabei ja
keine Rolle). Dieser „Schutz” ist aber sowieso schon sehr dünn, da er
quasi nur aus der Geheimhaltung der Adresse zum DBUS-Socket besteht. Die
lässt sich unter meinem Benutzerkontext aber auch trivial herausfinden.
Ergebnis der Überlegungen also: minimal geschwächte Sicherheit zur Laufzeit, viel bewahrte Sicherheit in Ruhe (Laptop aus), weil das Kennwort nicht unverschlüsselt irgendwo notiert ist.
DBUS aus systemd heraus ansprechen
Die Lösung ist, wenn man sich erstmal die Funktion von DBUS in dem Fall angesehen hat, ziemlich einfach:
Man startet aus der Desktop-Umgebung heraus nach dem Login ein Script,
was die nötigen Werte der Umgebungsvariablen in eine Datei schreibt, die
man dann später aus systemd
referenzieren kann.
Dann klappt auch der Abruf von Kennworten aus dem Keyring:
Ich habe also ein Script
~/.local/bin/export-dbus.sh
:
#!/bin/bash
touch $HOME/.dbus_addr
chmod 600 $HOME/.dbus_addr
env | grep DBUS_SESSION_BUS_ADDRESS > $HOME/.dbus-addr
echo "export DISPLAY=:1" >> $HOME/.dbus-addr
echo "export DBUS_SESSION_BUS_ADDRESS" >> $HOME/.dbus-addr
Dieses Script wird zum Autostart der Desktopumgebung hinzugefügt, dazu
braucht man eine Datei
~/.config/autostart/export-dbus.desktop
:
[Desktop Entry]
Name=DBUS Address export
Comment=Make DBUS session bus available outside the DE
Exec=~/.local/bin/export-dbus.sh
Terminal=false
Type=Application
Categories=System
StartupNotify=false
systemd-Timer einrichten
Viel besser oder schlechter sind die Timer von
systemd
gegenüber Cronjobs auch nicht. Nur anders.
Um alle 10 Minuten E-Mails via IMAP synchronisieren zu lassen, richtet
man folgende zwei Units ein:
Den eigentlichen Dienst,
~/.config/systemd/user/offlineimap.service
:
[Unit]
Description=OfflineIMAP
After=network.target
[Service]
Type=simple
ExecStart=~/.local/bin/offlineimap
und den dazugehörigen Timer:
[Timer]
OnUnitInactiveSec=600
Unit=offlineimap.service
Wie man im Dienst schon gesehen hat, habe ich noch einen Wrapper für
offlineimap
erstellt. In diesem wird die vorhin
gespeicherte DBUS-Adresse noch verfügbar gemacht:
#!/bin/bash
# Wrapper to make offlineimap with GNOME Keyring usable from systemd
source $HOME/.dbus-addr
# Run the original offlineimap
/usr/bin/offlineimap
Ausführen
Man muss nur noch den Timer aktivieren:
systemctl enable --user offlineimap.timer
systemctl start --user offlineimap.timer
und den Dienst anstoßen:
systemctl enable --user offlineimap.service
systemctl start --user offlineimap.service
Ob alles klappt, kann man im Log beobachten:
journalctl -f