Kurztipp: PDFs mit Stirling PDF reparieren
Falls ihr meinen Beitrag „Was läuft auf dem Home Server?“ gelesen habt, wisst ihr, dass auf meinem Home Server unter anderem ein LXC mit Stirling PDF vorhanden ist. Ich hatte Stirling PDF aber noch...
Falls ihr meinen Beitrag „Was läuft auf dem Home Server?“ gelesen habt, wisst ihr, dass auf meinem Home Server unter anderem ein LXC mit Stirling PDF vorhanden ist. Ich hatte Stirling PDF aber noch...
Paperless-NGX ist ein bekanntes und beliebtes Open Source Dokumenten-Management-System (DMS). Auch ich möchte zukünftig meinen „Papierkram“ darin verwalten.
In diesem Artikel halte ich meine Gedanken fest, wie ich plane, paperless-ngx in meiner Umgebung aufzusetzen und zu betreiben.
Dies hilft mir, zu prüfen, ob ich auch an alles Wichtige gedacht habe. Falls euch das Konzept gefällt, dürft ihr es selbstverständlich gerne nachahmen. Und wenn ihr schwerwiegende Fehler darin entdeckt, freue ich mich über einen Hinweis.
Es ist kein Tutorial und keine Schritt-für-Schritt-Anleitung. Zwar mag dieser Text dazu dienen, sich eine eigene Umgebung aufzubauen, Mitdenken ist dabei jedoch zwingend erforderlich.
In meinem Heimnetzwerk betreibe ich einen Desktop-/Server-PC. Auf diesem läuft aktuell RHEL 9 als KVM/QEMU-Hypervisor. Er dient mir ebenfalls als Ansible Control Node. Hierauf betreibe ich eine RHEL-9-VM mit einer rootless-Podman-Installation. Diese VM wird auch meine Paperless-NGX-Instanz hosten.
In der VM wird das EPEL-Repository aktiviert, um daraus die Pakete podman-compose
und python3-pexpect
installieren zu können.
Falls ich mal nicht mehr weiß, wie dieses Setup aufgebaut wird, finden sich dazu Hinweise in folgenden Links:
Für die Installation der Anwendung wird die Container Route verwendet. Die Installation wird dabei unter Nutzung der Ansible-Rolle tronde.paperless_ngx_with_rootless_podman
automatisiert.
Das Playbook deploy_paperless_ngx.yml
, welches auf meiner Synology Diskstation abgelegt ist, führt die Installation und Konfiguration der Anwendung durch. Es installiert und konfiguriert zudem Samba und die Datei-Freigabe des Consumption-Verzeichnisses.
In dem Playbook werden folgende Rollen verwendet:
paperless_ngx_with_rootless_podman
(Eigenkreation)Die Rollen sind mit dem Playbook in meinem Ansible-Projekt-Verzeichnis auf meiner Synology Diskstation installiert.
Alle Playbooks und Rollen werden mit Git versioniert. Die Repositories werden auf entfernte Rechner synchronisiert.
Die Dateien docker-compose.postgres-tika.yml
, docker-compose.env
und .env
werden aus dem Projekt-Repository in das Rollen-Verzeichnis files
meiner Ansible-Rolle heruntergeladen. Die Datei docker-compose.postgres-tika.yml
wird dabei zu docker-compose.yml
umbenannt und bearbeitet.
Um Datenverlust vorzubeugen, wird die Ansible-Rolle mit den angepassten Dateien in die regelmäßige Datensicherung aufgenommen.
Folgende Variablen werden in meinem Ansible-Vault hinterlegt:
# Paperless-ngx with podman-compose
pnwrp_podman_user: alice
pnwrp_podman_group: alice
pnwrp_compose_dir: /home/{{ pnwrp_podman_user }}/paperless-ngx
pnwrp_paperless_superuser: alice
pnwrp_paperless_superuser_email: alice@example.com
pnwrp_paperless_superuser_password: ImWunderland
## Username and password for document scanner
brother_scanner_user: scanner
brother_scanner_pass: ImWunderland
Die Werte der Variablen werden selbstverständlich angepasst.
Folgender Code-Block zeigt das fertige Playbook mit Beispielwerten:
---
- hosts: host.example.com
remote_user: alice
debugger: never
vars_files:
- files/alice.vault
tasks:
- name: Setup Paperless-NGX with podman-compose in rootless Podman
include_role:
name: ansible_role_paperless-ngx_with_rootless_podman
- name: Enable Port 8000/tcp in host firewall
ansible.posix.firewalld:
port: 8000/tcp
immediate: true
permanent: true
state: enabled
become: true
- name: >-
Create and add {{ brother_scanner_user }} to
{{ pnwrp_podman_group }}
ansible.builtin.user:
name: "{{ brother_scanner_user }}"
comment: "Brother Dokumenten-Scanner"
create_home: false
groups: "{{ pnwrp_podman_group }}"
append: true
shell: /usr/sbin/nologin
state: present
system: true
become: true
- name: Include role vladgh.samba.server
include_role:
name: vladgh.samba.server
vars:
ansible_become: true
samba_users:
- name: "{{ pnwrp_podman_user }}"
password: "{{ alice_password }}"
- name: "{{ brother_scanner_user }}"
password: "{{ brother_scanner_pass }}"
samba_shares:
- name: consumption
comment: 'paperless consumption directory'
path: "{{ pnwrp_compose_dir }}/consume"
read_only: false
guest_ok: false
browseable: true
owner: "{{ pnwrp_podman_user }}"
group: "{{ pnwrp_podman_group }}"
write_list: +{{ pnwrp_podman_group }}
- name: Enable samba in host firewall
ansible.posix.firewalld:
service: samba
immediate: true
permanent: true
state: enabled
become: true
Das Playbook gewinnt sicher keinen Schönheitswettbewerb, doch arbeitet es bisher robust und tut, was es soll. In Tests habe ich meine Wunschumgebung damit mehrmals provisioniert.
Wie es sich gehört, wird erst ein Backup erstellt, dann die Anwendung inkl. aller Daten gelöscht und wiederhergestellt.
Für das Backup verwende ich ein Ansible-Playbook, welches sich zum Podman-Host verbindet und dort folgende Aufgaben ausführt:
Es fehlt die Aufgabe, alte Backups aufzuräumen. Darum werde ich mich kümmern, wenn 70% des verfügbaren Speicherplatzes belegt sind.
Der folgende Code-Block zeigt ein Muster des verwendeten Playbooks:
---
- name: Backup podman volumes
hosts: host.example.com
gather_facts: true
vars:
paperless_ngx_dir: /home/alice/paperless-ngx
docker_compose_file: docker-compose.yml
remote_backup_dir: /home/alice/backups
diskstation_backup_dir: /home/alice/diskstation/home/backups/host.example.com
tasks:
- name: Ensure backup directory exists
ansible.builtin.file:
path: "{{ remote_backup_dir }}"
state: directory
owner: alice
group: alice
mode: 0777
- name: Stop paperless-ngx containers
ansible.builtin.command: >
podman-compose -f {{ paperless_ngx_dir }}/{{ docker_compose_file }} stop
- name: List podman volumes
ansible.builtin.command: podman volume ls --quiet
register: __podman_volumes
tags:
- volumes
- name: Output __podman_volumes
ansible.builtin.debug:
msg: "{{ item }}"
loop: "{{ __podman_volumes['stdout_lines'] }}"
tags:
- volumes
- name: Export podman volumes
ansible.builtin.command: >
podman volume export {{ item }} --output {{ remote_backup_dir }}/{{ item }}_{{ ansible_facts['date_time']['date'] }}.tar
loop: "{{ __podman_volumes['stdout_lines'] }}"
- name: Compact {{ paperless_ngx_dir }}
community.general.archive:
path: "{{ paperless_ngx_dir }}"
dest: "{{ remote_backup_dir }}/paperless-ngx_{{ ansible_facts['date_time']['date'] }}.tar.gz"
format: gz
- name: Start paperless-ngx containers
ansible.builtin.command: >
podman-compose -f {{ paperless_ngx_dir }}/{{ docker_compose_file }} start
- name: Compress volume exports
community.general.archive:
path: "{{ remote_backup_dir }}/{{ item }}_{{ ansible_facts['date_time']['date'] }}.tar"
format: gz
remove: true
loop: "{{ __podman_volumes['stdout_lines'] }}"
tags:
- compress
- name: Sync backups to diskstation
ansible.posix.synchronize:
archive: true
compress: false
delete: false
dest: "{{ diskstation_backup_dir }}"
mode: pull
private_key: /home/alice/.ssh/ansible_id_rsa
src: "{{ remote_backup_dir }}/"
delegate_to: localhost
tags:
- rsync
- name: Sync backups from diskstation to contabo S3
ansible.builtin.command: rclone sync -P ../backups/ secure:backups
delegate_to: localhost
tags:
- rsync
Das Playbook wird einmal wöchentlich ausgeführt. Ob ich für die geplante Ausführung cron
oder systemd timer units
verwende, habe ich noch nicht entschieden. Ich tendiere aus Neugier zu letzterem.
Um ein Offsite-Backup zu haben, werden die Dateien von der Diskstation einmal wöchentlich verschlüsselt und in einen S3-Speicher synchronisiert. Ich nutze dafür das Programm rclone
und S3-kompatiblen Speicher von Contabo. Die folgenden Links bieten weiterführende Informationen dazu:
Der Ablaufplan für die Wiederherstellung der Anwendung mit ihren Daten sieht wie folgt aus:
podman-compose
bereitstellengunzip -c hello.tar.gz | podman volume import myvol -
Bereitstellung, Sicherung und Wiederherstellung funktionieren wie beschrieben. Damit kann ich nun beginnen und die Anwendung konfigurieren und mit meinem Papierkram füttern.
Die Samba-Freigabe habe ich ebenfalls getestet. Sie funktioniert wie erwartet. PDF-Dateien mit dem Befehl find Documents -type f -iname "*.pdf" -exec cp {} /consume \;
hineinzukopieren ist übrigens besonders dann eine gute Idee, wenn man sehen möchte, welche Dateien so in den Tiefen des eigenen Dateisystems schlummern.