Previews & the workbench
Ask a session to start a dev server and publish it — you get a real URL like
https://<label>.preview.… that tunnels straight into the VM: full pages, APIs, websockets and
hot reload, on one origin. Previews belong to the thread and are revoked when it closes.
Choosing what to publish
Section titled “Choosing what to publish”/sparkyard ports lists what is actually listening inside your machine, with the program that
holds each one:
3000 node · next dev [Publish]8080 node · api server [Publish]5432 PostgreSQL · postgres [Publish anyway…]6379 Redis [Publish anyway…]Nothing is exposed by looking — each button publishes that one port and nothing else.
A database can be published, and asks first. A preview URL is a bearer link: whoever has it reaches the port, and the only thing in front of your database is its own password — which on a development database is often weak or absent. So the button says what it is, and pressing it explains before it does anything.
The better answer for a database is /sparkyard db, which opens a
read-only console on a link only you can open, without exposing the port at all.
The list is read from the kernel rather than guessed, so it also answers the question people actually have when a preview 502s: whether the server is running, and whether it bound to loopback.
What a preview link can and cannot carry
Section titled “What a preview link can and cannot carry”- Several ports, one link. A frontend on 3000 and an API on 8080 are published under the same
hostname and routed by path —
/to one,/apito the other. Same origin, sofetch("/api/…")works with no CORS and cookies behave as they do in production. The prefix is stripped before the request arrives, since it is there to choose the service rather than to address a route inside it. - HTTPS servers. If what you are publishing only listens on TLS — nginx or Caddy on 443 — say so when you publish it and the hop inside the machine becomes HTTPS too. The public URL is HTTPS either way.
- Ports 80, 443 and 1024–60000. Everything else privileged is refused; nothing worth publishing lives on 22 or 25.
- Not databases. A preview is HTTP from end to end: the front door reads a
Host:header to work out which link you mean, and Postgres never sends one. Databases have their own door — below.
Reaching a database
Section titled “Reaching a database”/sparkyard db opens a read-only SQL console in your browser — DbGate, running in your own
machine, published on a link only you can open. Nothing to install, no port opened to the internet.
/sparkyard db # finds the database that is running/sparkyard db 5432 # or name the portThree things make it safe, and they are worth knowing because they are what you would otherwise have to arrange yourself:
- Only you can open it. The link is owner-locked: it needs a session minted for you by name,
not merely knowing the URL. That is stronger than exposing the database’s port, which has only
the database’s own password in front of it — and on a development database that is often
postgres/postgres. - It is read-only. DbGate is started with the connection marked read-only, so the worst case is reading data rather than dropping a schema.
- Sparkyard never sees your database password. The console asks for it in the browser; it is not in Slack, not in a config file here, and not in any log.
It handles PostgreSQL, MySQL, MariaDB, SQL Server, MongoDB, Redis and ClickHouse. The first one on
a machine pulls a 430 MB image, so it takes a minute; after that it is immediate. Part of the
workbench, so an admin turns it on with /sparkyard settings workbench on.
What you give up against a real client is your IDE — saved queries, keyboard shortcuts, your own tooling. If that matters more than the convenience, the SSH tunnel below is the other route.
Reaching a database with your own client
Section titled “Reaching a database with your own client”Point your database tool’s SSH tunnel at Sparkyard. DataGrip, TablePlus, DBeaver and pgAdmin all have this built in, so there is nothing to install.
/sparkyard ssh import— copies the public keys already on your GitHub account, which is almost certainly the key your laptop already uses. Once per person, ever. (If you would rather not,/sparkyard ssh add <contents of ~/.ssh/id_ed25519.pub>pastes one instead; that file is public, so it is safe in a message.) Sparkyard replies with the host, port and username.- In your tool’s SSH/SSL tab, use those. In the connection itself, use
127.0.0.1and whatever port the database listens on inside your machine.
The tunnel arrives on the same public address as everything else, on its own port — it needs no
load balancer of its own. It forwards to loopback ports inside your own microVM and nothing
else — no shell, no
commands, no file transfer, no other host. It is off until an admin turns the workbench on with
/sparkyard settings workbench on, because it is machine access rather than a shared link.
Limits
Section titled “Limits”A machine allows 256 preview connections and 64 tunnels at once, counted separately so a long database session cannot starve the browsing and a page load cannot kill a query. If you hit either, the refusal says which one.
They count connections, not requests, which is most of the headroom. A browser opens about six connections to one origin and reuses them, and a preview is deliberately one origin — so somebody with a page open costs about six however many things it fetches, and ten XHRs on an open connection cost nothing. Idle connections are closed after five seconds, so visitors drain rather than accumulate: ten people a minute apart is six connections at a time, not sixty.
A second limit sits in the gateway: 512 connections per machine, across everything that machine has open. It is above what a guest itself allows, so it never bites in normal use — it exists because the gateway is one process shared by every customer, and among the things it holds is each machine’s control connection. Without it, one busy machine could stop other people’s turns, not just their previews.
The numbers are per machine, not per thread — one VM serves all your threads and worktrees, so
two worktrees share them. Your own machine will not come close. A shared desk is one machine for
everybody using it, which is where it can matter. Only whoever operates the deployment can change
them (PREVIEW_MAX_STREAMS, TUNNEL_MAX_STREAMS, per tenant, no image rebuild) — every open
stream is held in the shared gateway, so raising it takes headroom from other customers rather than
from yourself.
Who can open a link
Section titled “Who can open a link”A preview is a bearer capability by design: whoever holds the URL gets in, the message handing one over says so, and a preview that needed a login is a preview nobody looks at.
A workbench link is not. The same leaked URL would be a root shell holding your credentials, in
a chat app where links are forwarded, screenshotted and searchable forever — so /sparkyard ide,
shell and db links are created locked to the person who asked for them. Opening one takes a
single-use claim, good for a minute, delivered privately by the chat platform at the moment you ask;
your browser trades it once for a cookie that lasts eight hours. Nothing has to become an identity
provider for that to work.
Widen a link deliberately, never by accident:
| Visibility | Who gets in |
|---|---|
owner | only the person it was made for — where every workbench link starts, db included |
people | named people |
workspace | anyone in the Slack workspace |
public | anyone holding the URL — where a preview starts |
/sparkyard share <label> <who> widens one, /sparkyard share list shows who holds what, and
/sparkyard link takes it back. A workspace can forbid the wider settings outright with
link-ceiling, and choose how people prove who they are with link-auth — the
private claim, your own OIDC provider, or both.