Skip to main content

Exposing an Application

A freshly deployed app runs on a private workspace network. Nothing reaches it from the outside until you say so. This page covers the three ways to change that, and how to pick between them.

The Network tab of an application, showing external access, routes and ports

First: declare a container port

Every method below needs Miabi to know which port your container listens on. This is the single most common reason an app looks deployed but answers nothing.

Open the app → Ports → Container ports → Add port (or Settings → Configuration → Container ports) and add the port your process binds inside the container — 3000 for a typical Node app, 8080 for many Java services, 80 for nginx.

FieldWhat it means
Container portThe port your process listens on inside the container. Not a host port.
Protocoltcp or udp. HTTP is always tcp.
Schemehttp or https — what your app speaks on that port. Miabi builds the gateway's backend URL from it. Set https only if your container terminates TLS itself, which is unusual.
NameOptional label, useful when an app exposes several ports (web, metrics, grpc).

Declaring a container port in application settings

tip

If your app reads a PORT environment variable, set it in Environment variables and declare the same number here. The two must agree.

Choosing how to expose it

MethodPublic URLNeedsBest for
External access<label>.<base-domain> (generated)An admin has set an external domain on the app's clusterGetting a working HTTPS URL in one click — previews, internal tools, demos
Custom domainWhatever you ownA verified domainAnything you want people to type or bookmark
Host portnode-ip:portPlatform-admin approvalNon-HTTP protocols, or a service that cannot sit behind the gateway

The first two go through Goma Gateway, which means automatic TLS, middlewares, and no ports open on the host. Prefer them. The third publishes a port on the node itself and bypasses all of that.


Method 1 — One-click external access

The fastest path to a working HTTPS URL. Miabi generates a hostname under the wildcard domain of the cluster the app runs in, and creates the route and certificate for you.

Application → Network → External access. Tick the HTTP ports you want reachable and press Save external access.

The external access card with a port selected and its generated URL

Each ticked port gets its own public hostname and a TLS route, generated under *.<base-domain>.

The label is stable

The generated hostname is <label>.<base-domain>, where the label defaults to <app-handle>-<token>. It is generated once and then pinned to the app, so the URL survives renames and redeploys — a link you shared last month keeps working after you rename the app.

If the card says it is unavailable

External access needs an external domain on the app's cluster. Each cluster has its own, set by a platform admin under Clusters → Edit. In a location without one the card explains that and offers nothing to tick. See Cluster mode.

Turning it off

Disable external access removes the generated routes and the app stops answering on those hostnames. The label is kept, so re-enabling later gives you the same URL back.

When the domain changes

If an admin changes the cluster's external domain, every generated URL in that cluster moves to the new domain with the same label: <label>.<old-domain> becomes <label>.<new-domain>, and the old hostname stops answering. Clearing the domain removes the generated routes. Custom domains are not affected.


Method 2 — Your own domain

Use this for anything real. It is a two-step flow: prove you own the domain, then point a route at your app.

Step 1 — Verify the domain

Add the domain under Networking → Domains and prove ownership by publishing the challenge TXT record, or by connecting a DNS provider so Miabi publishes it for you. Full detail in Domains.

A domain must be verified before a route on it will serve traffic — an unverified domain leaves its routes offline with a plain reason on the route.

Step 2 — Point DNS at the gateway

Create an A/AAAA record for the hostname pointing at the node running the gateway (or a CNAME to it). Ownership verification proves the domain is yours; this is what makes browsers actually arrive.

Step 3 — Create the route

Open the app → Routes → Add route.

Creating a route on an application

FieldNotes
HostsThe hostnames this route answers, e.g. app.example.com. Each must resolve under a verified domain.
PathOptional prefix. Leave blank for the whole host; use /api to route one path to this app and another elsewhere.
Target portWhich of the app's declared container ports receives the traffic.
TLS modeacme for an automatic Let's Encrypt certificate (the usual choice), custom to use a certificate you uploaded, or none for plain HTTP.
MethodsOptionally restrict to specific HTTP methods.
MiddlewaresAuth, rate limits, headers, geo rules — attached here and applied in order.

Save, and the gateway picks the route up within seconds. The route list shows its sync status; live means the gateway is serving it.

Serving several apps on one domain

Give each app a route on the same host with a different path/ to the frontend, /api to the backend. Routes are matched most-specific-first, so the order you create them in does not matter.


Method 3 — A published host port

Sometimes the gateway is the wrong tool: a game server on UDP, a TCP database you must reach directly, a protocol Goma does not speak. For those, publish a host port.

Open the app → Ports → Host port bindings → Request binding, choose the container port and the host port you want (Suggest picks one that is currently free).

Requesting a host port binding

It goes through review

Host ports are a node-wide shared resource — two apps cannot both own :8080 on the same machine. So a request enters a review queue and a platform admin approves it before anything is published. Admins review these under Platform admin → Infrastructure → Ports — see Moderating host ports.

Requests are bounded by MIABI_HOST_PORT_MIN / MIABI_HOST_PORT_MAX (default 1024 and above), so an ordinary workspace cannot ask for a privileged port.

A privileged workspace skips the queue and auto-approves, and may ask for any port from 1 to 65535 — but still only when the port is genuinely free on that node; a collision is refused with the current owner named.

It publishes on the next deploy

An approved binding is not live until the app is deployed again — publishing a port means recreating the container. Miabi flags the app as needing a redeploy when the approval lands.

caution

A published port is open on the node's network interface, with no TLS termination, no middlewares, and no gateway logging. Everything Miabi gives you at the gateway is your responsibility here.


Checking your work

If the URL does not answer, work down this list — it is roughly the order things go wrong:

SymptomLikely cause
Route shows offlineThe domain is not verified, or is banned. The route's status reason says which.
Route is live, browser times outDNS does not point at the gateway node, or a firewall blocks 80/443.
502 / bad gatewayThe container is not listening on the declared port, or crashed. Check Logs.
404 from the gatewayThe Host header does not match any route host, or the path prefix does not match.
Certificate warningACME has not completed. It needs port 80 reachable for the HTTP-01 challenge — see TLS certificates.
Everything looks right, nothing respondsNo container port declared. Start at the top of this page.

The app's timeline records route and deploy events, which is usually the quickest way to see what changed.

Where to go next