Domains & SSL
Apps get a default subdomain on their stack at deploy time. Custom domains are added per-app and routed through the stack's nginx layer. Let's Encrypt issues certificates automatically once DNS resolves.
Default subdomain
Every deployed app is reachable on its stack at <app-name>.<stack-domain> — for instance hello.zenith-zone-582.app.ownstack.org. Useful for verifying a deploy before swapping DNS.
Add a custom domain
$ ownstack app domains:add <app> example.com
$ ownstack app domains:add <app> api.example.com
This registers the domain with dokku's nginx vhost and (by default) requests a Let's Encrypt cert. The cert is issued once DNS resolves to the stack.
DNS records you need
| Hostname | Record | Target |
|---|---|---|
Apex (example.com) | A | The stack's IP (visible in ownstack stacks). |
Subdomain (app.example.com) | A | The stack's IP. |
| Subdomain via CNAME | CNAME | <stack>.app.ownstack.org. (note trailing dot). |
Wildcard (*.example.com) | A | The stack's IP. Cert needs DNS-01 — see Wildcard certs. |
SSL: automatic via Let's Encrypt
The dokku letsencrypt plugin issues a cert automatically once DNS resolves. Renewal is automatic. Check status:
$ ssh dokku@<stack-ip> certs:report <app>
Ssl enabled: true
Ssl hostnames: example.com api.example.com
Ssl expires at: Aug 1 02:14:27 2026 GMT
Ssl issuer: Let's Encrypt
$ ssh dokku@<stack-ip> letsencrypt:list
Bring-your-own cert
If you'd rather supply a cert (corp wildcard, EV cert, internal CA), pass it in:
$ ownstack app domains:add <app> example.com \
--cert=./fullchain.pem --key=./privkey.pem
OwnStack stores the cert on the control plane and pushes it to every stack the app deploys to.
Multiple domains, one app
An app can have any number of domains attached. Each becomes a server_name in nginx. URLs the app generates use the primary domain — set it via the order of domains:add or in the dashboard.
Multi-stack
If an app deploys to multiple stacks, each stack independently routes the same domain — useful for active-active. The cert is issued separately per stack (each has its own letsencrypt state). DNS-level traffic shaping (split-horizon, geo, weighted) is your responsibility outside OwnStack.
Removing a domain
$ ownstack app domains <app> # list with IDs
$ ownstack app domains:remove <app> <id>
Removing a domain detaches it from nginx but does not delete the cert from the stack. To free everything, run letsencrypt:revoke on the stack first.