LinkWarden mit Docker installieren: Self-hosted kollaborativer Bookmark-Manager mit Webarchivierung
LinkWarden kombiniert Bookmark-Management mit automatischer Webarchivierung als Screenshot, PDF und HTML – für Teams, die Links dauerhaft vor Link-Rot schützen wollen. Diese Anleitung zeigt die vollständige Docker-Compose-Installation.

Wer kennt das nicht: Ein gespeicherter Link führt Monate später ins Leere – die Seite ist verschwunden, umgezogen oder gelöscht. LinkWarden löst dieses Problem radikal: Jeder gespeicherte Bookmark wird automatisch als Screenshot, PDF und als Single-File-HTML archiviert. So bleibt der Inhalt dauerhaft erhalten, auch wenn die Originalseite offline geht. Mit 18.600+ GitHub-Stars, nativen Mobile-Apps für iOS und Android, Browser-Extensions, Reader-View mit Annotations-Funktion, KI-gestütztem Tagging und Unterstützung für über 60 SSO-Provider ist LinkWarden die umfassendste Open-Source-Lösung im Bereich kollaborativer Web-Archivierung. Diese Anleitung zeigt, wie du LinkWarden mit Docker Compose auf einem beliebigen Linux-Host – ob VPS, Heimserver oder NAS – in Betrieb nimmst.
Voraussetzungen
- Docker Engine >= 24.x und Docker Compose v2 (Befehl:
docker compose, ohne Bindestrich) auf dem Host installiert – siehe Docker und Docker Compose auf Linux installieren - Linux-Host (x86_64 oder arm64) – Ubuntu 22.04/24.04 oder Debian 12 empfohlen; läuft identisch auf einem NAS mit Docker-Unterstützung
- Mindestens 4 GB RAM (empfohlen 8 GB, da drei Services parallel laufen: Next.js, PostgreSQL 16 und MeiliSearch); mindestens 20 GB freier Speicherplatz für Archivdaten
- Ausgehender HTTP/HTTPS-Zugriff vom Container zum Internet (LinkWarden lädt externe Seiten zur Archivierung herunter)
openssloderpython3zur Generierung sicherer Zufalls-Secrets- Optional: eigene Domain + Reverse Proxy (Nginx Proxy Manager, Traefik oder Caddy) für HTTPS-Betrieb – wie das funktioniert, erklärt Traefik als Docker-Reverse-Proxy mit automatischem HTTPS einrichten
Schritt 1: Projektordner anlegen
Lege einen dedizierten Ordner für LinkWarden an. Alle Daten – Datenbank, Archive und Suchindex – werden als Unterverzeichnisse relativ zu diesem Ordner gespeichert:
mkdir -p /opt/linkwarden
cd /opt/linkwardenDu kannst auch ~/linkwarden verwenden, wenn du keinen Root-Zugriff hast. Wichtig ist, dass der ausführende Benutzer Schreibrechte in diesem Verzeichnis hat – Unterverzeichnisse wie ./pgdata, ./data und ./meili_data werden beim ersten Start automatisch angelegt.
Verifizieren: ls -la /opt/linkwarden zeigt das leere Verzeichnis. Der aktuell angemeldete Benutzer ist Eigentümer (drwxr-xr-x ... deinuser).
Schritt 2: Sichere Secrets generieren
LinkWarden benötigt drei kryptografisch starke Zufalls-Strings. Generiere sie mit openssl:
# NEXTAUTH_SECRET (mindestens 32 Zeichen, signiert alle Auth-Sessions)
openssl rand -base64 36
# POSTGRES_PASSWORD (Datenbankpasswort)
openssl rand -base64 24
# MEILI_MASTER_KEY (mindestens 16 Zeichen für MeiliSearch-Produktion)
openssl rand -base64 36Notiere alle drei Ausgaben – du trägst sie im nächsten Schritt in die .env-Datei ein. Alternativ funktioniert auch python3 -c 'import secrets; print(secrets.token_urlsafe(36))'.
Verifizieren: Jeder generierte String ist mindestens 32 Zeichen lang und enthält Groß- und Kleinbuchstaben sowie Sonderzeichen. Alle drei Werte sind voneinander verschieden.
Schritt 3: .env-Datei anlegen und konfigurieren
Die .env-Datei enthält alle sensitiven Konfigurationswerte. Lege sie im Projektordner an:
# /opt/linkwarden/.env
# --- Pflichtfelder (alle drei MÜSSEN geändert werden!) ---
# Signiert Auth-Sessions; mindestens 32 Zeichen; generiert mit: openssl rand -base64 36
NEXTAUTH_SECRET=HIER_DEINEN_GENERIERTEN_STRING_EINTRAGEN
# Muss exakt das Suffix /api/v1/auth enthalten – sonst schlägt der Login fehl!
# Lokal: http://localhost:3000/api/v1/auth
# Mit Reverse Proxy: https://links.meinedomain.tld/api/v1/auth
NEXTAUTH_URL=http://localhost:3000/api/v1/auth
# PostgreSQL-Datenbankpasswort; generiert mit: openssl rand -base64 24
POSTGRES_PASSWORD=HIER_DEIN_DB_PASSWORT
# MeiliSearch Master-Key; mindestens 16 Zeichen; generiert mit: openssl rand -base64 36
MEILI_MASTER_KEY=HIER_DEINEN_MEILI_KEY_EINTRAGEN
# --- Optionale Felder ---
# Nach der Erstregistrierung auf true setzen, um offene Registrierung zu sperren
NEXT_PUBLIC_DISABLE_REGISTRATION=false
# Sekunden Wartezeit vor Screenshot/PDF-Capture (Standard: 30)
# AUTOSCROLL_TIMEOUT=30
# Maximale Links pro Benutzer (Standard: 30000)
# MAX_LINKS_PER_USER=30000
# Archivierung deaktivieren (spart Ressourcen, aber kein Link-Rot-Schutz mehr)
# DISABLE_PRESERVATION=falseSchütze die Datei vor unbefugtem Zugriff:
chmod 600 /opt/linkwarden/.envVerifizieren: cat /opt/linkwarden/.env zeigt alle drei Pflichtfelder mit echten Werten (keine Platzhalter mehr). ls -la /opt/linkwarden/.env zeigt die Berechtigung -rw-------.
Schritt 4: compose.yaml erstellen
Erstelle die compose.yaml im Projektordner. Die Datei definiert drei Services: die LinkWarden-App selbst (Next.js), PostgreSQL 16 als Datenbank und MeiliSearch für die Volltextsuche. Nur Port 3000 wird nach außen freigegeben:
# /opt/linkwarden/compose.yaml
services:
postgres:
image: postgres:16-alpine
env_file: .env
restart: always
volumes:
- ./pgdata:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
meilisearch:
image: getmeili/meilisearch:v1.12.8
restart: always
env_file:
- .env
volumes:
- ./meili_data:/meili_data
linkwarden:
image: ghcr.io/linkwarden/linkwarden:latest
env_file: .env
environment:
- DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/postgres
restart: always
ports:
- "3000:3000"
volumes:
- ./data:/data/data
depends_on:
- postgres
- meilisearchEin paar wichtige Details zur Architektur: Das offizielle Image liegt auf der GitHub Container Registry (ghcr.io), nicht auf Docker Hub. Der MeiliSearch-Image ist bewusst auf v1.12.8 gepinnt – das vermeidet Kompatibilitätsprobleme bei Breaking Changes in neueren Versionen. Die Variable DATABASE_URL wird direkt im environment-Block gesetzt und muss nicht in der .env stehen, da sie dynamisch aus ${POSTGRES_PASSWORD} zusammengebaut wird.
Die folgende Tabelle fasst alle wichtigen Eckdaten des Stacks zusammen:
| Eigenschaft | Wert |
|---|---|
| Haupt-Image | ghcr.io/linkwarden/linkwarden:latest (v2.14.1) |
| Datenbank-Image | postgres:16-alpine |
| Suche-Image | getmeili/meilisearch:v1.12.8 |
| Exponierter Port | 3000 (Web-UI und API) |
| Volume: Archivdaten | ./data → /data/data |
| Volume: Datenbank | ./pgdata → /var/lib/postgresql/data |
| Volume: Suchindex | ./meili_data → /meili_data |
| Mindest-RAM | 4 GB (empfohlen 8 GB) |
| Mindest-Speicher | 20 GB für Archivdaten |
Verifizieren: cat /opt/linkwarden/compose.yaml zeigt alle drei Services ohne Syntaxfehler. docker compose config (im Projektordner) validiert die Datei und interpoliert die Umgebungsvariablen aus .env – die Ausgabe darf keine Fehler und keine Platzhalter-Werte enthalten.
Schritt 5: Stack starten
Starte alle drei Services mit einem Befehl:
cd /opt/linkwarden
docker compose up -dDocker lädt beim ersten Start die Images herunter (insgesamt ca. 1–2 GB) und startet die Container. PostgreSQL initialisiert beim ersten Start die Datenbank, was einige Sekunden dauert. Da depends_on ohne Healthcheck arbeitet, kann es vorkommen, dass LinkWarden kurz startet, bevor die Datenbank vollständig bereit ist. In diesem Fall genügt ein einmaliger Neustart:
docker compose restart linkwardenPrüfe den Status aller Services:
docker compose psErwartete Ausgabe (alle Services Up):
NAME IMAGE STATUS PORTS
linkwarden-linkwarden-1 ghcr.io/linkwarden/linkwarden:latest Up 0.0.0.0:3000->3000/tcp
linkwarden-postgres-1 postgres:16-alpine Up 5432/tcp
linkwarden-meilisearch-1 getmeili/meilisearch:v1.12.8 Up 7700/tcpSchau bei Problemen in die Logs:
# Alle Services gleichzeitig
docker compose logs -f
# Nur LinkWarden
docker compose logs -f linkwardenVerifizieren: docker compose ps zeigt alle drei Container im Status Up. Ein HTTP-Check bestätigt die Erreichbarkeit:
curl -I http://localhost:3000
# Erwartete Antwort: HTTP/1.1 200 OK oder HTTP/1.1 302 FoundSchritt 6: Admin-Account anlegen und Ersteinrichtung
Öffne im Browser http://localhost:3000 (bzw. die IP/Domain deines Servers). Du siehst die LinkWarden-Anmeldeseite. Klicke auf „Registrieren" – der erste registrierte Benutzer wird automatisch zum Admin. Wähle eine sichere E-Mail-Adresse und ein starkes Passwort.
Nach der Anmeldung stehen dir sofort alle Funktionen zur Verfügung: Links speichern (manuell oder per Browser-Extension), Collections anlegen, Tagging, die Reader-View und die Volltextsuche via MeiliSearch. Die Archivierung läuft im Hintergrund – nach dem Speichern eines Links dauert es je nach Seitenstruktur und Archivierungseinstellung (Standard: 30 Sekunden Wartezeit) einige Momente, bis Screenshot, PDF und HTML-Snapshot verfügbar sind.
Sperre danach die offene Registrierung, damit sich keine unbefugten Benutzer anmelden können:
# In .env den Wert ändern:
# NEXT_PUBLIC_DISABLE_REGISTRATION=true
# Dann den Container neu starten:
docker compose up -d --force-recreate linkwardenVerifizieren: Melde dich mit dem neuen Admin-Account an. Unter „Einstellungen" → „Profil" ist der Account als Administrator markiert. Versuche in einem privaten Browser-Fenster, einen zweiten Account zu registrieren – nach dem Setzen von NEXT_PUBLIC_DISABLE_REGISTRATION=true ist die Registrierungsseite nicht mehr zugänglich.
Schritt 7: Reverse Proxy und HTTPS (Produktion)
Für den Produktionsbetrieb mit einer eigenen Domain und HTTPS-Zertifikat musst du zwei Dinge anpassen:
1. NEXTAUTH_URL in der .env anpassen – der Wert muss die externe HTTPS-Domain samt dem Pflicht-Suffix /api/v1/auth enthalten:
NEXTAUTH_URL=https://links.meinedomain.tld/api/v1/auth2. Reverse Proxy konfigurieren – leite Port 443 auf den Container-Port 3000 weiter. Nginx Proxy Manager, Traefik oder Caddy eignen sich gut dafür. Wie das auf einem Docker-Host mit Nginx Proxy Manager klappt, erklärt die Anleitung Nginx Proxy Manager einrichten: Reverse Proxy und SSL Schritt für Schritt.
Nach der Änderung der .env den LinkWarden-Container neu starten:
docker compose up -d --force-recreate linkwardenVerifizieren: Öffne https://links.meinedomain.tld im Browser. Das Schloss-Symbol zeigt ein gültiges TLS-Zertifikat. Login und OAuth-Callbacks funktionieren korrekt. Einen Test-Link speichern und nach einigen Sekunden prüfen, ob der Screenshot erscheint.
Schritt 8: Updates und Backups
LinkWarden wird aktiv weiterentwickelt (zuletzt v2.14.1, April 2025). Mit dem :latest-Tag zieht ein einfaches Pull-Update die aktuelle Version:
cd /opt/linkwarden
docker compose pull
docker compose up -dLege vor jedem Update ein Backup der drei Volumes an:
# Kurz stoppen, Backup erstellen, wieder starten
docker compose down
tar czf ~/backup-linkwarden-$(date +%Y%m%d).tar.gz \
/opt/linkwarden/pgdata \
/opt/linkwarden/data \
/opt/linkwarden/meili_data
docker compose up -dFür eine automatisierte Backup-Strategie – etwa mit Restic auf eine externe Quelle – empfiehlt sich Restic Backup auf Linux und Windows einrichten und automatisieren.
Verifizieren: Nach dem Update zeigt docker compose ps alle Container im Status Up. docker compose logs linkwarden | head -20 enthält keine Fehlermeldungen zu Datenbankmigrationen oder fehlenden Umgebungsvariablen. Das Backup-Archiv ist vorhanden und lesbar: tar tzf ~/backup-linkwarden-*.tar.gz | head.
Troubleshooting / Typische Fehler
- Login schlägt fehl: „Invalid URL" oder Redirect-Fehler – NEXTAUTH_URL fehlt das Suffix
/api/v1/auth. Korrektes Format:http://HOST:3000/api/v1/auth. Nach Änderung:docker compose up -d --force-recreate linkwarden. - „Can't reach database server at postgres:5432" – LinkWarden hat gestartet, bevor PostgreSQL bereit war. Fix:
docker compose restart linkwarden. Dauerhafter Fix: Healthcheck zudepends_onhinzufügen. - POSTGRES_PASSWORD-Mismatch nach Passwortänderung – Das
pgdata-Volume wurde mit dem alten Passwort initialisiert. Lösung: Passwort direkt in PostgreSQL ändern:docker compose exec postgres psql -U postgres -c "ALTER USER postgres PASSWORD 'neues_passwort';"– oder Volume löschen (Datenverlust!) und neu initialisieren. - MeiliSearch startet im unsicheren Modus – MEILI_MASTER_KEY fehlt oder ist kürzer als 16 Zeichen. Neuen Key generieren (
openssl rand -base64 36), in.enveintragen unddocker compose up -d --force-recreate meilisearchausführen. - Archivierung schlägt lautlos fehl (Screenshots leer) – Playwright/Chromium benötigt bestimmte System-Libraries. Im offiziellen
ghcr.io-Image sind diese enthalten. Bei ARM64-Hosts prüfen:docker inspect ghcr.io/linkwarden/linkwarden:latest | grep -i architecture. - ./data-Volume falsch gemountet – Archivierte Dateien landen in
/data/dataim Container. Der Host-Mount muss./data:/data/datalauten (nicht./data:/data). Bei falschem Pfad gehen Archive nach einem Container-Neustart verloren. - NEXTAUTH_URL nach Reverse-Proxy-Umstieg falsch – Bei Betrieb hinter Nginx/Traefik muss
NEXTAUTH_URLdie externe HTTPS-URL sein, nichtlocalhost. OAuth-Callbacks und Session-Cookies schlagen sonst fehl. - Berechtigungsfehler auf ./pgdata oder ./data – Wenn diese Verzeichnisse als root angelegt wurden, kann der Container-Prozess nicht schreiben. Fix:
chown -R 1000:1000 /opt/linkwarden/data /opt/linkwarden/pgdata.
Häufige Fragen
Kann ich LinkWarden ohne MeiliSearch betreiben?
Ja, MeiliSearch ist optional. Ohne den meilisearch-Service und ohne MEILI_MASTER_KEY startet LinkWarden und verwendet die einfache PostgreSQL-Datenbanksuche. Die erweiterte Volltextsuche (unscharfe Suche, Relevanzbewertung) ist dann nicht verfügbar – für den Einstieg oder ressourcenbeschränkte Hosts aber völlig ausreichend.
Wie sperre ich die Registrierung nach der Ersteinrichtung?
Setze in der .env den Wert NEXT_PUBLIC_DISABLE_REGISTRATION=true und starte den Container neu: docker compose up -d --force-recreate linkwarden. Die Registrierungsseite ist danach nicht mehr zugänglich. Neue Benutzer können nur noch vom Admin eingeladen werden.
Wie viel Speicherplatz brauche ich für Archive?
Das hängt stark von der Nutzungsintensität ab. Pro archiviertem Link – Screenshot (PNG), PDF und HTML-Snapshot (via Monolith) – sind je nach Seitenstruktur 1–10 MB zu veranschlagen. Bei 1.000 Links mit durchschnittlich 3 MB ergibt das bereits 3 GB. Für intensive Teams mit Tausenden Links empfiehlt sich ein separates großes Volume oder S3-kompatibles Object Storage (AWS S3, MinIO, Hetzner Object Storage) über die SPACES_*-Umgebungsvariablen.
Wie konfiguriere ich KI-Tagging?
LinkWarden unterstützt mehrere KI-Provider für automatisches Tagging: lokal via Ollama (NEXT_PUBLIC_OLLAMA_ENDPOINT_URL), OpenAI (OPENAI_API_KEY) oder Anthropic (ANTHROPIC_API_KEY). Für datenschutzbewusste Teams ist Ollama mit einem lokalen Modell die beste Wahl – wie du Ollama als Docker-Container betreibst, erklärt Ollama und Open WebUI mit Docker: eigenes lokales KI-Sprachmodell ohne Cloud.
Wie aktiviere ich E-Mail und Passwort-Reset?
Setze in der .env folgende Werte und starte den Container neu: NEXT_PUBLIC_EMAIL_PROVIDER=true, EMAIL_FROM=noreply@meinedomain.tld, EMAIL_SERVER=smtp://user:pass@smtp.meinedomain.tld:587 und BASE_URL=https://links.meinedomain.tld. Ohne diese Konfiguration funktioniert die Passwort-Reset-Funktion nicht.
Wie stelle ich auf SSO (Google, GitHub, Authentik) um?
LinkWarden unterstützt über 60 SSO-Provider via NextAuth.js. Füge die entsprechenden Provider-Variablen in die .env ein, z. B. für Google: GOOGLE_CLIENT_ID und GOOGLE_CLIENT_SECRET. Die vollständige Liste der unterstützten Provider findet sich in der offiziellen LinkWarden Environment Variables Referenz.
Fazit
LinkWarden ist eine ausgereifte, aktiv gepflegte Lösung für Teams und Einzelpersonen, die Bookmarks nicht nur speichern, sondern dauerhaft archivieren wollen. Die Docker-Compose-Installation ist dank des offiziellen Images unkompliziert, setzt aber eine sorgfältige Konfiguration der drei Pflicht-Secrets voraus – besonders das korrekte NEXTAUTH_URL-Suffix ist ein häufiger Stolperstein. Mit MeiliSearch erhält der Stack eine vollwertige Volltextsuche; wer Ressourcen sparen will, kann den Service weglassen. Die automatische Archivierung als Screenshot, PDF und Single-File-HTML macht LinkWarden zur überzeugenden Antwort auf das Link-Rot-Problem.
Weiterführende Anleitungen und Quellen
- Docker und Docker Compose auf Linux installieren – die Self-Hosting-Grundlage
- Traefik als Docker-Reverse-Proxy mit automatischem HTTPS einrichten
- Ollama und Open WebUI mit Docker: eigenes lokales KI-Sprachmodell ohne Cloud
- Restic Backup auf Linux und Windows einrichten und automatisieren
- Paperless-ngx mit Docker einrichten: papierlose Dokumentenverwaltung mit OCR
- Firefly III mit Docker installieren: Self-hosted Finanzverwaltung
Offizielle Quellen: LinkWarden Installationsdokumentation | LinkWarden auf GitHub | Environment Variables Referenz