Skip to content

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

<domain> sent an invalid response.
ERR_SSL_PROTOCOL_ERROR

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:

  1. Check if the user is active in the database
  2. Reset the password: php artisan user:reset-password <email>
  3. Check the session configuration in .env
  4. 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

Report runner unavailable: cURL error 6: Could not resolve host: report-runner

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:
chmod -R 775 storage/app/dms
chown -R www-data:www-data storage/app/dms

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:

GET /api/v2/health

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_DATABASE in .env)
  • Redis connection (REDIS_HOST in .env)
  • File system permissions
  • Docker container status: docker compose ps