Troubleshooting¶
Solutions for common problems in calServer V2.
Common Problems¶
The site reports ERR_SSL_PROTOCOL_ERROR (V1 and V2 at once)¶
„This site can't provide a secure connection“
Symptom: The browser shows
V1 and V2 are affected at the same time.
This is not a certificate problem. nginx-proxy builds a name's
server block from the running containers. When the container carrying
VIRTUAL_HOST is gone, there is no block for that name at all: on 443
the default server answers with ssl_reject_handshake (TLS alert
unrecognized_name, ERR_SSL_PROTOCOL_ERROR in the browser), on 80 with
a bare 503.
Two lines confirm it, from any machine:
# 503 from the nginx default server instead of the application
curl -sS -o /dev/null -w '%{http_code}\n' http://<domain>/
# "tlsv1 unrecognized name" instead of a certificate error
curl -sS https://<domain>/
If another subdomain of the same installation answers over HTTPS just fine
(database.<domain>, for instance), then nginx-proxy, the certificates and
DNS are all healthy. Only the container carrying the vhost is missing:
| Mode | Container with VIRTUAL_HOST |
|---|---|
| V1 + V2 (default) | calserver-frontend |
V2 without V1 (V2_STANDALONE=true) |
calserver-frontend |
V1-only install (ENABLE_V2=false) |
calserver |
Everything under that name lives in the same server block
(docker/nginx/vhost.d/default_location) and is therefore gone together as
soon as the carrier is missing.
The carrier changed (August 2026)
Until then calserver (V1) carried the vhost, in parallel operation for
V2 as well. A failure of the Yii container inevitably took V2 with it.
Since then the frontend carries the name whenever V2 is running, and V1
hangs in the default_location like any other upstream: a V1 outage
now costs V1 only, /v2/ and /api/v2/ keep answering, the V1 paths
return a 502.
The single point of failure has not disappeared, it sits on the smaller
container. It can be moved back without a code change via
VHOST_CARRIER_PIN=v1 in .env plus ./deploy.sh.
Fix on the host:
cd /var/calserver
# State of every container, stopped ones included
docker compose ps -a
# Why it aborted — the reason is only ever in here
docker logs calserver --tail 50
# Bring it back (or just run ./deploy.sh)
docker compose up -d calserver
# Cross-check: the name has to be in the proxy
docker exec nginx-proxy nginx -T | grep server_name
If the container refuses to start, its logs hold the reason. Common ones:
a full disk (df -h), an unreachable database, a failed image pull.
Let's Encrypt does not renew meanwhile
Without a vhost the HTTP-01 challenge runs into the 503 as well, so the acme-companion cannot renew. It catches up once the container is back. Reissuing a certificate does not fix the outage.
./deploy.sh warns on its own since the vhost guard
After up -d the deploy checks whether nginx-proxy carries a server
block for CALSERVER_HOST, and prints container state and logs right
away when it does not. It used to probe HTTPS against localhost, which
hit the default server: green deploy, dark installation.
Login Issues¶
User cannot log in
Symptom: Login page shows an error message or loads indefinitely.
Solutions:
- Check if the user is active in the database
- Reset the password:
php artisan user:reset-password <email> - Check the session configuration in
.env - Clear cache:
php artisan cache:clear
Email Sending Not Working¶
| Check Point | Command |
|---|---|
| SMTP configuration | Check .env file (MAIL_HOST, MAIL_PORT) |
| Mail queue | php artisan queue:work --queue=mail |
| Mail log | Search storage/logs/laravel.log |
| Send test email | php artisan mail:test <recipient> |
Report Generation Fails¶
Every report is rendered by the report-runner service. While it is down,
every report fails, and so does the seal reconciliation.
# Check the service
docker compose ps report-runner
# Show the logs — the cause is in here
docker logs report-runner --tail 20
# Restart it
docker compose up -d report-runner
„Could not resolve host: report-runner" is not an address problem
When the UI reports
then REPORT_RUNNER_URL is not wrong. Docker DNS only knows running
containers: a service that aborts during startup has no name on the
compose network. The reason is only ever in docker logs report-runner.
Most common cause: since report-runner 2.2.0 the service refuses to
start unless either REPORT_RUNNER_TOKEN or
REPORT_RUNNER_ALLOW_ANONYMOUS=true is set (ADR-041). It compiles
caller-supplied templates and holds the PDF signing key, so anonymous
access has to be a decision.
The way back is documented under
Token for the report-runner.
On an installation with the updater sidecar the token is generated on the
next update; ./deploy.sh does it as well.
Older instructions mention a jasper service
There is none, and V2 never had one — docker compose ps jasper answers
"no such service". The service is called report-runner.
Saving fails with "duplicate key value" (PostgreSQL)¶
If creating a record reports duplicate key value violates unique constraint
"<table>_pkey", the table's sequence lags behind its contents. PostgreSQL only
advances a sequence when it handed out the id — rows that arrived with an
explicit id (V1 migration, demo data, a restored backup) leave it where it was.
Every write then fails, once per occupied id, which looks intermittent because
one gets through between failures. An aborted demo restore could leave the
same state behind; that is fixed, but a sequence that already lags has to be
moved once. A typical sign is the ticket deadline run failing on
mailer_message_pkey.
# Report only (writes nothing, exit code 1 if a sequence lags):
docker exec calserver-api-v2 php artisan db:repair-sequences --dry-run
# Set every affected sequence to MAX(id):
docker exec calserver-api-v2 php artisan db:repair-sequences
# A single table:
docker exec calserver-api-v2 php artisan db:repair-sequences --table=wiki_page_revision
MySQL and MS SQL Server cannot hit this — they keep the counter inside the table. There the command reports that there is nothing to do.
DMS Storage Issues¶
- File upload failed: Check storage space (
df -h) - Files not found: Check symlink (
php artisan storage:link) - Permission errors: Correct directory permissions:
System Logs¶
The AdminLogController provides access to system logs via the admin interface:
- Administration > Information > System Log: View and filter all log entries
- Filter by level:
ERROR,WARNING,INFO,DEBUG - Filter by time period and user
Application log (stack traces)¶
The System Log shows what the db channel wrote: the message and nothing
else. An exception's class, file, line and stack trace live in the log file
only. So for an HTTP 500, Administration > Information > Application log is
the place to look:
- reads
storage/logs/*.log, by default the most recently written file - switch to older files of the daily rotation via the "Datei" selector
- filter by level, full-text search across message and stack trace
- double-click a row for the complete entry including the stack trace, with a copy button
Only the end of the file is ever read. When the file is larger, the view says so explicitly — what is missing then is older entries, never newer ones.
View Log Files Directly¶
# Show current log
tail -f storage/logs/laravel.log
# Search for errors
grep "ERROR" storage/logs/laravel.log | tail -20
Clear Cache¶
The CacheController enables clearing various caches:
# Clear all caches
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear
# Rebuild optimization
php artisan optimize
Via admin interface
Cache can also be reset via Admin > System > Clear Cache.
Health Check¶
The health check endpoint verifies the system status:
Response for a healthy system:
{
"status": "ok",
"database": "connected",
"cache": "available",
"queue": "running",
"storage": "writable"
}
Critical errors
If the health check fails, verify:
- Database connection (
DB_HOST,DB_DATABASEin.env) - Redis connection (
REDIS_HOSTin.env) - File system permissions
- Docker container status:
docker compose ps