| .gitea/ISSUE_TEMPLATE | ||
| apache | ||
| migrations | ||
| public | ||
| scripts | ||
| src | ||
| tests | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| activate.sh | ||
| BERICHTE.md | ||
| Changes.md | ||
| CLAUDE.md | ||
| composer.json | ||
| docker-compose.yml | ||
| docker-entrypoint.sh | ||
| Dockerfile | ||
| install.sh | ||
| LICENSE.md | ||
| README.md | ||
| steuerkram.service | ||
Achtung! work in progress – es kann zu BREAKING CHANGES kommen. Ich ändere diese Phase der schnellen Änderungen erst, wenn ich mit meiner Software selber produktiv gehe.
Steuerkram
Self-hosted Buchhaltungs- und Steueranwendung für deutsche Freiberufler und Kleinunternehmer. Entwickelt als datensouveräne Alternative zu SaaS-Diensten.
Funktionsumfang
- Kontenrahmen SKR03 – DATEV-konformer SKR03 mit 157 Systemkonten (Klassen 0, 1, 2, 4, 8); zugeschnitten auf EÜR-Buchhalter ohne Bilanzierung (CRUD)
- Belegverwaltung – Upload von PDF, PNG, TIFF und ZUGFeRD-XML; SHA-256 Integritätsprüfung
- Buchungen – EÜR-Buchungsmodell (Einnahme/Ausgabe) mit Kategorie- und Zahlungskonto; GoBD-konforme Trigger verhindern nachträgliche Manipulation
- Kundenverwaltung – CRUD
- Ausgangsrechnungen – DIN 5008 Layout, PDF-Export via mPDF
- UStVA – Kennzahlen-Berechnung aus Buchungen, ELSTER XML-Export
- EÜR – Jahresauswertung mit PDF-Export
- Einstellungen – Firmendaten, Logo, ELSTER-Steuernummer
- Benutzerverwaltung – Benutzer anlegen, bearbeiten, deaktivieren und löschen; session-basierte Authentifizierung mit 24 h Timeout
Tech Stack
Dieses Projekt wurden mit Unterstützung von Claude Code entwickelt.
| Schicht | Technologie |
|---|---|
| Webserver | Apache 2.4 |
| Backend | PHP 8.3 (MVC, kein Framework) |
| Datenbank | MariaDB 11 |
| PDF-Generierung | mPDF 8.x |
| Frontend | HTML, CSS, JavaScript (keine Bibliotheken) |
| Deployment | Docker / Docker Compose |
Voraussetzungen
- Docker ≥ 24
- Docker Compose ≥ 2.20 (in neueren Docker-Versionen enthalten)
- Git
Installation
Automatische Installation
Das Script install.sh übernimmt die gesamte Installation: es erkennt die Linux-Distribution, installiert git, curl und Docker, klont das Repository in das gewünschte Verzeichnis und legt die .env-Datei an.
Das Script muss vor dem Klonen des Repositories heruntergeladen werden – es erledigt das Klonen selbst:
curl -fsSL https://codeberg.org/fds2610/Steuerkram/raw/branch/main/install.sh -o install.sh
sudo bash install.sh
Das Script muss als root ausgeführt werden, da es Pakete installiert und ggf. den Docker-Dienst aktiviert. Mit
sudo bash install.shfunktioniert das ohne dauerhaft als root angemeldet zu sein.
Nach der Installation die .env-Datei im gewählten Installationsverzeichnis anpassen (siehe Hinweis am Ende des Scripts) und anschließend die Container starten:
cd /opt/Steuerkram # oder das gewählte Verzeichnis
docker compose up -d
Manuelle Installation
1. Repository klonen
git clone <repository-url> steuerkram
cd steuerkram
2. Konfiguration anpassen
Kopiere .env.example nach .env und passe die Werte an:
cp .env.example .env
DB_PASS=sicheres-passwort # Datenbankpasswort – in docker-compose.yml spiegeln
APP_SECRET=zufaelliger-string # Zufälligen langen String eintragen (für Sessions)
Außerdem in docker-compose.yml das MARIADB_PASSWORD im db-Service auf denselben Wert wie DB_PASS setzen.
3. Container starten
docker compose up -d
Beim ersten Start werden automatisch:
- die Datenbank initialisiert (
migrations/001_initial_schema.sql) - der SKR03-Kontenrahmen eingespielt (
migrations/002_seed_skr03.sql) - das Docker-Image mit PHP-Abhängigkeiten (mPDF) gebaut
4. Anwendung aufrufen
http://localhost:8080
Beim ersten Aufruf erscheint die Ersteinrichtung: dort den ersten Benutzer-Account anlegen. Danach ist die Anwendung passwortgeschützt.
Weitere Benutzer können nach dem Login unter Benutzer in der Seitenleiste verwaltet werden.
5. KI-Beleganalyse einrichten (optional)
Die KI-gestützte Belegerkennung ist standardmäßig deaktiviert. Sie kann unter Einstellungen → KI-Kontierungsvorschlag aktiviert werden, sobald ein LLM erreichbar ist.
Option A – Lokales Ollama (kein API-Schlüssel nötig, aber hoher Ressourcenbedarf):
ollama pull mistral # oder llama3.2 etc.
In .env ist keine weitere Konfiguration nötig – die App erkennt Ollama auf localhost:11434 automatisch. Modell und URL können optional überschrieben werden:
OLLAMA_URL=http://localhost:11434
OLLAMA_MODEL=mistral
Option B – Remote-API (OpenAI-kompatibel, z. B. OpenAI, OpenRouter, LM Studio):
LLM_API_URL=https://api.openai.com/v1
LLM_API_KEY=sk-...
LLM_MODEL=gpt-4o-mini
Hinweis: Die Ergebnisqualität hängt stark vom gewählten Modell ab. Tests mit
mistral(lokal via Ollama) lieferten bisher mäßige Ergebnisse.
6. Firmendaten hinterlegen
Nach dem ersten Login unter Einstellungen Firmendaten, Logo und ELSTER-Steuernummer eintragen. Diese Angaben erscheinen auf Ausgangsrechnungen und im EÜR-Export.
Port ändern
Der Standard-Port ist 8080. Um ihn zu ändern, passe in docker-compose.yml die ports-Zeile an:
ports:
- "9090:80" # Beispiel: Port 9090 auf dem Host
Datenpersistenz
| Pfad | Inhalt |
|---|---|
./data/mariadb/ |
MariaDB-Datenbankdateien |
Docker Volume uploads |
Hochgeladene Belege |
Beide Pfade liegen außerhalb des Containers und bleiben bei docker compose down erhalten.
Systemd-Service einrichten
Damit Steuerkram automatisch beim Systemstart startet und als Dienst verwaltet werden kann, liegt im Repository die Datei steuerkram.service.
1. Service-Datei installieren
sudo cp steuerkram.service /etc/systemd/system/steuerkram.service
Die Datei setzt WorkingDirectory=/opt/Steuerkram voraus. Falls das Repository in ein anderes Verzeichnis geklont wurde, den Pfad in der Service-Datei anpassen:
sudo nano /etc/systemd/system/steuerkram.service
# WorkingDirectory= auf das tatsächliche Installationsverzeichnis setzen
2. Service aktivieren und starten
sudo systemctl daemon-reload
sudo systemctl enable steuerkram # automatisch beim Systemstart
sudo systemctl start steuerkram
3. Status prüfen
sudo systemctl status steuerkram
journalctl -u steuerkram -f # Live-Log inkl. Migrations-Ausgabe
Wichtige Service-Befehle
| Befehl | Wirkung |
|---|---|
sudo systemctl start steuerkram |
Container starten |
sudo systemctl stop steuerkram |
Container stoppen |
sudo systemctl restart steuerkram |
Neustart (z.B. nach Update) |
sudo systemctl status steuerkram |
Aktueller Status |
Backup
bash scripts/backup.sh
Das Skript erstellt ein Dump der Datenbank sowie ein Archiv der Uploads im Verzeichnis backups/.
Update
Datenbankmigrationen werden automatisch beim nächsten Container-Start eingespielt – kein manueller Eingriff nötig. Das Script scripts/migrate.php prüft beim Start, welche Migrations-Dateien noch nicht angewendet wurden, und führt sie der Reihe nach aus.
Ohne Systemd-Service (manuell)
git pull
docker compose up -d --build
Der Web-Container führt scripts/migrate.php automatisch beim Start aus. Die Ausgabe ist im Container-Log sichtbar:
docker compose logs web
Mit Systemd-Service
git pull
docker compose build
sudo systemctl restart steuerkram
Migrations-Ausgabe im Journal:
journalctl -u steuerkram -f
GoBD-Hinweise
- Gebuchte Sätze können nicht geändert oder gelöscht werden (MariaDB
BEFORE UPDATE/DELETETrigger). - Korrekturen erfolgen ausschließlich über Stornobuchungen.
- Jeder hochgeladene Beleg erhält einen SHA-256 Hash zur Integritätsprüfung.
Berechnungslogik UStVA und EÜR
Detaillierte Informationen darüber, welche Buchungsattribute und Konten in welche Positionen der UStVA (ELSTER-Kennzahlen) bzw. der EÜR einfließen, sind in BERICHTE.md dokumentiert.
Support
Issues können im Codeberg-Repo gemeldet werden. Mit dem Label automate werden sie automatisch verarbeitet.
Automatisierter Agent
Ein stündlich per Cron gestarteter Agent (Claude CLI) verarbeitet Issues mit dem Label automate nacheinander – mit Lockfile-Schutz gegen Parallelläufe. Mehrere offene Tickets werden in einer Sitzung sequenziell abgearbeitet.
Ablauf je Ticket
- Issue-Body und alle Kommentare laden (inkl. Diskussionsergebnisse früherer Rückfragen)
- Relevante Codebase-Dateien lesen
- Klarheitscheck: Sind die Anforderungen eindeutig? Falls nicht → Rückfragen als Kommentar posten,
automate-Label entfernen, warten - Analyse mit Claude Opus (Ursache, Lösungsplan, Risiken)
- Lösung implementieren
- Tests ausführen (
php tests/run.php), Fehler beheben - Commit & Push:
Fix #NR: Kurzbeschreibung - Kommentar mit Zusammenfassung im Issue posten
- Labels aktualisieren, Issue offen lassen
Label-Ausgänge
| Ergebnis | automate |
gesetztes Label |
|---|---|---|
| Erfolgreich umgesetzt | entfernt | testing |
| Unklar / Rückfrage offen | entfernt | (keins) |
| Zu riskant / abgelehnt | entfernt | abgelehnt |
Lizenz
Dieses Projekt steht unter der MIT-Lizenz – siehe LICENSE.md für Details.