Docs
How to install a Connector, expose a Service, and control who can reach it.
Quickstart
Get one local service onto a public URL.
**Target: five minutes.** If it takes you longer, that is a bug in this page or in the product, and we would like to hear which.
> **Not all of this works yet.** Steps 2 and 3 are waiting on Connector > registration, and each step below says plainly whether it is live. Nothing > here describes a screen that does not exist.
---
Before you start
You need:
- a service already running and reachable on the machine you will install on — try `curl http://127.0.0.1:8080` first, and fix that before continuing; - an account (sign in from the landing page — there is no separate login URL); - one of the seven supported platforms:
| Platform | Architectures | |---|---| | Linux | amd64, arm64 | | macOS | amd64, arm64 | | Windows | amd64 only — **Windows on ARM is not supported in v1** | | Docker | amd64, arm64 |
---
1. Sign in — **live**
Go to the landing page and use **Sign in**. Either Google, or a six-digit code sent to your email address. There is no password anywhere in the product, so there is nothing to forget, leak or rotate.
Your first sign-in creates a Workspace for you automatically, with you as its Owner and on the Free plan. You are not asked to name anything.
A **Workspace** is the billing, membership and policy boundary. Everything you create belongs to exactly one, and workspaces cannot see each other.
---
2. Install a Connector — **not available yet**
The install page is at **Connectors** in the console. It shows the command for each platform, but the enrollment tokens the command needs cannot be issued yet, so the install will not complete.
When it does work, you will get two forms of the command, and you should prefer the second if you are at all careful:
# one line
curl -fsSL https://<host>/install.sh | VIASTEAD_TOKEN=<token> sh# or download it, read it, then run it curl -fsSL https://<host>/install.sh -o install.sh less install.sh VIASTEAD_TOKEN=<token> sh install.sh ```
The one-liner asks you to run code you have not read. The second form exists so that declining to do that is a supported path rather than something you have to improvise.
Three things the installer guarantees, and why each matters:
- **A truncated download does nothing.** The whole script is wrapped in a function that is only called on the very last line. If your connection drops halfway, you get an incomplete file that defines a function and exits — rather than half an installation. - **The binary's checksum is verified** before it runs, by default, not behind a flag you have to remember. - **You can pin a version**, so a fleet stays on a known build instead of tracking whatever is newest.
---
3. Approve the machine — **not available yet**
A newly installed Connector reports in as **pending**. It carries no traffic until somebody approves it.
The console shows its machine fingerprint, Site, version and source IP. **Check those against the machine you just installed on** before approving — that comparison is the entire security value of this step. A token that leaked would produce a pending Connector that looks almost right, and the fingerprint is how you tell.
Who can do what:
| | Issue a token | Approve | Disable / enable / revoke | |---|---|---|---| | Owner | ✅ | ✅ | ✅ | | Admin | ✅ | ✅ | ✅ | | Operator | ✅ | ❌ | ✅ | | Viewer | ❌ | ❌ | ❌ | | Billing | ❌ | ❌ | ❌ |
An Operator can hand out tokens and take a misbehaving machine out of service, but cannot admit a new machine to the workspace. That split is deliberate.
---
4. Expose a Service — **live in the console, but you cannot reach step 2 yet**
You point an Endpoint at a local address, and confirm once.
The confirmation says exactly what you are about to do — "you are about to expose `127.0.0.1:8080` to the public internet at `https://…`" — and until you confirm, the Endpoint stays a draft with no public address at all. It is asked once, on whichever side you are already using; the other side shows the event but does not ask again.
Some addresses are refused:
- **Cloud metadata endpoints** (`169.254.169.254`, `fd00:ec2::254`, `metadata.google.internal`) are refused with **no override on any plan**. Those addresses hand out your instance's credentials to anything that can reach them, so exposing one would turn your tunnel into a credential leak. - **LAN addresses** need a paid plan and have to be switched on deliberately. Loopback (`127.0.0.1`, `::1`) works everywhere with no extra setting. - **The Connector's own inspector port**, which would publish the agent's control surface through the tunnel it is running.
---
5. Choose who can reach it — **live**
Access Policy is the second step of creating an Endpoint, not a setting buried somewhere you might never visit. The options are Public, Passcode, IP allowlist, OAuth via Google or GitHub, and Consent-only.
With Consent-only you invite a named person from the endpoint itself; they accept, and they decide how long the access lasts. It always expires.
---
What you get either way
Free includes 1 GB of traffic a month and automatic TLS. Security is not paywalled: automatic TLS, passcodes, IP allowlists, token revocation and abuse handling are all on Free too.
If you go far enough over your allowance, traffic is suspended rather than billed silently. The [FAQ](./faq.md) covers what that means in practice.
---
If it did not work
- **The install command does nothing / says the host is unknown** — expected today. See step 2. - **You signed in but the console says your workspace setup is incomplete** — workspace creation failed without failing your login, on purpose. Use the retry on that page; your account and billing are unaffected. - **`curl http://127.0.0.1:8080` fails on the machine itself** — that is not a viastead problem yet. Fix it locally first; nothing downstream can work until it does.
CLI reference
> **Skeleton.** The CLI is not released, and its command names and flags are > **not settled**. This page is the structure the reference will fill, plus the > behaviour that IS already decided — which is worth writing down now, because > it is the part that constrains everything else. > > Nothing below should be treated as a stable interface. Where a name is not > decided, this page says so rather than picking one that would then have to be > broken.
---
What is already decided
These come from the product specification and will hold whatever the commands end up being called.
The CLI is one of two equal places to confirm an exposure
The first time you expose a new Service, you are asked to confirm **once**, on whichever side you are already working — CLI or console. The other side shows that it happened but does not ask again.
This matters if you are scripting: there is exactly one confirmation, and it is not a double approval. Until it happens the Endpoint stays a draft and has no public address.
The confirmation prompt names both addresses
It tells you the local address and the public URL together, so you can check you are exposing what you meant to. A prompt that only asked "are you sure?" would give you nothing to check.
`--help` is a first-class surface
Most people meet this tool through `--help` and the first screen of the console, and never read a documentation site. `--help` is expected to be sufficient for the common path on its own.
Exit codes distinguish "refused" from "broken"
A command that was refused for a reason you can act on — over quota, not approved, insufficient role — must not exit the same way as a crash. Scripts need to tell a policy decision from a failure, and retrying a policy decision is pointless.
The specific numbers are not assigned yet.
---
Structure this reference will take
Each command gets: one-line purpose, synopsis, flags with defaults, at least one worked example, the exit codes it can produce, and what it does NOT do.
Planned command groups
| Group | Covers | Names settled? | |---|---|---| | Authentication | Signing the CLI in against a Workspace | No | | Connector | Install, status, version, disable, revoke | No | | Service | Registering a local address the Connector can reach | No | | Endpoint | Creating a public address, pausing, deleting | No | | Access policy | Public / passcode / IP allowlist / OAuth | No | | Diagnostics | Connectivity checks, last error, log location | No |
The groups follow the object model — Site, Connector, Service, Endpoint, Access Policy — because those are the nouns the product is built from and the ones the console uses. A CLI that invented different nouns would make the two surfaces harder to learn than either alone.
---
Not in the CLI, deliberately
- **Approving a Connector.** Approval requires checking a machine fingerprint against the machine in front of you, and it is restricted to a human session — an API key cannot do it. A CLI flag would turn a deliberate check into a scripted one. - **Anything that changes billing.** Plan changes and payment methods live in the console.
---
Conventions the reference will follow
- Every example is copy-pasteable and complete. No `<placeholders>` that are not explained on the same screen. - Every destructive command states what is lost before it asks. Deleting an Endpoint permanently retires its address after the restore window — a confirmation that does not say so is not a confirmation. - Long output is paged, never truncated silently. - Nothing prints a credential. Tokens are shown once at creation and never again, including in logs and error messages.
FAQ
The questions people ask first.
> ⚠️ **Copy discipline for editors.** The traffic-limit answer below is > constrained by frozen copy (`docs/PRD-addendum.md` A.2) and gate G-38. The > ban is semantic, not literal: `rather than stopping`, `always stays up`, > `keeps running no matter what` and **any other phrasing that promises traffic > never stops** are prohibited (ADD-Q1-04). Do not soften this section.
---
Do I have to open a port on my router?
No, and there is nothing to open. The Connector only ever dials **out**. It never accepts an inbound connection, so there is no listening port to forward, no firewall hole, and nothing exposed if your home IP changes.
Is my traffic decrypted at your edge?
Briefly, and only for routing, authentication and abuse prevention. We do not collect request or response bodies from tunneled traffic, do not send them to our control plane, logging or analytics systems, and do not retain them. Bodies shown in Request Inspector exist only in the memory of your Connector, on your own machine.
There is one exception, and it does not come from your traffic: evidence a third party submits in an abuse report may contain bodies. That is stored in an encrypted, physically isolated vault, is not searchable by default, and is retrievable only by case ID. The full statement is on the privacy page.
What happens when I run out of traffic?
Paid plans use graduated throttling. During the 100% and 300% throttle stages, requests continue at the rate for that stage; at 500%, traffic is suspended. Free endpoint traffic stops when the Free plan's included monthly traffic is used.
If an Endpoint is suspended at 500%, **you cannot resume it yourself** — the Resume control is disabled. It comes back when any one of these happens:
- you upgrade your plan, - you buy a traffic pack, - your billing period resets.
This is deliberate. A suspension you could click your way out of would not be a limit.
Will my URL change?
No. An Endpoint's address is assigned once and is permanent. It survives pausing, sleeping, deleting and restoring within the restore window.
After an Endpoint is deleted and its 30-day restore window closes, the address is **retired permanently and never issued to anyone again**. That is why deleting is worth a moment's thought: bookmarks and webhooks pointing at it will stop working, and recreating the Endpoint will not bring the old address back.
The reason it is never recycled is worth stating: if addresses were reused, an old bookmark or a webhook someone configured months ago could quietly start reaching **a different customer's service**. Storing a retired address forever costs almost nothing; that failure would not be almost nothing.
What happens if my machine goes offline?
The Endpoint stays; the traffic does not. Visitors get a clear error page rather than a timeout, and the Connector reconnects on its own when the machine comes back.
On Free, an Endpoint with no traffic for 30 days goes to sleep — it stops forwarding and releases runtime capacity, but **keeps its address**. It wakes when the Connector reconnects or when you wake it, at the same address.
Can I use my own domain?
Yes, on paid plans, with automatic TLS. Platform subdomains get automatic TLS on every plan including Free.
Is security a paid feature?
No. Automatic TLS, passcodes, IP allowlists, token revocation and abuse handling are all available on Free. The paid plans buy capacity, regions and scale — not the ability to protect what you expose.
Who can see my services?
Nobody, until you choose. Every Endpoint gets an Access Policy as the second step of creating it — not a setting buried somewhere you might never open. The options are Public, Passcode, IP allowlist, and OAuth via Google or GitHub.
Workspaces cannot see each other's anything.
Can I give a customer temporary access without adding them to my team?
Yes — that is what the Consent Portal is for. You send a request bound to their email address; they choose an expiry and approve, reject, suspend or revoke it themselves.
Two properties are worth knowing:
- **Every grant expires.** There is no permanent option; the longest you can choose is 30 days. - **Revoking is precise.** Revoking one customer's grant closes their sessions within 60 seconds and does not disturb anyone else's, including your own team's.
They do not consume a management seat. Members and authorized visitors are different things and only Members are billed as seats.
Do you support raw TCP?
On paid plans, with payment card verification. Not on Free — creating one there is rejected with upgrade guidance rather than silently failing.
The full protocol table, including what is **not** supported (h2c, WebSocket over HTTP/2, HTTP/3, TLS passthrough, UDP), is on the [documentation front page](./README.md).
What uptime do you promise?
None, and we would rather say so than imply otherwise. v1 is best-effort, with a public status page and announced maintenance windows. There are no service credits and no published uptime figure, because none is promised.
The [status page](https://viastead.com/status) reports current state. It does not yet cover the relay path itself — that arrives with the relay.
How do I delete my account and data?
Self-service export and account closure are available. Closure is not a single switch that erases everything: some records are deleted outright, and others are retained where we are legally required to, with the traffic-derived ones irreversibly anonymised. The retention table is on the privacy page and lists each category rather than making a blanket claim.
Why "viastead"?
*Via* — the way through. *Stead* — a place that stays put. Which is the whole product: a fixed address for something that lives at your place.