Skip to content
Q
QuoteNode

Installation

Installation Troubleshooting

Common QuoteNode deployment problems with links, CORS, SMTP, DNS, Docker health checks, and lost secrets.

Installation Troubleshooting

Most installation problems come from URL mismatch, missing SMTP, blocked ports, or lost secrets. Start with the visible URL in your browser and work inward.

Check what URL was copied or sent.

  • http://localhost/... works only on the same machine.
  • http://192.168.x.x/... works only on the LAN or VPN. VPN can be a valid bridge for internal teams, but it is not a public customer-link strategy.
  • https://crm.example.com/... works publicly only when DNS, HTTPS, proxy, and firewall are correct.

For public customer links, deploy with a public domain using Ubuntu public server or Coolify.

Browser shows CORS errors

CORS_ALLOWED_ORIGINS must match the browser origin exactly. These are different origins:

https://crm.example.com
https://www.crm.example.com
http://crm.example.com
https://crm.example.com:8443

Fix the variable, redeploy, and retry in a fresh browser session.

Email is not delivered

Check these first:

  • SMTP_HOST and SMTP_PORT are correct.
  • SMTP_AUTH=true when your provider requires authentication.
  • SMTP_STARTTLS=true for port 587.
  • SMTP_USERNAME and SMTP_PASSWORD are valid.
  • The provider allows SMTP/app-password login.
  • NOTIFICATIONS_EMAIL_ENABLED=true when notification emails should be sent.

Manual public-link sharing and PDF download can still work without SMTP.

Set:

NOTIFICATIONS_PUBLIC_PREFERENCES_URL=https://<frontend-domain>/notifications/preferences

Do not leave it pointing to localhost in a public deployment.

Docker containers are unhealthy

Run:

docker compose ps
docker compose logs -f backend
docker compose logs -f frontend
docker compose logs -f gotenberg

Common causes:

  • PostgreSQL is still starting.
  • DB_PASSWORD differs between PostgreSQL and backend.
  • DB_ENCRYPTION_KEY is missing or malformed.
  • Gotenberg is not healthy, so PDF generation cannot start.
  • Host ports 80/443 are already used by another service.

After fixing configuration, restart the affected service or the stack:

docker compose restart backend
docker compose up -d

My IP is blocked — cannot log in

There are two common causes: the IP allowlist locked you out, or brute-force protection blocked your IP after too many failed logins.

IP allowlist lockout

QuoteNode has an IP allowlist configured in Settings > Security > IP Allowlist (or via the SECURITY_IP_WHITELIST environment variable). When enabled it gates the whole admin surface — including the login and 2FA screens — so an excluded address gets 403 IP_NOT_ALLOWED and cannot even sign in. (Health checks and customer-facing public offer links stay reachable.)

First, wait two minutes if you just changed it in the app. An in-app enable or narrow is lockout-protected: it must be re-confirmed by your session within a short window (default 120 s), and if your current address is not covered it rolls back automatically to the previous allowlist. So an accidental self-lockout from the Security screen heals itself — just wait and retry. (This safety net does not apply to the SECURITY_IP_WHITELIST environment variable, which is enforced at startup.)

Recovery (operator override): if you are still locked out — e.g. an operator SECURITY_IP_WHITELIST, an invalid stored list, or you cannot wait — add this variable to the backend container environment (.env or docker-compose environment: section) and restart:

SECURITY_IP_WHITELIST_FORCE_DISABLE=true
docker compose restart backend

This bypasses the allowlist entirely and lets you log in. Once inside, fix the allowlist in Settings > Security, then remove SECURITY_IP_WHITELIST_FORCE_DISABLE and restart again.

Do not leave SECURITY_IP_WHITELIST_FORCE_DISABLE=true in production. It disables the entire IP access control.

Brute-force protection lockout

QuoteNode blocks IPs that fail too many login attempts within one hour:

ThresholdFailures in 1 hEffect
Soft10Progressive delay (1 s per extra attempt, max 30 s)
Temp lock20Locked for 5 minutes
Hard lock50Locked until manually cleared

How to unblock:

  1. Admin panel — another administrator opens Settings > Security Dashboard > Blocked IPs and clicks Unblock.
  2. Wait — temp locks expire after SECURITY_TEMP_LOCK_MINUTES (default 5 minutes). Hard locks do not expire on their own.
  3. Raise thresholds temporarily if locked out and no other admin can help. Add to .env, restart, log in, then remove:
SECURITY_MAX_FAILED_LOGINS_SOFT=9999
SECURITY_MAX_FAILED_LOGINS_TEMP_LOCK=9999
SECURITY_MAX_FAILED_LOGINS_HARD_LOCK=9999

Reset these to their defaults after regaining access.

The public link rate limiter blocks IPs that exceed probe or failure limits. These blocks are in-memory and expire after PUBLIC_RATE_LIMIT_IP_BLOCK_MINUTES (default 60 minutes) or after a backend restart.

HTTPS certificate does not issue

For public deployments:

  • DNS must point to the deployment server.
  • Ports 80 and 443 must be reachable from the internet.
  • Only one proxy should terminate HTTPS for the same domain.
  • In Coolify, assign the domain to the frontend service.

I lost .env

If you lost .env, stop and assess before rotating values.

  • DB_PASSWORD can usually be reset with PostgreSQL admin access.
  • TIMING_TOKEN_SECRET and PUBLIC_LINK_PASSWORD_SESSION_SECRET can be regenerated, but existing sessions/tokens may expire.
  • DB_ENCRYPTION_KEY is critical. Without the original key, encrypted values cannot be decrypted.
  • If PII encryption is enabled, encrypted customer/contact fields depend on DB_ENCRYPTION_KEY.

Restore .env from backup whenever possible.

Recovery if .env is lost but database backup exists

  1. Create a fresh .env with new secrets.
  2. Restore the database from your backup (pg_dump / pg_restore).
  3. All business data (customers, offers, products, users) will be fully accessible.
  4. Only a few fields are lost: MFA codes (users re-enroll), SMTP password (re-enter in settings), FX API key (re-enter). If ENCRYPT_PII=true was enabled, encrypted customer data is also lost.

If your backups are age-encrypted (the default), you need the age identity file from your recovery kit to decrypt them first. See the Backup and Recovery guide.

Forgot admin password

Use a non-destructive recovery path:

  1. If SMTP is configured, use the login page: Forgot your password?
  2. If another administrator can still sign in, open Users in the admin panel and reset the password.
  3. If no administrator can sign in and the email reset flow is unavailable, restore access from a known-good backup or use your internal maintenance procedure.

docker compose down -v is not a password reset procedure. It deletes all data — users, offers, customers, settings, and backups. Use it only for disposable test environments.

License verification fails

For real deployments, keep:

LICENSE_SKIP_SIGNATURE_CHECK=false

If a valid license still fails, check that the deployment has the expected app version and an NTP-synced system clock. Confirm that the license matches the deployed edition/version, then contact support or replace the license file through the documented operator path. Do not set signature bypass to true as a production workaround.

Last reviewed: Recently