-
Notifications
You must be signed in to change notification settings - Fork 0
IT Konfiguration
Caution
Diese Seite richtet sich ausschliesslich an Informatikerinnen und Informatiker. Nicht für Laien geeignet: Falsche Werte können Anmeldungen verhindern, alle Personen abmelden, jede Anfrage sperren oder Schutzmechanismen ausser Kraft setzen. Ohne Fachkenntnisse bitte den Bereich Installation Schritt für Schritt verwenden.
Für wen ist diese Seite? Referenz aller Umgebungsvariablen und Konfigurationsdateien von SmallTime 2027. Quelle: backend/src/lib/config.ts, backend/src/lib/constants.ts, backend/.env.example, backend/config/*.json, frontend/vite.config.ts, scripts/package-dist.mjs.
- Grundregeln
- Umgebungsvariablen
- config/backend.json
- config/security.json
- frontend.json und Vite
- convert/convert.json
- Fest eingebaute Werte
- Empfohlene Produktionswerte
-
Vorrang: Umgebungsvariable > Konfigurationsdatei > Standard im Code (Ausnahmen bei
TRUST_PROXY, siehe unten). -
.envwird mitdotenvaus dem Arbeitsverzeichnis des Prozesses geladen. Bereits gesetzte Umgebungsvariablen (z. B. aus systemd, Docker, Plesk) werden von.envnicht überschrieben. - Die JSON-Dateien werden beim Start mit zod validiert. Ein ungültiger Wert bricht den Start mit einer Meldung wie
security.json ist ungueltig: …ab. - Konfigurationsänderungen wirken erst nach einem Neustart. Ausnahme:
security.json, wenn sie über Administration → Sicherheit gespeichert wird (sofort wirksam). - Ablage der Dateien: Betriebspaket
config/, Repositorybackend/config/(Frontend:frontend/config/), siehe Pfadauflösung.
| Name | Standard | Bedeutung |
|---|---|---|
NODE_ENV |
development |
production: Frontend wird ausgeliefert, SESSION_SECRET Pflicht, Kompression standardmässig an, morgan im Format combined. development: kein Frontend-Auslieferung, morgan dev. |
PORT |
backend.json → port, sonst 55000
|
HTTP-Port des Backends. Viele Hostings (Plesk/Passenger) setzen ihn selbst. |
SESSION_SECRET |
Dev-Standard SmallTime-dev-session-secret
|
Schlüssel für JWT-Signatur und signierte Cookies. In production Pflicht; ist er leer oder gleich dem Dev-Standard, bricht der Start ab (SESSION_SECRET muss in Produktion explizit gesetzt werden.). Mind. 48 zufällige Bytes empfohlen. Ändern meldet alle Personen ab.
|
FRONTEND_ORIGIN |
http://localhost:<frontend.json port> = http://localhost:55001
|
Öffentliche Origin exakt wie im Browser: Schema, Host, optional Port, ohne Pfad und ohne / am Ende (wird entfernt). Muster ^https?://[^/\s]+$, sonst Startabbruch. Wird für CORS/Origin-Prüfung und für die Lizenz-Domain verwendet. |
SECURE_COOKIE |
false |
true: Cookies immer mit Secure, HSTS-Header immer gesetzt. Hinter einem TLS-Proxy auf true. |
TRUST_PROXY |
false (bzw. backend.json → trustProxy) |
true: Express trust proxy = 1 (genau ein Hop). request.ip aus X-Forwarded-For, request.secure aus X-Forwarded-Proto, Hostname aus X-Forwarded-Host. Länder-Header werden nur mit TRUST_PROXY ausgewertet. Aktiv, wenn Env oder Datei true ist. |
ENABLE_COMPRESSION |
production: true, sonst false (bzw. backend.json → enableCompression) |
gzip/deflate über compression. Nur true/false erlaubt, sonst Startabbruch. /api/auth* und /api/csrf-token werden nie komprimiert (BREACH). |
BCRYPT_COST |
security.json → bcryptCost, sonst 10
|
bcrypt-Kostenfaktor 4–15. Produktion: 12 (vom Paket so gesetzt), sofern die Login-Latenz passt. |
REDIS_URL |
leer | z. B. redis://redis:6379. Leer oder nicht erreichbar → In-Memory-Benutzer-Cache (Warnung im Log). |
USER_CACHE_TTL_SECONDS |
120 |
TTL des Benutzer-Caches (positive Ganzzahl). |
LICENSE_SERVER_URL |
https://lizenz.small.li/info |
Endpunkt der Lizenzprüfung (POST, Formularfelder LizenzKey, Domain). Nur für Tests/Hersteller ändern. |
SMALLTIME_AUTO_IMPORT |
– |
false schaltet den automatischen Import aus convert/ beim Start ab (zusätzlich zu autoImport in convert.json). |
SMALLTIME_ORIGIN |
– |
Nur beim Paketbau (scripts/package-dist.mjs): Wert für FRONTEND_ORIGIN in der erzeugten .env. Ohne Angabe Platzhalter https://smalltime.example.ch. |
FRONTEND_PORT |
frontend.json → port, sonst 55001
|
Nur Vite-Dev-Server (frontend/vite.config.ts). |
Note
PORT wirkt in vite.config.ts zusätzlich als Ziel des Dev-Proxys (http://localhost:<PORT>).
backend/.env.example (Entwicklung):
PORT=55000
FRONTEND_ORIGIN=http://localhost:55000
SESSION_SECRET=change-me
NODE_ENV=development
SECURE_COOKIE=false
TRUST_PROXY=false
ENABLE_COMPRESSION=false
BCRYPT_COST=10Vom Paketbau erzeugte .env (Produktion):
NODE_ENV=production
FRONTEND_ORIGIN=https://smalltime.example.ch
SESSION_SECRET=<48 zufällige Bytes, Base64>
# PORT=55000
SECURE_COOKIE=true
TRUST_PROXY=true
ENABLE_COMPRESSION=true
BCRYPT_COST=12Warning
prod.cmd erzeugt bei jedem Lauf eine neue .env mit neuem SESSION_SECRET. Beim Update die .env auf dem Server nicht überschreiben.
| Schlüssel | Standard | Bedeutung |
|---|---|---|
port |
55000 |
HTTP-Port (von PORT übersteuert) |
trustProxy |
false |
wie TRUST_PROXY
|
enableCompression |
abhängig von NODE_ENV
|
wie ENABLE_COMPRESSION (Env hat Vorrang) |
apiRateLimit |
{ "limit": 300, "windowMinutes": 15 } |
globales Limit für /api pro Client-IP (express-rate-limit). Antwort 429 / E1007. |
uploads.allowedExtensions |
Code: .bmp .csv .gif .jpeg .jpg .json .md .png .txt .webp; ausgelieferte Datei zusätzlich .zip .pdf .doc .docx .xls .xlsx .ppt .pptx
|
erlaubte Endungen für Uploads. Leere Liste → Code-Standard. Punkt wird ergänzt, Kleinschreibung. |
Ausgelieferte Datei:
{
"port": 55000,
"uploads": {
"allowedExtensions": [".bmp", ".csv", ".gif", ".jpeg", ".jpg", ".json", ".md", ".png", ".txt",
".webp", ".zip", ".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx"]
}
}Note
Das Frontend liest backend/config/backend.json beim Build (vite.config.ts) für die Dateiauswahl im Browser. Die verbindliche Prüfung (Endung, Dateiinhalt über file-type, Grösse) macht das Backend. Nach einer Änderung der Liste sollte das Frontend neu gebaut werden, damit die Auswahl übereinstimmt.
Important
Alle Personen hinter einer gemeinsamen öffentlichen IP (Büro mit NAT) teilen sich apiRateLimit. Bei vielen Personen oder Terminals hinter einer IP das Limit erhöhen.
Wird beim ersten Start mit den Standardwerten angelegt, falls sie fehlt (Registrierung aus). Über Administration → Sicherheit änderbar; dabei wird die Datei normalisiert neu geschrieben.
| Schlüssel | Standard im Code | Repo-Datei | Betriebspaket | Bedeutung |
|---|---|---|---|---|
rateLimits.login |
5 / 5 min | gleich | gleich | Login-Versuche pro Client-IP (auch erfolgreiche). 429 / E1025. Gilt auch für Terminal-Stempeln mit Passwort. |
rateLimits.passwordChange |
5 / 15 min | gleich | gleich | Passwortwechsel pro IP |
rateLimits.upload |
20 / 10 min | gleich | gleich | Uploads pro IP |
allowedCountries |
[] |
DE AT CH IT LI |
[] |
ISO-3166-Alpha-2-Codes. Leere Liste = Länderfilter aus (IP-Listen wirken trotzdem). |
countryHeaders |
CF-IPCountry, CloudFront-Viewer-Country, X-Country-Code, X-Geo-Country, X-Country
|
gleich | gleich | Header, aus denen der Ländercode gelesen wird (erster gültiger gewinnt). Nur mit TRUST_PROXY. Leere Liste → Standard. |
allowedIpRanges |
[] |
[] |
[] |
IP oder CIDR. Nicht leer → nur diese IPs zugelassen. |
blockedIpRanges |
[] |
[] |
[] |
IP oder CIDR, immer gesperrt |
allowRegistration |
false |
false |
false |
Selbstregistrierung. Für SmallTime ausgeschaltet lassen; Konten legt der Admin an. |
allowLocalhost |
true |
true |
false |
Anfragen von Loopback (bzw. Host localhost + private IP) umgehen Länder-/IP-Filter und das globale API-Limit. |
bcryptCost |
10 |
10 |
10 |
4–15; BCRYPT_COST hat Vorrang |
Auswertungsreihenfolge (getSecurityDecisionForRequest): Länderliste und beide IP-Listen leer → erlaubt. Sonst: allowLocalhost → blockedIpRanges → allowedIpRanges → (nur bei nicht leerer Länderliste) Ländercode aus Header. Ohne gültigen Ländercode: 403 «Kein gültiger Ländercode vom Proxy geliefert».
Warning
-
allowedIpRangesundblockedIpRangeswerden auch bei leerer Länderliste ausgewertet. - Ist
allowedCountriesnicht leer und liefert der Proxy keinen Länder-Header (oderTRUST_PROXYist aus), wird jede externe Anfrage mit 403 abgelehnt. Der Code-Standard ist deshalb[](Länderfilter aus); so wird auchconfig/security.jsonbeim ersten Start angelegt (z. B. leeres Docker-Volume). - Hinter einem Reverse-Proxy
allowLocalhostauffalse, sonst gelten bei falscher Proxy-Konfiguration alle Anfragen als lokal.
frontend/config/frontend.json (Betriebspaket: config/frontend.json, nicht ausgeliefert, optional):
{ "port": 55001 }| Wert | Wirkung |
|---|---|
port |
Port des Vite-Dev-Servers; im Backend Teil der Standard-FRONTEND_ORIGIN und der erlaubten Origins (http://localhost:<port>, http://127.0.0.1:<port>) |
Beim Build definiert Vite __APP_FRONTEND_PORT__, __APP_BACKEND_PORT__ und __APP_ALLOWED_UPLOAD_EXTENSIONS__ (aus backend.json). Der Dev-Server leitet /api (mit WebSocket) und /custom.css an das Backend weiter.
Erlaubte Origins (CORS und WebSocket): FRONTEND_ORIGIN, http://localhost:<frontendPort>, http://127.0.0.1:<frontendPort>, http://localhost:<PORT>, http://127.0.0.1:<PORT>. Andere Origins erhalten 403 / E1006. Für den WebSocket gilt zusätzlich eine Origin gleich http(s)://<Host-Header> als erlaubt.
Optionen des Imports aus SmallTime PHP (conversion-options.ts, .strict() – unbekannte Schlüssel sind ein Fehler). Kommandozeile (npm run convert -- …, nur im Repository) > Datei > Standard.
| Schlüssel | Standard | Bedeutung |
|---|---|---|
cutoverDate |
erster Tag des Folgemonats | Stichtag YYYY-MM-01
|
legacyTimeZone |
Europe/Paris |
Zeitzone der Unix-Zeitstempel der Altversion |
timeZone |
aus Land (settings.txt [12]) |
fachliche Zeitzone (IANA) |
calendarCode |
aus Land |
CH, DE, AT, LI
|
autoImport |
true |
automatischer Import bei leerer DB |
Details: Umstieg von SmallTime PHP.
Nicht konfigurierbar (src/lib/constants.ts u. a.):
| Wert | Grösse |
|---|---|
Access-Token (Cookie SmallTime.access) |
15 Minuten |
Refresh-Token (Cookie SmallTime.refresh, Pfad /api/auth) |
2 Tage ohne Aktivität |
| CSRF-Cookie / -Header |
SmallTime.csrf / x-csrf-token
|
| Upload | max. 5 MB pro Datei, max. 10 Dateien pro Anfrage |
| JSON-/Formular-Body | max. 2 MB |
| Terminal-Rate-Limit | 120 Anfragen pro Minute und Gerätetoken |
| Kontosperre | 30 Fehlversuche innerhalb 60 Minuten pro Konto |
| Altpasswörter aus SmallTime PHP | 60 Tage gültig (Einstellung legacyPasswordValidDays) |
| Lizenzprüfung | beim Start, dann alle 24 h, Timeout 10 s |
| Datenbank-Kopie | täglich, data/backups/, alte Kopien werden automatisch rotiert |
SQLite busy_timeout
|
5000 ms |
| WebSocket-Heartbeat | 30 s, max. Nachricht 1 KiB |
| HSTS | max-age=31536000; includeSubDomains |
NODE_ENV=production
FRONTEND_ORIGIN=https://zeit.example.ch
SESSION_SECRET=<node -e "console.log(require('crypto').randomBytes(48).toString('base64'))">
SECURE_COOKIE=true
TRUST_PROXY=true
ENABLE_COMPRESSION=true
BCRYPT_COST=12
# REDIS_URL=redis://127.0.0.1:6379Dazu security.json mit allowLocalhost: false, allowRegistration: false und – nur wenn ein vertrauenswürdiger Proxy/CDN einen Länder-Header setzt – einer Länderliste. Siehe Reverse-Proxy und HTTPS.
Weiter mit: Reverse-Proxy und HTTPS · Sicherheit und Betrieb · Übersicht
SmallTime 2027 · Version 1.0 · Zur Startseite · Fragen? Zuerst in den häufigen Fragen für Anwender oder Admins nachsehen.
👤 Anwender
🧑💼 Admins
- Erste Schritte
- Personen
- Arbeitsmodelle
- Ferien und Absenzen
- Saldo und Auszahlungen
- Monatsabschluss
- Gruppen und Rechte
- Stammdaten
- Einstellungen
- Terminals und Badges
- Protokoll und Sicherheit
- Häufige Fragen
🛠️ Einrichten
💻 Informatik (nur Fachleute)