HTTPS and certificates
How Synq gets free Let's Encrypt certificates over HTTP-01 without Cloudflare, issues wildcard certificates through a DNS provider, installs your own certificate, redirects HTTP to HTTPS, and renews everything.
Every Synq server runs an edge: OpenResty listening on ports 80 and 443 in front of all your apps. The edge ends HTTPS for each domain with its own certificate. This page explains where those certificates come from and what you can change.
In short:
- A normal domain gets a free Let's Encrypt certificate over HTTP-01. You only need an
Arecord and port 80 open. No Cloudflare account, no DNS provider, no API token. - A wildcard (
*.example.com) needs DNS-01, which needs a connected DNS provider (Cloudflare today). - You can upload your own certificate instead, for example a Cloudflare Origin CA certificate.
- Once a real certificate is in place, plain
http://is redirected to HTTPS automatically. - Certificates renew by themselves 14 days before they expire.
Let's Encrypt over HTTP-01 (no Cloudflare needed)
HTTP-01 is how Let's Encrypt checks that you control a name: it asks for a file at
http://<hostname>/.well-known/acme-challenge/<token> on port 80. The edge answers that request itself, so
your apps keep serving while it happens, and a successful answer proves the name points at this server.
What the domain needs
- An
Arecord for the hostname pointing at the server's public IPv4 address. The Domains page and the project's DNS records panel show the exact value. - Port 80 reachable from the internet. Open it in the server's firewall and in any cloud security group or NAT in front of it. Port 443 must be open for visitors too.
- No
AAAArecord pointing somewhere else. Let's Encrypt tries IPv6 first. Either point theAAAAat this server or delete it. - No other
Arecords for the same name pointing at other machines; the challenge may land on one of them. - The Synq edge owns port 80. If nginx, Apache or Caddy still holds it, take it over first (see The edge).
- With a CDN in front (for example Cloudflare's proxy, the orange cloud), turn the proxy off (DNS only) until the certificate is issued, or make sure the CDN forwards plain HTTP on port 80 to the server.
Verification is the certificate
On a Synq server, "verifying" a domain means obtaining its certificate. Synq doesn't compare your DNS with the
server's IP and doesn't ask for an ownership TXT record: a certificate can only be issued if the name really
reaches this server, which is the proof. The live DNS check on the Domains page is advice to help you get
there.
Issue a certificate
You can start issuance from three places. All of them stream certbot's log live, so you see the real reason if it fails.
- Domains page: open the row's ⋯ menu and choose Verify and issue certificate (or Issue certificate for a domain that's already verified).
- Project → Domains & Routes: press Verify {hostname} under the DNS records, or the Verify button on the domain's card.
- CLI:
synq domain verify <domainId>(get the ID fromsynq domain list --project <projectId>).
synq domain list --project <projectId>
synq domain verify <domainId>A new domain whose project has never deployed doesn't request a certificate yet: the first deploy creates the route, and the certificate follows once the domain verifies. You don't need to redeploy after a successful verify; the edge re-registers the existing route with TLS.
If the server already holds a valid certificate for the name with more than 14 days left, Synq reuses it and doesn't ask Let's Encrypt again ("a valid certificate is already present; no new certificate was requested").
Automatic retries
You don't have to keep pressing Verify. The Domain DNS verification job (domains:verify-pending) runs
about every 13 minutes. It first checks a pending domain once it is 10 minutes old, then backs off after each
failure: 15 minutes, 30 minutes, 1 hour, 2 hours, 4 hours, then every 6 hours. It also finishes certificates
for verified domains whose first issuance failed. Only domains of projects with a live deployment are
retried. The domain's details show the Next scheduled check; press Verify for an immediate retry.
You can see and change the job under Jobs in the sidebar.
Mind Let's Encrypt's rate limits
Let's Encrypt limits how often a name may fail validation and how many certificates you can get for the same names each week. When issuance fails, read the reason in the log and fix it before retrying. To experiment freely, switch to the staging directory (see Certificate authority settings).
Wildcard certificates with a DNS provider
A wildcard certificate such as *.example.com covers every single-level subdomain (a.example.com,
b.example.com) with one certificate. Let's Encrypt only issues wildcards through DNS-01: Synq creates a
temporary _acme-challenge TXT record through your DNS provider's API, waits for Let's Encrypt to read it,
then deletes it.
Connect your DNS provider
Cloudflare is the supported provider. In Cloudflare, create an API token at dash.cloudflare.com/profile/api-tokens with Zone:Read and DNS:Edit on the zones Synq should manage.
In Synq, open Settings → Credentials (organization admins), choose Cloudflare, give it a Label, paste the API token and save. Synq checks the token with Cloudflare before storing it, encrypted. The Certificates tab of the Domains page then says "A DNS provider is connected, so wildcard certificates are available."
Point the wildcard at the server
At Cloudflare, add an A record for * (that is, *.example.com) pointing at the server's IP, so traffic
for the subdomains reaches the edge.
Add the wildcard domain
Open the project's Domains & Routes tab, press Add domain, choose Custom domain and type
*.example.com. Use DNS-01 challenge switches on by itself and can't be turned off for a wildcard
("Wildcard certificates require DNS-01 and a connected DNS provider."), and Include www is disabled.
Press Add domain. The Domains page wizard accepts a wildcard hostname too.
Verify
Press Verify. The log shows "Requesting a certificate for *.example.com (DNS-01 via connected DNS provider)" and, when it succeeds, the certificate is installed for every subdomain.
You can also use DNS-01 for a normal hostname: turn on Use DNS-01 challenge when adding it ("Issue and renew the certificate through your connected DNS provider. Use this when port 80 cannot be reached."). Renewals then use DNS-01 too.
Limits:
- A wildcard covers one level:
*.example.comcoversapp.example.combut notexample.comitself ora.b.example.com. Add the apex as its own domain if you need it. - Only Cloudflare is supported as a DNS provider. Without a connected provider, verification stops with "DNS-01 challenge for *.example.com requires a connected DNS provider (e.g. Cloudflare) in Settings → DNS." (the provider lives under Settings → Credentials in the current panel).
- If Cloudflare rejects the stored token, the message starts with "DNS provider credential rejected". Replace the token under Settings → Credentials.
Free subdomains don't need a wildcard certificate
The free <app>.<base> subdomains rely on a wildcard DNS record (*.<base>), not a wildcard certificate.
Each app gets its own HTTP-01 certificate, so no DNS provider is needed for them.
Upload your own certificate
Use this when the certificate must come from somewhere else:
- Cloudflare Full (strict): Cloudflare connects to your server over HTTPS and requires a certificate it trusts. A free Cloudflare Origin CA certificate (valid up to 15 years) is a good fit.
- A certificate from your company's CA, or one you already bought.
Verify the domain first
The domain must be verified before a certificate can be installed. A domain behind a proxy that owns TLS is usually added with External ingress & TLS, which verifies without issuing anything.
Open the upload dialog
On the Domains page, open the row's ⋯ menu and choose Upload certificate, or use Upload certificate in the domain's menu on the project's Domains & Routes tab.
Paste the PEM files
Paste the Certificate (PEM, full chain), starting with -----BEGIN CERTIFICATE----- and including the
intermediates, and the matching Private key (PEM). Press Install certificate.
Before touching the edge, Synq checks that the certificate parses, that the key matches it, that it covers the hostname and that it hasn't expired. A certificate that fails is refused with "Invalid certificate: ..." and nothing changes, because a broken pair would stop OpenResty from reloading for every other domain too.
After the upload the certificate shows as Uploaded, with Auto-renew: Manual. Synq stops running certbot for that domain and never renews it. There is no expiry reminder for uploaded certificates: watch the countdown on the Certificates tab and upload a new certificate before it lapses.
HTTPS redirect
You don't switch the redirect on; it follows the certificate. The HTTP to HTTPS column on the Domains page shows the current state:
| State | Behaviour |
|---|---|
| On | The domain has a real certificate (issued or uploaded). Every plain http:// request gets a 301 to https://<hostname><path>?<query>, on every path the domain serves. |
| After certificate | No certificate yet. HTTP requests are served normally so the site works while the certificate is pending; the redirect starts as soon as it is active. |
| Upstream | TLS is handled by your own proxy or CDN (external ingress). Visitors reach HTTPS through that proxy, so configure the HTTP to HTTPS redirect there. |
Two details matter behind a CDN:
- A request that arrives with the header
X-Forwarded-Proto: httpsis not redirected. That header means a CDN (for example Cloudflare in Flexible mode) already served HTTPS to the visitor and reached the server on port 80; redirecting it would loop forever. The app is told the request was HTTPS. - Let's Encrypt's challenge path
/.well-known/acme-challenge/is never redirected, so renewals keep working.
Synq doesn't send an HSTS header. If you want one, add it for a domain with custom proxy config.
Renewal
The SSL certificate renewal job (ssl:renew) runs once a day at 03:17 (server time). It renews every
certificate that Synq issued and that has fewer than 14 days left, up to 50 per run. Uploaded certificates and
domains whose TLS ends at your own proxy are skipped.
- The Automatic renewal card on the Domains page's Certificates tab shows the next and last run.
- Renew {n} due on the Domains tab renews every due certificate right away.
- Renew certificate in a row's menu forces one renewal;
synq domain renew <domainId>does the same, andsynq domain renew-allrenews every near-expiry certificate in your organization. - Recheck certificate (
synq domain verify-ssl <domainId>) only reads what's on the server, without asking Let's Encrypt, and updates the state.
When the job fails to renew a certificate, the domain's certificate turns Failed and an SSL cert expiring notification is sent (see Notifications).
synq domain renew <domainId>
synq domain renew-all
synq domain verify-ssl <domainId>Certificate authority settings
By default certbot uses Let's Encrypt's production directory. You can point it at another ACME certificate authority, add a contact email, or change the key type with environment variables on the server. The Certificate authority card on the Certificates tab shows the values in effect.
| Variable | What it sets |
|---|---|
SYNQ_ACME_EMAIL | Contact email for the ACME account; the CA sends expiry notices here. With no email at all, certificates are requested without a contact address. An instance administrator can override it on the Certificates tab. |
SYNQ_ACME_DIRECTORY_URL | ACME directory. Unset means Let's Encrypt production. Staging is https://acme-staging-v02.api.letsencrypt.org/directory; ZeroSSL is https://acme.zerossl.com/v2/DV90. |
SYNQ_ACME_EAB_KID and SYNQ_ACME_EAB_HMAC_KEY | External account binding, required by CAs such as ZeroSSL. Set both or neither. |
SYNQ_ACME_KEY_TYPE | ec256, ec384, rsa2048 or rsa4096. Unset uses certbot's default. |
SYNQ_ACME_CA_BUNDLE | Absolute path to a CA root bundle, for a private ACME server whose certificate isn't publicly trusted. |
SYNQ_ACME_TOS_AGREED | Accept the CA's terms of service non-interactively. Defaults to true. |
To change them on a server installed with the installer, add the lines to /root/.synq/compose/.env on the
server (your additions are kept across updates), then apply them with sudo synq up. For example, to test with
the staging directory:
# on the server
echo 'SYNQ_ACME_DIRECTORY_URL=https://acme-staging-v02.api.letsencrypt.org/directory' | sudo tee -a /root/.synq/compose/.env
sudo synq upThe Provider row on the card then reads Let's Encrypt (staging). Browsers don't trust staging certificates, so remove the line and apply again to go back to production.
What visitors see before an app is live
The edge answers every hostname that reaches it, even when nothing is deployed there. So you know what you're looking at:
| Situation | What the visitor gets |
|---|---|
| Not deployed yet: a verified custom domain whose project has never had a live deployment | A 503 page titled "{hostname} is not deployed yet": "This domain is connected and ready. The site will appear here as soon as its first deployment goes live." |
| Last deploy failed before anything went live | A 503 page titled "{hostname} is not live": "The last deploy failed, so there is nothing to serve yet. See the dashboard for the deploy log." |
| The app's container isn't answering (restarting, crashed, booting) | A 502 page titled "Application unavailable". |
| A hostname no route knows (a typo, a stray wildcard record, a visit by IP) | A 404 page titled "Service not found". |
The "not deployed yet" page is served with the domain's real certificate, so the browser shows a padlock
rather than a certificate warning, and it tells browsers and crawlers to retry later (Retry-After: 120,
Cache-Control: no-store, noindex). It appears after the domain is verified, and the first successful deploy
replaces it with your app.
Related
Custom domains
Add a domain to a project, with www, redirects and external ingress.
Domains page
Every domain and certificate at a glance, with renew and upload.
Cloudflare Tunnel and external proxies
Let another proxy own HTTPS for a domain.
Domains, DNS & SSL troubleshooting
Every failure message explained.
Custom domains, DNS & SSL
Put your app on your own address like app.example.com, or on a free subdomain of your install, with automatic HTTPS. Add the domain, point one DNS record at your server, verify, done.
Redirects, basic auth and security rules
Redirect paths, put a password on a site or a folder, rate-limit clients and block IPs, countries or bots, all enforced at the edge and applied instantly without a redeploy.