Skip to main content

Ports

Declare a port on a template and Superheat publishes it when the instance launches, mapping the container port to a host port on the machine you rented. Anything your workload listens on that you want to reach from outside — an inference server, a web UI, a metrics endpoint — needs a row here.

Declaring a port​

Each row in the Ports section has five parts.

PartAcceptsMeaning
Container port1 to 65535The port your process listens on inside the container.
Protocoltcp, udp, http, httpsWhat the port serves. http and https are published over TCP; the distinction records intent and drives how the console presents the port.
Labelup to 64 charactersA human name, shown on the template detail. Some values are reserved — see below.
Publicswitch, on by defaultRecorded on the port entry.
AccessOpen, Access proxy or App checks token (the API's auth: unset, proxy or app)Whether the port requires the instance access token, and who checks it. See Requiring the access token.

You declare the container port only. The host port is assigned at launch from the machine's published range, and you will not know it in advance. Inside the container, each published TCP port is available as SUPERHEAT_TCP_PORT_<container_port>:

echo "$SUPERHEAT_TCP_PORT_7860"

That environment variable is how you read the host port from inside your workload. The instance page's Connect tab renders the SSH command and, where the template has one, the Open or Open JupyterLab link. See Ports and networking.

Labels​

Labels are trimmed and compared without case, and six of them map onto the four reserved roles.

LabelEffect
open, open_button, open-buttonMakes this the Open button target. The port is published with the open_button role and its number is passed to the container as OPEN_BUTTON_PORT.
sshPublished with the ssh role.
jupyterPublished with the jupyter role.
appPublished with the app role — the default.
anything elseKept as the display label; the port is published with the app role.

So a port labeled Jupyter, jupyter or JUPYTER all mean the same thing, while Gradio UI is a plain app port with a friendly name.

Ports you do not declare​

Launch modes prepend the ports they need. In ssh mode, container port 22 is added for you. In jupyter mode, 22 and 8080 are both added. Declaring them yourself is harmless but redundant: the list is de-duplicated by container port and protocol, and the implicit entry wins over a plain app entry.

The precedence, highest first, is ssh and jupyter, then open_button, then app. That is what lets a template both declare a port in the list and point the Open button at it — the surviving entry carries the open_button role.

In args mode nothing is prepended. If you want SSH access to an args template, you are responsible for running an SSH server in the image and declaring the port yourself, or you should switch to ssh mode with a base-derived image.

The Open button port​

The console shows an Open button on an instance when the template named a target port. Set it by labeling exactly one port open:

{
"ports": [
{ "container_port": 7860, "protocol": "http", "label": "open", "public": true },
{ "container_port": 9090, "protocol": "http", "label": "metrics", "public": true }
]
}

Label more than one port open and the last one in the list wins, which is rarely what you meant. Declare one.

In jupyter mode you do not need an Open button port at all — the console renders Open JupyterLab from the Jupyter role, with the access token already in the URL. See JupyterLab. An Open button port behind the access proxy gets the token in its URL too.

Requiring the access token​

A published port is reachable by anyone who finds the machine's address and the port. Every instance can carry a secret of its own, the access token, and a port's auth field says how that port requires it:

Access (auth)Who checks the tokenWhat the template has to do
Access proxy (proxy)The access proxy in the Superheat base image. It takes the published port and passes only requests that carry the token — ?token= from the Open button, the cookie it swaps that for, or Authorization: Bearer — to the appUse a base-derived image, and start the app on "${SUPERHEAT_APP_HOST:-0.0.0.0}" — for example --listen "${SUPERHEAT_APP_HOST:-0.0.0.0}". The base image sets that variable to 127.0.0.1 whenever it runs the proxy. An app that binds 0.0.0.0 on a guarded port anyway fails to start rather than serving unauthenticated
App checks token (app)The application itselfWire the token into the app's own authentication: an environment entry whose value is exactly ${SUPERHEAT_ACCESS_TOKEN} is replaced with the token at deploy, and $SUPERHEAT_ACCESS_TOKEN is set in the container for args_str and onstart. The app's check has to cover every route
Open (unset)NobodyNothing. The port is published as it always was, and no token is minted unless the template is in jupyter mode

Set it per port with the access menu in the template editor's Ports section, or as auth through the API (POST /v1/templates or PATCH /v1/templates/{id}). A saved template keeps the value either way. For a proxied port the Open link carries ?token=; for an app port it does not, because the app signs you in itself.

The editor warns under the port list when a choice will not do what it says. The warnings do not stop you saving:

Warning is aboutWhenWhy it matters
Access proxy on another imageThe port uses the access proxy, but the image is not a Superheat image: superheat/<name>, with or without a registry in front, so superheat-cn-registry.cn-shanghai.cr.aliyuncs.com/superheat/<name> on ACR countsThe proxy lives in the Superheat base image. On any other image nothing guards the port
App checks token that never reaches the appThe port says the app checks the token, but no environment entry has the value ${SUPERHEAT_ACCESS_TOKEN} exactly, and neither the arguments nor the on-start script use $SUPERHEAT_ACCESS_TOKENThe app has no token to check, so it cannot require it
A public web port left OpenA public http or https port has no access ruleAnyone who finds the machine's address and port can use the app on it

The platform's values win: a renter's environment override cannot replace the token in a variable that carries it.

Ports are part of the recipe​

The ports list is a launch field, so editing it re-mints the template's hash_id and invalidates pinned share links. Running instances keep the port map they launched with; a new port only appears on instances deployed after the edit.