Custom Domains
Every app gets a primary domain at https://{name}.foundrydb.com with a platform-issued certificate. You can also serve the app on your own hostnames: add up to five custom domains to app_config.custom_domains and the platform obtains and renews a certificate for each one automatically via ACME (HTTP-01).
Add custom domains at creation
curl -u "$USER:$PASS" -X POST https://api.foundrydb.com/app-services \
-H "Content-Type: application/json" \
-d '{
"name": "my-api",
"plan_name": "tier-2",
"zone": "se-sto1",
"app_config": {
"image_ref": "ghcr.io/acme/api:1.0.0",
"container_port": 8080,
"custom_domains": ["api.acme.com", "www.acme.com"]
}
}'
Add or change custom domains on a running app
PATCH /app-services/{id} replaces app_config wholesale, so include the full desired list of custom domains alongside the rest of your config:
curl -u "$USER:$PASS" -X PATCH https://api.foundrydb.com/app-services/{id} \
-H "Content-Type: application/json" \
-d '{
"app_config": {
"image_ref": "ghcr.io/acme/api:1.0.0",
"container_port": 8080,
"custom_domains": ["api.acme.com", "www.acme.com", "acme.com"]
}
}'
Changing custom_domains triggers a zero-downtime blue/green redeploy so the ingress and certificates are updated.
DNS configuration
After adding a custom domain, point it at the app. Two options:
| Record type | Target | When to use |
|---|---|---|
CNAME | {name}.foundrydb.com | Easiest option; works for subdomains (e.g. api.acme.com). |
A | App's floating IP | Required for apex domains (e.g. acme.com), which cannot use CNAME. |
Get the app's floating IP from the detail response (GET /app-services/{id}).
The platform probes each custom domain over HTTP-01 to issue the certificate, so the DNS record must be live before the certificate can be issued. The platform retries automatically; there is no manual step to trigger certificate issuance after the DNS record propagates.
How certificate provisioning works
The diagram below walks the full lifecycle: ACME order, domain-control challenge, certificate issuance, installation on the service endpoint, and automatic renewal well before expiry.
Issuance steps
- Order. As soon as the DNS record is live and the platform detects it, an ACME order is placed with Let's Encrypt for the custom domain.
- Challenge. Let's Encrypt issues an HTTP-01 challenge. The platform answers it by serving a well-known token over port 80 on the app's ingress, proving it controls the domain.
- Issue. Let's Encrypt verifies the challenge and returns a signed certificate and the full intermediate chain.
- Install. The certificate is installed on the app's ingress endpoint. TLS 1.2 and 1.3 are served from that point forward; clients that verify the certificate and hostname (
verify-full) will succeed. - Serve. Clients connect over HTTPS. The primary
{name}.foundrydb.comdomain and all custom domains share the same app, served from the same floating IP. - Auto-renew. Well before the certificate expires the platform re-runs the full ACME order silently. The renewed certificate is hot-installed with no downtime and no action required from you.
Certificate details
| Property | Value |
|---|---|
| CA | Let's Encrypt (ACME) |
| Challenge type | HTTP-01 |
| TLS versions | 1.2, 1.3 |
| Renewal | Automatic, before expiry |
| Scope | One certificate per custom domain |
Rules and limits
- Up to five custom domains per app.
foundrydb.comsubdomains are not allowed as custom domains.- The primary
{name}.foundrydb.comdomain is always active and cannot be removed. - Certificates are renewed automatically before expiry. No action is needed on your part.
- The DNS record for a custom domain must resolve to the platform before the certificate can be issued. If the record is not yet live, the platform will keep retrying.
Removing custom domains
To remove a custom domain, patch the app with an app_config that omits it:
curl -u "$USER:$PASS" -X PATCH https://api.foundrydb.com/app-services/{id} \
-H "Content-Type: application/json" \
-d '{
"app_config": {
"image_ref": "ghcr.io/acme/api:1.0.0",
"container_port": 8080,
"custom_domains": ["api.acme.com"]
}
}'
The platform removes the certificate for the dropped domain and updates the ingress. You can then remove the DNS record on your side.