Installation¶
Eine neue Anlage setzt der Ein-Klick-Installer auf, siehe Probe mit einem Befehl. Diese Seite beschreibt den Umstieg auf einem Server, auf dem bisher calServer v1 läuft: V2 einschalten und die Daten aus v1 übernehmen.
Detaillierte Erstinstallation
Eine vollständige Schritt-für-Schritt-Anleitung finden Sie unter Erstinstallation. Diese Seite beschreibt die wesentlichen Schritte im Überblick.
V2 aktivieren¶
Setzen Sie in der .env-Datei im Projektverzeichnis (Deploy-Verzeichnis, z. B. /var/calserver/.env) die folgenden Variablen:
ENABLE_V2=true
# Datenbank-Engine für V2: pgsql (Default), mysql oder sqlsrv
# pgsql startet einen eigenen PostgreSQL-Container und erfordert PG_PASSWORD;
# mysql nutzt die bestehende V1-MySQL-Datenbank weiter.
V2_DB_CONNECTION=pgsql
PG_PASSWORD=<sicheres-passwort>
PG_PASSWORD ist Pflicht bei pgsql
Ohne gesetztes PG_PASSWORD überspringt deploy.sh die V2-Dienste vollständig — es werden dann keine V2-Container gestartet.
DMS_STORAGE_MODE jetzt entscheiden, nicht später
Wo V2 seine Dokumente ablegt, wird beim Aufsetzen festgelegt: own
(Vorgabe, eigener Baum unter storage/app — für eine Anlage, die neben
einer laufenden V1 aufgebaut wird) oder v1-tree (V2 schreibt im
V1-Dateimanager-Baum weiter — für das reine Update einer bestehenden
Installation). Ein Wechsel nach dem ersten Upload lässt die schon
abgelegten Dokumente an der alten Stelle zurück.
deploy.sh leitet daraus ab, ob der Dateimanager-Baum schreibgeschützt
eingehängt wird; ein zweiter Schalter ist nicht zu stellen. Ausführlich:
Betrieb → Dateispeicher.
Anschließend starten Sie das Deployment:
Das Skript erstellt und startet automatisch alle benötigten Docker-Container.
Update-Sidecar aktivieren (empfohlen)¶
Damit spätere Updates direkt aus der Anwendung heraus laufen (In-App-Updates statt manuellem deploy.sh), aktivieren Sie den Updater-Sidecar. Dazu genügt ein Token in der Host-.env — am besten direkt vor dem ersten Deployment:
deploy.sh aktiviert damit automatisch das Compose-Profil v2-updater und startet den Container calserver-updater. Update-Prüfung, Updates, Rollbacks und der Versionsverlauf stehen anschließend in der Admin-Oberfläche unter Administration → Updates (/admin/updates) zur Verfügung. Der Updater erneuert dabei ausschließlich die V2-Container — die V1-Installation bleibt unberührt.
Bei privaten Docker-Images setzen Sie zusätzlich DOCKERHUB_USERNAME und DOCKERHUB_PULL_TOKEN.
Details zum Update-System
Architektur, Ablauf und alle Umgebungsvariablen des Update-Systems sind in der Update-Anleitung beschrieben.
On-Premise: Stack wird direkt über docker compose gesteuert¶
Viele On-Premise-Mandanten starten den Stack nicht über deploy.sh, sondern direkt über docker compose mit einem zusätzlichen SSL-Overlay (häufig docker-compose.ssl.yml). In diesem Fall entfallen die Automatismen von deploy.sh — drei Dinge sind manuell zu erledigen:
Erst nachsehen, ob es wirklich ein Overlay ist
Unter demselben Dateinamen kursieren zwei grundverschiedene Dinge. Ein
Overlay ergänzt docker-compose.yml und hängt dem nginx-proxy nur
Zertifikate an; dafür gilt die Anleitung unten. Ein eigenständiger
Stack bringt seine Dienste selbst mit, terminiert TLS im V1-Container
(Ports 80:8080 und 443:8443, Container heißt dann meist
calserver_ssl) und fährt ohne nginx-proxy. Bei ihm ist LETSENCRYPT
kein ACME-Schalter, sondern die Bedingung, unter der der Container
überhaupt eine HTTPS-Site schreibt (docker/app/common.sh) — auf false
gesetzt liefert die Anlage nur noch HTTP aus.
Welcher Fall vorliegt, sagt der laufende Container:
docker inspect <container> --format \
'project={{index .Config.Labels "com.docker.compose.project"}}
files={{index .Config.Labels "com.docker.compose.project.config_files"}}'
Nennt files nur die eigene SSL-Datei, ist es der eigenständige Stack.
Dann gilt: deploy.sh, update.sh und die Compose-Dateien des Repos
nicht darüberkopieren, sie kennen diesen Aufbau nicht. Das Routing für
V2 übernimmt dort der V1-Container selbst, sobald ENABLE_V2=true in
seiner Umgebung steht — er schreibt dann /api/v2/ und /v2/ als
eigene nginx-Locations. Zusätzlich fehlt in einem solchen Stack der
report-runner; ohne ihn scheitert in V2 jeder Bericht.
Und Vorsicht mit --remove-orphans: Läuft der eigene Stack aus demselben
Verzeichnis, trägt er dasselbe Compose-Projekt. Ein docker compose down
--remove-orphans gegen docker-compose.yml entfernt dann die laufenden
Container mit.
-
Compose-Profile in der Host-
.envsetzen (sonst starten PostgreSQL- und Updater-Container nicht): -
V2-Overlay in die Dateiliste aufnehmen:
-
Updater-Dateiliste angleichen, falls das SSL-Overlay Konfiguration an den V2-Services selbst ergänzt (z. B.
VIRTUAL_HOST-Variablen). Der Updater arbeitet standardmäßig nur mitdocker-compose.yml:docker-compose.v2.yml— bei einem In-App-Update würde er die V2-Container sonst ohne die Overlay-Konfiguration neu erstellen:Ergänzt das Overlay nur Proxy-/Zertifikats-Dienste (wie
docker-compose.https.ymlin diesem Repository), ist der Default ausreichend.
Docker-Container¶
Nach erfolgreichem Deployment laufen die folgenden zusätzlichen Container:
| Container | Aufgabe | Port |
|---|---|---|
calserver-api-v2 |
Laravel 13 API Backend | 8081 (intern) |
calserver-frontend |
Nuxt 4 Frontend | 3000 (intern) |
redis |
Cache, Queue, Sessions | 6379 (intern) |
calserver-postgres |
PostgreSQL 16 — nur bei V2_DB_CONNECTION=pgsql |
5432 (intern) |
calserver-updater |
Update-Sidecar — nur bei gesetztem UPDATER_TOKEN |
8080 (intern) |
Container-Status prüfen
Verwenden Sie docker compose ps, um den Status aller Container zu prüfen. Alle Container müssen den Status running anzeigen.
Datenbank einrichten¶
Nach dem ersten Start muss die Datenbank initialisiert werden:
| Flag | Beschreibung |
|---|---|
--v1 |
Übernimmt vorhandene v1-Daten in das v2-Schema |
--clean |
Entfernt bestehende v2-Tabellen vor der Neuanlage |
--force |
Führt den Befehl ohne Rückfrage aus (für Skripting) |
Datenverlust bei --clean
Das Flag --clean löscht alle bestehenden v2-Tabellen und legt sie neu an. Verwenden Sie dieses Flag nur bei der Erstinstallation oder wenn ein vollständiger Reset gewünscht ist.
Datenübernahme aus V1 mit MET/TRACK (Sybase ASA)¶
Viele V1-Installationen sind über SymmetricDS an eine MET/TRACK-Datenbank (Sybase SQL Anywhere / ASA) angebunden — die V1-MySQL-Tabellen sind dann eine 1:1-Replik der MET/TRACK-Kerntabellen. Für die Übernahme der Bestandsdaten nach V2 gibt es deshalb zwei Wege:
Weg A — aus der V1-Datenbank (v1:sync)¶
Empfohlen, wenn die V1-Replik aktuell ist (laufender SymmetricDS-Sync). Die Daten werden aus der V1-MySQL-Datenbank übernommen; Kerntabellen werden dabei auf lesbare Spaltennamen gemappt (z. B. I4201 → asset_number):
# Vorschau ohne Schreiben
docker compose exec calserver-api-v2 php artisan v1:sync --dry-run
# Vollständige Übernahme
docker compose exec calserver-api-v2 php artisan v1:sync
Kalibrierart der Auftragspositionen
V1 führt die Kalibrierart einer Auftragsposition in zwei Spalten:
complexity (daran hängen Preiszeilen und der Zuschlag) und
calibration_type (vom Katalogartikel vorbelegt). Die Übernahme führt beide
zusammen — wo complexity leer ist, wird der Wert aus calibration_type
ergänzt. Ein gepflegter Wert wird nie überschrieben, und die Quellspalte
behält ihren Inhalt. Ohne diesen Schritt käme eine Position mit „DAkkS" in
V2 an, ohne dass der DAkkS-Zuschlag je greifen würde.
Zum Abschluss jeder Übernahme geht derselbe Schritt noch einmal über den
Bestand — er fängt, was an der Zuordnung vorbeikam (Teilimport, früher
übernommener Bestand). Prüfen lässt sich das jederzeit mit
php artisan articles:backfill-calibration-type (Bericht; --apply
schreibt).
Die Dokumentdateien kommen nicht mit
v1:sync überträgt die Dokumentdatensätze (Tabelle dms), nicht die
Dateien. Im Modus own liegen die Bytes danach weiterhin nur im V1-Baum:
Die Dokumente stehen vollständig in den Listen, und jeder Download läuft
ins Leere. Einmalig nachholen:
docker exec calserver-api-v2 php artisan dms:import-v1 # Bericht, schreibt nichts
docker exec calserver-api-v2 php artisan dms:import-v1 --apply --force
Der Befehl überschreibt nichts und ist wiederholbar. Im Modus v1-tree
entfällt er — dort benutzt V2 denselben Baum weiter — und er verweigert
sich dann auch, weil Quelle und Ziel identisch wären.
Dieselbe Lücke gibt es für die Berichtsvorlagen: v1:sync bringt die
Metadaten, die JRXML-Pakete und PDF-Briefpapiere holt
php artisan reports:import-templates nach (Quelle storage/app/reports
bzw. --source=PFAD).
Weg B — direkt aus MET/TRACK (mettrack:import)¶
Liest die ASA-Datenbank direkt, ohne den Umweg über SymmetricDS und V1. Die Verbindung kann entweder in der Admin-Oberfläche eingegeben werden (siehe „Weg B (UI)" unten) oder in der Host-.env konfiguriert werden; der ASA-Server muss dafür vom Docker-Host aus per TDS erreichbar sein (Standard-Port 2638):
METTRACK_DB_HOST=asa-server
METTRACK_DB_PORT=2638
METTRACK_DB_DATABASE=mtrack
METTRACK_DB_USERNAME=mt
METTRACK_DB_PASSWORD=<passwort>
# Optional:
# METTRACK_DB_DRIVER=dblib # dblib (FreeTDS/TDS, Standard) oder odbc
# METTRACK_DB_OWNER=mt # Tabellen-Eigentümer in ASA
# METTRACK_ODBC_DSN= # nur bei METTRACK_DB_DRIVER=odbc
Führen Sie danach ./deploy.sh aus, damit der API-Container die Variablen beim Start übernimmt, und starten Sie den Import:
# Verbindung, Module und Zeilenstände prüfen (importiert nichts)
docker compose exec calserver-api-v2 php artisan mettrack:import --list
# Alle MET/TRACK-Module importieren
docker compose exec calserver-api-v2 php artisan mettrack:import --force
Importiert werden die MET/TRACK-Kerntabellen customers, inventory, assethistory, calibration, results, results_raw, standards, repair, location und userlist; nicht gemappte Spalten landen in custom_fields. Der Import liest die Quelle ausschließlich — MET/TRACK und V1 bleiben unverändert.
Weg B (UI) — Anmeldung und Server-Auswahl direkt in der Oberfläche¶
Die Erstmigration steht auch in der Admin-Oberfläche unter Administration → Datenmigration zur Verfügung (Quelle „MET/TRACK (Sybase ASA)", Berechtigung data_migration_admin; der Superadmin hat sie immer, jede andere Rolle bekommt sie über das Rollenmanagement). Die Zugangsdaten der Quelle stehen unter Administration → Schnittstellen → MET/TRACK, mit demselben Recht. Dort lassen sich Server (Host/Port), Datenbank und Anmeldung direkt eingeben — die METTRACK_DB_*-Variablen aus der .env sind dann nicht nötig.
Auf Schnittstellen → MET/TRACK Verbindungstyp (dblib oder ODBC-DSN), Host, Port, Datenbank, Benutzer und Passwort erfassen und „Verbinden & testen" klicken. Steht der mitgelieferte Quellcontainer bereit, genügt der Umschalter „Interne MET/BASE" plus Benutzer und Passwort; Host, Port, Datenbank und Treiber leitet der Server selbst ab.
Bei Erfolg wird der Zugang verschlüsselt für diese Anlage hinterlegt (kein Passwort im Browser-Speicher, nicht in der URL, in der Datenbank nur verschlüsselt). Er gilt damit auch für die Erreichbarkeitsprobe, die Diagnose und php artisan mettrack:import auf der Kommandozeile. „Sitzung trennen" entfernt nur die eigene Anmeldung des angemeldeten Benutzers, nicht die hinterlegte Verbindung der Anlage.
Die Reihenfolge ist: eigene Sitzung, dann hinterlegte Verbindung der Anlage, dann METTRACK_DB_* aus der .env. Wer beides pflegt, bekommt die hinterlegte — sie ist die jüngere und die einzige, die nachweislich funktioniert hat.
Zugangsdaten nach der Übernahme entfernen
Die METTRACK_DB_*-Variablen werden nur für die einmalige Erstmigration benötigt. Entfernen Sie sie nach erfolgreicher Übernahme wieder aus der Host-.env.
Wenn eine Tabelle abbricht¶
Die Oberfläche holt jede Tabelle in Fenstern und schreibt sie einzeln. Was das für einen Modul-Import bedeutet:
- Ein Fenster wird bei einem Netz- oder Serverfehler mehrfach wiederholt. Erst wenn alle Versuche scheitern, gibt die Oberfläche diese Tabelle auf.
- Der Lauf geht mit der nächsten Tabelle weiter. Eine abgebrochene Tabelle stoppt das Modul nicht mehr; sie wird in der Tabellenliste als „Abgebrochen" ausgewiesen, mit dem Grund im Fehlerprotokoll.
- Sehr breite Tabellen bekommen kleinere Fenster.
resultshat 269 Spalten — der Server begrenzt das Fenster dort selbst auf rund 900 Zeilen statt der angefragten 2.000. Der Import braucht dadurch mehr Anfragen und läuft entsprechend länger. - Das Fehlerprotokoll ist die Bilanz, nicht die Zeilenzahl. Gekappte Zeichenketten und geleerte Datumswerte (V1 speichert
0000-00-00, PostgreSQL nimmt das nicht an) stehen dort als Warnung. Die Zeile bleibt erhalten, der Wert nicht — was gekappt wurde, findetphp artisan fields:report-truncation.
Health Check¶
Nach der Installation können Sie die Verfügbarkeit der API mit dem Health-Endpoint prüfen:
Erwartete Antwort:
Health Check schlägt fehl?
Prüfen Sie in folgender Reihenfolge:
- Laufen alle Container? →
docker compose ps - Sind die Umgebungsvariablen korrekt? →
docker compose exec calserver-api-v2 php artisan env - Ist die Datenbank erreichbar? →
docker compose exec calserver-api-v2 php artisan db:monitor - Container-Logs prüfen →
docker compose logs calserver-api-v2 --tail 50
Nächste Schritte¶
Nach erfolgreicher Installation:
- Konfiguration — Umgebungsvariablen und Routing anpassen
- Benutzer anlegen — Erste Administratoren einrichten
- Rollen konfigurieren — Berechtigungen vergeben
- Update-Anleitung — In-App-Updates über den Updater-Sidecar