docs / getting-started / installation.md
Installation
Diese Anleitung bringt eine selbst gehostete entrytwo-Instanz zum Laufen.
entrytwo ist KI-native doppelte Buchführung mit Git-ähnlichem Datenmodell. Die KI bucht echte Journalbuchungen bei hoher Sicherheit. Vollständige Historie, Branches, Blame. Self-hosted.
Betrieb: Die meisten Produktions-Setups nutzen einen VPS mit Docker und HTTPS. Du kannst genauso lokal installieren und produktiv nutzen (z. B. auf dem Mac): dieselbe volle App, wie klassische Buchhaltungssoftware ohne Cloud. Läuft auf deinem VPS oder lokal.
Lass die KI die Installation machen
Kein Terminal-Mensch? Du kannst entrytwo trotzdem installieren. Gib einem KI-Coding-Agenten diese Seite (und das Repo) und bitte ihn, die Installation für dich zu erledigen — z. B. Claude Code, OpenClaw, Hermes, Cursor oder ein vergleichbares Tool, das Befehle auf deinem Rechner oder VPS ausführen kann. Sag ihm dein Ziel (lokal Mac vs. VPS + Domain), schick Fehlermeldungen zurück, wenn etwas scheitert, und teile Secrets (Passwörter, API-Keys) nicht in Chats, denen du nicht vertraust. Die Schritte unten bleiben die Quelle der Wahrheit; der Agent führt dich nur durch. Kanonische Agent-Dateien: llms.txt und SKILL.md.
Voraussetzungen
Wähle einen der zwei unterstützten Installationswege:
Weg A — Git / npm (klonen und lokal bauen)
- Node.js 22.12 oder neuer, auf dem aktuellen 22.x (Prisma-Engines lehnen früheres 22.x ab; ein pauschales
>= 22reicht nicht) - npm, Git und
openssl - PostgreSQL 16 (lokal oder per Docker)
- Optional, aber empfohlen: Docker & Docker Compose (für Postgres)
Node von der offiziellen nodejs.org Download-/Versionsmanager-Seite installieren, dann prüfen:
node --version # erwartet v22.12.0 oder ein späteres 22.x (Pin: v22.23.4)
Ohne nvm: Diese Befehle installieren das offizielle 22.23.4-Binary in
deinem Home-Verzeichnis, prüfen die Prüfsumme und ergänzen PATH im aktuellen
Terminal. Das entspricht dem exakten .nvmrc-Pin des Repositorys. 22.12.0 ist
das Minimum, nicht der empfohlene Patchstand. Unterstützt werden Debian/Ubuntu
(glibc) x64/ARM64 und macOS Intel/Apple Silicon; Alpine/musl braucht einen
anderen Build. Benötigt curl, tar und sha256sum (Linux) oder shasum
(macOS). Vor npm ci ausführen:
NODE_VERSION=22.23.4
case "$(uname -s)/$(uname -m)" in
Linux/x86_64) NODE_PLATFORM=linux-x64 ;;
Linux/aarch64|Linux/arm64) NODE_PLATFORM=linux-arm64 ;;
Darwin/x86_64) NODE_PLATFORM=darwin-x64 ;;
Darwin/arm64) NODE_PLATFORM=darwin-arm64 ;;
*) echo "Unsupported platform; use nodejs.org/en/download" >&2; exit 1 ;;
esac
NODE_HOME="$HOME/.local/share/node-v$NODE_VERSION-$NODE_PLATFORM"
(
set -eu
NODE_TMP="$(mktemp -d)"
trap 'rm -rf "$NODE_TMP"' EXIT
cd "$NODE_TMP"
ARCHIVE="node-v$NODE_VERSION-$NODE_PLATFORM.tar.gz"
curl -fLO "https://nodejs.org/dist/v$NODE_VERSION/$ARCHIVE"
curl -fLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt"
grep " $ARCHIVE$" SHASUMS256.txt > CHECKSUM
if command -v sha256sum >/dev/null 2>&1; then
sha256sum -c CHECKSUM
else
shasum -a 256 -c CHECKSUM
fi
mkdir -p "$NODE_HOME"
tar -xzf "$ARCHIVE" --strip-components=1 -C "$NODE_HOME"
) && export PATH="$NODE_HOME/bin:$PATH" && node --version
Für neue Terminals export PATH="<installierter NODE_HOME-Pfad>/bin:$PATH"
in die eigene ~/.bashrc (Linux bash) oder ~/.zshrc (macOS zsh) eintragen
oder manuell wiederholen. Die Befehle ändern keine Shell-Profile und brauchen
kein sudo. Mit bereits installiertem nvm stattdessen im Clone
nvm install && nvm use ausführen.
Weg B — Docker Compose pull (veröffentlichtes Image, ohne Clone)
- Docker Engine oder Docker Desktop mit Docker Compose v2
curlundopensslzum Herunterladen und Erzeugen von Secrets
Für Docker werden Node.js, PostgreSQL und Git auf dem Host nicht benötigt.
Optional, aber nützlich:
- Domain + Reverse-Proxy (Caddy, Nginx, Traefik) für HTTPS
- SMTP für Magic-Link-Login (und Einladungs-E-Mails)
- Google- und/oder Microsoft-Entra-ID-OAuth-Apps für Mitarbeiter-Login
- LLM-API-Key (OpenAI, Anthropic, xAI usw.)
Weg A: Git / npm (Entwicklung und Anpassungen)
Das Quellcode-Repository ist öffentlich.
Es gibt keine zusätzliche Unterverzeichnisebene entrytwo_v1 im Clone.
git clone https://github.com/felixkrusch/entrytwo.git
cd entrytwo
node --version # erwartet v22.12.0 oder ein späteres 22.x
cp .env.example .env
npm ci
Wenn npm oder Prisma danach ein Update- oder Security-Banner zeigt: Lockfile-Versionen
behalten. npm audit fix oder npm audit fix --force nicht als Installationsschritt
ausführen.
Setze in .env DATABASE_URL, AUTH_SECRET, ENCRYPTION_KEY,
JOB_RUNNER_SECRET und deinen LLM-Anbieter/Key. Erzeuge jedes Secret unabhängig
mit openssl rand -hex 32 (Werte nicht wiederverwenden, nicht in Agent-Chats
einfügen). ENCRYPTION_KEY muss genau 64 Hex-Zeichen haben.
openssl rand -base64 48 ist für AUTH_SECRET und JOB_RUNNER_SECRET ebenfalls
gültig (≥ 32 Zeichen), aber eine Konvention verwenden: hex 32 für alle.
xAI-Beispiel (Modell-ID aus deinem xAI-Konto, nicht raten):
NEXT_LLM_PROVIDER=xai
NEXT_LLM_MODEL=<Modell-ID aus der xAI-Konsole>
XAI_API_KEY=<dein Key>
Bewahre den ursprünglichen ENCRYPTION_KEY für Wiederherstellungen auf. Falls noch
keine lokale Datenbank läuft, passt dieses Beispiel zu DATABASE_URL aus der Vorlage:
docker run --name entrytwo-dev-db \
-e POSTGRES_USER=entrytwo \
-e POSTGRES_PASSWORD=entrytwo_dev_password \
-e POSTGRES_DB=entrytwo \
-p 127.0.0.1:5432:5432 \
-v entrytwo_dev_postgres:/var/lib/postgresql/data \
-d postgres:16-alpine
i=0
until docker exec entrytwo-dev-db pg_isready -U entrytwo -d entrytwo; do
i=$((i + 1))
if [ "$i" -ge 30 ]; then
echo "PostgreSQL wurde nicht bereit" >&2
exit 1
fi
sleep 1
done
Diese Zugangsdaten sind ausschließlich für lokale Entwicklung. Bei einer
vorhandenen Datenbank den Beispielcontainer (und die pg_isready-Schleife)
überspringen und DATABASE_URL anpassen. Der mitgelieferte Compose-db-Service
veröffentlicht keinen Host-Port; docker compose up -d db allein reicht daher für
eine native Node.js-App nicht. Warte auf die Bereitschaft von PostgreSQL und führe
dann aus:
npx prisma generate
npx prisma migrate deploy
mkdir -p .data/files .data/backups
npm run dev
Öffne http://localhost:3000, lege den ersten Admin an und schließe das
Firmen-Onboarding ab; dabei wird der Kontenplan angelegt. Der Sofort-E-Mail-Login
funktioniert nur in der Entwicklung. Für Hintergrundjobs starte in einem zweiten
Terminal node --env-file=.env scripts/job-worker.mjs. Echte Rechnungs-E-Mails
benötigen SMTP.
Keine echten Installationen seeden. npx prisma db seed leert vorhandene
Anwendungstabellen, bevor Beispieldaten angelegt werden. Nur für wegwerfbare
Entwicklungsdatenbanken verwenden, niemals als Installations- oder Update-Schritt.
prisma migrate dev ist für die Entwicklung von Schemaänderungen; veröffentlichte
Migrationen werden mit migrate deploy angewendet.
Weg B: Docker Compose (veröffentlichte Images)
- Verzeichnis erstellen und öffentliche Installationsdateien herunterladen:
mkdir entrytwo && cd entrytwo
RELEASE_URL=https://github.com/felixkrusch/entrytwo-releases/releases/latest/download
curl -fL "$RELEASE_URL/compose.yaml" -o compose.yaml
curl -fL "$RELEASE_URL/entrytwo.env.example" -o .env.example
- Beispiel-Umgebung kopieren:
umask 077
cp .env.example .env
.envbearbeiten und mindestens setzen:
DATABASE_URL(oder Compose-Defaults nutzen)POSTGRES_PASSWORD(von Compose benötigt; unabhängigopenssl rand -hex 32)AUTH_SECRET– unabhängigopenssl rand -hex 32(≥ 32 Zeichen)ENCRYPTION_KEY– unabhängigopenssl rand -hex 32(genau 64 Hex-Zeichen)JOB_RUNNER_SECRET– unabhängigopenssl rand -hex 32UPDATER_TOKEN– unabhängigopenssl rand -hex 32(für den Updater-Sidecar) -LICENSE_VERIFY_URL=https://entrytwo.com/api/license/verify(später nötig, um einen bezahltenet1.-Key zu aktivieren; die 30-Tage-Testphase braucht keinen Key. Menschen kaufen unter Kaufen; Agenten dürfen Stripe-Checkout nicht abschließen.)- Mindestens einen LLM-Key, wenn du KI/Chat willst. xAI:
NEXT_LLM_PROVIDER=xai,XAI_API_KEY,NEXT_LLM_MODEL= Modell-ID aus deinem xAI-Konto NEXT_LLM_PROVIDERundNEXT_LLM_MODEL
Jedes Secret separat erzeugen, Werte nicht wiederverwenden, nicht in Agent-Chats
einfügen. openssl rand -base64 48 ist für Auth-/Job-/Updater-Secrets ebenfalls
gültig, aber eine Konvention verwenden: hex 32 für alle.
- Stack starten:
docker compose config --quiet
docker compose pull
docker compose up -d
Das startet:
app(Next.js auf Port 3000)db(PostgreSQL)worker(Hintergrundjobs)updater(isolierter Sidecar für signierte Updates – siehe Self-Hosted Updates)redis
-
Migrationen laufen automatisch. Die mitgelieferten Werte für
COSIGN_IDENTITYundUPDATE_MANIFEST_URLbeibehalten. Immer aus dem Installationsverzeichnis heraus starten. Für einen lokalen HTTP-TestAUTH_ALLOW_HTTP=truesetzen; öffentliche Server benötigen HTTPS. -
http://localhost:3000 öffnen
Beim ersten Besuch ohne Admin-Benutzer kannst du das initiale ADMIN-Konto anlegen.
Das Quellcode-Repository ist öffentlich, wird für diese Image-Installation aber
nicht benötigt. App und Updater sind getrennte öffentliche Container-Images;
ein GitHub-Login ist nicht erforderlich. Port 3000 ist standardmäßig nur an
127.0.0.1 gebunden. Der Updater hat privilegierten Docker-Socket-Zugriff und
darf nicht öffentlich erreichbar sein.
Auch auf einem Laptop laufen diese Container im Produktionsmodus: vollständiges SMTP/OAuth und TOTP für Administratoren sind erforderlich. Für Rechnungs-E-Mails werden SMTP und der Worker auch dann benötigt, wenn OAuth die Anmeldung übernimmt.
Handler-Modus (ein Compose pro Mandant)
entrytwo ist nicht mandantenfähig. Ein laufender Stack = eine juristische Person.
Wenn du Bücher für mehrere Firmen führst (Kanzlei, Agentur, „Handler“), bekommt jeder Mandant ein eigenes Compose-Projekt:
- Eigenes Verzeichnis (mindestens eigene
.env, Volumes und Backups) - Eigener
COMPOSE_PROJECT_NAME(z. B.entrytwo-acme) - Eigener, an Loopback gebundener Host-Port (
127.0.0.1:3000:3000,127.0.0.1:3001:3000, …) - Eigene Secrets
- Eigene
.etbackup-Dateien — niemals Backup von Firma A in Firma B einspielen
RAM: ≥ 2 GB pro Stack. Chat-Lock für Bulk-Arbeit durch Agenten; vor Massenimport branchen; nie unter 0,85 Confidence buchen; ein Mensch schließt die Periode.
Eine bezahlte Lizenz deckt Installationen für Unternehmen ab, die dir gehören. Fremde Mandanten benötigen eigene Lizenzen. Der öffentliche Quellcode steht unter einer proprietären Source-Available-Lizenz, nicht unter einer Open-Source-Lizenz.
Umgebungsvariablen (die wichtigsten)
.env.example kopieren und ausfüllen:
Erforderlich (lokal oder Produktion)
DATABASE_URLAUTH_SECRET(≥ 32 Zeichen)POSTGRES_PASSWORD(bei Compose)LICENSE_VERIFY_URL—https://entrytwo.com/api/license/verify(Aktivierung bezahlter Keys; Testphase braucht keinen Key)
In Produktion erforderlich (App startet nicht sauber / Health bleibt degraded ohne diese)
ENCRYPTION_KEY(64 Hex-Zeichen)JOB_RUNNER_SECRETAUTH_URL(öffentliche Origin, z. B.https://books.example.com)AUTH_TRUST_HOST=true(hinter nginx/caddy/traefik)- Mindestens eine echte Anmeldemethode:
- SMTP:
SMTP_HOST,SMTP_USER,SMTP_PASS(idealerweiseSMTP_FROM), und/oder - Google:
GOOGLE_CLIENT_ID+GOOGLE_CLIENT_SECRET, und/oder - Microsoft:
MICROSOFT_ENTRA_ID_ID+MICROSOFT_ENTRA_ID_SECRET(+ Issuer)
- SMTP:
Für den veröffentlichten Docker-Stack erforderlich
UPDATER_TOKEN– Shared Secret für den Updater-Sidecar
Für KI-Funktionen
- LLM-Key +
NEXT_LLM_PROVIDER/NEXT_LLM_MODEL - xAI-Beispiel:
NEXT_LLM_PROVIDER=xai,XAI_API_KEY,NEXT_LLM_MODELauf eine Modell-ID aus deinem xAI-Konto (aus der Konsole kopieren, Version nicht raten)
Für Produktion / Updates
UPDATE_MANIFEST_URL– zeigt auf dein signiertes Release-Manifest- Cosign-Einstellungen (
COSIGN_IDENTITY,COSIGN_PUBLIC_KEYusw.) STRIPE_WEBHOOK_SECRET/ PayPal-Secrets (bei Processor-Feeds)
Vollständige Liste in der App-.env.example. Auth-Go-Live: VPS-Auth-Install.md.
Manuelles Postgres (ohne Docker)
- Datenbank anlegen:
CREATE USER entrytwo WITH PASSWORD 'entrytwo_dev_password';
CREATE DATABASE entrytwo OWNER entrytwo;
- In
.envsetzen:
DATABASE_URL="postgresql://entrytwo:entrytwo_dev_password@localhost:5432/entrytwo"
Das SQL als PostgreSQL-Administrator ausführen. Das Passwort dient nur als lokales Entwicklungsbeispiel. Für echte Installationen ein frisches Passwort verwenden. Als Datenbankeigentümer hat die App-Rolle die nötigen Schema-Rechte.
- Im geklonten Repository Abhängigkeiten installieren und Migrationen anwenden:
npm ci
npx prisma generate
npx prisma migrate deploy
mkdir -p .data/files .data/backups
npm run dev
Erster Admin (Bootstrap)
entrytwo ist so gebaut, dass der allererste Benutzer einer frischen Installation ADMIN wird.
- Existiert kein
ADMIN, erlaubt der Anmelde-/Onboarding-Flow die Erstellung (Firma, Sprache, Standard-Kontenplan). - Danach kommen weitere Benutzer nur per Einladung (Admin → Benutzer). Anmeldung mit genau der eingeladenen E-Mail über Google, Microsoft oder Magic Link.
- Rollen:
ADMIN,ACCOUNTANToderVIEWER. - In Produktion muss ADMIN TOTP (2FA) einrichten, bevor die App nutzbar ist.
Siehe Erste Schritte.
Authentifizierung (Kurzüberblick)
| Umgebung | Anmeldung |
|---|---|
| Lokale Entwicklung | Sofort-E-Mail („Weiter“) – kein SMTP nötig |
| Produktion | Magic Link (SMTP) und/oder Google-OAuth und/oder Microsoft Entra ID |
Sofort-E-Mail ist bei NODE_ENV=production deaktiviert. OAuth-Redirect-URIs: {AUTH_URL}/api/auth/callback/google und .../microsoft-entra-id.
Health und grundlegende Prüfung
- App-Health:
GET /api/health - Produktion sollte
"ready": trueundauth.productionReady: truemelden - Nach
docker compose up -dhat der App-Container einen Healthcheck auf diesem Endpoint
Optional: lokaler Git/npm-Smoke (nur frische Installationen)
Nur auf einer brandneuen lokalen npm run dev-Installation verwenden. Legt den
ersten Admin und die Firma an. Nicht gegen eine echte Geschäftsinstanz, einen
Docker-Produktionsstack oder eine Datenbank mit bestehenden Benutzern ausführen.
POST /api/auth/dev liefert in Produktion (NODE_ENV=production) 403,
einschließlich veröffentlichter Docker-Images.
curl --fail-with-body --silent --show-error http://localhost:3000/api/health
node scripts/check-install.mjs http://localhost:3000
# Nur statt Browser-Onboarding, mit den gewünschten Inhaberdaten:
node scripts/check-install.mjs http://localhost:3000 --bootstrap --email you@example.com --company "Meine Firma"
Der Bootstrap-Befehl prüft Entwicklungs-Provider und verweigert Änderungen,
wenn bereits ein Administrator existiert. Er führt Onboarding vor dem Dev-Login
aus, prüft die ADMIN-Session und hält Cookies nur im Speicher, ohne Cookie-Datei.
Die App initialisiert .data/files und .data/backups auch beim Start; der
explizite mkdir-Schritt zeigt das erforderliche Speicherlayout. Agenten finden
llms.txt, AGENTS.md und skills/entrytwo/SKILL.md auch lokal im Clone.
Produktion / VPS (kurz)
Vor dem ersten produktiven Start:
- Secrets —
AUTH_SECRET,ENCRYPTION_KEY,JOB_RUNNER_SECRET,POSTGRES_PASSWORD(pro Installation neu). - Anmeldung — volles SMTP (
SMTP_HOST+USER+PASS) und/oder Google/Microsoft-OAuth. Sofort-E-Mail ist in Produktion aus. - Öffentliche URL —
AUTH_URL=https://deine.domain,AUTH_TRUST_HOST=true. - DNS — A-Record auf die VPS-IP bevor HTTPS erwartet wird. Nach spät gesetztem DNS Reverse-Proxy neu starten (z. B. Caddy).
- Deploy — Weg B:
docker compose pull, danndocker compose up -d; der Entrypoint führt Migrationen aus. Weg A läuft nativ:prisma migrate deploy,npm run build, dannnpm startund separatnode --env-file=.env scripts/job-worker.mjsunter einem Prozessmanager mit derselben Umgebung./api/health→ready: trueprüfen. - Erster Admin — Bootstrap, danach TOTP für ADMIN.
RAM: ≥ 2 GB für einen Stack; ~4 GB, wenn mehrere Installationen auf einem Host laufen.
Installationsdateien und Update-Manifeste: öffentliche Releases. Quellcode: felixkrusch/entrytwo.
Typische nächste Schritte
- Erste Schritte lesen
- Mindestens einen LLM-Key setzen und den Chat testen
- SMTP und/oder OAuth konfigurieren, damit Teammitglieder sich anmelden können
- (Produktion) HTTPS, starke Secrets und die VPS-Auth-Checkliste
- (Später) Bank-Feeds, Updates und Lizenzierung
Siehe auch: