Vary has had an answer for the language and the toolchain for a while. What it did not have was an answer for what to do with a Vary app once it was written. The shape of the gap was familiar. You had source. You wanted a running service with a domain, a database, config, secrets, and logs. The path in the middle was the operator's problem.
Via is the answer, and it is the start of an enterprise application server ecosystem for Vary. The first wave is one host that knows how to run Vary apps end to end. Operators get a single piece of infrastructure to install. App owners get a short path from committed source to a tested, running service with routes, domains, config, secrets, and add-on bindings. More pieces of the ecosystem are landing on top of that foundation.
The whole product follows one rule: app owners submit source, and Via decides what becomes a running release.
Each step has a name and a state. An app moves through queued, building, typechecking, testing, artifact_ready, deploying, and running. Failure at any step is recorded and does not replace a healthy runtime that is already serving traffic.
| Piece | Responsibility |
|---|---|
| Control plane | Owns apps, users, source intake, releases, operations, audit, domains, routes, and add-on state. |
| Builder | Tests, compiles, packages, and signs Vary app artifacts from clean source. |
| Runner | Verifies signed artifacts and starts or supersedes Vary app runtime containers. |
| Config server | Gives running workloads authorized config, secrets, and add-on descriptors. |
| Add-ons | Provides resources such as managed SQLite through app bindings. |
| Proxy | Publishes validated app routes through managed Caddy. |
Each piece has a narrow job. The control plane never builds. The builder never serves traffic. The runner never decides what is allowed to be a release. That split is what makes the audit trail honest.
App owners talk to Via from a workstation. The flow is short:
vary login https://vary.example.com --name alice --token adm_...
vary app init --server https://vary.example.com --app my-api
vary app deploy
vary app status
vary app logs --runtime
vary app deploy pushes the current commit to the server-hosted Git endpoint. The server takes it from there. No artifact ever leaves the developer's machine. The deploy token is short-lived, scoped to the app, repo, and ref, and is not written to normal Git credential storage.
Public traffic is a separate gate. Hostname ownership has to be proven before a route is allowed to attach:
vary app domain request my-api my-api.apps.example.com --target prod
vary app domain verify my-api my-api.apps.example.com --target prod
vary app route add my-api my-api.apps.example.com --target prod --port 8080
The split is deliberate. A deploy proves the source, build, and runtime path. The domain and route commands prove hostname ownership and only attach traffic once the platform policy gates pass. A failed route does not take down a healthy runtime.
Operators install the host, bring up the platform services, mint the first admin token, define domain policy, approve protected hostnames, manage add-ons, and inspect operations. The basic host path is:
via install
via init --domain vary.example.com
via doctor
via admin create alice
via app ensure my-api --owner alice
Operator commands are run on the host by a user in the Via admin/shared group. App owner commands are run from a workstation against the operator's URL. The two surfaces do not overlap.
The guardrails are the part that is worth knowing about. They are not security theatre: each one removes a category of incident the operator would otherwise have to defend against.
| Guardrail | What it does |
|---|---|
| No workstation binaries | The builder compiles from a clean checkout on the server. The runner verifies the signature on every artifact before launching it. There is no path for a developer-built jar to end up serving production traffic. |
| Workload identity for secrets | Secrets are delivered through workload identity, not command-line arguments or environment files. Each container gets a short-lived signed token, and the config server enforces what that token is allowed to fetch. |
| Managed SQLite by binding | Apps refer to their database as a named binding. Via owns the file. The app does not know or care where it lives, and there is no credential to leak. |
| Route gates separate from deploys | Hostname ownership is proved out of band. Routes attach only after domain verification, policy match, and certificate coverage. A failed route never replaces a healthy runtime. |
| Auditable releases | Every release is signed, every route change is recorded, and every config delivery is tied to a workload identity. There is one log to read. |
The combination is the point. Each guardrail closes one of the doors that operator handbooks would otherwise have to keep watching.
Via is moving fast. The shape since the start of the year:
| Addition | What it covers |
|---|---|
| App-bound route domains | Self-service hostname requests with DNS TXT proof and per-app domain state. |
| Custom Caddy certificate bindings | Per-route certificates wired into the proxy before routes flip. |
| Observability settings and routing APIs | Per-app structured logging, metrics recording, and tuning. |
| App add-on and runtime APIs | Typed endpoints for lifecycle, config, secret, and descriptor refresh. |
| Managed SQLite | Served through the config daemon, with backup, restore, and bound-app drain flows. |
The direction is the same direction the rest of Vary is going. The platform should be the one source of truth for the parts that have to be coherent across the whole release.
If you want to read the canonical product description, start at the Via introduction. If you want to install Via, start with the Install and Start Via Server course. Then use Push and Test an App on Via to deploy a real Vary app. There is also a companion article on installing Via and deploying the echo server.