2026-09-16 05:36:36 +02:00
2026-09-12 22:22:17 +02:00
2026-09-12 22:22:17 +02:00
2026-09-12 22:22:17 +02:00
2026-09-12 22:22:17 +02:00
2026-09-12 22:22:17 +02:00
2026-09-12 22:22:17 +02:00
2026-09-12 22:22:17 +02:00
2026-09-12 22:22:17 +02:00
2026-09-12 22:22:17 +02:00
2026-09-12 22:22:17 +02:00
2026-09-12 22:22:17 +02:00
2026-09-12 22:22:17 +02:00
2026-09-12 22:22:17 +02:00
2026-09-12 22:22:17 +02:00

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-migrate für lokale Migrationen und Integrationstests
  • make fü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

  1. Konfiguration anlegen und mindestens das Datenbankpasswort ändern:

    cp .env.example .env
    

    POSTGRES_PASSWORD und das Passwort in GARDOMATIC_DB_DSN sollten übereinstimmen, damit auch lokale CLI- und Testbefehle dieselbe Datenbank erreichen können. .env ist von Git ausgeschlossen.

  2. Datenbank, Migrationen, API und Webanwendung starten:

    docker compose up --build
    

    Bei Podman kann je nach Installation stattdessen podman compose oder podman-compose verwendet werden.

  3. Einen ersten aktiven Benutzer anlegen. Dazu in einem zweiten Terminal die DSN aus der lokalen .env setzen 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-password
    

    Das generierte Passwort wird einmalig ausgegeben.

  4. 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 gofmt formatierter 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 Präfixe production/*, testserver/* und demo/* verwenden denselben Deployment-Ablauf, aber getrennte Zielhosts und Laufzeitkonfigurationen. Sie sind auf die vorhandene Gardomatic-Infrastruktur zugeschnitten, führen Migrationen sowie Dienstneustarts aus und sollten vor jeder Verwendung geprüft werden.

Die drei SSH-Verbindungen werden gemeinsam in config.mk konfiguriert. Eine kommentierte Vorlage mit Zielhost, SSH-Admin, Port, optionalem privaten Schlüssel und Zielarchitektur steht in config.mk.example. Die Präfixe der Variablen sind PRODUCTION_, TESTSERVER_ und DEMO_. 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.

Das Server-Setup unter remote/setup/provision-server.sh liest seine Konfiguration aus einer zum Ziel gehörenden Datei. Alle drei Dateien werden von make config/init mit Modus 0600 angelegt und bleiben von Git ausgeschlossen:

Make-Präfix SSH-Einstellungen Laufzeitkonfiguration
production/ PRODUCTION_* in config.mk remote/setup/.env
testserver/ TESTSERVER_* in config.mk remote/setup/.env.testserver
demo/ DEMO_* in config.mk remote/setup/.env.demo

Jede Laufzeitdatei benötigt eine eigene Datenbank-DSN, eigene Passwörter und die URL des jeweiligen Servers. Für Produktion wird GARDOMATIC_ENV=production verwendet. Der Testserver kann GARDOMATIC_ENV=test und dateibasierten Mailversand nutzen. Die öffentliche Demo läuft gehärtet mit GARDOMATIC_ENV=production, aber mit GARDOMATIC_DEMO_RESET_ENABLED=true, GARDOMATIC_DEMO_ACCOUNT_EMAIL=demo@example.com und GARDOMATIC_SMTP_MODE=file. Ein gemeinsames Runtime-Environment wird absichtlich nicht verwendet, damit ein Demo-Deployment keine Produktionsdatenbank erreichen kann.

*/provision überträgt das Setup und streamt ausschließlich die zugehörige 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 auf dem jeweiligen Server 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

# Entsprechend für die anderen Instanzen:
make testserver/provision
make testserver/deploy
make testserver/create-admin

make demo/provision
make demo/deploy

Jedes Präfix bietet connect, provision, deploy und create-admin. */deploy überträgt Binärdateien, Migrationen, systemd-Units und die Admin-Hilfe, wendet Migrationen an und startet die Dienste. */create-admin erstellt interaktiv einen aktivierten Anwendungsadministrator und gibt das generierte Passwort einmalig aus.

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

Öffentliche Demo-Instanz

Für eine öffentliche Demo empfiehlt sich eine eigene Gardomatic-Installation mit eigener PostgreSQL-Datenbank und eigener Domain, nicht ein Demo-Garten in einer Produktivdatenbank. Die Anwendung sollte weiterhin mit GARDOMATIC_ENV=production, HTTPS und sicheren Cookies laufen. Ausschließlich auf dieser wegwerfbaren Instanz wird GARDOMATIC_DEMO_RESET_ENABLED=true gesetzt. GARDOMATIC_DEMO_ACCOUNT_EMAIL=demo@example.com schützt das gemeinsame Konto serverseitig: Profil, E-Mail-Adresse, Passwort, Passwort-Zurücksetzen und die globale Sitzungsverwaltung können von Besuchern nicht verändert werden. Die Garteninhalte bleiben vollständig bedienbar.

Der Befehl gardomatic-cli --yes demo reset --password-stdin ersetzt alle Benutzer- und Gartendaten atomar durch einen zeitlich aktuellen Beispieldatensatz. Er erstellt den Garten Sonnengarten mit drei Mitgliedern, Einladung und eigener Gartenrolle, acht detaillierten Orten, zwölf Arten, Pflegehinweisen, Aufgabenvorlagen, sechzehn Pflanzen in unterschiedlichen Zuständen, fälligen, wiederkehrenden und erledigten Aufgaben, Tags, längeren Tagebuch- und Pinnwandeinträgen sowie einer bebilderten Medienbibliothek. Das gewünschte Login lautet standardmäßig demo@example.com; das Passwort wird nicht im Repository gespeichert.

Die mitgelieferte systemd-Konfiguration setzt die Demo jede Nacht um 04:00 Uhr zurück. Für einen frisch aufgesetzten Demo-Server:

  1. In remote/setup/.env.demo GARDOMATIC_DEMO_RESET_ENABLED='true', GARDOMATIC_DEMO_ACCOUNT_EMAIL='demo@example.com' und GARDOMATIC_SMTP_MODE='file' setzen.

  2. Den Server mit make demo/provision provisionieren.

  3. Auf dem Demo-Server das Passwort verdeckt einlesen und mit Enter bestätigen:

    make demo/connect
    sudo install -d -m 0750 -o root -g gardomatic /etc/gardomatic
    systemd-ask-password 'Demo-Passwort:' | \
        sudo tee /etc/gardomatic/demo-password >/dev/null
    sudo chown root:gardomatic /etc/gardomatic/demo-password
    sudo chmod 0640 /etc/gardomatic/demo-password
    exit
    
  4. make demo/deploy ausführen. Das Deployment befüllt die Demo sofort und aktiviert gardomatic-demo-reset.timer.

Mit systemctl list-timers gardomatic-demo-reset.timer lässt sich der nächste Lauf prüfen; journalctl -u gardomatic-demo-reset.service zeigt die Reset-Läufe. Ein Reverse Proxy sollte zusätzlich Request-Größen begrenzen und die vorhandene Rate-Limitierung aktiviert lassen. Für die Demo sollte der Mailversand im file-Modus bleiben, damit Besucher keine E-Mails an Dritte auslösen können. Da Besucher Schreibrechte besitzen, dürfen auf diesem Host keine anderen schützenswerten Anwendungen oder Datenbanken mit denselben Zugangsdaten betrieben werden.

Weiterführende Dokumentation

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.

S
Description
No description provided
Readme
2.2 MiB
Languages
Go 81.9%
Go Template 10.2%
JavaScript 3.1%
CSS 2.7%
Shell 1%
Other 1%