MotoDealerHQ

SSL certificates

How MotoDealerHQ issues and renews Let's Encrypt certificates, how to read the SSL certificates page, set DNS, switch to production and fix failures.

Last updated For MotoDealerHQ operators Documentation for MotoDealerHQ 1.0.0-beta.1 “Assen”

MotoDealerHQ issues and renews its own HTTPS certificates from Let's Encrypt. The web application never runs certbot itself: the console only queues work, and a root worker (bin/tls-worker, run by a systemd timer every minute) issues, renews and removes certificates, then regenerates the nginx configuration and reloads nginx.

What gets a certificate #

  • The platform hosts: one certificate for motodealerhq.com, www, admin, dealer and api.
  • Public dealership subdomains (<slug>.motodealerhq.com): one each, unless a *.motodealerhq.com wildcard certificate covers them.
  • Verified custom domains: one each, together with the www or bare twin when that is also a verified domain of the same dealership.

A dealership subdomain is public only when it has a verified row on the canonical domain. New signups get one. For other dealerships, open the tenant page and use Make public / Make private (domains.manage), which also requests or removes the certificate.

Read the SSL certificates page #

Open Operations › SSL certificates. Times are in UTC.

  1. Certificates: each certificate with its hosts and whether their DNS points at the server, its status, expiry, issuer and actions (Issue, Renew, Retry, Re-check DNS, Remove, depending on status).
  2. Not requested yet: hosts that need a certificate but have none. "Every host that needs a certificate has one or is queued" means nothing is missing.
  3. DNS records to create: the records for the platform domain, copy-ready, with each host's last DNS check.
  4. Worker: when it last ran, whether it succeeded, and the last run's log. "The worker has never run" means the timer isn't installed.
  5. Settings and Wildcard certificate (DNS-01) (see below).
  6. Recent events.

Certificate statuses move through pending_dns → queued → issuing → active → renewal_due → active, plus failed, expired and removed. A hostname can be on only one live certificate.

Settings #

SettingWhat it does
ACME account emailLet's Encrypt sends expiry warnings here. Blank uses the existing certbot account.
Certificate authorityStaging (testing, untrusted; the default) or Production.
Public IPv4 / IPv6 addressesDNS must point here before an order is placed. Behind NAT, use the public address that forwards ports 80 and 443.
Issue certificates for custom domains automatically once verifiedOff by default. When off, dealers request HTTPS on their Domains page.
HSTS from the applicationOff by default, because nginx already sends HSTS.

A value set in the server's .env (TLS_ACME_EMAIL, TLS_CA, TLS_PUBLIC_IPV4, TLS_PUBLIC_IPV6, TLS_AUTO_ISSUE_CUSTOM, TLS_WILDCARD, TLS_DNS_PROVIDER, TLS_HSTS) locks the matching field.

Move from staging to production #

  1. Leave the CA on staging and issue the platform certificate.
  2. Check that curl -kv https://admin.motodealerhq.com shows a "(STAGING)" issuer.
  3. Switch Certificate authority to Production and save. Every staging certificate is queued for reissue.

The worker never downgrades a valid production certificate to staging. Staging certificates are served for testing, but plain-HTTP requests are only redirected to HTTPS for hosts with a trusted production certificate.

Before every order: DNS pre-check #

For each hostname, the worker checks the A and AAAA records. Every A record must be one of the public IPv4 addresses on the page, and any AAAA record must be ours. Otherwise no order is placed: the certificate waits in pending_dns and is re-checked every 10 minutes. This keeps failed validations, and rate-limit hits, away.

Wildcard certificate (optional) #

With Use one *.motodealerhq.com certificate on, the worker orders a wildcard certificate using a DNS-01 challenge. This needs a DNS provider adapter, and every adapter needs credentials (stored encrypted, never shown again):

  • Cloudflare API: an API token with Zone.DNS:Edit and the zone id.
  • RFC 2136 / nsupdate: DNS server, TSIG key name, algorithm and secret; the server needs nsupdate installed.
  • acme-dns: server URL, username, password and subdomain, plus a one-time CNAME for _acme-challenge.motodealerhq.com.

Renewals, rate limits and alerts #

  • Renewal. certbot's own timer renews certificates 30 days before expiry, and its deploy hook records the new expiry. If a certificate still isn't renewed 10 days before expiry, the worker renews it itself.
  • Rate limits. The worker defers orders rather than risk Let's Encrypt limits: at most 3 failed validations per hostname per hour, 40 certificates per registered domain per week, 4 duplicates per week, and 5 orders per run. Failures back off from 15 minutes up to a day; after 8 failures automatic retries stop until someone selects Retry.
  • Alerts (in Operations › Alerts, emailed): a platform or subdomain certificate expiring within 14 days (critical under 3), failed certificates, and the worker not running for 15 minutes. Custom-domain expiry comes from a separate monitor that checks every 6 hours. See Alerts and the server page.

Troubleshooting #

SymptomWhat to check
pending_dnsThe page shows what the host resolves to. Fix the A record and remove stray AAAA records.
failed with "unauthorized" or 404http://<host>/.well-known/acme-challenge/x must reach this server (port 80 forwarded).
failed with "rateLimited"Wait for the time in the error. Don't keep selecting Renew.
nginx error eventRun sudo nginx -t. The previous configuration was restored automatically.
Worker alertsystemctl status dealerx-tls-worker.timer and journalctl -u dealerx-tls-worker.
HTTP not redirecting to HTTPSStaging certificates never redirect; switch to production.

Permissions #

Limitations #

Screenshots show the fictional demo dealership. Something unclear or out of date? Tell your MotoDealerHQ contact or email support@motodealerhq.com.

v1.0.0-beta.1 “Assen”