Skip to content

IT Uebersicht

IT-Master Heizmann edited this page Sep 18, 2026 · 2 revisions

Übersicht und Architektur

Caution

Diese Seite richtet sich ausschliesslich an Informatikerinnen und Informatiker. Nicht für Laien geeignet: Fehler bei den hier beschriebenen Schritten können den Betrieb unterbrechen, Daten zerstören oder SmallTime ungeschützt ins Internet stellen. Ohne Fachkenntnisse bitte den Bereich Installation Schritt für Schritt verwenden.

Für wen ist diese Seite? Für Informatikerinnen und Informatiker, die SmallTime 2027 betreiben, in eine bestehende Infrastruktur einbinden oder weiterentwickeln. Sie gibt den Überblick; Details stehen auf den verlinkten Seiten.

Inhalt

  1. Komponenten
  2. Laufzeitmodell
  3. Ports
  4. Ordnerstruktur
  5. Pfadauflösung
  6. Vorrang der Konfiguration
  7. Betriebsvarianten
  8. Einschränkungen

Komponenten

Komponente Technik
Laufzeit Node.js >= 26.9.0 < 27 (engines in backend/package.json), npm >= 11.19.1 < 12. Node 26 wird u. a. wegen Temporal benötigt.
Backend Express 5, TypeScript, mit esbuild zu ESM gebündelt (backend/dist/server.js, backend/dist/migrate.js, Target node26, Abhängigkeiten extern)
Frontend React 19, MUI 9, Vite 8; statischer Build (frontend/dist), im Betrieb vom Backend ausgeliefert
Datenbank SQLite (sqlite3 über Sequelize), PRAGMA journal_mode = WAL, foreign_keys = ON, busy_timeout = 5000
Cache optional Redis für den Benutzer-Cache bei der JWT-Prüfung (REDIS_URL); ohne Redis bzw. bei Verbindungsfehler In-Memory-Cache mit Warnung im Log
Live-Updates WebSocket unter /api/live (Paket ws, Heartbeat 30 s), meldet angemeldeten Browsern Änderungen
Lizenz Abfrage https://lizenz.small.li/info (POST) beim Start und alle 24 h
Native Module sqlite3, bcrypt – werden bei npm install für die Zielplattform installiert
flowchart LR
  B[Browser / Kiosk-Terminal] -- HTTPS --> P[Reverse-Proxy<br/>nginx / Caddy / Plesk]
  P -- HTTP :55000<br/>inkl. WebSocket /api/live --> N[Node.js<br/>app.cjs → dist/server.js]
  N --> S[(data/app.sqlite<br/>WAL)]
  N --> F[data/documents<br/>uploads/]
  N -. optional .-> R[(Redis)]
  N -. HTTPS ausgehend .-> L[lizenz.small.li]
Loading

Laufzeitmodell

Beim Start (src/index.ts → createServer() in src/server.ts):

  1. .env aus dem aktuellen Arbeitsverzeichnis laden (dotenv/config).
  2. Konfiguration laden (src/lib/config.ts), fehlende Ordner config/, data/, uploads/ anlegen; config/security.json mit sicheren Standardwerten schreiben, falls nicht vorhanden.
  3. SQLite öffnen, Migrationen ausführen (nur vorwärts, protokolliert in sequelize_migrations).
  4. Leere Datenbank und convert/Data/users.txt vorhanden → automatischer Import aus SmallTime PHP (Umstieg).
  5. Keine Benutzer vorhanden → Konto admin / admin1234 mit Passwortwechsel-Pflicht anlegen.
  6. data/custom.css anlegen, falls nicht vorhanden; Lizenzprüfung starten; HTTP-Server auf PORT starten.

Mit NODE_ENV=production liefert das Backend das gebaute Frontend aus (public/ bzw. frontend/dist) und ersetzt in index.html den Platzhalter __CSP_NONCE__ pro Anfrage. Mit NODE_ENV=development (Standard, wenn nicht gesetzt) liefert es kein Frontend aus, sondern nur einen Hinweistext unter /.

SIGINT/SIGTERM schliessen HTTP-Server, Redis und Datenbank geordnet.


Ports

Port Dienst Quelle
55000 Backend (API, WebSocket, im Betrieb auch Frontend) PORT > config/backend.json → port > 55000
55001 nur Entwicklung: Vite-Dev-Server, leitet /api (inkl. WebSocket) und /custom.css an 55000 weiter Vite: FRONTEND_PORT > frontend/config/frontend.json → port > 55001

Das Backend liest den Frontend-Port nur aus frontend.json (nicht aus FRONTEND_PORT). Er fliesst in die Standard-FRONTEND_ORIGIN (http://localhost:55001) und in die Liste der erlaubten Origins ein.


Ordnerstruktur

Betriebspaket (von prod.cmd / scripts/package-dist.mjs erzeugt, siehe Entwicklung):

<app>/
├── app.cjs              CommonJS-Startdatei, lädt dist/server.js per import() (Plesk/Passenger)
├── dist/server.js       Backend (ESM, minifiziert, mit Source-Map)
├── dist/migrate.js      Migrationen separat (npm run migrate)
├── public/              Frontend-Build
├── config/              backend.json, security.json (Länderfilter aus, allowLocalhost false)
├── package.json         nur Laufzeitabhängigkeiten; start: node app.cjs, migrate: node dist/migrate.js
├── package-lock.json
├── .env                 NODE_ENV=production, zufälliges SESSION_SECRET, FRONTEND_ORIGIN
├── .env.example
│   --- zur Laufzeit angelegt ---
├── node_modules/
├── data/app.sqlite      (+ -wal, -shm)
├── data/backups/        tägliche Kopien DB_YYYY.MM.DD.sqlite (rotiert)
├── data/documents/      Dokumente, PDF-Archiv aus SmallTime PHP
├── data/custom.css      installationsspezifisches CSS, unter /custom.css ausgeliefert
├── uploads/             Datei-Uploads
└── convert/             optional, Quelldaten SmallTime PHP

Repository:

SmallTime_2027.01/
├── backend/             Express-Backend (src/, tests/, config/, data/, uploads/, Dockerfile)
├── frontend/            React-Frontend (src/, config/frontend.json, Dockerfile, nginx.conf)
├── scripts/package-dist.mjs
├── convert/             Quelldaten SmallTime PHP (nicht in Git)
├── dist/                erzeugtes Betriebspaket (nicht in Git)
├── dev.cmd, prod.cmd
└── .nvmrc, .node-version   26.9.0

Pfadauflösung

resolveProjectRoot() in src/lib/config.ts erkennt drei Layouts:

Layout Erkennung config data / uploads Frontend
Repository Ordner frontend/ und backend/ im Projektstamm backend/config (Frontend: frontend/config) backend/data, backend/uploads frontend/dist
Betriebspaket Ordner config/, dist/, public/ nebeneinander config/ (auch frontend.json) data/, uploads/ public/
Fallback (z. B. Docker-Image backend) keines von beiden <root>/backend/config <root>/backend/data, …/uploads <root>/frontend/dist

Der Ordner convert/ liegt immer im Projektstamm (<projectRoot>/convert). Im Docker-Image backend ist das /app/convert.


Vorrang der Konfiguration

Umgebungsvariable > Konfigurationsdatei > Standardwert im Code.

Ausnahmen:

  • TRUST_PROXY: aktiv, wenn TRUST_PROXY=true oder backend.json → trustProxy: true. TRUST_PROXY=false kann einen Wert true aus der Datei nicht aufheben.
  • SECURE_COOKIE, SESSION_SECRET, FRONTEND_ORIGIN, REDIS_URL: nur als Umgebungsvariable.
  • security.json wird zusätzlich über Administration → Sicherheit geschrieben (normalisiert). BCRYPT_COST überschreibt bcryptCost aus der Datei.

Vollständige Liste: Konfiguration.


Betriebsvarianten

Variante Seite
Plesk (Phusion Passenger), z. B. Shared Hosting README.md im Repository, Reverse-Proxy und HTTPS
Windows-Server als Dienst Installation unter Windows
Linux mit systemd Installation unter Linux
Docker / Docker Compose Docker

Einschränkungen

  • Genau eine Instanz pro Datenbank. Rate-Limits, Login-Zähler im Speicher, Lizenzstatus, WebSocket-Verteilung und SQLite sind nicht für mehrere Prozesse ausgelegt. Kein Cluster-Modus, kein Load-Balancing über mehrere Instanzen.
  • Datenbank und Dateien auf lokalem Dateisystem; SQLite im WAL-Modus nicht auf Netzlaufwerke (SMB/NFS) legen.
  • HTTPS terminiert nicht Node.js selbst, sondern ein vorgeschalteter Reverse-Proxy.
  • Ausgehende HTTPS-Verbindung zu lizenz.small.li wird für die Lizenzprüfung benötigt (ohne Antwort bleibt die letzte bekannte Lizenz gültig).

Weiter mit: Konfiguration · Installation unter Windows · Installation unter Linux · Docker

Clone this wiki locally