Files
ifb-schulapp/README.md
T
Simon c217705eb5 docs: add README, LICENSE, .env.example
README in German with universal framing (class, study group, cohort)
rather than INFO1-specific wording. MIT license. Update package.json
with description, keywords, repository URL, proper license field,
start script. Add .env.example documenting required environment
variables.
2026-04-18 11:36:22 +02:00

6.3 KiB

INFO1

Ein selbst gehostetes Dashboard für eine Klasse, Lerngruppe oder kleine Kohorte. Ein Ort für Stundenplan, Hausaufgaben, Noten, Fehlzeiten, gemeinsamen Kalender, Klassenchat und Ende zu Ende verschlüsselte Direktnachrichten.

Bewusst unspektakulär aufgebaut: Node.js, Express, SQLite, vanilla JavaScript. Kein Buildschritt, kein Framework Lock in, läuft auf einem 1 GB VPS.

License Node No Build Step Self Hosted

Worum geht es

Die meisten Schul- und Lernplattformen sind schwergewichtig, kommerziell oder an eine bestimmte Institution gebunden. INFO1 ist das Gegenteil: eine einzige App, die jede Gruppe für sich selbst hosten kann, mit voller Kontrolle über die eigenen Daten und ohne Anbieter dazwischen.

Das Projekt nimmt Datenschutz ernst (Direktnachrichten werden im Browser verschlüsselt, der Server sieht nie Klartext), bleibt im Umfang ehrlich (für ein paar hundert aktive Nutzer, nicht für tausende) und ist so geschrieben, dass eine Person den Code an einem Nachmittag vollständig lesen kann.

Funktionen

Persönliches Dashboard

  • Stundenplan, Hausaufgabenverwaltung, Notenbuch mit automatischen Durchschnitten
  • Fehlzeitenprotokoll, persönliche Todos, Countdowns, anpassbare Schnelllinks
  • Dateiablage pro Nutzer mit Speicherkontingent

Geteilte Klassenebene

  • Klassenkalender für Prüfungen, Ferien, Ereignisse (ohne Login einsehbar)
  • Klassenchat mit Rate Limiting und sanfter Moderation
  • Ende zu Ende verschlüsselte Gruppennachrichten (ECDH P-256 und AES-GCM, Schlüssel verlassen nie den Browser)

Lehrerwerkzeuge

  • Fachbezogene Ankündigungen, Materialupload, Klausurplanung
  • Direktes Setzen von Noten für einzelne Schüler
  • Freigabeprozess: neue Lehrerkonten landen in einer Warteschlange für einen Admin

Adminkonsole

  • Nutzerverwaltung (sperren, entsperren, befördern, zurückstufen, löschen)
  • Manuelles Freischalten der E-Mail-Verifizierung, Rollenänderung, Auditlog
  • Triage von Supporttickets mit Thread-Antworten
  • Speicher- und Nutzungsstatistiken pro Nutzer

Auth und Kontosicherheit

  • E-Mail-Verifizierung bei der Registrierung über Resend
  • Passwort-Reset per Mail mit einmalig verwendbaren Tokens (1 Stunde gültig)
  • TOTP-Zweifaktor-Authentifizierung mit QR-Code
  • Passwort-Hashing mit bcrypt (Kosten 12), JWT in HttpOnly-Cookie
  • Rate Limiting auf allen sensiblen Endpoints

Technologie

Schicht Wahl
Laufzeit Node.js 20, Express 5
Datenbank SQLite über better-sqlite3 (synchron, in-process)
Auth JWT im HttpOnly-Cookie, bcrypt, otplib für TOTP
Mail Resend (austauschbar gegen jeden SMTP-Anbieter)
Frontend Vanilla JavaScript, kein Bundler, kein Framework
Security Helmet, CSP, express-rate-limit

Gesamtgröße: rund 3 KLOC Servercode und eine Handvoll eigenständige HTML-Dateien.

Schnellstart

git clone https://github.com/lulinretrograde/ifb-schulapp.git info1
cd info1
npm install
cp .env.example .env   # dann bearbeiten
node index.js

Die App bindet an 127.0.0.1:3010. Für öffentliche Deployments einen Reverse Proxy davorschalten (Caddy, nginx, Cloudflare Tunnel).

Konfiguration

Alle Einstellungen laufen über Umgebungsvariablen. Vollständige Liste in .env.example.

JWT_SECRET=              # Pflicht, 32+ zufällige Bytes
RESEND_API_KEY=          # Pflicht für Verifizierungs- und Reset-Mails
MAIL_FROM=noreply@deinedomain.example
MAIL_FROM_NAME=Klassenportal
APP_URL=https://deinedomain.example
NODE_ENV=production

E-Mail-Domain-Beschränkung

Die Registrierung ist standardmäßig auf eine einzige E-Mail-Domain beschränkt, via Regex in src/routes.js. IFB_EMAIL_RE anpassen oder entfernen, um die Beschränkung zu lockern, oder durch eine eigene Allowlist ersetzen.

Datenbank

SQLite-Datei liegt unter ./data.db und wird beim ersten Start erzeugt. Migrationen sind idempotent und stehen am Ende von src/db.js. Für ein Backup die Datei zur Laufzeit kopieren (SQLite erlaubt parallele Lesezugriffe während des Kopierens).

Deployment

Minimale systemd-Unit:

[Unit]
Description=INFO1
After=network.target

[Service]
Type=simple
User=www
WorkingDirectory=/opt/info1
ExecStart=/usr/bin/node index.js
Restart=always
Environment=NODE_ENV=production
EnvironmentFile=/opt/info1/.env

[Install]
WantedBy=multi-user.target

TLS am Reverse Proxy terminieren und NODE_ENV=production setzen, damit das Auth-Cookie das Secure-Flag bekommt.

Sicherheit

  • Die App startet nicht, wenn JWT_SECRET nicht gesetzt ist.
  • Direktnachrichten werden im Browser verschlüsselt, bevor sie hochgeladen werden. Der Server speichert ausschließlich opaken Chiffretext und kann auch mit Datenbankzugriff den Inhalt nicht lesen.
  • Alle schreibenden Endpoints sind Rate limitiert. Die Limits sind für kleine Gruppen abgestimmt und sollten für größere Deployments nachgezogen werden.
  • Adminaktionen landen in admin_logs mit Akteur, Ziel und einem JSON-Detail-Blob.

Verantwortungsvolle Offenlegung von Schwachstellen: Issue mit Kurzbeschreibung öffnen, Details per Mail nachreichen.

Projektstruktur

index.js              Express-Bootstrap, Static Serving, Routenmontage
src/
  db.js               SQLite-Singleton, Schema, Migrationen
  auth.js             JWT-Hilfsfunktionen, requireAuth-Middleware
  routes.js           Auth-Endpoints, Admin, Tickets, Chat, Klassenkalender
  teacher.js          Lehrer-Endpoints und Material-Upload
  files.js            Dateiablage pro Nutzer mit Quota
  mailer.js           Resend-Wrapper und Mail-Templates
public/
  index.html          Öffentliche Startseite
  login.html          Login, Registrierung, Passwort-Reset
  app.html            Hauptdashboard nach Login
  admin.html          Adminkonsole
  reset-password.html Zielseite für Passwort-Reset-Links
  datenschutz.html    Datenschutzerklärung
  e2ee.js             Kryptoprimitiven für Ende zu Ende Verschlüsselung

Status

Aktiv entwickelt für eine einzelne Kohorte. Im produktiven Einsatz bei einer kleinen Gruppe von Lernenden und Lehrenden. Die APIs sind nicht versioniert und können sich zwischen Commits ändern.

Lizenz

MIT. Siehe LICENSE.