Vsync
Vsync distributes large game builds without downloading the entire build every time. It divides files into content-addressed chunks, reuses chunks already on your machine, and downloads only what changed.
Choose the guide that matches what you need to do:
- Get a build: install the desktop or command-line client, then connect to your team's server.
- Publish builds: use the desktop Commit page
or
vsync commit. - Run a server: follow Install and configure.
- Manage a server: open the admin panel.
Your Vsync administrator provides the server address, access method, game name, and platform names used by your team.
How Vsync works
You only need a few concepts to use Vsync effectively.
Builds
A build is an immutable snapshot of a directory. Its build ID is derived from its contents, so identical directories have the same ID. Builds can also carry a human-readable version, source revision, build configuration, notes, and status flags.
Games and platforms
One server can host several games. Each build belongs to one game and one
platform, such as win64, linux, ps5, or xsx.
Streams
A stream is a movable name such as nightly, release, or qa. It points to
one build per platform and keeps a history of its previous builds. Fetching a
stream gets its current build; fetching a build ID always gets that exact
immutable build.
Cache and checkouts
The local cache stores chunks and manifests that can be reused by future builds. A checkout is a normal directory containing a materialized build that you can run, copy, or inspect.
Deleting cached chunks does not delete checkouts. Deleting a checkout does not necessarily remove its chunks from the cache.
Deduplication
Before transferring a build, Vsync asks which chunks the destination already has. Only missing chunks cross the network. Updating a checkout is staged and then swapped into place, so cancellation or failure leaves the previous build intact.
Install the clients
Download current client packages from the Vsync downloads page.
Windows
Run the x86-64 NSIS installer and launch Vsync from the Start menu. The installer is per-user and does not normally require administrator access.
For command-line or CI use, download the Windows CLI zip, extract vsync.exe,
and place it in a directory on PATH.
macOS
Download the universal DMG, open it, and drag Vsync into Applications. The universal application supports Apple Silicon and Intel Macs.
The CLI tarball contains a universal vsync binary. Extract it into a location
on PATH, such as /usr/local/bin.
Linux
Download the x86-64 AppImage, make it executable, and run it:
chmod +x Vsync_*.AppImage
./Vsync_*.AppImage
The CLI tarball contains the vsync binary:
tar -xzf vsync_*_linux-x86_64.tar.gz
sudo install -m 755 vsync /usr/local/bin/vsync
Verify the CLI
vsync --version
The desktop app and CLI share the same login, build root, and local cache on a machine.
Connect to a server
Ask your administrator for:
- The server address, normally
https://builds.example.com. - Either an access token or permission to sign in through Perforce.
- The game and platform names used by your team.
- A local directory where downloaded builds should live.
Desktop app
On the sign-in screen:
- Enter the server address.
- Choose Token or Perforce login.
- Choose your local build root.
- Sign in.
For token login, paste the token when prompted. For Perforce login, make sure
p4 is on PATH and you already have a live all-hosts ticket:
p4 login -a
Command-line client
Token login:
vsync login --server https://builds.example.com
Perforce login:
p4 login -a
vsync login --server https://builds.example.com --p4
Set the shared checkout directory:
vsync root D:\builds
On macOS or Linux, use a path such as ~/builds instead.
The login is stored for future sessions. Run vsync logout to remove the
stored server and token; cached data and checkouts remain untouched.
CI credentials
Automation should not run interactive login. Provide credentials through the environment:
export VSYNC_SERVER=https://builds.example.com
export VSYNC_TOKEN=vs_...
export VSYNC_GAME=my-game
export VSYNC_PLATFORM=win64
Environment values take precedence over the stored login.
Desktop app
The desktop app organizes builds by game and lets you fetch, update, inspect, and publish them without using the command line.
Select a game
The app is scoped to one game at a time. Choose the current game from the game picker. Builds, streams, search results, and publishing all use that game.
Browse builds
The Builds page groups matching platform builds into one version row. Use search and stream filters to narrow the feed. A row can show:
- Version or source revision.
- Platforms available for that build.
- Stream membership.
- Author, age, notes, and broken status.
- Whether a checkout is already local.
- How much data must be downloaded.
Open a build to see its complete metadata and platform variants.
Fetch a build
Select a platform and choose Fetch build. You can create a new checkout or update a checkout associated with a stream.
Vsync downloads only missing chunks. The new checkout is staged before it replaces the old one. If you cancel or the operation fails, downloaded chunks remain cached for the next attempt and the previous checkout remains usable.
From a local build you can:
- Open its directory.
- Fetch it again to verify and repair the checkout.
- Update it when its stream has moved.
- Delete the checkout without clearing the shared cache.
Work with streams
The Streams page shows each stream, its description, current platforms, tip builds, and local status. Open a stream to inspect its history and fetch a previous build. Administrators and publishers can edit stream descriptions.
Publish a build
Open Commit and:
- Choose the build directory.
- Wait for Vsync to stage and price the upload.
- Select the platform.
- Enter a version and optional source revision, build configuration, stream, release notes, and pin status.
- Review the number of missing chunks and bytes to upload.
- Choose Publish.
Versions must be unique for a game and platform. Pointing a stream at the new build is atomic: clients see either the old tip or the new tip.
Settings and storage
Open Settings to change the build root, inspect cache and checkout usage, open or delete local checkouts, clear cached downloads, or sign out.
Clearing the cache keeps checkouts but makes future downloads transfer those chunks again. A local-only commit that has never been uploaded can no longer be reconstructed after its cached data is cleared.
Command-line client
Run vsync <command> --help for the exact options supported by your installed
version.
Common context
Most remote commands need a game and platform:
vsync --game hippo --platform win64 list
You can set VSYNC_GAME and VSYNC_PLATFORM instead.
Browse builds
vsync --game hippo --platform win64 list
The output includes streams and recent builds, including versions, authors, source revisions, broken status, pin status, and notes.
Fetch builds
Fetch the current tip of a stream:
vsync --game hippo --platform win64 fetch nightly
Fetch an exact version:
vsync --game hippo --platform win64 fetch --version 2193.1.2
Fetch an immutable build ID to an explicit directory:
vsync fetch 067c4e9949d5d77952ac78bfb1a823ab --out D:\builds\test
Without --out, Vsync creates a path below the configured build root.
Publish a build
vsync --game hippo --platform win64 commit D:\build-output \
--stream nightly \
--version 2193.1.2 \
--rev CL45210 \
--config development
The final line is the immutable build ID. Recommitting identical contents produces the same ID and uploads no duplicate chunks.
Manage streams
vsync --game hippo --platform win64 stream set nightly <build-id>
vsync --game hippo stream describe nightly "Latest automated build"
vsync --game hippo --platform win64 stream rm nightly
Removing a stream removes its pointer and history. It does not immediately delete build data; normal retention and garbage collection rules apply.
Flag and pin builds
vsync flag <build-id> --broken --note "Crashes during startup"
vsync flag <build-id> --ok
vsync pin <build-id>
vsync pin <build-id> --remove
Pinned builds are protected from server garbage collection.
Sign out
vsync logout
This forgets the login only. It does not remove cached chunks or checkouts.
Local storage
Vsync separates its reusable cache from materialized checkouts.
Default locations
The cache defaults to ~/.vsync. Override it with --store or
VSYNC_STORE. The desktop app and CLI use the same cache.
The build root is the parent directory for checkouts created without an
explicit --out path:
vsync root
vsync root D:\builds
Inspect the cache
vsync cache status
Prune old cached builds
Preview first:
vsync cache prune --keep-builds 3 --dry-run
Then reclaim the space:
vsync cache prune --keep-builds 3
Pruning keeps the selected newest cached build manifests and all chunks they need. A remote build can be downloaded again later.
Clear the cache
vsync cache clear --yes
This removes cached manifests and chunks but leaves materialized checkouts on disk. Do not clear the only copy of a local build that has not been uploaded.
Client troubleshooting
“No server” or “run vsync login”
Sign in again and confirm the server address:
vsync login --server https://builds.example.com
For CI, verify that both VSYNC_SERVER and VSYNC_TOKEN are present.
Unauthorized or invalid token
The token may be mistyped, expired, or revoked. Ask an administrator to issue
a new token. If you use Perforce, run p4 login -a and then repeat
vsync login --p4.
Perforce login returns 401
- Confirm
p4is installed and onPATH. - Run
p4 login -a, not onlyp4 login. - Confirm your client uses the same spelling of
P4PORTconfigured on the server. - Ask the administrator whether Perforce authentication is enabled.
No build root configured
Set one or pass an explicit output directory:
vsync root D:\builds
vsync fetch <build-id> --out D:\temporary-build
Build or stream not found
Check the selected game and platform. Stream names are scoped by game and platform, and versions are unique within that pair.
Interrupted download
Run the fetch again. Completed chunks remain in the cache and are reused. The old checkout remains intact until staging completes.
A checkout looks damaged
Fetch the same build again from the desktop app, or run vsync fetch against
the managed destination. Vsync reconstructs the checkout from verified chunks.
Disk usage is too high
Inspect Settings in the desktop app or run vsync cache status. Delete unused
checkouts separately from pruning or clearing the cache.
Server overview
vsync-server is the shared object store and metadata service used by the
desktop and command-line clients. One server can host multiple games,
platforms, streams, and users.
The supported production deployment is:
- A Linux x86-64 server.
- Local NVMe storage.
vsync-servermanaged by systemd.- Caddy or another reverse proxy providing HTTPS.
- One access token per person, or Perforce-based login.
The server stores:
- Content-addressed chunks in
objects/. - Immutable build manifests in
manifests/. - Builds, streams, users, and activity metadata in
meta.sqlite.
The server itself speaks plain HTTP. Do not expose its listening port directly to the internet; put an HTTPS reverse proxy in front of it.
Sizing
For a small team, start with 2–4 CPU cores, 8 GB RAM, and fast local NVMe. Storage and outbound bandwidth matter more than CPU. Size the disk for one full copy of the initial builds plus the changed chunks retained from later builds.
Avoid storage backed by a slow network filesystem. Chunk transfer, manifest assembly, and garbage collection benefit from predictable local filesystem latency.
Supported server platforms
Linux is the supported production platform. An experimental Windows x86-64 binary is available for evaluation and small internal setups, but it does not yet include native Windows Service integration. macOS is not a server target.
Install and configure
Install the Linux package
Download the current .deb from the Vsync downloads page
and install it:
sudo apt install ./vsync-server_<version>-1_amd64.deb
The package installs:
/usr/bin/vsync-server/etc/vsync/server.tomlvsync-server.service- A locked-down
vsyncsystem user /var/lib/vsyncfor server data
The service is not automatically enabled on first installation. Review the configuration before starting it.
Configure the server
Edit /etc/vsync/server.toml:
root = "/var/lib/vsync"
addr = "127.0.0.1:7770"
# Optional integrations:
# p4 = "ssl:perforce.example.com:1666"
# webhook = "https://hooks.example.com/services/..."
[gc]
enabled = true
keep_history = 14
keep_days = 7
Settings mean:
root: chunks, manifests, and metadata location.addr: local address and port on which the HTTP server listens.p4: exactP4PORTused to validate Perforce tickets.webhook: optional Slack- or Discord-compatible incoming webhook.gc.enabled: run garbage collection at startup and daily.gc.keep_history: retain this many previous builds per stream.gc.keep_days: retain builds younger than this many days.
Unknown settings are rejected so configuration mistakes do not silently pass.
Command-line arguments override file values. Use --config <path> or
VSYNC_SERVER_CONFIG=<path> to select a different file.
Start the service
sudo systemctl enable --now vsync-server
sudo systemctl status vsync-server
curl http://127.0.0.1:7770/healthz
The health endpoint should return ok.
After changing server.toml:
sudo systemctl restart vsync-server
Create the first administrator
Start the service once so it creates its database with the correct ownership, then create an admin token as the service user:
sudo -u vsync vsync-server token create admin --admin
The token is displayed once. Store it securely and use it to sign in at
https://<your-server>/admin after HTTPS is configured.
Experimental Windows server
Extract the Windows server zip, create a writable data directory and a
server.toml, then run:
vsync-server.exe --config C:\Vsync\server.toml serve
Run it behind an HTTPS reverse proxy. The current package does not install a Windows Service; use Linux for unattended production deployment.
HTTPS and networking
The normal layout is:
clients → HTTPS :443 → Caddy → HTTP 127.0.0.1:7770 → vsync-server
Create a DNS record such as builds.example.com pointing at the VPS. Allow
ports 80 and 443 through the firewall, but do not allow public access to port
7770.
Caddy configuration
builds.example.com {
reverse_proxy 127.0.0.1:7770
request_body {
max_size 256MB
}
}
Reload Caddy and verify the public endpoint:
sudo systemctl reload caddy
curl https://builds.example.com/healthz
Caddy obtains and renews the TLS certificate automatically when DNS and ports 80/443 are correct.
Private-network alternative
For a server that must not be reachable from the public internet, place the
server and every client on a private network such as Tailscale. Bind Vsync to
the private interface and use the private address as VSYNC_SERVER.
Tokens are still required. If you use plain HTTP on a trusted private network, remember that production desktop updater and browser security features may still require HTTPS for their own endpoints.
Webhooks
When webhook is configured, the server posts build publications and stream
moves to that incoming webhook. Treat the webhook URL like a credential: limit
who can read the server configuration and rotate the URL if it leaks.
Users and authentication
Every API request requires a bearer token. Create separate identities for people and CI systems so access can be revoked without disrupting everyone.
Create a token
sudo -u vsync vsync-server token create ali
The token is shown once and only its hash is stored by the server. Send it to the user through a private channel. They sign in with:
vsync login --server https://builds.example.com
List and revoke tokens
sudo -u vsync vsync-server token list
sudo -u vsync vsync-server token revoke ali
Revoking a name immediately invalidates every token currently held by that name, including tokens on other machines and admin-panel sessions.
Administrator tokens
sudo -u vsync vsync-server token create ali --admin
Admin tokens can use the normal clients and sign in to /admin. Give them only
to people who should manage access, retention, streams, and build status.
CI tokens
Create a distinct identity for each automation system. Store its token in the CI secret store and expose it only to trusted jobs:
VSYNC_SERVER=https://builds.example.com
VSYNC_TOKEN=vs_...
Never commit a token or print it in build logs.
Perforce login
Set the exact Perforce endpoint in server.toml:
p4 = "ssl:perforce.example.com:1666"
Install the p4 CLI on the server and trust the server fingerprint as the
vsync user:
sudo -u vsync p4 -p ssl:perforce.example.com:1666 trust
Users need a live all-hosts ticket:
p4 login -a
vsync login --server https://builds.example.com --p4
The Vsync token issued through Perforce expires after seven days. A disabled
Perforce account cannot obtain another token. Use token revoke <name> when
access must end immediately.
Storage, backups, and upgrades
Data layout
With the packaged defaults, server data lives in /var/lib/vsync:
meta.sqlite users, builds, streams, flags, and activity
manifests/ immutable build manifests
objects/ content-addressed chunks
Metadata and manifests are small and essential. Chunks are much larger, but may be recoverable from original builds or client caches.
Back up safely
The metadata database uses SQLite WAL mode. Do not copy only meta.sqlite
while the service is running.
For a simple consistent backup, briefly stop the service:
sudo systemctl stop vsync-server
sudo tar -C /var/lib/vsync -czf /backup/vsync-metadata.tgz meta.sqlite manifests
sudo systemctl start vsync-server
Back up objects/ as well when storage and backup bandwidth allow. Keep at
least one backup outside the VPS.
Test restoration periodically on a separate directory or server.
Garbage collection
Preview a sweep:
sudo -u vsync vsync-server gc --dry-run
Run it immediately:
sudo -u vsync vsync-server gc
Garbage collection retains current stream tips, configured stream history, pinned builds, and young builds. A grace period prevents newly written files from being collected during an in-flight operation.
The server normally sweeps at startup and once per day. You can also preview or run a sweep from the admin dashboard.
Upgrade
Download the new package and install it over the existing version:
sudo apt install ./vsync-server_<new-version>-1_amd64.deb
sudo systemctl restart vsync-server
curl https://builds.example.com/healthz
The package preserves /etc/vsync/server.toml and /var/lib/vsync. Take a
metadata backup before upgrades that include database migrations.
Logs
sudo journalctl -u vsync-server -f
The admin activity trail records user-facing events such as logins, pushes, fetches, stream moves, flags, token changes, and garbage collection. systemd logs remain the source for startup errors and operational failures.
Server troubleshooting
Service does not start
sudo systemctl status vsync-server
sudo journalctl -u vsync-server -n 100 --no-pager
Common causes are an invalid TOML setting, a root directory the vsync user
cannot write, or another process already listening on the configured address.
Public health check fails
Check each layer separately:
curl http://127.0.0.1:7770/healthz
sudo systemctl status caddy
curl https://builds.example.com/healthz
If the local request works but HTTPS fails, inspect DNS, firewall rules, the Caddy configuration, and Caddy logs.
Uploads fail with request too large
Ensure the reverse proxy accepts bodies up to 256 MB. The Caddy example uses:
request_body {
max_size 256MB
}
Clients receive 401
- Confirm the token is active with
vsync-server token list. - Check that the client uses the correct server URL.
- For Perforce, confirm the exact
P4PORT, server trust,p4binary, and a client ticket created withp4 login -a.
Disk is filling up
Open the admin dashboard to inspect deduplicated store size and free space. Run a GC dry run, review retention values, and only then run the sweep. Check for large backups or unrelated files on the same volume as well.
Database permission errors
The packaged service runs as vsync. The data root and its contents must be
writable by that user. Run server maintenance commands with sudo -u vsync to
avoid creating root-owned files in the data directory.
Admin panel
The admin panel is available at:
https://builds.example.com/admin
Sign in with a token created using --admin. Normal user tokens cannot access
the panel.
The navigation contains:
- Dashboard: storage, free disk, games, GC, and recent activity.
- Builds: stream pointers and build status by game.
- Tokens: create, inspect, and revoke access tokens.
Session security
The admin token is stored in an HttpOnly, SameSite=Strict cookie scoped to
/admin. The server revalidates it on every request. Revoking the token signs
the browser out immediately.
Always access the panel through HTTPS. Do not use an admin token in screenshots, chat messages, tickets, or shared shell history.
Dashboard
The dashboard shows:
- Physical deduplicated store size and chunk count.
- Free space on the data volume.
- Number of active tokens.
- Build, stream, and pre-dedup content totals per game.
- Current GC retention policy and the last completed sweep.
- Recent activity with actor, action, game, and details.
Builds and streams
Open Builds and select a game or choose all.
Streams
The streams table shows the game, stream, platform, current build ID, and last update time.
Remove deletes that stream pointer and its recorded history for the selected game and platform. This can make older builds eligible for garbage collection, so confirm that important builds are pinned or referenced elsewhere first.
Use the desktop or CLI client to move a stream to another build or edit its description.
Builds
The builds table shows ID, game, platform, version, size, file count, uploader, age, state, and notes.
Available actions are:
- broken: warn clients that the build should not be used.
- ok: clear the broken flag.
- pin: protect the build from garbage collection.
- unpin: return the build to normal retention rules.
Flagging a build does not alter its files. Pinning protects the build and its chunks but does not move any stream.
Tokens and access
The Tokens page lists each identity, authentication source, role, status, and creation time.
Create a token
- Enter a descriptive person or automation name.
- Enable admin only when the identity needs admin-panel access.
- Choose create token.
- Copy the token immediately; it is shown once.
- Send it through a private channel.
Use distinct names for CI systems and human users. Avoid shared team tokens; they make revocation and the activity trail less useful.
Revoke access
Choose revoke all next to an identity. Revocation takes effect immediately and invalidates all tokens held under that name across every machine. Existing admin sessions under the name are also signed out.
Perforce-issued tokens display their source and expiry. Manually created tokens remain active until revoked.
Storage and garbage collection
The dashboard reports physical chunk storage after deduplication, free disk space, and pre-dedup content totals per game.
What GC keeps
Garbage collection retains:
- Every current stream pointer.
- The configured number of historical builds per stream.
- Pinned builds.
- Builds younger than the configured retention age.
- Files inside the safety grace period.
Everything else may be removed, including chunks no retained build needs.
Preview a sweep
Choose dry run. The result reports how many builds and chunks would be removed and how much space would be reclaimed. No data changes.
Run a sweep
After reviewing the dry run, choose run now. The result reports removed and retained data, and the action appears in recent activity.
GC is designed to run while the server is available. Backups are still separate: garbage collection is not a substitute for a tested metadata backup.