18 KiB
Gardomatic
Gardomatic ist eine mobile, mehrbenutzerfähige Webanwendung zur gemeinsamen Organisation von Gärten. Sie bündelt Pflanzenwissen, Pflanzorte, anstehende Arbeiten, Bilder und ein Gartentagebuch in einer Anwendung.
Das Projekt besteht aus einer JSON-API und einer serverseitig gerenderten Webanwendung in Go. PostgreSQL speichert alle Fachdaten. Das Frontend ist mobile-first, bleibt in den wesentlichen Abläufen ohne JavaScript nutzbar und verwendet htmx für komfortable Teilaktualisierungen. Eine installierbare PWA stellt eine Offline-App-Shell bereit; die eigentlichen Gartendaten bleiben serverseitig.
Projektstatus: Gardomatic wird aktiv entwickelt. Datenmodell, API und Bedienoberfläche können sich noch verändern.
Funktionen
- mehrere voneinander isolierte Gärten pro Benutzer
- gemeinsame Gartenpflege mit Einladungen, Rollen und Berechtigungen
- Verwaltung von Arten, Sorten, konkreten Pflanzen und Pflanzorten
- Pflegehinweise, Kategorien, Tags und Bilder
- Aufgaben mit Fälligkeitsfenstern, Prioritäten und Wiederholungen
- Aufgabenvorlagen pro Art und automatische, idempotente Aufgabenerzeugung
- Aufgabenansicht und Kalenderdarstellung
- Gartentagebuch, Pinnwand und Bildbibliothek
- Benutzerkonto, Aktivierung, Sitzungsverwaltung und Passwortänderung
- administrative Einladung, Anonymisierung und Verwaltung von Benutzern, Rollen und Anwendungseinstellungen inklusive maskierter Laufzeitkonfiguration und Testmailversand
- Kommandozeilenwerkzeug zur Benutzer- und Datenbankadministration
Architektur
Browser
│
▼
Webanwendung :4040 ──► typisierter API-Client
│
▼
JSON-API :4000
│
▼
Storage-Schnittstellen
│
▼
PostgreSQL 16
Die API ist die maßgebliche Sicherheits- und Fachgrenze. Sie verwaltet
Authentifizierung, Sitzungen, Autorisierung, Validierung und Datenzugriff. Die
Webanwendung greift nicht direkt auf die Datenbank zu, sondern leitet das
Session-Cookie eines Requests über lib/client an die API weiter.
Gartenbezogene Browserrouten beginnen mit /g/{gardenID}/, die entsprechenden
API-Ressourcen mit /v1/gardens/{gardenID}/. Ein Garten bildet eine abgeschlossene
Daten- und Berechtigungsgrenze.
Programme
| Programm | Aufgabe | Standardadresse |
|---|---|---|
cmd/api |
JSON-API und Fachlogik | http://localhost:4000 |
cmd/web |
serverseitig gerenderte Weboberfläche | http://localhost:4040 |
cmd/cli |
Administration direkt über PostgreSQL | keine |
Voraussetzungen
Für den vollständigen lokalen Betrieb werden benötigt:
- Go gemäß der Version in
go.mod(aktuell Go 1.26 oder neuer) - PostgreSQL 16
- optional Docker oder Podman mit Compose-Unterstützung
golang-migratefür lokale Migrationen und Integrationstestsmakefür die bereitgestellten Entwicklungsbefehle
Die Compose-Variante bringt PostgreSQL und golang-migrate bereits als Container
mit. Go wird dort nur benötigt, wenn das Administrations-CLI auf dem Host verwendet
werden soll.
Schnellstart mit Compose
-
Konfiguration anlegen und mindestens das Datenbankpasswort ändern:
cp .env.example .envPOSTGRES_PASSWORDund das Passwort inGARDOMATIC_DB_DSNsollten übereinstimmen, damit auch lokale CLI- und Testbefehle dieselbe Datenbank erreichen können..envist von Git ausgeschlossen. -
Datenbank, Migrationen, API und Webanwendung starten:
docker compose up --buildBei Podman kann je nach Installation stattdessen
podman composeoderpodman-composeverwendet werden. -
Einen ersten aktiven Benutzer anlegen. Dazu in einem zweiten Terminal die DSN aus der lokalen
.envsetzen und das CLI starten:export GARDOMATIC_DB_DSN='postgres://gardomatic:change-me@localhost:5432/gardomatic?sslmode=disable' go run ./cmd/cli users create \ --name 'Admin' \ --email 'admin@example.com' \ --role application:admin \ --active \ --generate-passwordDas generierte Passwort wird einmalig ausgegeben.
-
http://localhost:4040 öffnen und anmelden.
Die API-Gesundheitsprüfung ist unter http://localhost:4000/v1/healthcheck, die Web-Gesundheitsprüfung unter http://localhost:4040/ping erreichbar. Eine lesbare Statusseite mit API- und Serverinformationen steht unter http://localhost:4040/healtcheck bereit.
Den Stack beendet docker compose down. Die PostgreSQL-Daten liegen im benannten
Volume gardomatic-postgres-data und bleiben dabei erhalten. docker compose down -v löscht dieses Volume und damit die lokale Datenbank dauerhaft.
Lokale Entwicklung ohne Anwendungscontainer
PostgreSQL und die Migrationen können weiterhin über Compose laufen:
cp .env.example .env
docker compose up -d postgres migrate
Der Makefile bindet eine lokale, nicht versionierte .envrc ein. Mindestens die
Datenbankverbindung muss darin für API-, CLI- und Datenbankbefehle exportiert sein:
export GARDOMATIC_DB_DSN='postgres://gardomatic:change-me@localhost:5432/gardomatic?sslmode=disable'
Danach API und Webanwendung in getrennten Terminals starten:
make run/api
make run/web
Alternativ können beide Programme direkt mit go run ./cmd/api und
go run ./cmd/web gestartet werden, sofern die benötigten Umgebungsvariablen in
der Shell gesetzt sind. Die API benötigt zwingend GARDOMATIC_DB_DSN; alle
anderen Entwicklungswerte besitzen sinnvolle Standardwerte.
Konfiguration
.env.example dokumentiert eine vollständige lokale Konfiguration. Geheimnisse
gehören ausschließlich in .env, .envrc, einen Secret Store oder die
Produktionsumgebung und dürfen nicht eingecheckt werden.
Compose-Variablen
| Variable | Standard/Beispiel | Beschreibung |
|---|---|---|
POSTGRES_DB |
gardomatic |
Datenbankname des PostgreSQL-Containers |
POSTGRES_USER |
gardomatic |
Datenbankbenutzer des Containers |
POSTGRES_PASSWORD |
change-me |
Datenbankpasswort; lokal unbedingt ändern |
POSTGRES_PORT |
5432 |
auf dem Host veröffentlichter PostgreSQL-Port |
API_PORT |
4000 |
auf dem Host veröffentlichter API-Port |
WEB_PORT |
4040 |
auf dem Host veröffentlichter Web-Port |
Laufzeitvariablen
| Variable | Standard | Verwendung |
|---|---|---|
GARDOMATIC_ENV |
development |
development, test oder production |
GARDOMATIC_DB_DSN |
erforderlich | PostgreSQL-Verbindungszeichenfolge für API und CLI |
GARDOMATIC_DB_MAX_OPEN_CONNS |
25 |
maximale offene DB-Verbindungen |
GARDOMATIC_DB_MAX_IDLE_CONNS |
25 |
maximale ungenutzte DB-Verbindungen |
GARDOMATIC_DB_MAX_IDLE_TIME |
15m |
maximale Leerlaufzeit einer DB-Verbindung |
GARDOMATIC_API_HOST |
leer | Bind-Adresse der API |
GARDOMATIC_API_PORT |
4000 |
Listener-Port der API |
GARDOMATIC_WEB_HOST |
leer | Bind-Adresse der Webanwendung |
GARDOMATIC_WEB_PORT |
4040 |
Listener-Port der Webanwendung |
GARDOMATIC_API_BASE_URL |
http://localhost:4000 |
API-Adresse für den Web-Client |
GARDOMATIC_WEB_BASE_URL |
http://localhost:4040 |
öffentliche Basis-URL für Links aus API und CLI |
GARDOMATIC_SESSION_COOKIE_NAME |
gardomatic_session |
gemeinsamer Name des Session-Cookies |
GARDOMATIC_SESSION_LIFETIME |
12h |
absolute Lebensdauer einer Sitzung |
GARDOMATIC_SESSION_IDLE_TIMEOUT |
30m |
Ablaufzeit bei Inaktivität |
GARDOMATIC_COOKIE_SECURE |
false |
nur HTTPS-Cookies; in Produktion zwingend true |
GARDOMATIC_RATE_LIMIT_ENABLED |
true |
API-Ratenbegrenzung aktivieren |
GARDOMATIC_RATE_LIMIT_RPS |
10 |
erlaubte Requests pro Sekunde |
GARDOMATIC_RATE_LIMIT_BURST |
40 |
kurzfristig erlaubte Request-Spitze |
GARDOMATIC_CORS_TRUSTED_ORIGINS |
leer/lokal gesetzt | kommaseparierte erlaubte Origins |
E-Mail-Versand
| Variable | Standard | Beschreibung |
|---|---|---|
GARDOMATIC_SMTP_MODE |
file |
file für Entwicklung oder smtp |
GARDOMATIC_SMTP_HOST |
leer | SMTP-Server |
GARDOMATIC_SMTP_PORT |
25 |
SMTP-Port |
GARDOMATIC_SMTP_USERNAME |
leer | SMTP-Benutzername |
GARDOMATIC_SMTP_PASSWORD |
leer | SMTP-Passwort |
GARDOMATIC_SMTP_SENDER |
gardomatic@localhost |
Absenderadresse |
GARDOMATIC_SMTP_FILE_PATH |
/tmp/gardomatic-mails.log |
Ausgabe im file-Modus |
Im Entwicklungsmodus schreibt der voreingestellte file-Mailer E-Mails in die
angegebene Datei. In der Compose-API liegt diese Datei innerhalb des Containers;
sie kann beispielsweise mit docker compose exec api cat /tmp/gardomatic-mails.log gelesen werden.
Datenbankmigrationen
Migrationen liegen als fortlaufend nummerierte Up-/Down-Paare in
internal/storage/postgres/migrations.
Eine neue Migration anlegen:
make db/migrations/new name=describe_change
Alle ausstehenden Migrationen anwenden:
make db/migrations/up
Alle angewendeten Migrationen zurücknehmen:
make db/migrations/down
migrate down ohne Schrittzahl setzt das gesamte Schema zurück und kann sämtliche
Anwendungsdaten löschen. Die Make-Ziele verwenden GARDOMATIC_DB_DSN; vor Up- und
besonders Down-Befehlen daher immer prüfen, auf welche Datenbank die Variable zeigt.
Bereits veröffentlichte Migrationen sollten nicht verändert werden;
Schemaänderungen erhalten eine neue Migration.
Tests und Qualitätsprüfungen
Alle Unit- und Handler-Tests ausführen:
go test ./...
Die PostgreSQL-Integrationstests werden ohne GARDOMATIC_TEST_DB_DSN automatisch
übersprungen. Für einen vollständigen Integrationslauf eine separate Testdatenbank
konfigurieren und zuerst migrieren:
export GARDOMATIC_TEST_DB_DSN='postgres://user:password@localhost/gardomatic_test?sslmode=disable'
migrate -path ./internal/storage/postgres/migrations -database "$GARDOMATIC_TEST_DB_DSN" up
go test -count=1 ./internal/storage/postgres
Alternativ migriert folgendes Ziel die in GARDOMATIC_DB_DSN konfigurierte
Datenbank und führt die Integrationstests dagegen aus:
make test/integration
Dieses Ziel ausschließlich mit einer entbehrlichen Testdatenbank verwenden.
Der vollständige lokale Qualitätslauf umfasst Modulprüfung, go vet,
staticcheck und Tests mit Race Detector:
make audit
Quelltext modernisieren und formatieren:
make tidy
make tidy kann go.mod, go.sum, den Vendor-Bestand und Go-Quelltext verändern.
Den resultierenden Diff deshalb immer prüfen.
Die CI unter .github/workflows/ci.yml ist dafür konfiguriert, PostgreSQL zu
migrieren, Module und Quelltext zu prüfen, alle Tests mit Race Detector auszuführen
und alle drei Programme zu bauen.
Administration mit dem CLI
Das CLI benötigt für Datenbankbefehle GARDOMATIC_DB_DSN. Globale Optionen stehen
vor dem Unterbefehl. Mit --json liefert es maschinenlesbare Ausgabe; --yes
bestätigt bewusst konfigurierte Produktionsoperationen.
Häufige Befehle:
go run ./cmd/cli users list
go run ./cmd/cli users show --email alice@example.com
go run ./cmd/cli users invite --email alice@example.com --send-email
go run ./cmd/cli users activate --email alice@example.com
go run ./cmd/cli users deactivate --email alice@example.com
go run ./cmd/cli users reset-password --email alice@example.com --generate-password
go run ./cmd/cli db ping
Passwörter werden absichtlich nicht als Kommandozeilenargument angenommen. Sie
werden sicher abgefragt, generiert oder mit --password-stdin von der
Standardeingabe gelesen. Eine ausführliche Referenz mit Beispielen enthält
doc/cli.md.
Build
Einzelne Programme für das lokale System und Linux/AMD64 bauen:
make build/api
make build/web
make build/cli
Alle Programme bauen:
make build/all
Artefakte landen unter bin/ und werden nicht versioniert. Der Dockerfile
enthält getrennte, minimale Laufzeit-Targets für API und Web.
Projektstruktur
cmd/
api/ Start und Konfiguration der JSON-API
web/ Start und Konfiguration der Webanwendung
cli/ Administrations-CLI
internal/
api/ API-Handler, Middleware und Fachabläufe
auth/ Passwort- und Tokenfunktionen
mailer/ Mailversand und Vorlagen
platform/ kleine technische Basispakete
storage/ Modelle und Storage-Schnittstellen
postgres/ PostgreSQL-Implementierungen und Migrationen
web/ Handler, Templates und statische Assets
lib/
client/ typisierter Go-Client für die JSON-API
doc/ Planung und weiterführende Dokumentation
remote/ Produktionsbeispiele für systemd
request/ manuelle HTTP-Beispielanfragen
Entwicklungskonventionen
Bei Änderungen sind insbesondere folgende Grundsätze verbindlich:
- idiomatischer, mit
gofmtformatierter Go-Code - klare Verantwortlichkeiten und bestehende Schichtengrenzen
- Wiederverwendung vorhandener Helfer und Fachlogik statt Codeduplizierung
- Tests für neues oder korrigiertes Verhalten, soweit technisch möglich
- neue Migrationen statt Änderungen an bereits veröffentlichten Migrationen
- keine Zugangsdaten oder lokalen Umgebungsdateien im Repository
Ausführliche Arbeitsregeln für Coding Agents und Beitragende stehen in
AGENTS.md.
Beiträge
Beiträge sind willkommen. Der vollständige Ablauf, Qualitätsanforderungen und der
Umgang mit Fremdmaterial sind in CONTRIBUTING.md beschrieben.
Vor dem ersten Pull Request müssen Beitragende die
Contributor License Agreement lesen und im Pull Request selbst
akzeptieren. Beitragende behalten ihr Copyright, räumen dem Projektinhaber jedoch
die notwendigen Rechte ein, den Beitrag sowohl unter der öffentlichen
Projektlizenz als auch unter separaten kommerziellen oder proprietären Lizenzen zu
verwenden. Beiträge im Namen eines Unternehmens müssen vorab abgestimmt werden.
Deployment
Der Dockerfile kann Images für API und Web erzeugen. Unter remote/production
liegen außerdem Beispielkonfigurationen für systemd. Die
production/*-Ziele im Makefile sind auf die vorhandene Gardomatic-Infrastruktur
zugeschnitten, enthalten einen fest konfigurierten Zielhost und führen Migrationen
sowie Dienstneustarts aus. Sie sind keine allgemeine Deployment-Anleitung und
sollten vor jeder Verwendung geprüft werden.
Die lokale Produktionsverbindung wird in config.mk konfiguriert. Eine kommentierte
Vorlage mit Zielhost, SSH-Admin, Port, optionalem privaten Schlüssel und
Zielarchitektur steht in config.mk.example. Der SSH-Admin ist der vom Hoster oder
bei der LXC-Erstellung bereitgestellte Benutzer (root, ubuntu oder ähnlich)
und benötigt Root-Rechte oder passwortloses sudo. Private SSH-Schlüssel bleiben
ausschließlich auf dem lokalen Rechner; auf dem Server muss vorab nur der
zugehörige öffentliche Schlüssel für diesen Admin hinterlegt sein.
Das Server-Setup unter remote/setup/provision-server.sh liest seine Konfiguration
aus remote/setup/.env. Als Ausgangspunkt dient remote/setup/.env.example; die
echte Datei muss auf Modus 0600 gesetzt werden und bleibt von Git ausgeschlossen.
make production/provision überträgt das Skript und streamt die Konfiguration über
SSH, ohne die Quelldatei dauerhaft auf dem Server abzulegen. Das Provisioning legt
den gesperrten Servicebenutzer gardomatic ohne Login, SSH-Schlüssel oder
sudo-Rechte an und installiert die Laufzeitwerte als
/etc/gardomatic/gardomatic.env.
Ein vollständiger Erstbetrieb besteht aus:
make config/init
# Die benötigten lokalen Konfigurationsdateien bearbeiten, dann:
make production/provision
make production/deploy
make production/create-admin
production/deploy überträgt Binärdateien, Migrationen, systemd-Units und die
Admin-Hilfe über denselben SSH-Admin, wendet Migrationen an und startet die Dienste.
production/create-admin fragt interaktiv nach Name und E-Mail und erstellt den
Benutzer aktiviert und mit der Rolle application:admin; das sichere generierte
Passwort wird einmalig ausgegeben.
Für Produktion gelten mindestens folgende Anforderungen:
GARDOMATIC_ENV=production- HTTPS am Reverse Proxy
GARDOMATIC_COOKIE_SECURE=true- starke, extern verwaltete Zugangsdaten
- eingeschränkter Datenbankzugriff und regelmäßige Backups
- korrekte öffentliche Web-URL und vertrauenswürdige CORS-Origins
- SMTP statt dateibasiertem Mailversand, sofern E-Mails zugestellt werden sollen
Weiterführende Dokumentation
doc/planung.md– Produktbeschreibung, Leitplanken und Fahrplandoc/cli.md– vollständige Bedienung des Administrations-CLIdoc/issues.md– bekannte Themen und Arbeitsnotizendoc/ideen.md– mögliche spätere Erweiterungen
Lizenz
Gardomatic steht unter der PolyForm Noncommercial License 1.0.0. Sie erlaubt Nutzung, Veränderung und Weitergabe für nichtkommerzielle Zwecke unter den Bedingungen der Lizenz.
Kommerzielle Nutzung ist von dieser Lizenz nicht abgedeckt und erfordert eine separate, kostenpflichtige Lizenzvereinbarung. Anfragen können an alex@kleiax.de gerichtet werden.
Für Beiträge Dritter gilt zusätzlich die
Gardomatic Contributor License Agreement.
Wegen des Ausschlusses kommerzieller Nutzung ist Gardomatic „source-available“, aber keine Open-Source-Software nach der Definition der Open Source Initiative.