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

HostnameRecordTarget
Apex (example.com)AThe stack's IP (visible in ownstack stacks).
Subdomain (app.example.com)AThe stack's IP.
Subdomain via CNAMECNAME<stack>.app.ownstack.org. (note trailing dot).
Wildcard (*.example.com)AThe 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.