Install
One binary, or a container, on the host that can reach your sources.
View as MarkdownThe worker is a single static binary with no runtime dependencies of its own. Put it on a
host that can reach your sources, give it a config.yaml, and run it.
Install it after you have provisioned the worker, because the config it needs contains the key that provisioning prints once. See Registration.
Pre-1.0
The current release is v0.1.0, and it
is marked pre-release. It was tagged before the release pipeline was fixed, so that tag
carries no binaries and its image is linux/arm64 only. Until the next tag,
build from source.
Pick a path
Every path ends the same way: a binary and a config.yaml in a directory, and something that
keeps the process running.
Linux
Binary under systemd. The usual answer for a server.
macOS
Binary under launchd, and why a laptop is a poor host.
Windows
Binary under Task Scheduler, or a service wrapper.
Container
The image, which ships the dump tools already.
Build from source
Go 1.26, one command, and the only path on some architectures.
What the host needs
| Requirement | Detail |
|---|---|
| Outbound network | The worker dials out. Nothing dials in, and no port needs opening |
| Disk | Room for the dump and its encrypted copy at the same time, so budget roughly twice the dump size |
| Tools | pg_dump, mysqldump or curl, but only for the source types you use. redis needs none |
| Reachability | A route to the sources themselves, which is the whole reason it runs where it does |
| A clock | More than a few minutes of skew fails certificate validation |
The binary is self-contained. The dump tools are not: a Postgres backup shells out to
pg_dump, and that has to be installed separately. See
external tools for which source type needs
what, and note that the container image ships all four.
Egress
Three destinations, all outbound TCP 443, all initiated by the worker.
| Destination | Why |
|---|---|
Your api_url, normally api.saved.sh | Startup identity, presigned upload URLs, and the confirm call |
hub.saved.sh | The orchestration hub it polls for work |
| The object storage host in each presigned URL | Where the encrypted artifact is PUT |
| Your own sources | Whatever the backups point at, on their own ports |
There is no inbound rule to write and no allowlist of ours to maintain. That is the point of running the worker yourself. See IP addresses.
Platforms
Released binaries are built with CGO disabled, so they are statically linked and do not care which libc the host has.
| OS | Architectures | Supervisor to use |
|---|---|---|
| Linux | amd64, arm64 | systemd |
| macOS | amd64 (Intel), arm64 (Apple silicon) | launchd |
| Windows | amd64, arm64 | Task Scheduler, or a service wrapper |
The container image is Linux only, and which architectures a given tag carries is a property of that tag rather than of the project. Check before you pin one:
docker buildx imagetools inspect ghcr.io/savedhq/local-worker:v0.1.0Anything not in that table, a BSD or a 32-bit ARM board, is a source build away. Go cross-compiles to far more targets than we publish.
What it does not have
The worker takes no flags, no subcommands and no config-path argument. It reads
config.yaml from its working directory and starts. That is the whole interface, and it is
why every page here sets a working directory rather than passing a path.
There is also no version flag. To find out what a host is running, read its startup log or its image tag. See knowing what each worker runs.