1 · Start
Wähle deinen Modus
Nur offline
Kein Server und kein Konto. Die verschlüsselten Notizen bleiben ausschließlich im Speicher dieses Geräts.
Android installierenEigener Sync-Server
Web-App und API laufen per Docker auf deinem Server. Android verbindet sich mit derselben, von dir festgelegten URL.
Docker einrichtenDas Löschen der App, der App-Daten oder des Browser-Speichers kann lokale Notizen unwiederbringlich entfernen. Offline-Daten werden derzeit nicht automatisch auf einen Server migriert.
2 · Android & Offline
Safernotes auf Android installieren
- App beziehen Installiere Safernotes aus dem Google Play Store oder lade die APK direkt herunter.
- APK bei Bedarf freigeben Bei einer direkten APK kann Android einmalig „Unbekannte Apps installieren“ für deinen Browser oder Dateimanager verlangen.
- Offline starten Wähle auf dem ersten Bildschirm Nur offline verwenden. Es wird keine Verbindung zu einem Safernotes-Server aufgebaut.
Für Erinnerungen muss Android Benachrichtigungen erlauben. Auf GrapheneOS müssen zusätzlich die Benachrichtigungsberechtigung und eine passende Akku-Einstellung für Safernotes aktiv sein. Lokale Erinnerungen benötigen weder Google Play Services noch einen Safernotes-Server.
3 · Self-Hosting
Mit Docker installieren
Du brauchst Git, Python 3, Docker Engine und Docker Compose v2. Der Stack enthält die Web-App, Django-API, PostgreSQL und Redis. Verschlüsselte Anhänge werden direkt in einem dauerhaften Docker-Volume gespeichert.
1. Quellcode herunterladen
git clone https://github.com/MosesEllermann/safernotes.git
cd safernotes
2. Deine URL festlegen und starten
Ersetze die Beispieladresse durch deine eigene HTTPS-Adresse:
python3 tools/init_selfhost.py --url https://notizen.example.com
sudo docker compose up --build -d
Die Docker-Befehle hier verwenden sudo für einen
Linux-Server. Wenn dein Benutzer bereits Docker-Zugriff hat oder
du Docker Desktop bzw. Rootless Docker verwendest, lasse
sudo weg. Das Python-Setup und Git führst du immer
als normaler Benutzer aus, damit deine Dateien dir gehören.
Das Setup speichert die Adresse als PUBLIC_URL und erzeugt
alle internen Geheimnisse automatisch in deiner privaten .env.
Erlaubte Hosts, Browser-Zugriffe und App-Links werden aus dieser einen
Adresse abgeleitet. Beim ersten Start werden Datenbankmigrationen und
der Speicherbereich für verschlüsselte Anhänge automatisch angelegt.
Der erste Build lädt zusätzlich die Flutter-Buildumgebung herunter:
mehrere Gigabyte, die nur zum Kompilieren benötigt werden. Das fertige
Web-Image enthält Nginx und die gebaute App. Docker speichert die
Build-Layer für spätere Builds zwischen. Plane beim ersten Start
einige Minuten und ausreichend freien Speicher ein.
Eine vorhandene .env wird nicht überschrieben.
Behalte die erzeugten Geheimnisse auch bei Updates und sichere die Datei
privat. Für einen bestehenden Server folge Updates & Backups.
3. Domain und HTTPS verbinden
Ein A-Record verbindet den Domainnamen mit einer IPv4-Adresse; HTTPS und die Weiterleitung zur App richtest du zusätzlich ein. Bei einem Homelab hinter einem Router zeigt der A-Record auf deine öffentliche IP-Adresse. Leite TCP-Port 80 und 443 am Router zum HTTPS-Reverse-Proxy weiter und erlaube sie in der Firewall. Bei CGNAT brauchst du eine alternative Erreichbarkeit, etwa einen Tunnel.
- Web-Container prüfenStarte den Stack und
prüfe
sudo docker compose ps. Bei einem belegten Port hilft die Anleitung für Portkonflikte. - Proxy-Ziel eintragenLeite deine Domain per
HTTP an die Serveradresse und den Web-Port weiter, standardmäßig
8080. Läuft der Proxy als eigener Docker-Container, verwende die LAN-IP des Servers;localhostbezeichnet dort den Proxy-Container selbst. Ein Proxy direkt auf dem Host kann127.0.0.1verwenden. - TLS aktivierenFordere im Proxy ein
Zertifikat für deine Domain an und aktiviere die Weiterleitung
von HTTP auf HTTPS. Danach öffnest du deine vollständige
PUBLIC_URLim Browser.
Der Proxy muss den ursprünglichen Host und
X-Forwarded-Proto: https weitergeben und Uploads bis
100 MiB erlauben. Beschränke den direkten Zugriff auf den Web-Port
auf den Proxy; öffentlich erreichbar sein sollen dessen Ports 80 und 443.
Beispiel: Caddy direkt auf dem Server
Wenn Caddy auf dem Host installiert ist und dessen Ports 80 und
443 frei und von außen erreichbar sind, setze in deiner
.env beispielsweise
SAFERNOTES_WEB_PORT=127.0.0.1:8088 und starte den
Stack mit sudo docker compose up -d erneut.
Trage in die Caddy-Konfiguration ein und lade sie neu:
notizen.example.com {
reverse_proxy 127.0.0.1:8088
}
Ersetze die Domain durch deine eigene. Caddy richtet das Zertifikat automatisch ein. Bei einem bestehenden Reverse-Proxy legst du stattdessen dort einen weiteren Host an.
Nur die Web-App veröffentlicht einen Port. API, PostgreSQL und Redis bleiben im Docker-Netz. Anhänge laufen ebenfalls über deine App-Adresse: kein zusätzlicher Speicher-Port, keine zweite Domain und kein Cloud-Konto. Domain, HTTPS und Backups bleiben Aufgaben des Serverbetreibers.
Erst einmal lokal ausprobieren
Führe nach dem Herunterladen des Quellcodes diese Befehle statt der Einrichtung mit eigener Domain aus:
python3 tools/init_selfhost.py
sudo docker compose up --build -d
Öffne http://localhost:8080 auf demselben Rechner.
Für den Zugriff vom Smartphone brauchst du eine von dort erreichbare
HTTPS-Adresse. Stelle dafür PUBLIC_URL in der bestehenden
.env um und starte den Stack erneut; die Geheimnisse bleiben gleich.
Optional: E-Mail über SMTP
SMTP-Schlüssel gehören ausschließlich in deine lokale
.env-Datei. Setze dort EMAIL_BACKEND,
EMAIL_HOST, EMAIL_PORT, Benutzername,
Passwort, TLS/SSL und DEFAULT_FROM_EMAIL. Ohne SMTP
schreibt die Standardkonfiguration Verifizierungs- und
Wiederherstellungs-E-Mails in das Container-Log.
Ausführlichere Betreiberhinweise stehen auch im Self-Hosting-Handbuch im Repository.
4 · Verbinden
Android mit deinem Server verbinden
-
Safernotes öffnen
Trage auf dem Anmeldebildschirm dieselbe vollständige URL wie bei
PUBLIC_URLein, zum Beispielhttps://notizen.example.com. -
Konto anlegen oder anmelden
Verwende danach Registrierung oder Anmeldung gegen deinen eigenen Server. Hänge kein
/apian die URL an. - URL später ändern Öffne Einstellungen → Sync-Server. Die URL wird nur lokal auf diesem Gerät gespeichert.
Die von Docker ausgelieferte Web-App verwendet automatisch ihre eigene Domain. Dort muss keine Server-URL eingetragen werden.
5 · Betrieb
Updates und Backups
Installation aktualisieren
Falls du bereits Anhänge mit der früheren Speicher-Version genutzt hast, lies vor dem Update die Hinweise zum Wechsel direkt darunter.
git pull --ff-only
sudo docker compose up --build -d
sudo docker compose ps
Lies vor einem Update die Versionshinweise und sichere deine Daten. Datenbankmigrationen laufen beim Start des API-Containers.
Von einer älteren Docker-Konfiguration wechseln
Behalte deine bestehende .env,
SECRET_KEY, POSTGRES_PASSWORD und alle
Volumes. Prüfe nur deine öffentliche Adresse:
PUBLIC_URL=https://notizen.example.com
Eine Speicher-URL oder zusätzliche Speicher-Zugangsdaten werden
nicht mehr verwendet. Alte Einträge in deiner .env
werden ignoriert. Starte danach den Stack wie oben beschrieben.
Erzeuge keine neuen Passwörter und lösche keine Volumes, um ein
Startproblem zu umgehen.
Bei bereits gespeicherten Anhängen aus der früheren MinIO/S3-Version: Diese werden nicht automatisch übernommen. Sichere und exportiere sie vor dem Wechsel; das alte Speicher-Volume darf nicht einfach als neues Anhang-Volume eingebunden werden. Hinweise zur Übernahme stehen im Self-Hosting-Handbuch. Wenn die bisherige Installation schon beim Image-Download gescheitert ist, gibt es keine hochgeladenen Anhänge zu übernehmen.
PostgreSQL sichern
sudo docker compose exec -T postgres \
pg_dump -U safernotes safernotes > safernotes-backup.sql
Sichere zusätzlich das Docker-Volume attachment_data mit den verschlüsselten
Anhängen und bewahre deine .env sicher auf. Prüfe
Wiederherstellungen regelmäßig auf einem getrennten System.
Stoppe für einen zusammengehörigen Datenbank- und Dateistand die
API während der Sicherung. Die Volume-Namen tragen normalerweise
den Compose-Projektnamen als Präfix. Verwende für Updates niemals
docker compose down -v: Das löscht die dauerhaften Daten.
6 · Fehlersuche
Wenn etwas nicht funktioniert
Docker meldet „address already in use“
Dann belegt ein anderer Dienst bereits den Web-Port. Die Images müssen deshalb nicht erneut gebaut werden. Prüfe zuerst die Belegung:
sudo ss -ltnp 'sport = :8080'
sudo docker ps --format 'table {{.Names}}\t{{.Ports}}'
Behalte den anderen Dienst und wähle für Safernotes einen freien
Port, zum Beispiel 8088. Ändere den vorhandenen Eintrag
in deiner .env (für einen Proxy direkt auf dem Host
stattdessen SAFERNOTES_WEB_PORT=127.0.0.1:8088):
SAFERNOTES_WEB_PORT=8088
Starte danach die bereits gebauten Container und prüfe die API:
sudo docker compose up -d
sudo docker compose ps
curl --fail http://127.0.0.1:8088/api/v1/health/live
Trage auch im Reverse-Proxy den neuen Zielport 8088
ein. PUBLIC_URL bleibt deine HTTPS-Domain ohne diesen
internen Port. Behalte das Projektverzeichnis, die Geheimnisse und
die Volumes; das Setup-Skript brauchst du nicht erneut auszuführen.
Docker meldet „permission denied“
Wenn der Zugriff auf /var/run/docker.sock verweigert
wird, fehlen deinem Linux-Benutzer die Docker-Berechtigungen.
Das ist kein App- oder Passwortfehler. Führe im Projektverzeichnis aus:
sudo docker compose up --build -d
sudo docker compose ps
Eine bereits erzeugte .env bleibt erhalten; das Setup-Skript
musst du nicht erneut ausführen. Dauerhafter Zugriff ohne
sudo lässt sich über die Docker-Gruppe einrichten – diese
gewährt jedoch root-ähnliche Rechte. Details stehen in der
offiziellen Docker-Anleitung.
Mache den Docker-Socket nicht für alle Benutzer beschreibbar.
sudo docker compose ps
sudo docker compose logs --tail=200 api
sudo docker compose logs --tail=200 web
curl https://notizen.example.com/api/v1/health/live
- Es wird noch ein separates Speicher-Image heruntergeladen: Aktualisiere den Quellcode mit
git pull --ff-only. Die aktuelle Compose-Datei benötigt keinen separaten Speicherdienst mehr. Behalte deine.envund vorhandene Daten. - Server nicht erreichbar: Prüfe HTTPS, DNS, Firewall und ob die URL ohne
/apigespeichert wurde. - Setup meldet eine vorhandene Datei: Das schützt deine Zugangsdaten. Bearbeite bei Bedarf
PUBLIC_URLin der bestehenden.env; lösche die Datei nicht. - Registrierungs-E-Mail fehlt: Prüfe die
EMAIL_*-Werte und das API-Log. Bei der Console-Konfiguration steht der Inhalt nur im Log. - Anhänge schlagen fehl: Prüfe das API-Log, freien Speicherplatz, Schreibrechte im Anhang-Volume und das Upload-Limit deines HTTPS-Proxys. Es gibt keinen zusätzlichen Speicher-Port oder Speicher-Zugangsschlüssel.
- Android-Erinnerungen fehlen: Erlaube Benachrichtigungen, kontrolliere Datum und Uhrzeit und entferne Akku-Beschränkungen für Safernotes.
Veröffentliche weder deine .env noch ungeprüfte Logs.
Ohne SMTP können Verifizierungs- und Wiederherstellungslinks im
API-Log stehen. Auch temporäre Anhang-Links gehören nicht in öffentliche Fehlerberichte.
7 · Q&A
Häufige Fragen
Brauche ich für Safernotes einen Server?
Nein. Im Offline-Modus arbeitet die App ohne Konto und ohne API. Einen Server brauchst du nur für Synchronisierung oder die selbst gehostete Web-App.
Kann ich eine beliebige Safernotes-URL in der App verwenden?
Ja. Trage die Basis-URL deiner eigenen Installation ein, beispielsweise https://notizen.example.com. Die App enthält keine verpflichtende Anbieter-URL.
Brauche ich mehrere Domains oder URLs?
Nein. Du konfigurierst nur PUBLIC_URL. Web-App,
Android-Synchronisierung und Anhang-Transfers verwenden diese
Adresse. Die internen Host-, Browser- und Link-Einstellungen
werden automatisch daraus abgeleitet.
Muss ich API-Keys oder Passwörter selbst erstellen?
Nein. tools/init_selfhost.py erzeugt die internen
Geheimnisse automatisch und speichert sie in deiner privaten
.env. Für die Standardinstallation brauchst du kein
externes Konto und keine API-Keys. Die Geheimnisse bleiben bei
Updates erhalten und gehören in dein privates Backup.
Wofür sind die zwei automatisch erzeugten Geheimnisse?
SECRET_KEY sichert serverinterne Funktionen ab;
er ist nicht der Entschlüsselungsschlüssel deiner Notizen.
POSTGRES_PASSWORD schützt den Datenbankzugang.
Du musst sie normalerweise nicht bearbeiten.
Ist der Speicher bereits enthalten?
Ja. PostgreSQL speichert unter anderem verschlüsselte Notizen
und Kontodaten; verschlüsselte Anhänge liegen direkt im dauerhaften
Docker-Volume attachment_data auf deinem Server.
Die API prüft den Zugriff. Es gibt keinen externen Speicherdienst
und keine zusätzliche Speicher-Konfiguration.
Muss ich Ports für Datenbank oder Dateispeicher freigeben?
Nein. Diese Dienste bleiben im Docker-Netz und veröffentlichen keine eigenen Ports auf dem Server. Nur der Web-Port wird an deinen HTTPS-Proxy angebunden. Eine gesonderte Speicher-Domain oder öffentliche Verwaltungsoberfläche brauchst du nicht.
Was muss ich beim Self-Hosting noch selbst einrichten?
Du benötigst einen Server mit Docker, eine erreichbare Domain, einen HTTPS-Reverse-Proxy und regelmäßige Backups. Das Setup übernimmt interne Geheimnisse und Datenbankmigrationen, aber keine Domainregistrierung oder automatische Datensicherung. SMTP ist optional; ohne SMTP werden E-Mails nur in die privaten Container-Logs geschrieben.
Kann der Server meine Notizen lesen?
Notiztitel, Texte, Checklisten und Anhänge werden clientseitig verschlüsselt. Der Server verarbeitet weiterhin notwendige Konto-, Freigabe- und technische Metadaten.
Funktionieren Erinnerungen ohne Google Play Services?
Ja. Erinnerungen werden lokal über Android geplant. Safernotes benötigt dafür die Benachrichtigungsberechtigung und darf nicht durch Akku- oder Hintergrundbeschränkungen gestoppt werden.
Kann ich Offline-Notizen später automatisch synchronisieren?
Noch nicht. Offline-Modus und Server-Vault sind getrennt. Verlasse dich bis zu einer Export-/Import-Funktion nicht auf eine automatische Migration.
Was kostet Self-Hosting?
Safernotes selbst ist kostenlos und unter AGPL-3.0-or-later verfügbar. Kosten können für deinen Server, Domain, Speicher, SMTP-Dienst oder Backups entstehen.
Wo melde ich Fehler oder schlage Funktionen vor?
Nutze die GitHub Issues des Open-Source-Projekts und beschreibe Plattform, App-Version und reproduzierbare Schritte.