Fehlerbehebung¶
Loesungen fuer haeufige Probleme in calServer V2.
Haeufige Probleme¶
Die Anlage meldet ERR_SSL_PROTOCOL_ERROR (V1 und V2 gleichzeitig)¶
„Diese Website kann keine sichere Verbindung bereitstellen“
Symptom: Der Browser zeigt
V1 und V2 sind gleichzeitig betroffen.
Das ist kein Zertifikatsproblem. nginx-proxy baut den Server-Block
eines Namens aus den laufenden Containern. Fehlt der Container, der
VIRTUAL_HOST traegt, gibt es fuer den Namen ueberhaupt keinen Block:
auf 443 antwortet der Vorgabeserver mit ssl_reject_handshake
(TLS-Alert unrecognized_name, im Browser ERR_SSL_PROTOCOL_ERROR), auf
80 mit einer nackten 503.
Zwei Zeilen bestaetigen den Befund, von jedem Rechner aus:
# 503 vom nginx-Vorgabeserver statt der Anwendung
curl -sS -o /dev/null -w '%{http_code}\n' http://<domain>/
# "tlsv1 unrecognized name" statt eines Zertifikatsfehlers
curl -sS https://<domain>/
Antwortet eine andere Subdomain derselben Anlage sauber ueber HTTPS
(z. B. database.<domain>), dann sind nginx-proxy, Zertifikate und DNS in
Ordnung. Es fehlt nur der Container, der den vhost traegt:
| Betrieb | Container mit VIRTUAL_HOST |
|---|---|
| V1 + V2 (Standard) | calserver-frontend |
V2 ohne V1 (V2_STANDALONE=true) |
calserver-frontend |
Reine V1-Anlage (ENABLE_V2=false) |
calserver |
Alles unter diesem Namen liegt im selben Server-Block
(docker/nginx/vhost.d/default_location) und ist deshalb gemeinsam weg,
sobald der Träger fehlt.
Der Träger hat gewechselt (August 2026)
Bis dahin trug calserver (V1) den vhost, im Parallelbetrieb also auch
für V2. Ein Ausfall des Yii-Containers nahm V2 damit zwangsläufig mit.
Seither trägt das Frontend den Namen, sobald V2 mitläuft, und V1 hängt
als gewöhnlicher Upstream in der default_location: ein V1-Ausfall
kostet nur noch V1, /v2/ und /api/v2/ antworten weiter, die
V1-Pfade geben ein 502.
Der Einzelpunkt ist damit nicht verschwunden, er sitzt auf dem kleineren
Container. Zurückdrehen lässt er sich ohne Codeänderung mit
VHOST_CARRIER_PIN=v1 in der .env plus ./deploy.sh.
Behebung auf dem Host:
cd /var/calserver
# Zustand aller Container, auch der gestoppten
docker compose ps -a
# Ursache des Abbruchs — hier und nur hier steht sie
docker logs calserver --tail 50
# Wieder hochfahren (oder gleich ./deploy.sh)
docker compose up -d calserver
# Gegenprobe: der Name muss im Proxy stehen
docker exec nginx-proxy nginx -T | grep server_name
Kommt der Container nicht hoch, steht der Grund in seinen Logs. Haeufig:
volle Platte (df -h), Datenbank nicht erreichbar, fehlgeschlagener
Image-Pull.
Let's Encrypt erneuert waehrenddessen nicht
Ohne vhost laeuft auch die HTTP-01-Challenge in die 503, der acme-companion kann also nicht erneuern. Das holt er nach, sobald der Container zurueck ist. Ein Zertifikat neu ausstellen zu lassen, behebt den Ausfall nicht.
./deploy.sh warnt seit dem vhost-Waechter von selbst
Der Deploy prueft nach up -d, ob nginx-proxy einen Server-Block fuer
CALSERVER_HOST fuehrt, und gibt bei Fehlanzeige Containerzustand und
Logs gleich mit aus. Frueher pruefte er HTTPS gegen localhost und traf
damit den Vorgabeserver: gruener Deploy, dunkle Anlage.
Login-Probleme¶
Benutzer kann sich nicht anmelden
Symptom: Login-Seite zeigt Fehlermeldung oder laedt endlos.
Loesungen:
- Pruefen Sie, ob der Benutzer in der Datenbank aktiv ist
- Setzen Sie das Passwort zurueck:
php artisan user:reset-password <email> - Pruefen Sie die Session-Konfiguration in
.env - Cache leeren:
php artisan cache:clear
E-Mail-Versand funktioniert nicht¶
| Pruefpunkt | Befehl |
|---|---|
| SMTP-Konfiguration | .env-Datei pruefen (MAIL_HOST, MAIL_PORT) |
| Mail-Queue | php artisan queue:work --queue=mail |
| Mail-Log | storage/logs/laravel.log durchsuchen |
| Testmail senden | php artisan mail:test <empfaenger> |
Berichterstellung schlaegt fehl¶
Jeder Bericht wird vom Dienst report-runner gerendert. Laeuft er nicht,
schlaegt jeder Bericht fehl, und der Siegel-Abgleich ebenfalls.
# Zustand pruefen
docker compose ps report-runner
# Logs anzeigen — hier steht die Ursache
docker logs report-runner --tail 20
# Neu starten
docker compose up -d report-runner
„Could not resolve host: report-runner" ist kein Adressfehler
Meldet die Oberflaeche
dann ist nicht REPORT_RUNNER_URL falsch. Docker-DNS kennt nur
laufende Container: ein Dienst, der beim Start abbricht, hat keinen Namen
im Compose-Netz. Der Grund steht ausschliesslich in
docker logs report-runner.
Haeufigste Ursache: ab report-runner 2.2.0 verweigert der Dienst den
Start, solange weder REPORT_RUNNER_TOKEN noch
REPORT_RUNNER_ALLOW_ANONYMOUS=true gesetzt ist (ADR-041). Er kompiliert
vom Aufrufer gelieferte Vorlagen und haelt den PDF-Signaturschluessel,
deshalb muss anonymer Zugriff eine Entscheidung sein.
Der Weg zurueck steht unter
Token fuer den report-runner.
Auf einer Anlage mit Updater-Sidecar erzeugt der das Token beim naechsten
Update selbst; ./deploy.sh tut es ebenfalls.
Alte Anleitungen sprechen von einem Dienst jasper
Den gibt es nicht und gab es in V2 nie — docker compose ps jasper
antwortet mit „no such service". Der Dienst heisst report-runner.
In-App-Update scheitert an einem undefinierten Dienst¶
Meldet Administration -> Updates etwas wie
compose pull: exit status 15 (output: … service "calserver-api-v2" depends on
undefined service "report-runner": invalid compose project)
oder no such service: report-runner, dann passen Dienstliste und
compose-Dateisatz des Updaters nicht zusammen. Der Updater faehrt bewusst mit
weniger Dateien als deploy.sh (UPDATER_COMPOSE_FILE, per Vorgabe
docker-compose.yml:docker-compose.v2.yml). Auf gewachsenen Installationen
heisst die V1-Datei aber manchmal anders — etwa docker-compose.ssl.yml — und
der Runner ist dann in einer Datei definiert, die der Updater gar nicht laedt.
Welche Dateien die laufenden Container wirklich benutzen, sagt ihr Compose-Label:
docker inspect calserver-api-v2 \
--format '{{index .Config.Labels "com.docker.compose.project.config_files"}}'
# und wo der Runner definiert ist:
grep -ln 'report-runner:' /opt/calserver/docker-compose*.yml
Danach UPDATER_COMPOSE_FILE in der Host-.env auf denselben Satz setzen
(Doppelpunkt als Trenner) und den Updater neu erstellen:
# Beispiel, wenn die V1-Dienste in docker-compose.ssl.yml stehen:
# UPDATER_COMPOSE_FILE=docker-compose.ssl.yml:docker-compose.v2.yml
docker compose up -d calserver-updater
Der zuverlaessige Weg bleibt ./deploy.sh
Es benutzt seinen eigenen, vollstaendigen Dateisatz und zieht dabei auch
das Updater-Image nach. Ein Updater, der zu alt ist, kann sich aus diesem
Zustand nicht selbst befreien: er aktualisiert sich per Vorgabe nicht
selbst, damit ein compose up ihn nicht mitten im Update abraeumt.
Speichern schlaegt mit "duplicate key value" fehl (PostgreSQL)¶
Meldet das Anlegen eines Datensatzes duplicate key value violates unique
constraint "<tabelle>_pkey", haengt die Sequenz der Tabelle hinter ihrem
Inhalt zurueck. PostgreSQL zaehlt eine Sequenz nur hoch, wenn sie die ID
vergeben hat — Zeilen, die mit fester ID hereinkamen (V1-Uebernahme,
Demo-Daten, eingespielte Sicherung), lassen sie stehen. Danach scheitert jeder
Schreibvorgang, einmal pro belegter ID; das wirkt sporadisch, weil zwischen
zwei Fehlern immer wieder einer durchgeht. Eine abgebrochene
Demo-Wiederherstellung konnte denselben Zustand hinterlassen; das ist
behoben, eine schon zurueckgebliebene Sequenz muss aber einmal nachgezogen
werden. Ein typisches Anzeichen ist der Fristen-Lauf des Ticketsystems, der
mit mailer_message_pkey scheitert.
# Erst nachsehen (schreibt nichts, Exit-Code 1 wenn etwas zurueckhaengt):
docker exec calserver-api-v2 php artisan db:repair-sequences --dry-run
# Alle betroffenen Sequenzen auf MAX(id) setzen:
docker exec calserver-api-v2 php artisan db:repair-sequences
# Nur eine bestimmte Tabelle:
docker exec calserver-api-v2 php artisan db:repair-sequences --table=wiki_page_revision
Auf MySQL und MS SQL Server kann das nicht auftreten — dort steckt der Zaehler in der Tabelle. Der Befehl meldet dort, dass nichts zu tun ist.
DMS-Speicherprobleme¶
- Datei-Upload fehlgeschlagen: Speicherplatz pruefen (
df -h) - Dateien nicht auffindbar: Symlink pruefen (
php artisan storage:link) - Berechtigungsfehler: Verzeichnisrechte korrigieren:
System-Logs¶
Der AdminLogController bietet Zugriff auf Systemprotokolle ueber die Admin-Oberflaeche:
- Administration > Information > System Log: Alle Log-Eintraege anzeigen und filtern
- Filter nach Level:
ERROR,WARNING,INFO,DEBUG - Filter nach Zeitraum und Benutzer
Anwendungslog (Stacktraces)¶
Das System Log zeigt, was der db-Kanal geschrieben hat: die Meldung, sonst
nichts. Klasse, Datei, Zeile und Stacktrace einer Exception stehen nur in der
Logdatei. Bei einem HTTP 500 ist also Administration > Information >
Anwendungslog der richtige Ort:
- liest
storage/logs/*.log, standardmaessig die zuletzt geschriebene Datei - Umschalten auf aeltere Dateien der Tagesrotation ueber die Auswahl "Datei"
- Filter nach Level und Volltextsuche ueber Meldung und Stacktrace
- Doppelklick auf eine Zeile oeffnet den vollstaendigen Eintrag samt Stacktrace, mit Schaltflaeche zum Kopieren
Gelesen wird immer nur das Ende der Datei. Ist sie groesser, sagt die Ansicht das ausdruecklich — es fehlen dann aeltere Eintraege, nicht neuere.
Log-Dateien direkt einsehen¶
# Aktuelles Log anzeigen
tail -f storage/logs/laravel.log
# Nach Fehlern suchen
grep "ERROR" storage/logs/laravel.log | tail -20
Cache leeren¶
Der CacheController ermoeglicht das Leeren verschiedener Caches:
# Alle Caches leeren
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear
# Optimierung neu aufbauen
php artisan optimize
Ueber die Admin-Oberflaeche
Cache kann auch ueber Admin > System > Cache leeren zurueckgesetzt werden.
Health-Check¶
Der Health-Check-Endpoint prueft den Systemzustand:
Antwort bei gesundem System:
{
"status": "ok",
"database": "connected",
"cache": "available",
"queue": "running",
"storage": "writable"
}
Kritische Fehler
Falls der Health-Check fehlschlaegt, pruefen Sie:
- Datenbankverbindung (
DB_HOST,DB_DATABASEin.env) - Redis-Verbindung (
REDIS_HOSTin.env) - Dateisystem-Berechtigungen
- Docker-Container-Status:
docker compose ps