UGREEN NAS: Mailpiler als E-Mail-Archiv einrichten
Teil 78 der UGREEN-Serie: Mailpiler 1.4.9 als verschlüsseltes E-Mail-Archiv auf der UGREEN NAS, mit den Rechteproblemen der offiziellen Vorlage, Standardpasswörtern, Import alter Mails und SMTP-Sperre.
Geprüft am 04.11.2026 · für UGOS Pro 1.21.0.0190, Mailpiler 1.4.9, MariaDB 12.0.2
WerbelinksMit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Mailpiler ist eine freie Lösung zur E-Mail-Archivierung: Es speichert E-Mails dauerhaft, verschlüsselt und durchsuchbar. Der Mailserver schickt jede Nachricht per SMTP zusätzlich an das Archiv, alte Mails importieren Sie als Datei. Diese Anleitung zeigt Mailpiler mit MariaDB, Manticore und Memcached auf der UGREEN NAS. Die offizielle Compose-Datei läuft mit Ordnern auf der NAS nicht unverändert: Wir zeigen die drei Rechteprobleme aus unserem Test, die falsche Weiterleitung nach der Anmeldung und die Sperre, mit der nur Ihr Mailserver Nachrichten einliefern darf.
Getestet auf einer UGREEN DXP4800 Pro mit UGOS Pro 1.21.0.0190 und Docker 29.6.2, mit Mailpiler 1.4.9 im Image sutoj/piler, MariaDB 12.0.2, Manticore 25.0.0 und Memcached 1.6.
Voraussetzungen
- Eine UGREEN NAS mit der App Docker, siehe Teil 63
- SSH-Zugang, siehe Teil 52
- Grundwissen zu Compose, siehe Docker Compose als Grundlage
- Ein Mailserver, der Kopien per SMTP weiterleiten kann, oder Mails als EML-Dateien
- Etwa 40 Minuten
Schritt 1: Ordner, Passwort und Vorlagen
Passen Sie volume2 in allen Befehlen an Ihre NAS an, auf vielen Geräten ist es volume1. Legen Sie den Projektordner an und schreiben Sie ein zufälliges Passwort für die Datenbank in eine eigene Datei:
sudo mkdir -p /volume2/docker/mailpiler
cd /volume2/docker/mailpiler
printf "MYSQL_PASSWORD=%s\n" "$(openssl rand -hex 24)" | sudo tee piler-db.env >/dev/null
sudo chmod 600 piler-db.env
Das Passwort erscheint dabei nicht auf dem Bildschirm. Nehmen Sie nur Buchstaben und Ziffern wie hier mit -hex, denn Mailpiler setzt das Passwort beim Start mit sed in seine Konfiguration ein, und Zeichen wie / oder & würden das stören. Laden Sie dann die beiden Konfigurationsdateien aus dem offiziellen Repository, piler.cnf für MariaDB und manticore.conf für den Suchindex:
BASE=https://raw.githubusercontent.com/jsuto/piler/master/docker
sudo curl -fsSL -o piler.cnf $BASE/piler.cnf
sudo curl -fsSL -o manticore.conf $BASE/manticore.conf
sudo chmod 644 piler.cnf
Die Vorlage selbst arbeitet mit benannten Volumes. Wir nutzen Ordner im Projekt, damit alles sichtbar an einer Stelle liegt und sich leicht sichern lässt. Genau das erfordert aber die Vorbereitung in Schritt 3.
Verifizieren: Die Ausgabe von ls -la zeigt piler-db.env mit -rw-------, piler.cnf und manticore.conf.
Schritt 2: Die Compose-Datei schreiben
services:
mysql:
image: mariadb:12.0.2
container_name: piler-db
restart: unless-stopped
cap_drop:
- ALL
cap_add:
- dac_override
- setuid
- setgid
env_file: piler-db.env
environment:
- MYSQL_DATABASE=piler
- MYSQL_USER=piler
- MYSQL_RANDOM_ROOT_PASSWORD=yes
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
volumes:
- ./db:/var/lib/mysql
- ./piler.cnf:/etc/mysql/conf.d/piler.cnf:ro
labels:
- wud.watch=false
manticore:
image: manticoresearch/manticore:25.0.0
container_name: piler-manticore
restart: unless-stopped
volumes:
- ./manticore.conf:/etc/manticoresearch/manticore.conf
- ./manticore:/var/lib/manticore
deploy:
resources:
limits:
memory: 512M
labels:
- wud.watch=false
piler:
image: sutoj/piler:1.4.9
container_name: piler
restart: unless-stopped
init: true
env_file: piler-db.env
environment:
- MANTICORE_HOSTNAME=manticore
- MEMCACHED_HOSTNAME=memcached
- MYSQL_HOSTNAME=mysql
- MYSQL_DATABASE=piler
- MYSQL_USER=piler
- PILER_HOSTNAME=192.168.1.10
- RT=1
ports:
- "2525:25"
- "8096:80"
volumes:
- ./etc:/etc/piler
- ./store:/var/piler/store
- ./import:/import:ro
healthcheck:
test: curl -s smtp://localhost/
interval: 20s
timeout: 3s
start_period: 15s
retries: 3
deploy:
resources:
limits:
memory: 512M
depends_on:
- mysql
- memcached
- manticore
labels:
- wud.watch=false
memcached:
image: memcached:1.6-alpine
container_name: piler-memcached
restart: unless-stopped
command: -m 64
labels:
- wud.watch=false
Was wir gegenüber der Vorlage geändert haben:
- Passwort aus der Datei: Die Vorlage schreibt piler123 direkt in die Compose-Datei. Hier lesen MariaDB und Mailpiler denselben Wert aus piler-db.env. Das Root-Passwort würfelt MariaDB selbst.
- Ports: Die Vorlage belegt 25 und 80. Port 80 war auf unserer NAS schon vergeben. Wir nutzen 8096 für die Weboberfläche und 2525 für SMTP.
- PILER_HOSTNAME: der Name oder die Adresse des Archivs, hier die Adresse der NAS ohne Port. Tragen Sie statt 192.168.1.10 Ihre ein.
- import: ein zusätzlicher Ordner, nur lesbar eingebunden, für den Import in Schritt 7.
- Feste Versionen und wud.watch=false: Die Vorlage nutzt memcached ohne Tag. Wir setzen bei Memcached die Reihe 1.6-alpine und nehmen alle Container von What's Up Docker aus, siehe Teil 75.
- Speichergrenzen: Mailpiler und Manticore dürfen je höchstens 512 MB belegen, wie in der Vorlage.
Prüfen Sie vorher, ob die Ports frei sind. Keine Ausgabe bedeutet frei:
sudo ss -ltn | grep -E ":(8096|2525) "
Verifizieren: Die Ausgabe von sudo docker compose config --quiet bleibt leer.
Schritt 3: Ordner mit den richtigen Besitzern anlegen
Bei unserem ersten Start lief nur die Hälfte. MariaDB startete immer wieder neu und meldete:
chown: changing ownership of '/var/lib/mysql/': Operation not permitted
Der Grund: Die Vorlage entzieht dem Container mit cap_drop alle Sonderrechte bis auf drei. Das Recht, Besitzer zu ändern, fehlt. Bei einem benannten Volume ist das egal, weil der Ordner schon dem Konto mysql gehört. Ein neuer Ordner auf der NAS gehört aber root. Danach nahm Mailpiler zwar Mails an, legte sie aber nicht ab:
mkdir /var/piler/store/00/6ae/b7/3b: error=No such file or directory
failed to store message
Mailpiler läuft als Konto piler mit der Nummer 1000. Unterhalb von store/00 legt es alle Ordner selbst an, den Ordner 00 aber nicht. 00 steht für die Server-Nummer server_id=0. Legen Sie deshalb alle Ordner vor dem ersten Start an und geben Sie sie den richtigen Konten. MariaDB nutzt im Image die Nummer 999:
sudo mkdir -p db store/00 import etc manticore
sudo chown 999:999 db
sudo chown -R 1000:1000 store
sudo chmod 700 store
sudo chmod 755 import
Den Ordner etc befüllt Mailpiler beim ersten Start selbst. Dort entstehen die Konfiguration und der Schlüssel piler.key, mit dem es alle Mails verschlüsselt. In etc liegen außerdem das Datenbank-Passwort im Klartext in config-site.php und .my.cnf. Auf unserer NAS gehörte die Nummer 1000 dem Benutzerkonto sedv, store und piler.key gehörten auf der NAS also diesem Konto. Mit getent passwd 1000 sehen Sie, welches Konto es bei Ihnen ist. Geben Sie den Ordner docker nicht als Netzwerkfreigabe für andere Benutzer frei.
Verifizieren: ls -ln zeigt db mit 999 und store mit 1000 als Besitzer.
Schritt 4: Starten und die Weiterleitung reparieren
sudo docker compose pull
sudo docker compose up -d
Die Images waren bei uns 321 MB für Mailpiler, 628 MB für Manticore, 330 MB für MariaDB und 13 MB für Memcached groß. Beim ersten Start legt Mailpiler die Tabellen an. Nach etwa einer Minute meldet der Container healthy, die Gesundheitsprüfung fragt den SMTP-Dienst ab. Mehr dazu in Docker Compose absichern.
sudo docker compose ps --format "{{.Name}} {{.Status}}"
piler Up About a minute (healthy)
piler-db Up About a minute
piler-manticore Up About a minute
piler-memcached Up About a minute
Die Anmeldeseite erschien unter http://ADRESSE-DER-NAS:8096 sofort. Nach der Anmeldung brach die Seite aber ab. Mailpiler leitete auf die Adresse ohne Port weiter, also auf Port 80. Die Adresse steht in etc/config-site.php als SITE_URL und wird nur aus PILER_HOSTNAME gebildet. Tragen Sie dort die vollständige Adresse mit Port ein:
sudo nano etc/config-site.php
$config['SITE_URL'] = 'http://192.168.1.10:8096' . $config['PATH_PREFIX'];
Mailpiler schreibt die Datei nur, wenn sie fehlt. Die Änderung blieb bei uns auch beim Neuerstellen des Containers erhalten. Die Anmeldung auf Port 8096 läuft unverschlüsselt über HTTP. Nutzen Sie sie nur im eigenen Netz und richten Sie für den Dauerbetrieb einen Reverse Proxy mit HTTPS ein, dann tragen Sie dort die Domain mit https ein.
Verifizieren: Nach der Anmeldung bleiben Sie auf Port 8096 und sehen die Suche.
Schritt 5: Standardpasswörter ändern
Mailpiler hat keine Registrierung. Es bringt zwei feste Konten mit, deren Passwörter in der Dokumentation stehen und damit allgemein bekannt sind:
- admin@local mit dem Passwort pilerrocks: verwaltet Benutzer, Domains und Einstellungen, sieht aber keine Mails.
- auditor@local mit dem Passwort auditor: darf alle archivierten Mails durchsuchen und lesen.
Melden Sie sich mit beiden Konten nacheinander an, klicken Sie oben rechts auf den Namen und ändern Sie unten auf der Seite Einstellungen unter Passwort ändern das Kennwort. Auf derselben Seite stellen Sie die Sprache auf de. In unserem Test stand danach für beide Konten ein neuer Passwort-Hash in der Datenbank.

Gewöhnliche Benutzer sehen nur Mails an ihre eigenen Adressen. Wer alle Mails sehen darf, sollte zusätzlich die Anmeldung mit Google Authenticator auf derselben Seite einschalten. Im Unternehmen legen Sie vorher fest, wer die Rolle Auditor bekommt.
Verifizieren: Sie können sich mit den Standardpasswörtern nicht mehr anmelden.
Schritt 6: Mails per SMTP einliefern
Im Betrieb schickt Ihr Mailserver jede Nachricht zusätzlich an Mailpiler, als Blindkopie oder Journal an den Port 2525 der NAS. Das setzt einen eigenen Mailserver im Netz voraus, etwa Postfix mit always_bcc. Liegt Ihr Postfach bei einem Anbieter wie Microsoft 365 oder IONOS, kommt keine Kopie bis zur NAS, ohne dass Sie den Port ins Internet öffnen. Dann übernehmen Sie die Mails mit pilerimport, siehe Schritt 7. Zum Test haben wir Mails mit Python vom Rechner aus eingeliefert, eine Testmail schicken Sie so:
python3 -c "import smtplib; from email.message import EmailMessage as M; m=M(); m['From']='test@example.com'; m['To']='archiv@example.com'; m['Subject']='Testnachricht Archiv'; m.set_content('Hallo Archiv'); smtplib.SMTP('192.168.1.10', 2525).send_message(m)"
Das Protokoll im Container zeigt das Ergebnis, hier gekürzt auf das Ende der Zeile:
sudo docker exec piler grep status= /var/log/mail.log | tail -3
status=stored

Die Mails liegen verschlüsselt unter store. Eine Suche nach einem Wort aus dem Text fand dort in keiner Datei einen Treffer, in der Weboberfläche dagegen sofort. Wir haben nach Hausratvertrag gesucht, ein Wort, das nur im Text einer Mail stand.

Nachricht verifiziert bedeutet, dass die Prüfsumme der gespeicherten Mail noch stimmt. Ab Werk bewahrt Mailpiler jede Mail 2557 Tage auf, also sieben Jahre und zwei Tage, eingestellt mit default_retention_days in etc/piler.conf. Danach löscht ein täglicher Lauf die Mail automatisch. Prüfen Sie vorher, wie lange Sie Ihre Mails aufbewahren müssen, und setzen Sie den Wert passend.
Verifizieren: In der Suche des Auditors stehen Ihre Testmails.
Schritt 7: Alte Mails importieren
Vorhandene Mails übernehmen Sie mit pilerimport. Legen Sie die EML-Dateien in den Ordner import, machen Sie sie lesbar und starten Sie den Import als Konto piler:
sudo chmod 644 import/*.eml
sudo docker exec -u piler -w /var/piler/tmp piler pilerimport -d /import
processed: 2
Ohne die Docker-Option -w /var/piler/tmp, also ohne beschreibbares Arbeitsverzeichnis, brach der Befehl bei uns mit cannot write current directory ab. Die importierten Mails behielten ihr ursprüngliches Datum aus dem Oktober. Ein zweiter Import derselben Dateien legte nichts doppelt an, Mailpiler meldete duplicated=2. pilerimport liest auch mbox-Dateien mit -m und holt Mails mit -i direkt von einem IMAP-Server.
Verifizieren: In der Suche stehen die importierten Mails mit ihrem alten Datum.
Schritt 8: Nur den eigenen Mailserver zulassen
Ab Werk nimmt Mailpiler von jedem Rechner im Netz Mails an, in etc/piler.conf steht smtp_access_list=0. Jeder könnte also Nachrichten ins Archiv schmuggeln. Legen Sie eine Liste der erlaubten Absender an, hier der Container selbst, den Mailpiler ohnehin zulässt und der die Gesundheitsprüfung ausführt, und Ihr Mailserver mit der Beispieladresse 192.168.1.20:
printf "127.0.0.1/32 permit\n192.168.1.20/32 permit\n" | sudo tee etc/smtp.acl
sudo sed -i "s/^smtp_access_list=0/smtp_access_list=1/" etc/piler.conf
sudo docker compose restart piler
Ein Versuch von unserem Rechner, der nicht in der Liste stand, scheiterte danach:
SMTPConnectError(550, b'Service currently unavailable')
denied connection from 192.168.1.183 by implicit default deny
Für Rechner im Netz reicht Docker die Adresse des Absenders an den Container durch, die Liste greift also auch mit veröffentlichtem Port. Der Container blieb healthy. Die Liste arbeitet nur mit IPv4-Adressen. Läuft Ihr Mailserver selbst als Container auf derselben NAS, sieht Mailpiler eine Adresse aus dem Docker-Netz. Geben Sie dann nie ganze Bereiche wie 172.16.0.0/12 frei.
Verifizieren: sudo docker exec piler grep acl /var/log/mail.log zeigt Ihre Einträge mit parsed acl. Mails von Ihrem Mailserver erscheinen weiterhin mit status=stored, Testmails von anderen Rechnern werden abgewiesen.
Typische Fehler
- MariaDB startet ständig neu, chown Operation not permitted: Der Ordner db gehört nicht 999. Besitzer setzen.
- failed to store message: store oder store/00 fehlt oder gehört nicht 1000. Die verworfenen Mails lagen bei uns im Container unter /var/piler/error und gehen beim Neuerstellen verloren, liefern Sie sie neu ein.
- Seite bricht nach der Anmeldung ab: SITE_URL ohne Port. In config-site.php ergänzen.
- Nach einem Update abgemeldet: Mailpiler speichert Sitzungen im Container. Nach dem Neuerstellen melden Sie sich neu an.
- cannot open directory beim Import: Der Ordner import ist für das Konto piler nicht lesbar. chmod 755 auf den Ordner, 644 auf die Dateien.
Häufige Fragen
Wie viel Arbeitsspeicher braucht Mailpiler?
Bei uns belegten die vier Container mit fünf Testmails zusammen rund 250 MiB: MariaDB 178 MiB, Mailpiler 46 MiB, Manticore 27 MiB und Memcached 2 MiB.
Was gehört in die Sicherung?
Der Ordner store mit den verschlüsselten Mails, der Ordner etc mit piler.key, der Ordner manticore mit dem Suchindex und eine Sicherung der Datenbank, alles zum selben Zeitpunkt. Ohne piler.key lassen sich die Mails nicht mehr entschlüsseln, bewahren Sie eine Kopie getrennt auf. Beim Wiederherstellen legen Sie etc mit piler.key zurück, bevor Sie den Container zum ersten Mal starten. Fehlt die Datei, erzeugt Mailpiler beim Start ohne Rückfrage einen neuen Schlüssel. Die Datenbank sichern Sie im laufenden Betrieb so:
sudo docker exec piler-db sh -c 'mariadb-dump -u piler -p"$MYSQL_PASSWORD" --single-transaction piler' | sudo tee piler.sql >/dev/null
sudo chmod 600 piler.sql
Die Datei enthielt bei uns alle Tabellen mit 8 INSERT-Anweisungen. Sie enthält die Metadaten aller Mails und die Passwort-Hashes, deshalb chmod 600. Wie Sie Docker-Daten sichern, zeigt Teil 61.
Wie aktualisieren Sie Mailpiler?
Lesen Sie vor jedem Update die Versionshinweise und die Seite Upgrade in der Dokumentation von Mailpiler. Dort stehen nötige Datenbank-Skripte und Änderungen für Docker, die Nummer des Kontos piler hat sich zwischen Versionen schon geändert. Sichern Sie die Daten, ändern Sie das Tag in der Compose-Datei und starten Sie neu:
sudo docker compose pull
sudo docker compose up -d
Prüfen Sie danach mit sudo docker exec piler id piler, ob das Konto piler noch die Nummer 1000 hat, sonst passen Sie den Besitzer von store an. Weil What's Up Docker diese Container nicht überwacht, abonnieren Sie auf GitHub unter Watch die Releases von jsuto/piler.
Wie greifen Sie von unterwegs zu?
Über VPN oder einen Reverse Proxy mit HTTPS. Den SMTP-Port 2525 geben Sie nie ins Internet frei, er ist nur für Ihren Mailserver da.
Fazit
Mailpiler läuft auf der UGREEN NAS mit vier Containern und rund 250 MiB Arbeitsspeicher. Es speichert Mails verschlüsselt, findet sie über die Volltextsuche und erkennt doppelte Importe. In unserem Test brauchte die offizielle Vorlage drei Handgriffe: Besitzer für db und store, den Ordner store/00 und den Port in SITE_URL. Danach ändern Sie die bekannten Standardpasswörter, lassen per smtp.acl nur Ihren Mailserver zu und sichern piler.key getrennt.


