Erste Schritte
Installation
Annuva mit Docker Compose starten, einen Reverse Proxy davorsetzen und die Datenbank wählen.
Voraussetzungen
- Ein Server oder Rechner mit Docker und Docker Compose
- Für den Zugriff aus dem Internet: eine Domain und ein Reverse Proxy mit TLS (z. B. Nginx Proxy Manager, Caddy, Traefik oder nginx)
Das Image ghcr.io/dasred/annuva-app:latest wird für linux/amd64 und linux/arm64 gebaut und läuft damit auch auf einem Raspberry Pi oder einem ARM-Server.
Schnellstart mit Docker Compose
Leg einen Ordner an, speichere die folgende Datei als compose.yaml und pass sie bei Bedarf an:
services:
annuva:
image: ghcr.io/dasred/annuva-app:latest
container_name: annuva
restart: unless-stopped
ports:
- "40100:40100"
volumes:
- ./data:/var/www/data
environment:
# Optional – siehe "Konfiguration"
DEFAULT_LOCALE: de
SMTP_HOST: smtp.example.com
SMTP_USER: annuva@example.com
SMTP_PASSWORD: secret
MAIL_FROM: annuva@example.comDer Container läuft als Benutzer node (uid 1000); der Datenordner muss für ihn beschreibbar sein:
mkdir -p data && sudo chown 1000:1000 data
docker compose up -dBeim ersten Start schreibt Annuva ein Setup-Token ins Log:
docker compose logs annuva | grep -A1 "Setup required"Öffne http://localhost:40100 (oder die Adresse deines Servers), gib das Token ein und folge dem Setup-Assistenten.
Reverse Proxy und TLS
Für alles jenseits von localhost gehört ein Reverse Proxy mit TLS vor den Container, der deine Domain an Port 40100 weiterleitet. Annuva liest seine öffentliche URL aus den Headern X-Forwarded-Host und X-Forwarded-Proto und funktioniert damit unter jeder Domain ohne Konfiguration.
Beispiel für Caddy:
annuva.example.com {
reverse_proxy localhost:40100
}Beispiel für nginx:
server {
listen 443 ssl http2;
server_name annuva.example.com;
location / {
proxy_pass http://127.0.0.1:40100;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 25m;
}
}Mit dem Nginx Proxy Manager legst du einen Proxy Host für deine Domain an, der auf http://<server>:40100 zeigt, aktivierst Force SSL und HTTP/2 und forderst ein Let's-Encrypt-Zertifikat an.
Erhöhe das Upload-Limit deines Proxys, wenn du Belege oder Angebote hochladen willst, die größer als dessen Standard sind (Annuva selbst akzeptiert 20 MB, siehe
UPLOAD_MAX_SIZE).
MySQL oder PostgreSQL
Für einen einzelnen Freelancer ist SQLite ideal. Wenn du lieber einen Datenbankserver nutzt, setze DB_DRIVER und die Verbindung – zum Beispiel mit PostgreSQL:
services:
annuva:
image: ghcr.io/dasred/annuva-app:latest
restart: unless-stopped
ports:
- "40100:40100"
volumes:
- ./data:/var/www/data
environment:
DB_DRIVER: postgres
DB_HOST: db
DB_NAME: annuva
DB_USER: annuva
DB_PASSWORD: change-me
depends_on:
- db
db:
image: postgres:17-alpine
restart: unless-stopped
volumes:
- ./postgres:/var/lib/postgresql/data
environment:
POSTGRES_DB: annuva
POSTGRES_USER: annuva
POSTGRES_PASSWORD: change-meStatt der einzelnen DB_*-Werte geht auch eine DATABASE_URL wie postgres://annuva:change-me@db/annuva. Der Datenordner wird trotzdem für hochgeladene Dateien, Rechnungs-PDFs und erzeugte Secrets gebraucht.
Ohne Compose
docker run -d --name annuva --restart unless-stopped \
-p 40100:40100 \
-v "$(pwd)/data:/var/www/data" \
ghcr.io/dasred/annuva-app:latestHealth Check
Der Container meldet seinen Zustand unter /api/health (Datenbankverbindung und Version); Docker nutzt das als Health Check.