Troubleshooting
Common issues and how to diagnose them. Run commands from the compose directory.
First-line diagnostics
Section titled “First-line diagnostics”docker compose ps # what's up / healthy / restartingdocker compose logs --tail=100 qsign-backenddocker compose logs --tail=50 nginx esign dbcurl -sI https://sign.example.com/health # 200 expectedBackend won’t start / restarts in a loop
Section titled “Backend won’t start / restarts in a loop”- Missing
SECRET_KEY→ the backend refuses to boot. Ensure it’s set inconfig/backend.env. - Database not reachable → check
dbis healthy (docker compose ps), thatDB_HOST/PORT/USER/PASSWORD/DB_NAMEmatchconfig/db.env, and that the DB finished initializing on first run (MySQL takes longer the first time). The backenddepends_onthe DB healthcheck. - Migrations failing → read
docker compose logs qsign-backend. If you just upgraded, consult the release notes; if needed, restore the pre-upgrade DB dump and retry. - Bad settings module →
DJANGO_SETTINGS_MODULEmust point at the intended settings.
Can’t log in (credentials correct)
Section titled “Can’t log in (credentials correct)”REACT_APP_LOGIN_PASSWORD_KEY≠BACKEND_LOGIN_PASSWORD_KEY. The login password is transport-encoded with the frontend key and decoded with the backend key; they must match exactly. This is the most common login failure.- “Logged in on another device” / blocked: QSign enforces a single active session per user. Log out elsewhere, or an admin can clear the user’s session token.
- Account locked: too many failed attempts. An admin must unlock the user.
- CORS error in the browser console: the request origin isn’t allowed — confirm
ALLOWED_HOSTS/ the configured CORS origins include your domain and you’re using HTTPS.
404 on /backend/othercompanyapi (or similar prefix)
Section titled “404 on /backend/othercompanyapi (or similar prefix)”The bare prefix has no page — that’s expected. Use a real endpoint, e.g.
/backend/othercompanyapi/openapi.json. If every /backend/* path 404s, the nginx
/backend/ → qsign-backend:8000 route or prefix-strip is misconfigured.
Uploads fail or hang
Section titled “Uploads fail or hang”- 413 / “request entity too large”: raise
client_max_body_sizein the nginx config (and any upstream LB limit) and reload nginx. - Office→PDF conversion errors: LibreOffice runs in the backend container; check backend logs and host CPU/RAM. Large/complex documents need more resources.
- Upload rejected as infected/too large: ClamAV flagged it (if AV is enabled) — check
docker compose logs clamavand the backend activity log.
Email not delivered (signing invites/reminders)
Section titled “Email not delivered (signing invites/reminders)”- Confirm an email provider is configured (
RESEND_API_KEYorZEPTOMAIL_TOKEN) and theDEFAULT_FROM_EMAILdomain is verified with that provider. - Check backend logs for send errors; verify outbound network egress to the provider API.
- Headless/API integrations may intentionally suppress emails (
is_mail_required: false) — use the returned signing links instead.
Signing fails
Section titled “Signing fails”- e-Signature/tamper-seal: ensure the
esignservice is up and reachable (docker compose logs esign) and the document storage volume is writable by both backend and esign. - Aadhaar eSign: verify outbound egress to the NSDL/Protean gateway, that
ASP_ID/ESIGN_*URLs / the signingP12_*cert are correct on the esign service, and that the callback URL (response_url_esign) is publicly reachable. Signature-validation errors in the logs usually mean a cert/URL/response mismatch. - DSC: confirm the certificate (and, for token signing, the agent) is available and the signing session hasn’t expired (sessions are short-lived); if using a TSA, confirm egress to the TSA endpoint.
API returns 401 / 403 / 429
Section titled “API returns 401 / 403 / 429”- 401/400: missing or wrong
X-Api-Key. Regenerate in the Developer portal if unsure. - 403: the account is suspended or its subscription has expired — an operator action in the super-admin console.
- 429: rate limit or monthly quota exceeded — check
X-RateLimit-*headers and/usage/summary/; honorRetry-After.
Webhooks not received
Section titled “Webhooks not received”- The URL must be a public
https://endpoint (internal/loopback URLs are rejected by SSRF protection). - Inspect delivery attempts at
GET /webhook/deliveries/. - Verify your endpoint responds
2xxquickly and that your HMAC verification matches (compute over the raw body with the exact secret).
Search returns nothing
Section titled “Search returns nothing”- Solr may be empty or out of sync. Rebuild:
docker compose exec qsign-backend /opt/venv/bin/python manage.py reindex_solr. - Confirm
SOLR_BASE_URL/SOLR_COREare correct and thesolrcontainer is up.
Rate limiting behaves oddly / disabled
Section titled “Rate limiting behaves oddly / disabled”- The API throttle uses Redis and fails open if Redis is down (so limits aren’t
enforced during a Redis outage). Check
redisis up if you expect limits to apply.
TLS / certificate issues
Section titled “TLS / certificate issues”- ACME (Let’s Encrypt) fails: port 80 must be reachable from the internet for the
webroot challenge; check DNS points at the host and the
certbotwebroot path matches the nginx/.well-known/acme-challenge/location. - Cert expired: renew (certbot) or replace your CA cert, then
docker compose restart nginx. Monitor expiry proactively.
Useful commands
Section titled “Useful commands”# Exec into the backend (use the venv python):docker compose exec qsign-backend /opt/venv/bin/python manage.py shell
# Check registered cron jobs:docker compose exec qsign-backend /opt/venv/bin/python manage.py crontab show
# DB console:docker compose exec db sh -c 'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" qsign'
# Restart a single service:docker compose restart qsign-backendEscalating to Quoqo
Section titled “Escalating to Quoqo”When opening a support ticket, include: the QSign image versions
(docker compose images), relevant log excerpts (docker compose logs --since 1h <service>), the failing request/response (redact secrets), and which optional
integrations are enabled. Never share secret values, certificates, or full env files.