Exposing Apps on Custom Ports
In a Dev Environment you can run any app or service on any port — a FastAPI server, a dashboard, a docs site — and open it straight from your browser. No extra tools or tunnels are needed: VS Code (code-server) automatically forwards every listening port for you.
This guide is for development environments only. If you want to deploy an app for end users, use Live Apps.
Who does the forwarding?
code-server (the browser-based VS Code that runs inside your Dev Environment) provides VS Code's
built-in automatic port forwarding. It detects any port a process starts listening on inside the
pod and exposes it through its own /proxy/<port>/ endpoint — that's the Auto Forwarded entry you
see in the PORTS tab.
MINEO's proxy simply routes /dev-env/<organization>/<dev-environment>/… to code-server (running on
port 8000), keeping MINEO's authentication in front. So a request flows like this:
The forwarded URL follows this pattern:
https://<host>/dev-env/<organization>/<dev-environment>/proxy/<port>/
How to expose a port
- Open a terminal in VS Code (Terminal → New Terminal).
- Run your app bound to all interfaces (
0.0.0.0), on whatever port you like:uvicorn app:app --host 0.0.0.0 --port 8888 - Open the PORTS tab (next to the terminal). The port appears as Auto Forwarded with a
Forwarded Address — click it to open your app, or build the
/proxy/<port>/URL manually.
Bind your app to 0.0.0.0, not 127.0.0.1. If it only listens on localhost the proxy may not be able
to reach it.
Apps that generate absolute URLs
The forwarding above works out of the box for apps that use relative URLs. But apps that build
absolute URLs — FastAPI's /docs (Swagger UI), many dashboards and SPAs — assume they are served
from the site root. Under the proxy their assets and API calls (/openapi.json, /static/…) resolve
to https://<host>/… and return 404, so the page renders blank or unstyled.
Fix it by telling the app the path prefix it is served under. Every Dev Environment exposes that prefix
as the environment variable MINEO_LIVE_APP_URL_PATH — its value is
/dev-env/<organization>/<dev-environment>/. Append proxy/<port> and pass it to your framework's
base-path setting.
For FastAPI, that setting is root_path:
import os
from fastapi import FastAPI
PORT = 8888
base = os.environ.get("MINEO_LIVE_APP_URL_PATH", "/").rstrip("/") # /dev-env/<org>/<dev-env>
app = FastAPI(root_path=f"{base}/proxy/{PORT}") # …/proxy/8888
Run it and open …/proxy/<port>/docs: Swagger UI now loads, because the app generates its absolute
URLs with the full prefix.
| Framework | Base-path setting |
|---|---|
| FastAPI | FastAPI(root_path=…) |
| Streamlit | --server.baseUrlPath=… |
| Plain JS / SPA | the framework's base / publicPath build option |
MINEO_LIVE_APP_URL_PATHThe same variable is also injected into Live Apps, where its value is
/live-app/<org>/<app>/ and the app runs on port 8000 — there you use it as root_path directly.
In a Dev Environment it is only the base path, so append proxy/<port> because your app is reached
through code-server's port proxy.
/proxy/ + root_path over /absproxy/code-server also exposes an /absproxy/<port>/ path that passes the URL through unchanged. Avoid it for
apps like FastAPI: it does not strip the prefix, so your routes (/, /docs) stop matching unless
you mount the whole app under that sub-path. Sticking with /proxy/<port>/ (the URL shown in the PORTS
tab) plus root_path is cleaner — the proxy strips the prefix so routing just works, and root_path
handles URL generation. Reserve /absproxy/ for apps that cannot be told a base path.
Learn more
- code-server — Securely Access & Expose code-server (the
built-in proxy and
/proxy/vs/absproxy/behavior).
📄️ Exposing Apps on Custom Ports
In a Dev Environment you can run any app or service on any port — a FastAPI server, a dashboard, a