S3 sync¶
Zero-knowledge multi-device sync through any S3-compatible bucket you own — AWS S3, Cloudflare R2, Backblaze B2, Wasabi, Hetzner, Scaleway, MinIO, or anything else that speaks the S3 API. There is no server to deploy: the plugin talks to your bucket directly with SigV4-signed requests.
S3 Sync is a marketplace plugin: Settings → Plugins → Marketplace → S3 Sync, or install it straight from the sync menu.
How it works¶
Everything lives under the folder you choose in the wizard (voltius/ by default; the folder can be
empty to use the bucket root):
<folder>/vault.json {"schema":1,"salt":"<32 hex chars>"}
<folder>/devices/<id>.b64 this device's encrypted state, base64
<folder>/devices/<id>.json {"label":"…","pushedAt":"…"} (plaintext metadata only)
<folder>/.voltius-probe written, read back and deleted by "Test and connect"
There is no manifest object. The device list comes from listing <folder>/devices/, and each
device's version is the ETag S3 already returns for its .b64 object — nothing has to be kept in
sync with the directory listing, and two devices pushing at once cannot clobber a shared index.
Each device writes only its own devices/<id>.* pair and reads everyone else's. The passphrase you
choose derives the encryption key locally; vault.json holds the salt so another device can derive
the same key from the same passphrase. The passphrase itself is never sent anywhere.
Deletes (the probe object, and a removed device's two files) go through S3 multi-object delete, not a
single-object DELETE — a storage service without multi-object delete fails at the Delete step of
Test and connect.
Setup¶
- Create a bucket in your provider's console. Any name and region works; the plugin does not create it for you.
-
Create an access key limited to that bucket. On AWS, or any provider with IAM-style policies, that is:
s3:ListBucketon the bucket (arn:aws:s3:::<bucket>)s3:GetObject,s3:PutObjectands3:DeleteObjectonarn:aws:s3:::<bucket>/<folder>/*
A key without
s3:ListBucketshows up as credentials rejected, not as a missing permission: S3 answersAccessDeniedboth to the device listing and to reading a file that does not exist yet. Step 2 of the wizard links to your provider's key documentation. 3. Run the wizard in Settings → S3 Sync: 1. Which storage provider? Pick a preset, which fills in the endpoint pattern, the default region and the right addressing style. Pick Other for anything not listed. 2. Connect to your bucket. Endpoint, region, bucket, folder and the key pair. Test and connect writes, reads back and deletes a probe object, so a wrong key or a missing bucket is reported here rather than on the first sync. 3. Passphrase. A new bucket asks for a passphrase twice and creates the vault; a bucket that already holds one asks for its passphrase and links this device to it.
Settings are saved only once step 3 succeeds. The access key and secret go into this device's vault, not into plugin storage.
Providers¶
| Preset | Endpoint | Region | Addressing |
|---|---|---|---|
| AWS S3 | https://s3.{region}.amazonaws.com |
e.g. eu-west-3 |
virtual-hosted |
| Cloudflare R2 | https://<ACCOUNT_ID>.r2.cloudflarestorage.com |
auto |
path |
| Backblaze B2 | https://s3.{region}.backblazeb2.com |
e.g. eu-central-003 |
path |
| Wasabi | https://s3.{region}.wasabisys.com |
e.g. eu-central-1 |
path |
| MinIO | http://localhost:9000 |
usually us-east-1 |
path |
| Hetzner | https://{region}.your-objectstorage.com |
fsn1, nbg1 or hel1 |
virtual-hosted |
| Scaleway | https://s3.{region}.scw.cloud |
fr-par, nl-ams or pl-waw |
path |
| Other | whatever you enter | blank means us-east-1 |
path (a checkbox switches it) |
A preset only prefills the form — every field stays editable, so any S3 API works through Other.
http:// endpoints are accepted only for localhost, private and link-local addresses, single-label
hostnames and names ending in .local, .lan, .home.arpa or .internal — everything else must be
https://.
A bucket name containing dots cannot be used with virtual-hosted addressing over https:// (the
provider's wildcard certificate does not cover a.b.s3.…): the wizard refuses that combination, so use
path-style addressing or a bucket name without dots.
Key scoping¶
Scope the access key to the one bucket — the plugin needs nothing account-wide, and the key never needs to reach any other bucket or service. Never reuse the secret access key as your sync passphrase: one is transport auth for the bucket, the other derives the encryption key, and they must stay independent.
Adding another device¶
On the second device, install the plugin, point it at the same endpoint, bucket and folder, and enter the same passphrase when asked. Each device gets its own access key if you want per-device revocation, or all devices can share one key scoped to the bucket.
Removing a device from the settings page deletes its two files from the bucket, but a device that is still running and connected pushes them again on its next sync — disconnect or uninstall the plugin on that device first.
Bucket layout¶
One bucket folder per vault. If you sync more than one vault, give each its own folder (or its own bucket) — do not point two vaults at the same folder.
Troubleshooting¶
- Credentials rejected — the access key or secret is wrong, or the key cannot access this bucket.
This is also what a key missing
s3:ListBucketlooks like, since S3 answersAccessDeniedto both cases. - Bucket not found — check the bucket name, region and endpoint; a bucket in the wrong region or behind the wrong endpoint shows the same error.
- Device clock is off — "This device's clock is off, so the storage provider rejected the request." Fix the system time and try again.
- Write/Read/Delete test failed — Test and connect runs three steps in order; the message names which one failed. A Delete failure on an otherwise-working bucket usually means the service does not support S3 multi-object delete.
S3 sync, Gist sync or Cloudflare sync?¶
All three are free and end-to-end encrypted, and any combination can run at the same time. Pick Gist sync if you already have GitHub and want the shortest setup. Pick Cloudflare sync if you want Voltius to deploy the Worker and bucket for you. Pick S3 sync if you already have a bucket — on AWS, R2, B2, Wasabi, Hetzner, Scaleway, MinIO or elsewhere — and would rather point Voltius at it directly than deploy a Worker.
Multiple sync providers
S3 sync runs alongside Cloud sync, Gist sync, Cloudflare sync and any other sync provider plugin — Voltius shows each one separately in the sync menu and title bar. See Building a sync provider.