Documentation
Four things make up a working backup here: an agent on each machine, a policy that says what to protect and for how long, a storage target that says where it lands, and a console that can prove it happened. This page describes what the software actually does, including where a choice costs you something.
Sign in and open Add device: it prints the exact one-liner for your control plane, with the address and a fresh single-use token already filled in. The commands below use https://www.outwestbackup.com and TICKET as stand-ins so you can see the shape of them.
Installing an agent
One command per machine. It downloads the build this control plane is serving, installs the agent as a system service — launchd, systemd, or a Windows service — so backups run whether or not anyone is signed in, enrols the machine, and exits. Re-running it upgrades in place and keeps the machine's existing identity, so it is safe to paste twice.
The machine appears in the fleet within seconds of enrolling. It will not back anything up until it has a policy, and the console flags a device that has none.
macOS and Linux
curl -fsSL https://www.outwestbackup.com/install.sh | sudo sh -s -- --server https://www.outwestbackup.com --token TICKET
- It needs root, and refuses without it: the agent has to read every user's files and start at boot. That is what the sudo is doing there — piping into sudo sh rather than sh.
- The binary lands at /usr/local/bin/outbacksync-agent, with state in /var/lib/outbacksync — on macOS, /Library/Application Support/OutBackSync.
- On macOS it also installs the menu-bar app, and you should grant the agent Full Disk Access afterwards. Without it Mail, Messages and other protected data are skipped and the backup still reports success, so the console raises a No Full Disk Access flag when the agent reports the check as denied.
- Both Intel and ARM, and FreeBSD builds exist for the same installer flow.
Windows
iwr https://www.outwestbackup.com/install.ps1 -UseBasicParsing | iex; Install-OutBackSync -Server 'https://www.outwestbackup.com' -Token 'TICKET'
- Run it in an elevated PowerShell; it checks, and stops if it is not administrator. 64-bit Windows only.
- It registers a service called OutBackSync, installs into %ProgramFiles%\OutBackSync and keeps state in %ProgramData%\OutBackSync.
Proxmox VE
A PVE node has no sudo installed by default and you are already root there, so a command carrying it fails with "command not found" on the one platform the script exists for. Run it as root — or su - first.
curl -fsSL https://www.outwestbackup.com/install-proxmox.sh | sh -s -- --server https://www.outwestbackup.com --token TICKET
- It refuses to install anywhere that is not a PVE node — no /etc/pve, or no vzdump, and it stops and points you at install.sh instead. Installing the hypervisor agent on a laptop would leave it tracking Proxmox builds forever and protecting nothing.
- This is a separate agent build from the one that protects laptops and servers. A node carries every guest on it, so it rolls forward on its own cadence: promoting a build for the fleet does not touch your nodes.
- Guests are backed up with vzdump in snapshot mode, so they keep running. QEMU virtual machines and LXC containers alike, disks and guest configuration together, so a restore point goes back with qmrestore or pct restore.
- Staging space matters. vzdump writes a full compressed archive before the engine reads it. The installer looks for a directory with at least 20 GiB free (/var/lib/vz/dump, /var/lib/vz, /var/tmp) and warns if it finds none; pass --stage /path/with/room to choose one. Filling a hypervisor's root filesystem does not merely fail a backup, it can stop the guests, so VM backups are refused rather than risked.
- It installs outbacksync-agent.service. Watch it with journalctl -u outbacksync-agent -f.
A machine that already has the agent
Enrol an existing install into a tenant without reinstalling it:
outbacksync-agent enroll --server https://www.outwestbackup.com --token TICKET
Enrolment tickets, and the tenant token
A machine joins a tenant by presenting a token. There are two kinds, and the difference is how much damage a stray copy of one can do. Both are accepted by every installer above — a ticket is a token, not a platform choice, so the same one enrols a Mac, a Windows box or a PVE node.
Two ways in
| Enrolment ticket | Tenant enrolment token | |
|---|---|---|
| Enrols | Exactly one device | Any number of devices |
| Lifetime | 2 hours by default; 7 days at the most | Never expires |
| Spent | The moment a device enrols with it, or at expiry — whichever comes first | Never |
| If it leaks | Someone can enrol one machine into the tenant, until it expires | Anything enrolled with it receives this tenant's storage credentials, so a copy left in a shell history or a chat log is a way into the bucket |
| Taking it back | Revoke it in the console | Rotate it. Devices already enrolled are unaffected — they authenticate with their own per-device token, which is what makes rotation safe |
Use a ticket. It exists so nobody has to paste a permanent credential into a terminal, and what ends up in a clipboard is then good for one machine and a couple of hours. The permanent token is still shown in the console, folded away and labelled, because reaching for it should be a deliberate act.
Policies
A policy is what to protect on a device, how often, and how long to keep it. One policy can be assigned to many devices, and a tenant can nominate a default that new devices inherit as they enrol — so a machine installed at 2am is protected by 2:01am without anyone touching the console.
What a policy protects
- Folders. Literal, machine-wide paths — /Users, C:\Users, /home — because the agent runs as a system service. A ~ would expand to the service account rather than the people whose files matter.
- Virtual machines. By name or id, or * for every guest the host reports, in which case guests created later are included automatically. A hypervisor policy may name no folders at all: on a PVE node the guests are the data.
- Databases. PostgreSQL, MySQL/MariaDB and SQL Server are exported by the engine before the files are read. A database copied as ordinary files is atomic at best and unrestorable at worst, which is why it is a separate thing to name rather than a folder you happen to include.
- Exclusions by name and by extension, plus an optional maximum file size. These are what keep node_modules, .git, caches and build output out of a "back up the home directory" policy.
How often it runs
An interval, in seconds. The starter templates use an hour for user data, four hours for configuration, and a day for full-machine and hypervisor policies — copying a whole machine every hour costs more than it protects. A backup can also be run on demand from the console without disturbing the schedule.
How long restore points are kept
Retention is grandfather-father-son: five independent counts, each keeping the newest N restore points that fall in its bucket.
- keep-last the N most recent, whatever their age.
- daily weekly monthly yearly the newest in each of the last N days, weeks, months and years.
The template default is keep-last 7, 7 daily, 4 weekly, 12 monthly and 3 yearly — generous, but cheap, because snapshots deduplicate and an unchanged file is stored once no matter how many restore points reference it. A restore point can also be pinned, which exempts it from retention entirely: the snapshot taken before a migration, or the one an auditor asked for, cannot then be aged out by a schedule nobody revisited.
Platform templates
Templates are starter policies that already know where the files live and which caches to skip. The console prefills a policy from one and you edit it; what gets saved is an ordinary policy, and the template it came from is recorded so the console can say "based on macOS user data" later.
- macOS — User data (/Users minus caches, Xcode derived data, iOS device backups and Trash), System configuration, Full machine.
- Windows — User data (C:\Users minus AppData temp, package caches and the Recycle Bin), Server data, Full system drive.
- Linux — User data (/home minus caches and package downloads), Server config and data, Full root filesystem.
- Proxmox VE — Every guest, Node configuration, or both in one policy. These are Linux policies, because a PVE node is a Linux machine and they have to be assignable to one; they are listed under their own heading so they are not buried among the laptop templates.
"Node configuration" is worth calling out: /etc/pve, the cluster database and /etc. It is tiny, so run it often. Reinstalling PVE is easy; reconstructing who had which disk on which bridge is not.
Storage targets
A storage target is where backups land. A policy names one; a policy that names none writes to a repository on the device itself. Data is encrypted and deduplicated on the machine before anything leaves it, whichever you choose.
Local to the device
A repository on the machine being backed up. It is the default, and it is genuinely fine for a single machine: it protects you from a bad edit, a bad update and a bad afternoon. It does not protect you from losing the machine, and the control plane cannot reach it — so every restore has to run on that device.
An S3 bucket you own
Any S3-compatible bucket: AWS, or an endpoint you supply for MinIO, Wasabi, Backblaze B2 and the like. You own it, you choose the region, and the storage bill comes from whoever hosts it. The secret key is sealed at rest with the control plane's KMS key, is never returned to a browser, and is only ever handed to agents — they are the only things that talk to the bucket.
- Object Lock, in governance or compliance mode, for a number of days you set. Backups can be written but not deleted or overwritten until it lapses; in compliance mode, not even by someone holding your credentials. This is the part that survives ransomware.
- Accept an unverified certificate exists for a self-signed MinIO or an on-prem gateway. The connection stays encrypted, but you give up the guarantee that the far end is who it claims to be, so it is a per-target decision rather than a global setting.
- The repository key belongs to the target, not to a device. A bucket and prefix are one repository, so every agent writing there opens it with the same key. That is also the point of sharing a bucket: identical blocks across machines are stored once.
"Allow restoring from this console"
It is off by default for exactly this reason, and it is a per-target choice rather than something to switch on across the board.
Off, the control plane holds the KMS master key but not the repository key. It can decrypt what an agent hands it and nothing else: it cannot open your backups on its own. That is why browsing a backup is a round trip to the device that holds the keys — we cannot read it ourselves.
On, the agent escrows the wrapped repository key here on its next backup. From then on the control plane can read every backup in that target, at any time, without asking the device. That is not a subtle change. It is also the only thing that makes restoring without the device possible — the stolen laptop, the dead hypervisor — and it is what VM export is built on.
Two honest caveats. Turning it off again does not un-escrow what has already been written: the key that could open those backups has been here. And it only applies to S3 targets, since a repository on a device is unreachable from here whatever the checkbox says. If you want both, use two targets: one device-only for the machines you can always reach, one console-restorable for the ones you cannot.
Restoring
To the device
The normal case, and the right one whenever the machine still exists. Choose a restore point, optionally choose paths inside it, give a destination directory, and the control plane queues a restore the agent picks up on its next poll. Up to 200 paths in one request — past that, restore the parent directory instead. This works with local and S3 targets alike, because the device holds the keys either way.
Browsing what is inside a backup
Walking the folders of a restore point is a round trip: the console asks for a path, the control plane queues a directory listing for the device, the agent answers on its next poll, and the answer is cached for five minutes. A path you have not opened before on a machine that is offline shows as pending rather than as a listing — the device has to be there to answer. Restore points are immutable, so a cached listing only goes stale if the repository itself changed underneath it.
Downloading a file from the console
Restoring to the device is the wrong tool when you want to read one document, and useless when the device is gone — which is the case people buy backup for. So the control plane can also read the bytes out of object storage itself and hand them to your browser: one file streams as itself, a directory arrives as a zip.
This needs an S3 target with console restore switched on and a repository key escrowed. Where any of those is missing it refuses and says which one, because the fix is different each time: point the policy at an S3 target, enable console restore, or wait for the next backup to escrow the key.
Exporting a VM
A guest's restore point can be converted into a disk image you import somewhere else. It runs as a job rather than a download, because the work is measured in gigabytes and minutes: materialising a snapshot and converting a disk cannot happen inside an HTTP request without timing out. As a job it also has somewhere to show progress and somewhere to record a failure.
Export formats
| Format | File | For |
|---|---|---|
| QCOW2 | .qcow2 | KVM, Proxmox VE, QEMU |
| VMDK | .vmdk | VMware ESXi, Workstation, Fusion |
| VHDX | .vhdx | Hyper-V on Windows Server 2012 and later |
| VHD | .vhd | Hyper-V, older Azure imports |
| VDI | .vdi | VirtualBox |
| Raw | .img | dd-style image; writes to a disk directly |
| Files | .zip | The restore point's contents, not a disk |
Format names match qemu-img's own, because that is what performs the conversion and a parallel vocabulary would only cause mistakes. A finished export is downloadable for 24 hours and is then deleted: it is a full copy of a machine's disk, and a stale one is a copy of your data sitting somewhere it need not be.
Checking a backup can be read
A backup that has been recorded and a backup that can be restored are different claims, and everything else in this product only ever proved the first. A repository that has lost a blob, a bucket whose lifecycle rule expired an object still referenced, a disk with a bad sector under a file nobody has opened in two years — every one of them looks like a healthy, green, backing-up-nightly machine right up to the restore.
What a check actually does
Two things happen and they are worth different amounts. Every file in the restore point is resolved to the pieces it is made of, and each piece is looked up — that proves the repository's index agrees with itself, costs almost no bandwidth, and is not evidence the data is there. Then a sample of files is fetched, decrypted and checked against its hashes. That second part is the evidence.
Because the two are not the same, the console never collapses them into one tick. A restore point that was checked but had none of its data read back says structure checked; one that had data fetched says read back, with how much.
Switching it on
Off for every policy until you ask, including policies that already exist — putting a fleet onto a bandwidth-consuming schedule because the control plane was upgraded is not a decision software should make for you. Edit a policy and set how often to check and how much of the data to read back.
The percentage is the dial between confidence and your egress bill. Five percent of a large restore point is still thousands of files, and successive runs sample different ones. Reading everything back is the strongest evidence and costs a full download of that restore point every time it runs. A percentage of zero checks the structure only, which is free and is not proof of anything. Where a restore point is small enough that a low sample would have read nothing at all, the check quietly reads all of it rather than reporting a pass on no evidence.
Checks run on their own schedule and are deliberately not tied to the backup schedule: a machine whose backups you have switched off still has restore points somebody may need, and those are exactly the ones nothing else is touching.
Three states, not two
Every restore point is read back, could not be read, or never checked. The third is the common one and it is shown rather than hidden. A backup nobody has ever read back is the normal state of almost every backup in the world; the point of saying so is that people assume otherwise.
A failure is a critical alert. Every other alert here means a backup did not happen; this one means it did, was reported as a success, is sitting in the catalog looking healthy, and cannot be read.
When the machine is gone
A dead device cannot be asked to check its own backups, and a dead device is the case people
buy backup for. On an S3 target with console restore switched on, the control plane can read a
restore point back itself — controlplane restore-check --verify opens the
repository from the server, fetches the data and checks it against its hashes with no agent
involved. Run it before somebody needs it rather than during.
Remote access
Backup is where you find the problem; this is where you fix it. Every enrolled machine can be reached from the same console, in a browser, with nothing to install and no inbound firewall rule — the agent dials out to the relay, so nothing needs to reach in.
Remote desktop
The agent captures the screen and drives the keyboard and mouse itself, so a machine needs no RDP, no Screen Sharing and no VNC server. That is what makes Windows Home, a headless box and a Mac with Screen Sharing switched off work at all. A machine with more than one monitor offers all of them and you choose which you are looking at, mid-session, without reconnecting.
Sound comes with it on macOS, Linux and FreeBSD: a speaker and a volume control in the viewer, enough to answer "can you hear that noise?" and "does the video play?". The volume changes only what you hear — the machine's own volume belongs to whoever is sitting at it. Where a machine cannot send sound the viewer shows a struck-through speaker carrying that machine's own reason, rather than a control that quietly does nothing. Windows machines cannot yet. On a Mac the sound comes from applications with windows, which is what ScreenCaptureKit can hear.
A shell, and the rest
A real terminal on a real PTY, sized to your window. The tunnel gets you as far as a login prompt and no further: the machine's own credentials are what open a shell, so reaching a machine and being allowed to use it stay separate questions.
Alongside it: browse the filesystem and move files either way, follow a log as it is written, and forward a port so a service that only listens on loopback can be reached from your browser.
What a machine permits
Five separate switches — shell, port forwarding, desktop, files and logs — set by policy and enforced by the agent on the machine, so the console cannot talk its way past a machine that says no. Sessions are time-boxed, every one is recorded in the activity log with who opened it and for how long, and the console is locked on the way out so a support session never leaves a desk signed in.
On desktops that require a person to approve screen sharing — Wayland on Linux, and macOS — the tray offers that grant so it can be given calmly in advance, rather than by a dialog appearing at the moment an administrator is waiting.
The protection report
What was protected over a period, and what the evidence for that is. Choose a period, and the report gives you a document you can print or save and hand to somebody: how many restore points were made, how much data, and — first, before any totals — the three things that need doing.
Those three are machines with no policy, machines whose backups failed, and machines whose backups have never been read back. It is deliberately willing to say unflattering things. A report that only ever showed green would be worth nothing to the person receiving it and worse than nothing to the person sending it.
What the agent reports
Everything the console shows about a machine comes from the agent on it. Nothing is inferred, and nothing is invented when the machine is quiet.
- Heartbeat, every 30 seconds: the agent's version and the results of its health checks. A device counts as online for two minutes after its last beat. The activity log records only the changes — came back online, agent version changed, a health check flipped — because one line every 30 seconds per device is a log nobody reads.
- Activity: what the machine is doing right now. The phase ("backing up VMs"), the item it is on, files and bytes so far, and when it started. How long it has been going is the part that separates working from stuck, so the console shows it.
- Restore points: one catalog entry per completed backup — its source, file and directory counts, bytes, and how the source was read: application-consistent, crash-consistent, or live. Restoring a database from a crash-consistent copy is a different proposition from a quiesced one, so the catalog records which it was rather than leaving you to assume.
- Failures: the agent's own error message, attached to whatever failed — a folder, a guest, a database. A job that fails on a remote machine appears in the console rather than only in that machine's logs, which is the whole point of having a console.
- Health checks, such as Full Disk Access on macOS. These matter because their failure mode is quiet: the backup succeeds while skipping the files it could not read, so the console raises it rather than waiting for you to notice.
Devices that are switched off or off the network lose nothing. Work queued for a device waits until it checks in, and the schedule resumes when it comes back.