Via

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

RequirementDetail
Host OSUbuntu 24.04 with sudo and active systemd.
Container runtimeDocker daemon running and reachable.
Git toolinggit and git-http-backend on PATH from the Ubuntu git package.
NetworkPort 8080 free on the host.
Vary releaseThe 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.

PathPurposeOwner / mode
/etc/via/Config rootvia-server:vary, 0755
/var/lib/via/Durable state (DB, identity, repos, builds, artifacts)via-server:vary, 2750
/var/log/via/Per-daemon log filesvia-server:vary, 2750
/etc/systemd/system/via-server.serviceControl-plane unitroot, 0644
/etc/systemd/system/via-builder.serviceBuild worker unitroot, 0644
/etc/systemd/system/via-runner.serviceRuntime supervisor unitroot, 0644
/etc/systemd/system/via-test-runner.serviceTest worker unitroot, 0644
/etc/systemd/system/via-config.serviceRuntime config unitroot, 0644
Managed proxy unitPublic routing unitroot, 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.

UserRole
via-serverOwns config and the SQLite control plane. Runs the HTTP daemon.
via-builderRuns build jobs in sandboxed containers. Member of docker.
via-runnerSupervises 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):

ProbeWhat it checks
schemaControl-plane DB exists and the embedded schema version matches the binary
systemdEach Via-managed unit is loaded and either inactive (pre-enable) or active
dockerdocker info succeeds and the vary-apps network exists
gitgit-http-backend is on PATH
portPort 8080 is either free (pre-start) or owned by via-server
keysSigning 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
UnitResponsibility
via-server.serviceControl-plane API, auth, JWKS, health, and Git HTTP frontend.
via-builder.serviceClaims queued deploys and runs checkout, typecheck, tests, compile, and signing.
via-runner.serviceVerifies signed artifacts and launches runtime containers.
via-test-runner.serviceRuns server-side test work.
via-config.serviceServes runtime config, secret, and add-on descriptor requests.
Managed proxy servicePublishes 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:

ResourceResult
App recordThe server-side app entry.
Source repositoryThe managed source repository for deploy intake.
HookManaged 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:

ResourceDefault 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.

← Introduction
Deploy an app →