Alpha. Vary is under active development and not ready for production use. Syntax, APIs, performance, and behaviour may change between releases.
Install
This page sets up one Via host. It installs the layout, writes config and signing keys, checks preconditions, mints the first operator credential, starts the services, and provisions the first app.
Operator examples assume via install has added your host user to the Via
admin/shared group. Reconnect or run newgrp vary after first install so the
membership is active in your shell.
Prerequisites
| Requirement | Detail |
|---|---|
| Host OS | Ubuntu 24.04 with sudo and active systemd. |
| Container runtime | Docker daemon running and reachable. |
| Git tooling | git and git-http-backend on PATH from the Ubuntu git package. |
| Network | Port 8080 free on the host. |
| Vary release | The release tarball, or a vary binary in /usr/local/bin/. |
VSIX packaging in the release archive requires Node 20 or newer. If your build
host has an older Node, the release script stops before npm ci with the
detected version and the exact fix instead of continuing through noisy package
engine warnings.
If a full local API smoke run includes an app that binds the generated service to its default port, port 8080 must be free for that smoke. On a host that was previously installed by Via, the expected owner may be the Via control-plane unit:
/etc/systemd/system/via-server.service
ExecStart=/opt/vary/bin/via start
Environment=VARY_HOME=/opt/vary
That is Via-owned host state, not a random leaked process. Do not have a local test harness stop it implicitly. Stop it deliberately before a local default-8080 smoke and start it again afterward:
sudo systemctl stop via-server.service
# run the local API smoke that needs 8080
sudo systemctl start via-server.service
If the host should move to a newer Via version, install and select that version
with varyup, then let Via promote it into the system services:
varyup toolchain install <version>
varyup default <version>
via upgrade
via doctor
You do not need to check these by hand. via install runs the same checks itself and refuses to continue if any are missing. The next two sections show what that looks like on a host that is not yet prepared and how to inspect the prerequisite script before running it.
No system JRE is required. The release bundles its own JRE; builder and runtime images carry their own, so do not install OpenJDK separately for Via.
What via install prints when prereqs are missing
On a clean Ubuntu 24.04 host without required host packages, via install runs preflight, prints a PASS/FAIL line for every probe, and exits non-zero before touching the host:
Checking Via host prerequisites
Passed ubuntu: 24.04
Passed systemd: active
Failed git: not found in PATH
Failed git-http-backend: not found; install the 'git' package (supplies /usr/lib/git-core/git-http-backend)
Failed docker: Docker daemon is not running or not reachable
Failed proxy: public proxy package is not installed
Warning docker-network: vary-apps missing; install step will create it
Passed port: 8080 available
Passed disk: /var/lib/via has 48 GB free
Passed permissions: /var/lib/via writable
Info java: not checked; Vary uses bundled runtime
error: preflight failed. Fix the issues above or pass --skip-preflight.
info: install Ubuntu host prerequisites with: via install --print-prereq-script | sudo bash
Every Failed line names the probe, the detail, and (where useful) the remediation. The vary-apps Docker network is reported as Warning because via install creates it for you on the next successful run.
Inspect the prerequisite script
--print-prereq-script prints a self-contained Ubuntu 24.04 bootstrap script to stdout and exits. It does not touch the host. Inspect the exact script from your installed Via build before piping it to sudo bash:
via install --print-prereq-script
The script refuses to run as a non-root user, refuses anything other than Ubuntu 24.04, installs only the host packages Via depends on, disables the distro-managed public proxy service so Via's managed service can take over, and creates the vary-apps Docker network. It does not create Via users, directories, systemd units, or signing keys; those are via install's job in the next step.
Step 1: install the host layout
# Install host prerequisites and the Via Docker network.
via install --print-prereq-script | sudo bash
# Create Via users, directories, systemd units, and admin group access.
via install
This command creates the host layout, three service users, the shared vary system group, and the Via-managed systemd unit files. Re-running it is safe and does nothing when the layout is already correct.
| Path | Purpose | Owner / mode |
|---|---|---|
/etc/via/ | Config root | via-server:vary, 0755 |
/var/lib/via/ | Durable state (DB, identity, repos, builds, artifacts) | via-server:vary, 2750 |
/var/log/via/ | Per-daemon log files | via-server:vary, 2750 |
/etc/systemd/system/via-server.service | Control-plane unit | root, 0644 |
/etc/systemd/system/via-builder.service | Build worker unit | root, 0644 |
/etc/systemd/system/via-runner.service | Runtime supervisor unit | root, 0644 |
/etc/systemd/system/via-test-runner.service | Test worker unit | root, 0644 |
/etc/systemd/system/via-config.service | Runtime config unit | root, 0644 |
| Managed proxy unit | Public routing unit | root, 0644 |
Three service users are created, all in the shared vary group. The invoking
operator is added to the same Via admin/shared group so follow-up commands such
as via init, via doctor, and via app ensure do not need to be run as root.
| User | Role |
|---|---|
via-server | Owns config and the SQLite control plane. Runs the HTTP daemon. |
via-builder | Runs build jobs in sandboxed containers. Member of docker. |
via-runner | Supervises runtime containers. Member of docker. |
After installation, reconnect to the host or run newgrp vary if this is the
first time your user was added to the group. via doctor verifies that the unit
files, service users, shared group, and Docker access are present.
Step 2: initialize the host
via init --domain <your-host-fqdn>
This writes /etc/via/server.toml, mints two signing keys under /var/lib/via/identity/, and creates the empty control-plane SQLite database at /var/lib/via/control-plane.db. One key signs identity tokens. The other signs artifacts. The default log path (/var/log/via/server.log), control-plane listen port (8080), and config-server port (8181) are recorded in server.toml.
server.toml has four sections:
[server]
domain = "your-host-fqdn"
external_url = "https://your-host-fqdn"
host = "127.0.0.1"
port = 8080
[storage]
root = "/var/lib/via"
[identity]
issuer = "https://your-host-fqdn"
[git]
https_enabled = true
backend = "git-http-backend"
root = "/var/lib/via/repos/bare"
[builder]
poll_interval_ms = 1000
[runner]
poll_interval_ms = 1000
[runtime]
backend = "docker"
network = "vary-apps"
[config_server]
host = "0.0.0.0"
port = 8181
[acme]
mode = "prod"
[logging]
log_file = "/var/log/via/server.log"
Re-running init against a populated /etc/via/ exits non-zero rather than rotating keys silently. Key rotation is a separate operator action.
After initialization, via doctor verifies that the config file, database,
signing keys, and app-build prerequisites are present. The app-build section
names the selected concrete toolchain from varyup, compiler input, stdlib
input, runtime input, runtime image readiness, Docker, and Git endpoint status.
Step 3: upgrade an installed host
After installing and selecting a newer Vary/Via toolchain with varyup,
promote it into the systemd service runtime with one command:
varyup toolchain install <version>
varyup default <version>
# Back up Via state, reconcile host layout, promote the runtime, and restart services.
via upgrade
via upgrade creates a pre-upgrade backup, applies any non-destructive host
layout changes from the new release, updates /opt/vary/current, rewrites the
service launchers, restarts all Via units, and checks that the services stay
active. You do not need to run via install before every upgrade.
If an upgrade is interrupted after the new toolchain is installed, rerun:
via upgrade resume
resume follows the same idempotent upgrade path and is safe after a
pre-baseline repair or after a previous attempt stopped before service
promotion.
For a host created by an unreleased pre-baseline Via build, via doctor may
report control-plane:migration-checksum with
prebaseline_checksum_drift. Do not force the migration. Use the supported
recovery path:
via backup create --include-control-plane --allow-checksum-drift /var/lib/via/backups/prebaseline.zip
via control-plane rebaseline --from-prebaseline --backup-id <backup-id> --confirm "REBASELINE /var/lib/via/control-plane.db TO 1"
via upgrade resume
via doctor
Step 4: check host health
# Confirm services, permissions, Docker, Git, and public-routing health.
via doctor
via doctor is a fast, read-only check. It reports schema version, systemd unit health, Docker reachability, the vary-apps Docker network, git-http-backend on PATH, port 8080 binding, and key file permissions. Use it after install, after config changes, and before investigating deploy failures.
Probes (each prints PASS or FAIL with a one-line reason):
| Probe | What it checks |
|---|---|
schema | Control-plane DB exists and the embedded schema version matches the binary |
systemd | Each Via-managed unit is loaded and either inactive (pre-enable) or active |
docker | docker info succeeds and the vary-apps network exists |
git | git-http-backend is on PATH |
port | Port 8080 is either free (pre-start) or owned by via-server |
keys | Signing keys have the expected owner and permissions |
Exit code is 0 only when every probe passes. Non-zero exit means a precondition for the next steps is missing.
Each probe prints a PASS line when the host is ready for the next step.
Step 5: create the first operator credential
On the host:
via admin create <your-name>
This prints a one-time adm_... token and a vary login command. The token is shown once. The server stores only a hash for verification. The token never lands in ~/.git-credentials or any keychain on the workstation. After vary login exchanges the admin token for a session, the workstation stores a short-lived session under ~/.vary/credentials/sessions/<slug>.json (mode 0600).
For deployment interruptions caused by an expired workstation session, create a short-lived scoped token instead of a new permanent admin credential:
via admin token create deployer --scope app:deploy --ttl 2h
vary login prints the resulting session scope and expiry so the developer can
verify they received the intended temporary access.
Sample output:
Admin user 'alice' created.
One-time token (will not be shown again):
adm_01HXXX...
Run on your workstation:
printf '%s\n' 'adm_01HXXX...' | vary login https://your-host-fqdn --name alice --token-stdin
On your workstation:
vary login https://<your-host-fqdn> --name <your-name> --token-stdin
vary login exchanges the admin token for a session JWT, stores the session at ~/.vary/credentials/sessions/<slug>.json with mode 0600, and prints the session expiry plus the stored path. The admin token is single-use; subsequent vary login calls re-use the session until it expires, then prompt for re-auth.
The saved session includes the server URL, key id, expiry, and bearer token, but never the original admin token.
What you have now
After steps 1 through 4, you have an installed, initialized, checked host with one operator credential exchanged for a short-lived session on your workstation.
Step 6: verify the server daemons
via init reloads systemd, enables the Via units, starts them, and checks that
each unit becomes active. Verify the running host through Via:
via status
via doctor
| Unit | Responsibility |
|---|---|
via-server.service | Control-plane API, auth, JWKS, health, and Git HTTP frontend. |
via-builder.service | Claims queued deploys and runs checkout, typecheck, tests, compile, and signing. |
via-runner.service | Verifies signed artifacts and launches runtime containers. |
via-test-runner.service | Runs server-side test work. |
via-config.service | Serves runtime config, secret, and add-on descriptor requests. |
| Managed proxy service | Publishes validated public routes. |
You want each service to report active. If a unit fails to start, via init
and via doctor print the journal command for the affected units.
Step 7: provision the first app
Before a project can deploy, the server needs an app record and managed source repository:
via app ensure my-api --owner alice
For clean-host validation, use the minimal smoke fixture
tests/fixtures/vary-server/hello as the first deployed app. It has a valid
[app] declaration, one build test, no external dependencies, and is the app
used by the remote smoke harness before larger apps such as issue-tracker.
This command is idempotent for the same app and owner. It creates:
| Resource | Result |
|---|---|
| App record | The server-side app entry. |
| Source repository | The managed source repository for deploy intake. |
| Hook | Managed deploy-intake hook. |
Finished state
The host is now installed, initialized, healthy, running the core daemons, and has one app ready for app-owner deploys.
Uninstall
To remove a Via host installation, stop the daemons first, run a dry run, then confirm the removal:
via uninstall --dry-run
via uninstall --yes
via uninstall --yes removes Via-managed config, logs, state, and systemd unit files:
| Resource | Default path |
|---|---|
| Config | /etc/via/ |
| State | /var/lib/via/ |
| Logs | /var/log/via/ |
| systemd units | /etc/systemd/system/via-*.service for Via-managed units |
Use --keep-data when you want to remove the host wiring but preserve durable server state:
via uninstall --keep-data --yes
With --keep-data, /var/lib/via/ is preserved, including the control-plane DB, identity keys, repos, artifacts, app state, add-ons, toolchains, and runtime image cache. Config, logs, and units are still removed. Host packages are left installed.
The uninstall command does not delete system users or groups (via-server, via-builder, via-runner, vary), does not remove Docker group membership, and does not remove Docker networks or containers. Clean those up separately only after confirming no other Via-managed processes or data need them.
Continue to Deploy an app.