On this page
Domains & HTTPS
Every app you deploy gets a working HTTPS URL immediately—including apps on servers with no public IP. When you're ready, point your own domain at it.
The generated URL#
As soon as an app is running, Anyport gives it a hostname on a domain we operate, with a certificate already issued. You don't configure anything: no ingress, no cert-manager annotations, no DNS.
This works even when your server has every inbound port closed. Traffic arrives at Anyport's gateway and travels to your app over the same outbound connection the agent already holds open. See The gateway for what that path does and what it sees, and Connecting clusters for how the channel is established.
Adding your own domain#
Adding a custom domain is two independent steps: proving you own it, and pointing traffic at Anyport. They can happen in either order.
- In your project, open Domains and enter the hostname you want (for example
api.acme.com). - Anyport shows you two records:
- a TXT record carrying a token unique to your organization—this proves ownership
- a CNAME or A record—this routes real traffic
- Add them at your DNS provider.
- Click Verify. Anyport checks the TXT record and, once it resolves, marks the domain verified.
Note
DNS propagation is not instant. If verification fails immediately after you add the record, wait a few minutes and try again. If it still fails, Troubleshooting shows how to check what is published and the record-name mistake most DNS providers make easy.
Why the ownership check exists#
Without it, anyone could claim a hostname that belongs to someone else and intercept traffic intended for them. The TXT token is scoped to your organization, so a domain verified by you cannot be claimed by another organization while it remains yours.
Certificates#
Once a domain is verified and pointing at Anyport, certificates are issued and renewed automatically. There is nothing to install and nothing to rotate.
Using Cloudflare's proxy#
If your DNS is on Cloudflare, you have two ways to point a domain at Anyport. Both affect only the records you change, so other sites in the same Cloudflare zone keep working as they are.
Option 1: DNS only (simplest)#
Set the domain's records, for example test.acme.com and *.test.acme.com, to DNS only (grey cloud). The proxy toggle is per record, so nothing else in the zone changes. Anyport sees the records point at it and handles HTTPS itself.
Option 2: keep the proxy on#
You can leave the proxy (the orange cloud) on. Cloudflare then answers DNS with its own addresses, so DNS alone can't show where your records point. On Recheck, Anyport sends a request for your domain through Cloudflare and checks that your cluster answers it; when it does, the record shows as pointed via Cloudflare. Until then it shows as proxied by Cloudflare. A few things make it work:
- Keep the records' target. Cloudflare forwards traffic to the CNAME or A target Anyport showed you, so that value still matters.
- Let Anyport's check through. The check asks for
/.well-known/anyport-routing/on your domain. If a Cloudflare firewall, bot or redirect rule blocks that path, the record stays proxied by Cloudflare even though traffic works. - Don't use Flexible SSL/TLS mode. See the modes below.
- Use a wildcard certificate. Turn it on for the domain and keep its
_acme-challengerecord DNS only. Per-app certificates are checked over plain HTTP and can fail to issue when Cloudflare forces HTTPS. - Check Cloudflare can serve your app URLs. Behind the proxy, browsers get Cloudflare's certificate, not Anyport's. Cloudflare's free certificate covers your zone and one level below it: for the zone
acme.com, that isacme.comand*.acme.com. If you registered a subdomain such astest.acme.com, app URLs likeapp.test.acme.comare two levels down and get a certificate error. Set*.test.acme.comto DNS only (the domain itself can stay proxied), or buy Cloudflare's Advanced Certificate Manager for an edge certificate that covers it. Recheck tests this and warns you.
Cloudflare's SSL/TLS modes#
The SSL/TLS mode decides how Cloudflare connects to Anyport after a visitor reaches Cloudflare. It does not change what visitors see in their browser.
| Mode | How Cloudflare connects to Anyport | Works with Anyport? |
|---|---|---|
| Off | Plain HTTP only | No: visitors get no HTTPS at all |
| Flexible | Plain HTTP | No: Anyport redirects plain HTTP to HTTPS, so browsers loop with "too many redirects" |
| Full | HTTPS, accepting any certificate | Yes, straight away |
| Full (strict) | HTTPS, only with a valid certificate | Yes, once Anyport has issued the certificate. Until then Cloudflare shows error 526 |
| Automatic | Cloudflare tests your servers and picks a mode | Yes, it normally lands on Full or Full (strict) |
Full (strict) is the most secure choice, because Cloudflare also checks that it is really talking to Anyport. Full is enough to get running.
Changing the mode without affecting other sites#
The mode is set for the whole Cloudflare zone, under SSL/TLS → Overview → Configure, so changing it there affects every proxied site in the zone. If the zone is already on Full, Full (strict) or Automatic, there is nothing to change.
If the zone has to stay on Flexible for your other sites, change the mode for the Anyport hostnames only:
- Open Rules → Configuration Rules and create a rule.
- Match hostname equals
test.acme.com, or hostname ends with.test.acme.com. - Set SSL to Full (or Full (strict)) and deploy the rule.
Configuration Rules are available on every Cloudflare plan, including Free. Or skip all of this by setting the Anyport records to DNS only (option 1).
Note
Behind the proxy, your apps see Cloudflare's addresses as the client IP; the visitor's own address arrives in the CF-Connecting-IP header. Cloudflare's own limits, such as upload size and request timeout, also apply.
Traffic and metering#
Traffic that reaches your app through Anyport's gateway counts toward your organization's gateway allowance. Traffic served directly by your own load balancer or ingress never passes through us and is never metered. See Pricing for the current allowances.
Public TCP and UDP ports#
A hostname carries HTTP. For anything else (raw gRPC without an HTTP/2 ingress, MQTT, a game server, DNS, a message broker) an app can open a public port instead, TCP or UDP:
anyport app expose mqtt --port 1883 -p iot
anyport app expose api --port 20017 --target 50051 -p demo
anyport app expose dns --port 30053 --target 53 --udp -p infra
anyport app ports api -p demoThe same form lives in the console under the app's Domains settings. Two limits are deliberate.
A cluster reached through the gateway cannot do this: it has no public address to answer on,
and the console refuses at once, naming anyport port-forward as the way to reach the service
from your machine. The same holds on Anyport Cloud, which publishes apps
over HTTPS only. And a database does not belong on a public port; the CLI says so, and
anyport port-forward is the tool for that job.
How a port reaches the internet#
Each port is a Kubernetes Service in the project, plus a network policy that admits traffic to that port alone through the project's isolation baseline. The Service's type is the part that can cost you money, so Anyport never picks a load balancer on its own. The agent reports what would answer one on your cluster, and the console acts on that:
| The cluster has | What happens |
|---|---|
| The Traefik ingress controller Anyport installed | A TCP port rides the ingress controller's own load balancer by default: the same address your apps answer on, and nothing new to pay for. Opening or closing a port restarts the controller's pods. UDP ports are not carried this way, since many cloud load balancers accept TCP only; they fall to the rows below. |
| k3s ServiceLB or MetalLB | A load balancer is used by default. It is free: the address is the node's own, or one from your MetalLB pool. |
| A cloud controller (EKS, GKE, AKS, Hetzner, DigitalOcean, …) with nodes that have public addresses | A node port is used by default. The load balancer is offered beside it with its cost stated, typically $10–20 a month per port, and is never preselected. |
| A cloud controller with nodes on private addresses only | Nothing is chosen for you: a node port would answer only inside your VPC, so the form asks you to accept the load balancer or to give the nodes public addresses. |
| Nothing that answers a load balancer (kubeadm, kind, a bare server) | A node port. The load balancer option is disabled with that reason, rather than a listener that waits for an address forever. |
A node port opens the same number on every node's own address and has to sit in the cluster's
node port range, 30000–32767 unless you changed it. Where an autoscaler creates and removes
the nodes (Cloudfleet, for one), node ports are not offered at all: a replaced node takes its
address with it. anyport app ports lists every address a port answers on; a load balancer or the
ingress controller has one, a node port has one per node. From the CLI, --via controller,
--via loadbalancer or --via nodeport makes the choice explicit.
On the ingress controller every project shares one address, so a port number can be held by one project at a time, and 80 and 443 are the controller's own.
The free plan allows one public port per cluster, Pro ten. In an anyport.yaml a port is
publicPorts: [{ port: 20017, target: 50051 }] on the app, with protocol: UDP and
via: controller, loadBalancer or nodePort where the defaults are not what you want.
Next steps#
- Apps — Deploy something to attach a domain to.
- Projects — How projects isolate apps and their config.
- Connecting clusters — The outbound agent that makes private serving possible.