- Python 82.1%
- HTML 14.6%
- CSS 1.3%
- Shell 0.6%
- Dockerfile 0.6%
- Other 0.8%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
build / build (push) Successful in 9s
Reviewed-on: #12 |
||
| .forgejo/workflows | ||
| alembic | ||
| assets | ||
| dev | ||
| docs | ||
| scripts | ||
| src/notenwart | ||
| tests | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| alembic.ini | ||
| CLAUDE.md | ||
| compose.dev.yaml | ||
| compose.yaml | ||
| Dockerfile | ||
| LICENSE | ||
| Makefile | ||
| pyproject.toml | ||
| README.md | ||
| uv.lock | ||
Notenwart
Selbst gehostetes Notenarchiv und Setlists für Musikvereine: Notensätze mit Metadaten, Notizen und PDF-Stimmen, Setlists mit A4-Druckansicht und öffentlichem Link. Mehrere Gruppen teilen sich eine Installation und bleiben streng getrennt.
Lizenz: AGPL-3.0-or-later.
Funktionen
- Anmeldung nur über OIDC, keine lokalen Passwörter
- Gruppen mit den Rollen Admin, Notenwart und Mitglied, Beitritt über Einladungslink
- Globaler Stückekatalog, Notensätze pro Gruppe, Suche mit Tippfehlertoleranz
- PDF-Upload pro Stimme, Mitglieder sehen zuerst die Stimmen ihres Instruments
- Setlists mit Drag-and-Drop, Dauer-Summe und eingefrorenem Stand nach dem Auftritt
- A4-Druckansicht im Design der Gruppe, widerrufbarer öffentlicher Link
Rollen
| Rolle | Darf |
|---|---|
| Mitglied | lesen, alle PDFs der Gruppe laden, Notizen schreiben, eigene Instrumente pflegen |
| Notenwart | zusätzlich Stücke, Notensätze, Uploads, Setlists und öffentliche Links |
| Admin | zusätzlich Mitglieder, Einladungen und Gruppendesign |
| Superadmin | Gruppen anlegen, Zugriff auf alle Gruppen, Instrumente umbenennen und löschen |
Entwicklung
Voraussetzungen: uv, Docker und einmalig das Netzwerk, das compose.yaml erwartet:
docker network create traefik
cp .env.example .env
make dev
make dev startet Postgres und Dex in Docker, baut die CSS, führt die Migrationen aus und startet die App auf http://localhost:8000. Dex ersetzt lokal PocketID, die Testnutzer stehen in dev/dex.yaml. admin@notenwart.test ist Superadmin.
| Befehl | Zweck |
|---|---|
make seed |
Demo-Gruppen, Stücke und eine Setlist anlegen (nur für die Entwicklung) |
make css-watch |
Tailwind-CSS bei Änderungen neu bauen |
make test |
Tests gegen eine eigene Test-Datenbank |
make lint |
ruff und Lizenzprüfung aller Abhängigkeiten |
make format |
Code formatieren |
Das Image lässt sich auch lokal bauen und starten, auf ARM64 wie auf x86. Dex ist im Container nicht unter localhost erreichbar, ein Login funktioniert dort also nicht:
docker compose -f compose.yaml -f compose.dev.yaml up -d --build --wait notenwart
Danach antwortet die App auf http://127.0.0.1:8001/health.
Arbeitsweise
Entwickelt wird nach Git Flow: pro Feature ein Branch feature/* von develop, Merge per Squash-PR. Ein Merge von develop nach main erzeugt ein Release.
Echte Noten gehören nicht in dieses Repository: Es ist öffentlich und die Noten sind urheberrechtlich geschützt. Tests arbeiten mit synthetischen PDFs.
Neue Abhängigkeiten müssen AGPL-kompatibel sein, make lint prüft das gegen die Liste in scripts/lint.sh.
Konfiguration
Alle Werte kommen aus der Umgebung, siehe .env.example.
| Variable | Bedeutung |
|---|---|
BASE_URL |
Öffentliche Adresse der App. Mit https:// werden Cookies als Secure gesetzt |
SECRET_KEY |
Signiert die Sessions, erzeugen mit openssl rand -hex 32 |
POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD |
Datenbank. Das Passwort landet in einer URL, also nur URL-sichere Zeichen verwenden |
NOTENWART_DB_DIR |
Hostpfad der Datenbank |
NOTENWART_DATA_DIR |
Hostpfad der PDFs und Logos |
PUID, PGID |
Benutzer des App-Containers, muss in NOTENWART_DATA_DIR schreiben dürfen |
OIDC_ISSUER, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET |
OIDC-Client |
BOOTSTRAP_ADMIN_EMAILS |
Kommagetrennte Adressen, die beim Login Superadmin werden |
MAX_UPLOAD_MB |
Größenlimit für einen PDF-Upload |
TZ |
Zeitzone des Containers |
PocketID einrichten
- Unter Administration → OIDC Clients mit Add OIDC Client einen Client
Notenwartanlegen. - Als Callback-URL
https://notenwart.makeitsystems.de/auth/callbackeintragen. - Auf dem Tab General die Option PKCE aktivieren und speichern.
- Client-ID und Secret als
OIDC_CLIENT_IDundOIDC_CLIENT_SECRETeintragen.OIDC_ISSUERisthttps://id.makeitsystems.de. - Die Adressen der Admins als verifiziert markieren: unter Administration → Application Configuration → Email die Option Emails verified by default aktivieren und die Benutzer unter Administration → Users verifizieren.
Der fünfte Schritt ist nötig: Eine Adresse aus BOOTSTRAP_ADMIN_EMAILS macht nur dann zum Superadmin, wenn der IdP sie mit email_verified: true bestätigt. Die Prüfung läuft bei jedem Login.
Das schützt nur, solange niemand eine fremde Adresse als verifiziert übernehmen kann. Benutzer dürfen ihre E-Mail-Adresse in PocketID also nicht selbst ändern können, wenn Emails verified by default aktiv ist.
Deployment im Homelab
compose.yaml passt zu den Konventionen des Homelabs: Netzwerk traefik, kein Host-Port, Bind-Mounts in Langform, Ressourcenlimits. Traefik leitet nach dem Service-Namen auf notenwart.makeitsystems.de weiter. Die Kette chain-default ist Absicht: Mit chain-tinyauth wären die öffentlichen Setlist-Links nicht mehr erreichbar.
Vor dem ersten Start:
- In
.envdie Homelab-Werte aus .env.example setzen. Secrets kommen aus Dockhand. - Das Verzeichnis
NOTENWART_DATA_DIRanlegen undPUID:PGIDzum Besitzer machen. - Das Icon unter
/mnt/cache/appdata/icons/notenwart.pngablegen.
Die Migrationen laufen beim Start des Containers. Anschließend mit einer Adresse aus BOOTSTRAP_ADMIN_EMAILS anmelden, Gruppen anlegen und unter Mitglieder die Einladungslinks erzeugen. Logo und Farben trägt ein Admin unter Einstellungen ein.
Image und Releases
.forgejo/workflows/build.yaml baut bei jedem Push auf main das Image für linux/amd64, schiebt es als latest und YYYY.MM.N in die Forgejo-Registry und legt ein Release an. Reicht das Workflow-Token nicht, die Repo-Secrets REGISTRY_USER und REGISTRY_TOKEN setzen.
Sicherung
Zu sichern sind beide Verzeichnisse, NOTENWART_DB_DIR und NOTENWART_DATA_DIR. Die Datenbank allein reicht nicht, sie enthält keine PDFs.