App URLs and HTTPS
Last updated
Every HTTPS port binding gets a public URL with a valid certificate. There's nothing to buy, configure, or renew.
How the URL is formed
When you add an HTTPS port, the app gets a hostname under the platform domain:
https://a<appId>-<hash>.<platform-domain>
You can set your own subdomain label instead of the generated one, on the Ports panel. It must start with a letter, contain only letters, digits, - and _, and be globally unique — labels matching the generated pattern are reserved.
Certificates are issued and renewed automatically. Your app should serve plain HTTP on the container port; TLS is terminated at the edge.
Custom domains are not available
You cannot point yourname.com at an app today. The generated hostname or your chosen subdomain label is what you get.
Two practical consequences:
- You can't publish DNS records for your app's hostname, because it isn't a domain you control. That matters most for email — SPF, DKIM and DMARC are DNS records under the sending domain, so you can't authenticate mail from an app hostname. Send through an email provider using a domain you own instead.
- Don't design around a vanity URL. If a specific domain is a requirement, this isn't the right platform for that part of your system yet.
Don't terminate TLS in your container
A common failure with frameworks built on Caddy, and with anything configured for automatic HTTPS: your app tries to obtain its own certificate, fails, and the startup logs fill with ACME errors.
Configure it to serve plain HTTP on the port you bound. For FrankenPHP and similar, setting the server name to a bare port (:8080) is usually enough to stop certificate provisioning.
The hostname isn't a secret
It's short and predictable in shape, so don't treat it as one. Anything reachable that shouldn't be public needs authentication in your app — there's no firewall or IP allowlist in front of it. See Networking.
That applies to webhook receiver URLs too: verify signatures rather than relying on the URL being unknown.