Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Docker 22.08.2026 · 9 min Lesezeit

AFFiNE mit Docker installieren: All-in-one Notion-Alternative mit Whiteboard und Kanban selbst hosten

AFFiNE vereint Docs, Whiteboard und Kanban in einer selbst betriebenen Plattform. Die Anleitung zeigt, wie Sie AFFiNE 0.27.4 per Docker Compose mit PostgreSQL (pgvector) und Redis installieren, absichern, aktualisieren und sichern.

Geprüft am 30.09.2026 · für affine 0.27.4

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

Symbolbild zur Anleitung: AFFiNE mit Docker installieren

AFFiNE ist ein quelloffener Arbeitsbereich, der Aufgaben von Notion, Miro und Trello abdeckt. Er vereint strukturierte Docs und Datenbanken, ein freies Whiteboard/Canvas und Kanban-Boards in einer einzigen Oberfläche. Dank local-first-Architektur (Daten liegen zuerst lokal und werden dann synchronisiert) läuft AFFiNE vollständig auf dem eigenen Server. Diese Anleitung zeigt die Installation von AFFiNE 0.27.4 mit Docker Compose auf einem Linux-Host.

Voraussetzungen

  1. Docker Engine >= 20.10 und Docker Compose Plugin v2 (oder Docker Desktop). Installation: Docker und Docker Compose auf Linux installieren.
  2. Linux-Host, VM oder NAS (x86_64 oder ARM64) mit mindestens 4 CPU-Kernen und 2 GB RAM; weniger führt zu Latenzproblemen bei mehreren gleichzeitigen Nutzern.
  3. Ausreichend Festplattenplatz für PostgreSQL-Daten, Uploads und Konfiguration (je nach Nutzung mehrere GB).
  4. openssl zum Erzeugen eines sicheren Datenbankpassworts (auf jedem Linux-System vorhanden).
  5. Für den Produktionsbetrieb: öffentliche IP-Adresse, Domain und ein Reverse-Proxy mit SSL-Terminierung (z. B. Traefik als Docker-Reverse-Proxy oder Caddy).
  6. Optional: SMTP-Zugangsdaten für E-Mail-Einladungen und Benachrichtigungen.

Schritt 1: Projektordner anlegen und Verzeichnisstruktur erstellen

Alle Dateien für den AFFiNE-Stack leben in einem gemeinsamen Projektordner. Legen Sie ihn an einem Ort mit genug Platz an, der in Ihrer Datensicherung enthalten ist, zum Beispiel unter /opt/affine/.

mkdir -p /opt/affine
cd /opt/affine
mkdir -p postgres storage config

Die drei Unterverzeichnisse entsprechen den Pflicht-Volumes: postgres/ für die Datenbankdaten, storage/ für Uploads und Blobs, config/ für Konfigurationsdateien. Die Pfade legen Sie in der .env fest. Ändern Sie sie nach dem ersten Start nur mit vollständiger Sicherung und Wiederherstellung.

Verifizieren: ls -la /opt/affine/ zeigt die drei Unterverzeichnisse postgres, storage und config.

Schritt 2: .env-Datei mit Secrets und Pfaden anlegen

Die .env-Datei enthält alle sensiblen und umgebungsspezifischen Werte. Das Datenbankpasswort muss zwingend vor dem ersten Start gesetzt sein; nachträgliche Änderungen erfordern einen vollständigen Datenbankdump und eine Neuinitialisierung.

Erzeugen Sie zunächst ein Passwort aus Buchstaben und Ziffern (Sonderzeichen würden die Datenbank-URL brechen):

openssl rand -hex 24

Erstellen Sie dann die .env im Projektordner und ersetzen Sie IHR_PASSWORT durch die erzeugte Zeichenkette:

# ── AFFiNE Self-Host .env ──────────────────────────────────────────────────

# Datenbankzugang (PFLICHT vor erstem Start – danach nicht mehr ändern!)
DB_USERNAME=affine
DB_PASSWORD=IHR_PASSWORT
DB_DATABASE=affine

# Speicherpfade (absolute oder relative Host-Pfade)
DB_DATA_LOCATION=./postgres
UPLOAD_LOCATION=./storage
CONFIG_LOCATION=./config

# Image-Version: feste Version für Produktion, alternativ stable | beta | canary
AFFINE_REVISION=0.27.4

# Host-Port für die Weboberfläche (nur lokal gebunden, siehe compose.yaml)
PORT=3010

# ── Produktionsbetrieb (Domain / HTTPS) ───────────────────────────────────
# Auskommentiert lassen, solange Sie nur lokal testen.
# AFFINE_SERVER_HOST=affine.example.com
# AFFINE_SERVER_HTTPS=true
# AFFINE_SERVER_EXTERNAL_URL=https://affine.example.com

# ── E-Mail (optional, für Einladungen) ────────────────────────────────────
# MAILER_HOST=smtp.example.com
# MAILER_PORT=465
# MAILER_USER=noreply@example.com
# MAILER_PASSWORD=SMTP_PASSWORT
# MAILER_SENDER=noreply@example.com

Schützen Sie die Datei gegen Lesezugriff anderer Benutzer:

chmod 600 /opt/affine/.env

Verifizieren: grep DB_PASSWORD /opt/affine/.env gibt Ihr Passwort aus (kein leerer Wert). ls -la /opt/affine/.env zeigt die Berechtigungen -rw-------.

Schritt 3: compose.yaml anlegen

Der Stack besteht aus vier Services. Der affine_migration-Container führt Datenbankmigrationen aus, bevor der Haupt-Container startet; ohne diesen Job startet AFFiNE nicht. Verwenden Sie ausschließlich das aktuelle Image ghcr.io/toeverything/affine; das ältere affine-self-hosted-Image ist veraltet und nutzt noch Port 3000. Der Port ist an 127.0.0.1 gebunden: Bis Sie den Admin-Account angelegt haben, könnte sonst jeder im Netz ihn übernehmen. Von außen erreichen Sie AFFiNE später über den Reverse-Proxy.

name: affine

services:
  affine:
    image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable}
    container_name: affine_server
    ports:
      - '127.0.0.1:${PORT:-3010}:3010'
    depends_on:
      redis:
        condition: service_healthy
      postgres:
        condition: service_healthy
      affine_migration:
        condition: service_completed_successfully
    volumes:
      - ${UPLOAD_LOCATION}:/root/.affine/storage
      - ${CONFIG_LOCATION}:/root/.affine/config
    env_file:
      - .env
    environment:
      - REDIS_SERVER_HOST=redis
      - DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine}
      - AFFINE_INDEXER_ENABLED=false
    restart: unless-stopped

  affine_migration:
    image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable}
    container_name: affine_migration_job
    volumes:
      - ${UPLOAD_LOCATION}:/root/.affine/storage
      - ${CONFIG_LOCATION}:/root/.affine/config
    command: ['sh', '-c', 'node ./scripts/self-host-predeploy.js']
    env_file:
      - .env
    environment:
      - REDIS_SERVER_HOST=redis
      - DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine}
      - AFFINE_INDEXER_ENABLED=false
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy

  redis:
    image: redis:8
    container_name: affine_redis
    healthcheck:
      test: ['CMD', 'redis-cli', '--raw', 'incr', 'ping']
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  postgres:
    image: pgvector/pgvector:pg16
    container_name: affine_postgres
    volumes:
      - ${DB_DATA_LOCATION}:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: ${DB_DATABASE:-affine}
      POSTGRES_INITDB_ARGS: '--data-checksums'
    healthcheck:
      test: ['CMD', 'pg_isready', '-U', "${DB_USERNAME}", '-d', "${DB_DATABASE:-affine}"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

PostgreSQL muss als pgvector/pgvector:pg16 laufen, nicht als Standard-postgres:16, weil AFFiNE die pgvector-Erweiterung für Vektorsuche und KI-Features benötigt.

Eckdaten auf einen Blick

ParameterWert
AFFiNE-Imageghcr.io/toeverything/affine:0.27.4 (Kanal stable)
PostgreSQL-Imagepgvector/pgvector:pg16
Redis-Imageredis:8
Web-UI Port127.0.0.1:3010 (konfigurierbar via PORT)
Upload-VolumeUPLOAD_LOCATION → /root/.affine/storage
Config-VolumeCONFIG_LOCATION → /root/.affine/config
DB-VolumeDB_DATA_LOCATION → /var/lib/postgresql/data
Mindest-Ressourcen4 CPU-Kerne, 2 GB RAM
LizenzMIT (Community Edition)

Verifizieren: docker compose config im Projektordner gibt die zusammengeführte Konfiguration ohne Fehler und ohne Warnung „variable is not set“ aus.

Schritt 4: Stack starten

Starten Sie alle Container im Hintergrund. Docker Compose lädt zunächst die Images herunter; das dauert je nach Verbindung einige Minuten.

cd /opt/affine
docker compose up -d

Der Startablauf ist durch die depends_on-Bedingungen streng geordnet: Zuerst starten Redis und PostgreSQL, deren Healthchecks müssen grün sein. Dann führt affine_migration die Datenbankmigrationen aus und muss erfolgreich abschließen (service_completed_successfully). Erst danach startet der eigentliche affine_server.

Verifizieren:

# Alle Container anzeigen
docker compose ps

# Erwartete Ausgabe (nach 1-2 Minuten):
# NAME                    STATUS
# affine_server           Up (running)
# affine_migration_job    Exited (0)
# affine_postgres         Up (healthy)
# affine_redis            Up (healthy)

# Logs der Haupt-App prüfen
docker compose logs affine --tail=30

# HTTP-Antwort prüfen
curl -I http://localhost:3010

Der affine_migration_job mit Exit-Code 0 ist korrekt: Er ist ein einmaliger Job, kein dauerhaft laufender Dienst. curl -I http://localhost:3010 liefert HTTP/1.1 200 oder eine 302-Weiterleitung. Falls affine_server nicht startet, liefert docker compose logs affine_migration den Grund.

Schritt 5: Ersteinrichtung im Browser

Rufen Sie http://localhost:3010 im Browser auf. Von einem anderen Rechner aus nutzen Sie bis zur Proxy-Einrichtung einen SSH-Tunnel: ssh -L 3010:127.0.0.1:3010 benutzer@server. AFFiNE zeigt beim ersten Aufruf einen Einrichtungsassistenten.

  1. Der erste registrierte Benutzer erhält automatisch Admin-Rechte. Legen Sie daher sofort nach dem ersten Start Ihren Admin-Account an.
  2. Workspace-Name und Einstellungen wählen Sie im Assistenten.
  3. E-Mail-Einladungen an weitere Teammitglieder funktionieren erst, wenn Sie die MAILER_*-Variablen in der .env gesetzt und den Stack neu gestartet haben (docker compose up -d).
  4. Für Einladungs- und Share-Links mit der richtigen externen URL setzen Sie im Produktionsbetrieb AFFINE_SERVER_EXTERNAL_URL (siehe Schritt 6).

Verifizieren: Nach dem Anlegen des Admin-Accounts öffnet sich das AFFiNE-Dashboard mit den drei Hauptmodi Docs, Edgeless (Whiteboard) und Database (Kanban/Grid). Ein neues Dokument lässt sich ohne Fehlermeldung anlegen und speichern.

Schritt 6: HTTPS und Produktionsbetrieb (optional, aber empfohlen)

AFFiNE bringt kein eigenes HTTPS mit; die SSL-Terminierung übernimmt ein vorgelagerter Reverse-Proxy. Traefik mit automatischem Let's-Encrypt-Zertifikat beschreibt die Anleitung Traefik als Docker-Reverse-Proxy mit automatischem HTTPS; für Nginx siehe Nginx als Reverse Proxy mit TLS manuell einrichten.

Sobald der Reverse-Proxy läuft, aktivieren Sie in der .env diese Zeilen (Raute entfernen) und starten Sie den Stack mit docker compose up -d neu:

AFFINE_SERVER_HOST=affine.example.com
AFFINE_SERVER_HTTPS=true
AFFINE_SERVER_EXTERNAL_URL=https://affine.example.com

Ohne AFFINE_SERVER_EXTERNAL_URL erzeugt AFFiNE Einladungs- und Share-Links mit localhost:3010, die für externe Nutzer nicht erreichbar sind. Einige Features wie Passwortänderung per E-Mail erfordern außerdem zwingend eine HTTPS-Umgebung (WSS).

Verifizieren: https://affine.example.com öffnet AFFiNE mit gültigem Zertifikat. Erstellen Sie eine Einladung für einen zweiten Benutzer und prüfen Sie, ob der Link in der E-Mail https://affine.example.com/... enthält (nicht localhost).

Schritt 7: Updates und Backup-Routine

AFFiNE befindet sich im Pre-1.0-Stadium. Neue Releases bringen Datenbankmigrationen mit; ein Rollback ist ohne vorheriges Backup nicht möglich.

Update-Workflow

cd /opt/affine

# 1. Backup ZUERST (vor jedem Update!)
docker compose exec postgres pg_dump -U affine affine > affine_backup_$(date +%Y%m%d).sql
cp -a ./storage ./storage_backup_$(date +%Y%m%d)

# 2. AFFINE_REVISION in .env auf die neue Version setzen, dann Images ziehen
docker compose pull

# 3. Stack neu starten (affine_migration läuft automatisch)
docker compose up -d

# 4. Logs prüfen
docker compose logs affine --tail=20

Backup-Strategie

Drei Komponenten müssen regelmäßig gesichert werden:

  1. PostgreSQL-Datenbank: Via pg_dump (wie oben) oder als Volume-Backup von DB_DATA_LOCATION.
  2. Blob-Storage: Gesamter Inhalt von UPLOAD_LOCATION (hochgeladene Dateien, Bilder).
  3. Konfiguration: Inhalt von CONFIG_LOCATION sowie die .env-Datei.

Eine vollständige Backup-Automatisierung mit Rotation und Cloud-Sync beschreibt unsere Anleitung MySQL & PostgreSQL Backup automatisieren mit cron.

Verifizieren: Nach dem Update zeigt docker compose ps alle Services als Up bzw. den Migrations-Job als Exited (0). docker compose logs affine --tail=30 enthält keine Fehler zu Datenbankverbindung oder Migrationen. Die AFFiNE-Web-UI ist erreichbar und alle bestehenden Workspaces und Dokumente sind noch vorhanden.

Troubleshooting / Typische Fehler

  1. affine_server startet nicht / wartet ewig: Der Migrations-Job ist fehlgeschlagen. Diagnose: docker compose logs affine_migration. Prüfen Sie, ob postgres und redis den Status healthy haben, und führen Sie docker compose up -d erneut aus.
  2. Falsches Image / Port 3000 statt 3010: Das veraltete ghcr.io/toeverything/affine-self-hosted:latest ist eingetragen. Ersetzen Sie es in der compose.yaml durch ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable} und führen Sie docker compose up -d --force-recreate aus.
  3. DB_PASSWORD leer / Datenbankverbindung schlägt fehl: Fehlt DB_PASSWORD in der .env, schlägt die PostgreSQL-Initialisierung fehl. Bei einer noch nicht initialisierten Datenbank: .env mit Passwort befüllen, docker compose down -v (Achtung: löscht Daten!), docker compose up -d. Bei bereits existierenden Daten ist ein vollständiger Dump, Neuinitialisierung und Restore nötig.
  4. Einladungslinks zeigen localhost:3010: AFFINE_SERVER_EXTERNAL_URL ist nicht gesetzt. In .env eintragen und docker compose up -d ausführen.
  5. Fehler „pgvector extension not found“: Eingetragen ist postgres:16 statt pgvector/pgvector:pg16. Images tauschen, bestehende Daten per pg_dump sichern, DB-Volume löschen, mit korrektem Image neu starten und Daten einspielen.
  6. Langsame Performance bei mehreren Nutzern: Ressourcen unter dem Minimum (4 CPU, 2 GB RAM). Prüfen Sie mit docker stats auf Memory-Druck oder CPU-Throttling.
  7. Redis-Reconnect-Fehler nach Neustart: Redis hat im offiziellen Setup kein Volume. Brauchen Sie Persistenz, ergänzen Sie ein benanntes Volume für /data.

Häufige Fragen

Welchen Tag soll ich für AFFINE_REVISION verwenden?

Für Produktionsbetrieb eine feste Versionsnummer wie 0.27.4; stable zeigt jeweils auf die neueste stabile Version (Stand September 2026: 0.27.4). beta und canary liefern Vorab- und Entwicklungs-Builds mit möglichen Breaking Changes und eignen sich nur für Tests.

Wie aktualisiere ich AFFiNE auf eine neue Version?

Tragen Sie die neue Version in AFFINE_REVISION ein und führen Sie im Projektordner docker compose pull && docker compose up -d aus. Der affine_migration-Container läuft automatisch mit und führt notwendige Datenbankmigrationen aus. Erstellen Sie vorher ein Backup von PostgreSQL und dem UPLOAD_LOCATION-Verzeichnis.

Wie richte ich den ersten Admin-Account ein?

Rufen Sie nach dem ersten Start http://localhost:3010 auf. Der erste registrierte Benutzer erhält im Einrichtungsassistenten Admin-Rechte. Weitere Benutzer laden Sie über das Admin-Panel ein, sofern die MAILER_*-Variablen gesetzt sind.

Kann ich AFFiNE auf ARM64 (Raspberry Pi, Apple Silicon) betreiben?

Ja. Das AFFiNE-Image gibt es für amd64, arm64 und armv7; redis und pgvector/pgvector:pg16 unterstützen arm64 ebenfalls. Auf einem Raspberry Pi beachten Sie die Mindestressourcen.

Wie sichere ich AFFiNE vollständig?

Drei Komponenten müssen gesichert werden: (1) PostgreSQL-Datenbank via pg_dump oder Volume-Backup von DB_DATA_LOCATION, (2) der gesamte Blob-Storage (UPLOAD_LOCATION), (3) die Konfiguration (CONFIG_LOCATION plus die .env-Datei). Testen Sie die Wiederherstellung regelmäßig in einer separaten Umgebung.

Fazit

AFFiNE eignet sich für Teams, die Docs, Whiteboard und Kanban selbst betreiben und ihre Daten kontrollieren wollen. Der Stack umfasst vier Container: Der Migrations-Job initialisiert die Datenbank, Healthchecks auf PostgreSQL und Redis sichern die Startreihenfolge. Die typischen Fehler sind veraltetes Image, fehlendes Datenbankpasswort und fehlende AFFINE_SERVER_EXTERNAL_URL. Da AFFiNE noch vor Version 1.0 steht, testen Sie Updates vor dem Einsatz im Team und sichern Sie vorher Datenbank und Uploads.

Weiterführende Anleitungen und Quellen

  1. Docker und Docker Compose auf Linux installieren – Grundlage für alle Docker-Deployments
  2. Traefik als Docker-Reverse-Proxy mit automatischem HTTPS – SSL für AFFiNE und andere Dienste
  3. MySQL & PostgreSQL Backup automatisieren mit cron – Backup-Automation für den AFFiNE-PostgreSQL-Stack
  4. Docker Compose absichern: Secrets, Healthchecks, Non-Root – Härtung für den Produktivbetrieb

Quellen: offizielle AFFiNE-Dokumentation unter docs.affine.pro und GitHub-Repository toeverything/AFFiNE.