
AppFlowy auf einem Hetzner Ubuntu-Server selbst hosten
Yulei ChenAppFlowy ist eine Open-Source-Alternative zu Notion, die dir volle Kontrolle über deine Daten gibt. Wenn du AppFlowy Cloud auf deinem eigenen Ubuntu-Server hostest, bekommst du einen kollaborativen Workspace mit AI-Features, Echtzeit-Sync und ohne Nutzungslimits — zu vorhersehbaren monatlichen Kosten.
Folge dieser leicht verständlichen Anleitung, um deine eigene AppFlowy Cloud-Instanz mit Docker und dem Caddy-Webserver für automatisches HTTPS aufzusetzen.
Für diesen Beitrag verwenden wir einen günstigen Server von Hetzner. Hetzner ist bekannt für großartigen Service zu einem außergewöhnlichen Preis-Leistungs-Verhältnis und eignet sich perfekt für das Hosten von AppFlowy.
Voraussetzungen
Bevor wir beginnen, achte drauf, dass du ein Hetzner Cloud-Konto hast (oder bereit bist, eines zu erstellen).
Schritt 1: Deinen Hetzner-Server einrichten
Wenn du noch keinen Hetzner-Server hast, folge diesen Schritten, um einen zu erstellen:
- Geh zur Hetzner Cloud Console, wähle ein Projekt aus oder erstelle ein neues, dann geh zu Servers → Add Server

- Folge Hetzners Richtlinien, um zu wählen:
- Server type: AppFlowy Cloud läuft mit mehreren Services (Datenbank, Auth, Object Storage und mehr), du brauchst also mindestens 4 GB RAM. Wir empfehlen einen CX22 oder größer.

- Location: Wähl einen Rechenzentrumsstandort, der dir oder deinen Nutzern am nächsten ist.

- Image: Wähl Ubuntu (neueste LTS-Version empfohlen).

- Add SSH key: Füg deinen öffentlichen SSH-Schlüssel für sicheren Zugriff hinzu. Wenn du noch keinen SSH-Schlüssel hast, kannst du einen mit
ssh-keygengenerieren:
ssh-keygen -t ed25519 -C "your_email@example.com"
Prüf ihn mit cat ~/.ssh/id_ed25519.pub und füg ihn bei deinem Server ein.

- Konfiguriere das Networking bei Bedarf, dann klick auf Create & Pay, um deinen Server bereitzustellen.

Sobald dein Server erstellt wurde, notier dir seine IP-Adresse. Du brauchst sie, um dich im nächsten Schritt per SSH zu verbinden.

Schritt 2: Deinen Server aktualisieren
Öffne dein Terminal und melde dich per SSH auf deinem Ubuntu-Server an:
ssh root@your-server-ip
und aktualisiere das System, damit es die neuesten Sicherheitspatches und Updates hat:
sudo apt-get update
sudo apt-get upgrade -y
Sobald das durch ist, ist dein Server bereit für die Installation der Software.
Schritt 3: UFW-Firewall installieren und konfigurieren
Halte nur notwendige Ports offen: SSH (22), HTTP (80), HTTPS (443).
Installiere UFW und konfiguriere die Firewall wie folgt:
sudo apt install ufw -y
sudo ufw allow 22 # SSH
sudo ufw allow 80 # HTTP
sudo ufw allow 443 # HTTPS
sudo ufw enable
Prüf deine Firewall-Konfiguration:
sudo ufw status verbose
Docker kann manchmal UFW-Regeln ignorieren. Mehr dazu und wie du das behebst, findest du hier erklärt.
Schritt 4: Docker installieren
Docker startet AppFlowy und alle zugehörigen Services in Containern. Installiere Docker mit diesen Befehlen:
Dependencies und Docker GPG-Key einrichten:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
| sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
Docker-Repository hinzufügen:
echo \
"deb [arch=$(dpkg --print-architecture) \
signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo $VERSION_CODENAME) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
Docker Engine und compose-plugin installieren:
sudo apt-get install docker-ce docker-ce-cli \
containerd.io docker-buildx-plugin docker-compose-plugin -y
Installation prüfen:
sudo docker run hello-world
Wenn du die "hello-world"-Meldung siehst, ist Docker bereit.
Schritt 5: Caddy für automatisches HTTPS installieren
Caddy vereinfacht die HTTPS-Konfiguration, weil es SSL-Zertifikate automatisch von Let's Encrypt holt.
Caddy installieren:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
| sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
| sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy -y
Bevor du Caddy konfigurierst, musst du deine Domain auf die IP-Adresse deines Servers zeigen. Wenn du DNS noch nicht eingerichtet hast, folge diesen Schritten:
DNS für deine Domain konfigurieren
- Melde dich im Dashboard deines Domain-Registrars an (wo du die Domain gekauft hast)
- Geh zu den DNS-Einstellungen oder dem DNS-Management-Bereich
- Füg einen A-Record mit diesen Einstellungen hinzu:
- Type:
A - Name:
@(für Root-Domain) oder eine Subdomain wieappflowy(fürappflowy.yourdomain.com) - Value/Target: Die IPv4-Adresse deines Hetzner-Servers
- Type:
- Füg einen AAAA-Record für IPv6-Support hinzu:
- Type:
AAAA - Name:
@(für Root-Domain) oder dieselbe Subdomain wie beim A-Record - Value/Target: Die IPv6-Adresse deines Hetzner-Servers
- Type:
DNS-Änderungen können ein paar Minuten bis mehrere Stunden brauchen, bis sie propagiert sind. Du kannst mit Tools wie dig oder Online-DNS-Checkern prüfen, ob dein DNS korrekt konfiguriert ist. Sobald der DNS-Record aktiv ist, kannst du mit der Caddy-Konfiguration weitermachen.
Caddy konfigurieren
Bearbeite die Caddyfile-Konfigurationsdatei:
sudo nano /etc/caddy/Caddyfile
Trag deine Domain ein und konfiguriere den Reverse Proxy. Ersetze "yourdomain.com" durch deine echte Domain:
yourdomain.com {
reverse_proxy localhost:8080
}
Wenn du noch keine Domain hast, nutze vorübergehend diese Variante:
:80 {
reverse_proxy localhost:8080
}
Starte Caddy neu, damit die Config geladen wird:
sudo systemctl restart caddy
Schritt 6: AppFlowy mit Docker Compose starten
AppFlowy Cloud besteht aus mehreren Services: dem Haupt-API-Server, Authentifizierung (GoTrue), einem Admin-Panel, einem Background Worker, AI-Service, PostgreSQL mit pgvector, Redis, MinIO für Object Storage und einem Nginx Reverse Proxy, der alles zusammenbringt.
Erstell zuerst ein Verzeichnis für AppFlowy und die Nginx-Config:
mkdir -p /opt/appflowy/nginx
cd /opt/appflowy
Environment-Datei erstellen
Generiere starke Passwörter für die Services:
openssl rand -base64 32
Führ diesen Befehl mehrmals aus, um für jedes Feld unten ein eigenes Passwort zu bekommen.
Erstell die .env-Datei:
sudo nano /opt/appflowy/.env
Füg folgenden Inhalt ein und ersetze alle CHANGE_ME_...-Werte durch deine generierten Passwörter:
# AppFlowy Base URL (deine Domain mit https, ohne Slash am Ende)
APPFLOWY_BASE_URL=https://yourdomain.com
# PostgreSQL
POSTGRES_USER=appflowy
POSTGRES_PASSWORD=CHANGE_ME_POSTGRES_PASSWORD
POSTGRES_DB=appflowy
# MinIO Object Storage
MINIO_USER=minioadmin
MINIO_PASSWORD=CHANGE_ME_MINIO_PASSWORD
# JWT Secret (generieren mit: openssl rand -base64 32)
JWT_SECRET=CHANGE_ME_JWT_SECRET
# GoTrue Admin-Zugangsdaten
ADMIN_EMAIL=admin@example.com
ADMIN_PASSWORD=CHANGE_ME_ADMIN_PASSWORD
# SMTP-Einstellungen (optional — für E-Mail-Einladungen)
SMTP_HOST=
SMTP_PORT=587
SMTP_USER=
SMTP_PASS=
SMTP_ADMIN_EMAIL=
# OpenAI API Key (optional — für AI-Features)
OPENAI_API_KEY=
Achte drauf, dass du jeden CHANGE_ME_...-Platzhalter durch ein starkes, einzigartiges Passwort ersetzt. Passwörter zwischen Services wiederzuverwenden ist ein Sicherheitsrisiko.
Nginx-Config erstellen
Der integrierte Nginx-Service leitet den Traffic an die richtigen AppFlowy-Backend-Services weiter.
sudo nano /opt/appflowy/nginx/nginx.conf
Füg folgende Config ein:
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
resolver 127.0.0.11 valid=10s;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
client_max_body_size 10M;
underscores_in_headers on;
set $appflowy_cloud_backend "http://appflowy_cloud:8000";
set $gotrue_backend "http://gotrue:9999";
set $admin_frontend_backend "http://admin_frontend:3000";
# GoTrue Authentication
location /gotrue/ {
proxy_pass $gotrue_backend;
rewrite ^/gotrue(/.*)$ $1 break;
proxy_set_header Host $http_host;
proxy_pass_request_headers on;
}
# WebSocket-Endpoint
location /ws {
proxy_pass $appflowy_cloud_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400s;
}
# API-Endpoints
location /api {
proxy_pass $appflowy_cloud_backend;
proxy_set_header X-Request-Id $request_id;
proxy_set_header Host $http_host;
# Publish-Endpoint (große Uploads)
location ~* ^/api/workspace/([a-zA-Z0-9_-]+)/publish$ {
proxy_pass $appflowy_cloud_backend;
proxy_request_buffering off;
client_max_body_size 256M;
}
# Chat-Endpoint (Streaming)
location /api/chat {
proxy_pass $appflowy_cloud_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
chunked_transfer_encoding on;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 600s;
proxy_connect_timeout 600s;
proxy_send_timeout 600s;
}
# Import-Endpoint (sehr große Uploads)
location /api/import {
proxy_pass $appflowy_cloud_backend;
proxy_set_header X-Request-Id $request_id;
proxy_set_header Host $http_host;
proxy_read_timeout 600s;
proxy_connect_timeout 600s;
proxy_send_timeout 600s;
proxy_request_buffering off;
proxy_buffering off;
proxy_cache off;
client_max_body_size 2G;
}
}
# Admin Frontend
location /console {
proxy_pass $admin_frontend_backend;
proxy_set_header X-Scheme $scheme;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 60s;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
}
# Root zur Admin-Konsole umleiten
location = / {
return 301 /console;
}
# Health Check
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
}
}
Docker Compose-Datei erstellen
sudo nano /opt/appflowy/compose.yml
Füg folgenden Inhalt ein:
services:
nginx:
image: nginx:1.29.2
restart: unless-stopped
ports:
- "8080:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- appflowy_cloud
- gotrue
- admin_frontend
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
appflowy_cloud:
image: appflowyinc/appflowy_cloud:0.9.149
restart: unless-stopped
environment:
- RUST_LOG=info
- APPFLOWY_BASE_URL=${APPFLOWY_BASE_URL}
- APPFLOWY_ENVIRONMENT=production
- APPFLOWY_DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
- APPFLOWY_REDIS_URI=redis://redis:6379
- APPFLOWY_GOTRUE_JWT_SECRET=${JWT_SECRET}
- APPFLOWY_GOTRUE_BASE_URL=http://gotrue:9999
- APPFLOWY_S3_CREATE_BUCKET=true
- APPFLOWY_S3_USE_MINIO=true
- APPFLOWY_S3_MINIO_URL=http://minio:9000
- APPFLOWY_S3_ACCESS_KEY=${MINIO_USER}
- APPFLOWY_S3_SECRET_KEY=${MINIO_PASSWORD}
- APPFLOWY_S3_BUCKET=appflowy
- APPFLOWY_S3_REGION=us-east-1
- APPFLOWY_MAILER_SMTP_HOST=${SMTP_HOST:-smtp.gmail.com}
- APPFLOWY_MAILER_SMTP_PORT=${SMTP_PORT:-587}
- APPFLOWY_MAILER_SMTP_USERNAME=${SMTP_USER:-notify@appflowy.io}
- APPFLOWY_MAILER_SMTP_EMAIL=${SMTP_USER:-notify@appflowy.io}
- APPFLOWY_MAILER_SMTP_PASSWORD=${SMTP_PASS:-email_sender_password}
- APPFLOWY_MAILER_SMTP_TLS_KIND=none
- APPFLOWY_ACCESS_CONTROL=true
- APPFLOWY_DATABASE_MAX_CONNECTIONS=40
- AI_SERVER_HOST=ai
- AI_SERVER_PORT=5001
- AI_OPENAI_API_KEY=${OPENAI_API_KEY:-}
- APPFLOWY_WEB_URL=http://appflowy_web:3000
healthcheck:
test: "curl --fail http://127.0.0.1:8000/api/health || exit 1"
interval: 5s
timeout: 5s
retries: 12
depends_on:
gotrue:
condition: service_healthy
postgres:
condition: service_healthy
redis:
condition: service_started
gotrue:
image: appflowyinc/gotrue:0.9.149
restart: unless-stopped
environment:
- GOTRUE_API_HOST=0.0.0.0
- GOTRUE_API_PORT=9999
- PORT=9999
- GOTRUE_ADMIN_EMAIL=${ADMIN_EMAIL:-admin@example.com}
- GOTRUE_ADMIN_PASSWORD=${ADMIN_PASSWORD}
- GOTRUE_DISABLE_SIGNUP=false
- GOTRUE_SITE_URL=appflowy-flutter://
- GOTRUE_URI_ALLOW_LIST=**
- GOTRUE_JWT_SECRET=${JWT_SECRET}
- GOTRUE_JWT_EXP=7200
- GOTRUE_DB_DRIVER=postgres
- API_EXTERNAL_URL=${APPFLOWY_BASE_URL}/gotrue
- DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?search_path=auth
- GOTRUE_SMTP_HOST=${SMTP_HOST}
- GOTRUE_SMTP_PORT=${SMTP_PORT:-587}
- GOTRUE_SMTP_USER=${SMTP_USER}
- GOTRUE_SMTP_PASS=${SMTP_PASS}
- GOTRUE_MAILER_URLPATHS_CONFIRMATION=/verify
- GOTRUE_MAILER_URLPATHS_INVITE=/verify
- GOTRUE_MAILER_URLPATHS_RECOVERY=/verify
- GOTRUE_MAILER_URLPATHS_EMAIL_CHANGE=/verify
- GOTRUE_SMTP_ADMIN_EMAIL=${SMTP_ADMIN_EMAIL}
- GOTRUE_SMTP_MAX_FREQUENCY=1ns
- GOTRUE_RATE_LIMIT_EMAIL_SENT=100
- GOTRUE_MAILER_AUTOCONFIRM=true
depends_on:
postgres:
condition: service_healthy
healthcheck:
test: "curl --fail http://127.0.0.1:9999/health || exit 1"
interval: 5s
timeout: 5s
retries: 12
admin_frontend:
image: appflowyinc/admin_frontend:0.9.149
restart: unless-stopped
environment:
- APPFLOWY_GOTRUE_BASE_URL=${APPFLOWY_BASE_URL}/gotrue
- APPFLOWY_BASE_URL=${APPFLOWY_BASE_URL}
depends_on:
gotrue:
condition: service_healthy
appflowy_cloud:
condition: service_started
appflowy_web:
image: appflowyinc/appflowy_web:0.9.132
restart: unless-stopped
environment:
- APPFLOWY_BASE_URL=${APPFLOWY_BASE_URL}
- APPFLOWY_GOTRUE_BASE_URL=${APPFLOWY_BASE_URL}/gotrue
- APPFLOWY_WS_BASE_URL=${APPFLOWY_BASE_URL}/ws/v2
depends_on:
- appflowy_cloud
ai:
image: appflowyinc/appflowy_ai:0.9.149
restart: unless-stopped
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY:-}
- AI_SERVER_PORT=5001
- DEFAULT_AI_MODEL=gpt-4.1-mini
- DEFAULT_AI_COMPLETION_MODEL=gpt-4.1-mini
- AI_APPFLOWY_HOST=http://appflowy_web:3000
- APPFLOWY_GOTRUE_JWT_SECRET=${JWT_SECRET}
- AZURE_OPENAI_API_KEY=${AZURE_OPENAI_API_KEY:-}
- AZURE_OPENAI_ENDPOINT=${AZURE_OPENAI_ENDPOINT:-}
- AZURE_OPENAI_API_VERSION=${AZURE_OPENAI_API_VERSION:-}
- APPFLOWY_S3_ACCESS_KEY=${MINIO_USER}
- APPFLOWY_S3_SECRET_KEY=${MINIO_PASSWORD}
- APPFLOWY_S3_BUCKET=appflowy
- APPFLOWY_S3_REGION=us-east-1
- AI_DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
- AI_REDIS_URL=redis://redis:6379
- AI_USE_MINIO=true
- AI_MINIO_URL=http://minio:9000
depends_on:
postgres:
condition: service_healthy
appflowy_worker:
image: appflowyinc/appflowy_worker:0.9.149
restart: unless-stopped
environment:
- RUST_LOG=info
- APPFLOWY_ENVIRONMENT=production
- APPFLOWY_WORKER_ENVIRONMENT=production
- APPFLOWY_WORKER_REDIS_URL=redis://redis:6379
- APPFLOWY_WORKER_DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
- APPFLOWY_WORKER_DATABASE_NAME=${POSTGRES_DB}
- APPFLOWY_WORKER_IMPORT_TICK_INTERVAL=30
- APPFLOWY_S3_USE_MINIO=true
- APPFLOWY_S3_MINIO_URL=http://minio:9000
- APPFLOWY_S3_ACCESS_KEY=${MINIO_USER}
- APPFLOWY_S3_SECRET_KEY=${MINIO_PASSWORD}
- APPFLOWY_S3_BUCKET=appflowy
- APPFLOWY_S3_REGION=us-east-1
- APPFLOWY_MAILER_SMTP_HOST=${SMTP_HOST:-smtp.gmail.com}
- APPFLOWY_MAILER_SMTP_PORT=${SMTP_PORT:-587}
- APPFLOWY_MAILER_SMTP_USERNAME=${SMTP_USER:-notify@appflowy.io}
- APPFLOWY_MAILER_SMTP_EMAIL=${SMTP_USER:-notify@appflowy.io}
- APPFLOWY_MAILER_SMTP_PASSWORD=${SMTP_PASS:-email_sender_password}
- APPFLOWY_MAILER_SMTP_TLS_KIND=none
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
minio:
image: minio/minio:RELEASE.2025-09-07T16-13-09Z
restart: unless-stopped
environment:
- MINIO_ROOT_USER=${MINIO_USER}
- MINIO_ROOT_PASSWORD=${MINIO_PASSWORD}
command: server /data --console-address ":9001"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
volumes:
- minio_data:/data
postgres:
image: pgvector/pgvector:pg16
restart: unless-stopped
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_HOST=postgres
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "${POSTGRES_USER}", "-d", "${POSTGRES_DB}"]
interval: 5s
timeout: 5s
retries: 12
redis:
image: redis:8.2.2-alpine3.22
restart: unless-stopped
volumes:
- redis_data:/data
healthcheck:
test: ["CMD-SHELL", "redis-cli -h localhost -p 6379 ping"]
interval: 5s
timeout: 5s
retries: 3
volumes:
minio_data:
postgres_data:
redis_data:
Die Image-Versionen oben waren zum Zeitpunkt des Schreibens aktuell. Prüf Docker Hub für die neuesten stabilen AppFlowy-Versionen.
Jetzt alle Services starten:
cd /opt/appflowy
sudo docker compose up -d
Damit werden alle Images heruntergeladen und der komplette AppFlowy Cloud-Stack gestartet. Der erste Start dauert ein paar Minuten, während PostgreSQL initialisiert und alle Health Checks durchlaufen. Du kannst den Fortschritt überwachen mit:
sudo docker compose logs -f
Warte, bis die Haupt-Services als healthy angezeigt werden, bevor du weitermachst. Du kannst das prüfen mit:
sudo docker compose ps
Schritt 7: Auf deine selbst gehostete AppFlowy-Instanz zugreifen
Sobald alle Services laufen, ist deine AppFlowy-Admin-Konsole unter https://yourdomain.com/console erreichbar. Bei temporärem HTTP-Setup öffne http://your-server-ip:8080/console.
Melde dich im Admin-Panel mit den Zugangsdaten aus deiner .env-Datei an:
- Email: Der
ADMIN_EMAIL-Wert (Standard:admin@example.com) - Password: Der
ADMIN_PASSWORD-Wert, den du konfiguriert hast
Um AppFlowy als Workspace zu nutzen, lad die AppFlowy Desktop- oder Mobile-App herunter und gib beim Setup deine Server-URL (https://yourdomain.com) an.
Sicherheitsempfehlungen
Ein öffentlicher Server sollte immer gut abgesichert sein:
- Nutze starke, einzigartige Passwörter für alle Services in deiner
.env-Datei. - HTTPS wird bereits automatisch von Caddy über Let's Encrypt gehandhabt.
- Spiel regelmäßig System-Updates und Sicherheitspatches ein mit
sudo apt-get update && sudo apt-get upgrade -y. - Prüf deine Firewall-Konfiguration regelmäßig mit
sudo ufw status verbose. - Richte regelmäßige Backups deiner PostgreSQL-Datenbank und des MinIO Object Storage ein. Schau dir unseren Guide zum Backup und Restore von Postgres via SSH-Tunnel für mehr Details an.
- Installiere Tools wie Fail2ban für zusätzlichen Brute-Force-Schutz.
AppFlowy-Installation aktualisieren
Wenn du AppFlowy aktualisieren willst, prüf zuerst Docker Hub für die neuesten Image-Versionen. Aktualisiere die Version-Tags in deiner compose.yml, dann führ aus:
cd /opt/appflowy
sudo docker compose pull
sudo docker compose up -d
Docker lädt die aktualisierten Images und ersetzt deine aktuellen Container. Deine Daten liegen in Docker Volumes und bleiben bei Updates erhalten.
Kostenvergleich mit anderen Anbietern
AppFlowy Cloud läuft mit mehreren Services und profitiert von einem Server mit mindestens 4 GB RAM:
| Provider | vCPU Cores | RAM | Disk | Geschätzte monatliche Kosten | Hinweise |
|---|---|---|---|---|---|
| Sliplane | 4 | 8 GB | 160 GB | €44 | Abrechnung pro Server |
| Render | 4 | 8 GB | 80 GB | ~$85–$120 | Pro-Plan nötig |
| Fly.io | 4 | 8 GB | 40 GB | ~$60–$80 | VM + Volumes |
| Railway | 4 | 8 GB | 40 GB | ~$50–$100 | Nutzungsbasiert |
Fazit
Du hast jetzt eine vollständig selbst gehostete AppFlowy Cloud-Instanz auf Hetzner mit Docker, automatischem HTTPS über Caddy und allen unterstützenden Services für einen kompletten kollaborativen Workspace. Verbinde dich mit der Desktop- oder Mobile-App und organisiere deine Projekte mit voller Datenhoheit.