Ports and endpoints
| Port | Protocol | Purpose | Direction |
|---|---|---|---|
| 8443 | TCP / HTTPS | Web app and API | Browser → control plane |
| 8080 | TCP / HTTP | Enrollment and health | GPU host → control plane; local health checks |
| 9091 | TCP / HTTP | Agent health | Localhost on GPU host only |
| Host ephemeral range | UDP | Game stream and input | Browser ↔ GPU host, directly |
| 5353 | UDP / mDNS | Chromium local ICE candidates | LAN peers ↔ GPU host |
Change the published ports with QUASAR_HTTP_PORT and QUASAR_TLS_PORT
(legacy Compose: CONTROL_PORT for HTTP, QUASAR_TLS_PORT for HTTPS). The hardened
Compose overlay puts Caddy on 443 and publishes no control-plane ports.
What has to reach what
Section titled “What has to reach what”- Browser to control plane on 8443. Can be proxied.
- Browser to GPU host on the ephemeral UDP range, directly. Can’t be proxied. See Reaching Quasar remotely.
- Node agent to control plane on 8080.
Firewall
Section titled “Firewall”The control plane needs no rules: Docker-published ports bypass the host firewall. The node agent does: it uses host networking, so a default-deny firewall silently drops its media while login and launch still work.
What has to be open
Section titled “What has to be open”Inbound to each GPU host, from your LAN or VPN clients:
| What | Why |
|---|---|
UDP, the ephemeral range (Linux default 32768-60999; check cat /proc/sys/net/ipv4/ip_local_port_range) |
WebRTC media. |
| UDP/5353 (mDNS) | Chrome sends .local ICE candidates. |
How Quasar tells you
Section titled “How Quasar tells you”The media_reachability readiness check in Admin ▸ Fleet ▸ Hosts fails when a
remote browser couldn’t connect, and names the rule to add. A pass only covers the
client that got through. See Readiness checks.
Adding the rule
Section titled “Adding the rule”Replace <lan-subnet> (for example 192.168.1.0/24) and <port-range>.
firewalld:
sudo firewall-cmd --get-default-zone # confirm <zone>sudo firewall-cmd --permanent --zone=<zone> \ --add-rich-rule='rule family=ipv4 source address=<lan-subnet> port port=<port-range> protocol=udp accept'sudo firewall-cmd --permanent --zone=<zone> --add-service=mdnssudo firewall-cmd --reloadufw:
sudo ufw allow proto udp from <lan-subnet> to any port <port-range>sudo ufw allow from <lan-subnet> to any port 5353 proto udpsudo ufw reloadiptables (insert ahead of your default-deny rule, then persist):
sudo iptables -I INPUT -p udp -s <lan-subnet> --dport <port-range> -j ACCEPTsudo iptables -I INPUT -p udp -s <lan-subnet> --dport 5353 -j ACCEPTnftables: add input accept rules for UDP <port-range> and 5353, scoped to
<lan-subnet>, ahead of the default-deny rule.
Endpoints worth knowing
Section titled “Endpoints worth knowing”Health
Section titled “Health”curl http://localhost:8080/health{"status":"ok","db":"ok"}The control plane. Not redirected to HTTPS.
curl http://127.0.0.1:9091/health{"status":"ok","sessions":0,"connected":true}The node agent, on its own host. connected means its link to the control plane is up.
The web app
Section titled “The web app”| Path | What |
|---|---|
/app |
The library and everything a player uses. |
/app/account |
Profile, quality default, devices, sessions, storage. |
/app/session/:id |
A live session. |
/admin |
The admin area. Admin role enforced on the server. |
/setup |
The first-run wizard, before the instance is claimed. |
/login, /register |
Authentication. |
Everything under /v1, with bearer tokens. Admin endpoints reject non-admin tokens.
| Endpoint | Purpose |
|---|---|
GET /v1/hosts |
Registered hosts and their status. |
GET /v1/hosts/{id}/gpus |
GPU inventory and memory for a host. |
GET /v1/admin/sessions/{id}/diagnostic-bundle |
The diagnostic bundle. |
GET /v1/admin/sessions/{id}/metrics |
Raw metrics for a session. |
POST /v1/sessions |
Launch a session. |
Full list: Control-plane API.
WebSockets
Section titled “WebSockets”| Path | Who | Purpose |
|---|---|---|
/v1/signal |
Browsers | WebRTC signaling. Gated by QUASAR_ALLOWED_ORIGINS. |
/agent/ws |
Node agents | Registration, capacity, session commands, heartbeat. |
A proxy in front must forward WebSocket upgrades and allow long idle connections.
Volumes
Section titled “Volumes”On a Quasar-owned machine:
| Volume | Contents |
|---|---|
quasar-machine |
Machine state: inputs, generated secrets, update records, pre-update dumps, the seed’s state. Never delete it. |
quasar-recovery-agent |
The agent’s socket to its recovery actor. |
quasar-agent-data |
The agent’s node secret and identity. |
quasar-node-agent-secrets |
The agent’s secrets, such as the enrollment string. Read-only. |
quasar-nvidia-driver |
NVIDIA hosts only. Driver libraries built from the running kernel module. |
quasar-postgres-data |
First machine, own database: the database. |
quasar-postgres-secrets |
The database password, for Postgres. |
quasar-control-data |
First machine: the TLS certificate and artwork cache. |
quasar-control-plane-secrets |
The control plane’s database password, secret key and (combined host) local enrollment token. |
quasar-final-dump |
Only after uninstall --purge with Quasar’s own database: the final dump. Never deleted by a purge. |
| The managed home root | A host bind mount: user saves and installed content. |
The first machine also has a quasar-platform bridge network.
Removing the seed or a container never removes a volume. Uninstalling keeps the
database, machine state, agent identity and homes. uninstall --purge removes this
install’s volumes after a final dump, but never the homes or a database you run
yourself. See Uninstalling.
On a legacy Compose install:
| Volume | Contents |
|---|---|
quasar-postgres-data |
The database. |
quasar-control-tls |
TLS certificate and artwork cache. |
quasar-agent-data |
The agent’s enrollment secret. |
quasar-updater-run |
The updater’s socket and apply results. |
quasar-nvidia-driver |
NVIDIA hosts only. Driver libraries built from the running kernel module. |
| The managed home root | A host bind mount: user saves and installed content. |
On disk, Compose prefixes names with the project (deploy_quasar-postgres-data
for a deploy directory). docker compose down -v destroys every volume above,
never the home root.