Zerobyte

Provisioned Resources

Manage repositories and volumes through a configuration file with secret references

Zerobyte can sync operator-managed repositories and volumes from a JSON configuration file at startup. This is useful when you want credentials and connection details to live in deployment-time configuration instead of being entered through the UI.

What Provisioning Supports Today

Provisioning currently supports:

  • repositories
  • volumes
  • secret references through env:// and file://
  • updating managed resources in place by keeping the same id
  • deleting managed resources with "delete": true

Provisioning does not currently support:

  • backup jobs or schedules
  • notification destinations
  • exporting UI-created resources back into provisioning JSON
  • live reloading without restarting the Zerobyte container

Provisioning is limited to repositories and volumes in schema version 1. If you need to manage backup jobs or notifications, create them through the UI or API for now.

Prerequisites

  • A running Zerobyte instance with an organization ID
  • The PROVISIONING_PATH environment variable pointing to your JSON file

Find your organization ID

  1. Sign in to Zerobyte and switch to the organization you want to provision into
  2. Open Settings
  3. Open the Organization tab
  4. Copy the read-only Organization ID value from Organization Details

The Organization tab is only visible to organization admin and owner members. If you do not see it, ask an organization admin or owner for the ID, or have them grant you the required role first.

Quick Start

Create the provisioning file

Create a provisioning.json file:

{
	"version": 1,
	"repositories": [
		{
			"id": "local-repo",
			"organizationId": "your-organization-id",
			"name": "Primary Local Repository",
			"backend": "local",
			"compressionMode": "auto",
			"config": {
				"backend": "local",
				"path": "/var/lib/zerobyte/repositories/primary",
				"isExistingRepository": false
			}
		}
	],
	"volumes": [
		{
			"id": "documents",
			"organizationId": "your-organization-id",
			"name": "Documents",
			"backend": "directory",
			"autoRemount": true,
			"config": {
				"backend": "directory",
				"path": "/data/documents"
			}
		}
	]
}

Mount the file and configure Zerobyte

Mount the provisioning file and set PROVISIONING_PATH:

services:
  zerobyte:
    image: ghcr.io/nicotsx/zerobyte:latest
    environment:
      - PROVISIONING_PATH=/config/provisioning.json
    volumes:
      - ./provisioning.json:/config/provisioning.json:ro
      - /var/lib/zerobyte:/var/lib/zerobyte
      - /srv/documents:/data/documents

Start or restart Zerobyte

docker compose up -d

On startup, Zerobyte reads the provisioning file, resolves supported secret references, encrypts the resolved secret values, and syncs the managed resources into the database.

Root File Format

The root object always has the same shape:

{
	"version": 1,
	"repositories": [],
	"volumes": []
}
FieldRequiredNotes
versionyesMust be 1
repositoriesnoArray of provisioned repositories. Defaults to []
volumesnoArray of provisioned volumes. Defaults to []

Repository Entry Reference

Each item in repositories uses this top-level shape:

{
	"id": "repo-id",
	"organizationId": "org-id",
	"name": "Repository Name",
	"backend": "local",
	"compressionMode": "auto",
	"delete": false,
	"config": {
		"backend": "local",
		"path": "/var/lib/zerobyte/repositories/repo-id"
	}
}
FieldRequiredNotes
idyesStable provisioning identifier inside the organization. Keep this stable if you want Zerobyte to update the same resource in place
organizationIdyesMust match an existing organization
nameyesDisplay name in Zerobyte
backendyesMust be one of local, s3, r2, gcs, azure, rclone, rest, sftp
compressionModenooff, auto, or max
deletenoDefaults to false
configyesBackend-specific object. config.backend must match the top-level backend value

Repository Shared Config Fields

These fields are available inside every repository config object:

FieldRequiredNotes
isExistingRepositorynoWhen true, Zerobyte treats the repository as already initialized. When omitted or false, a newly created provisioned repository is initialized with restic init on first sync
customPasswordnoOverrides the organization-level repository password
cacertnoCustom CA certificate contents
insecureTlsnoDisables TLS verification for supported backends
uploadLimitnoBandwidth limit object
downloadLimitnoBandwidth limit object

Bandwidth limit objects use this shape:

{
	"enabled": true,
	"value": 10,
	"unit": "Mbps"
}

unit must be one of Kbps, Mbps, or Gbps.

Repository Backends

FieldRequiredNotes
pathyesPath inside the Zerobyte container
{
	"backend": "local",
	"path": "/var/lib/zerobyte/repositories/primary",
	"isExistingRepository": false
}
FieldRequiredNotes
endpointyesExample: https://s3.amazonaws.com
bucketyesBucket name
accessKeyIdyesSupports secret references
secretAccessKeyyesSupports secret references
{
	"backend": "s3",
	"endpoint": "https://s3.amazonaws.com",
	"bucket": "company-backups",
	"accessKeyId": "env://AWS_ACCESS_KEY_ID",
	"secretAccessKey": "file://aws_secret_access_key",
	"isExistingRepository": true
}
FieldRequiredNotes
endpointyesYour Cloudflare R2 S3 endpoint
bucketyesBucket name
accessKeyIdyesSupports secret references
secretAccessKeyyesSupports secret references
{
	"backend": "r2",
	"endpoint": "https://<account-id>.r2.cloudflarestorage.com",
	"bucket": "zerobyte-backups",
	"accessKeyId": "env://R2_ACCESS_KEY_ID",
	"secretAccessKey": "env://R2_SECRET_ACCESS_KEY",
	"isExistingRepository": true
}
FieldRequiredNotes
bucketyesBucket name
projectIdyesGoogle Cloud project ID
credentialsJsonyesService account JSON. Supports secret references
{
	"backend": "gcs",
	"bucket": "zerobyte-backups",
	"projectId": "my-gcp-project",
	"credentialsJson": "file://gcs_credentials_json",
	"isExistingRepository": true
}
FieldRequiredNotes
containeryesBlob container name
accountNameyesStorage account name
accountKeyyesSupports secret references
endpointSuffixnoCustom endpoint suffix
{
	"backend": "azure",
	"container": "zerobyte-backups",
	"accountName": "storageaccount",
	"accountKey": "env://AZURE_STORAGE_ACCOUNT_KEY",
	"endpointSuffix": "core.windows.net",
	"isExistingRepository": true
}
FieldRequiredNotes
remoteyesName of the configured rclone remote
pathyesPath inside that remote
{
	"backend": "rclone",
	"remote": "remote-name",
	"path": "zerobyte/backups",
	"isExistingRepository": true
}
FieldRequiredNotes
urlyesBase REST server URL
usernamenoSupports secret references
passwordnoSupports secret references
pathnoOptional path below the REST endpoint
{
	"backend": "rest",
	"url": "https://rest-server.example.com",
	"username": "env://REST_USERNAME",
	"password": "file://rest_password",
	"path": "zerobyte",
	"isExistingRepository": true
}
FieldRequiredNotes
hostyesSFTP hostname
portnoDefaults to 22
useryesSSH username
pathyesRemote repository path
privateKeyyesPrivate key contents. Supports secret references
skipHostKeyChecknoDefaults to false
knownHostsnoContents of a known hosts file
{
	"backend": "sftp",
	"host": "backup.example.com",
	"port": 22,
	"user": "backup",
	"path": "/srv/restic",
	"privateKey": "file://sftp_private_key",
	"skipHostKeyCheck": false,
	"knownHosts": "backup.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI..."
}

Volume Entry Reference

Each item in volumes uses this top-level shape:

{
	"id": "volume-id",
	"organizationId": "org-id",
	"name": "Volume Name",
	"backend": "directory",
	"autoRemount": true,
	"delete": false,
	"config": {
		"backend": "directory",
		"path": "/data/volume"
	}
}
FieldRequiredNotes
idyesStable provisioning identifier inside the organization
organizationIdyesMust match an existing organization
nameyesDisplay name in Zerobyte
backendyesMust be one of nfs, smb, directory, webdav, rclone, sftp
autoRemountnoDefaults to true
deletenoDefaults to false
configyesBackend-specific object. config.backend must match the top-level backend value

Volume Backends

FieldRequiredNotes
pathyesPath inside the Zerobyte container
readOnlynoIf provided, it must be false
{
	"backend": "directory",
	"path": "/data/documents"
}
FieldRequiredNotes
serveryesNFS server hostname or IP
exportPathyesExported path on the server
portnoDefaults to 2049
versionyesMust be 3, 4, or 4.1
readOnlynoMount the volume read-only
{
	"backend": "nfs",
	"server": "10.0.0.10",
	"exportPath": "/exports/media",
	"port": 2049,
	"version": "4.1",
	"readOnly": true
}
FieldRequiredNotes
serveryesSMB server hostname or IP
shareyesShare name
usernamenoLogin username
passwordnoSupports secret references
guestnoUse guest authentication
versno1.0, 2.0, 2.1, 3.0, or auto. Defaults to auto
domainnoSMB domain or workgroup
portnoDefaults to 445
readOnlynoMount the volume read-only
{
	"backend": "smb",
	"server": "fileserver.local",
	"share": "team",
	"username": "backup-user",
	"password": "env://SMB_PASSWORD",
	"vers": "3.0",
	"domain": "WORKGROUP",
	"port": 445,
	"readOnly": false
}
FieldRequiredNotes
serveryesWebDAV hostname, without scheme
pathyesRemote path
usernamenoLogin username
passwordnoSupports secret references
portnoDefaults to 80
readOnlynoMount the volume read-only
sslnoEnable HTTPS
{
	"backend": "webdav",
	"server": "cloud.example.com",
	"path": "/team-a",
	"username": "team-a",
	"password": "env://WEBDAV_PASSWORD",
	"port": 443,
	"ssl": true
}
FieldRequiredNotes
hostyesSFTP hostname
portnoDefaults to 22
usernameyesSSH username
passwordnoSupports secret references
privateKeynoPrivate key contents. Supports secret references
pathyesRemote path
readOnlynoMount the volume read-only
skipHostKeyChecknoDefaults to false
knownHostsnoContents of a known hosts file
{
	"backend": "sftp",
	"host": "files.example.com",
	"port": 22,
	"username": "backup-user",
	"privateKey": "file://volume_sftp_private_key",
	"path": "/srv/data",
	"readOnly": true,
	"skipHostKeyCheck": false,
	"knownHosts": "files.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI..."
}
FieldRequiredNotes
remoteyesName of the configured rclone remote
pathyesPath inside that remote
readOnlynoMount the volume read-only
{
	"backend": "rclone",
	"remote": "remote-name",
	"path": "team-a",
	"readOnly": true
}

Secret References

Supported secret references use one of these prefixes:

ReferenceResolves FromExample
env://VARIABLE_NAMEContainer environment variablesenv://AWS_ACCESS_KEY_ID
file://secret_name/run/secrets/secret_namefile://aws_secret_access_key

file:// references always resolve from /run/secrets/ and must be a single filename, not a nested path.

Only specific fields are resolved as secret references. Other string fields are treated literally.

Repository fields that support secret references

  • shared fields: customPassword, cacert
  • s3: accessKeyId, secretAccessKey
  • r2: accessKeyId, secretAccessKey
  • gcs: credentialsJson
  • azure: accountKey
  • rest: username, password
  • sftp: privateKey

Volume fields that support secret references

  • smb: password
  • webdav: password
  • sftp: password, privateKey

Resolved secret values are encrypted before Zerobyte stores them in the database.

Rotating Secrets

To rotate a provisioned secret:

  1. Update the environment variable or secret file
  2. Restart Zerobyte with docker compose restart

Zerobyte re-resolves supported secret references on each startup.

Updating And Removing Managed Resources

  • Keep the same id to update a managed resource in place
  • Changing only name keeps the same underlying resource record
  • Setting "delete": true removes the managed resource on the next startup sync

Deletion entries still need the normal entry shape today because the provisioning file is validated before Zerobyte applies the delete flag:

{
	"id": "repo-to-remove",
	"organizationId": "your-organization-id",
	"name": "Repo to remove",
	"backend": "local",
	"delete": true,
	"config": {
		"backend": "local",
		"path": "/var/lib/zerobyte/repositories/old",
		"isExistingRepository": true
	}
}

Troubleshooting

No matching discriminator

This error usually means one of these is wrong:

  • backend is not a valid value for that resource type
  • config.backend does not match the top-level backend
  • the config object does not match the required fields for that backend

Secret reference errors

  • env://NAME requires the environment variable to exist in the Zerobyte container
  • file://name requires /run/secrets/name to exist
  • Zerobyte stops syncing when it hits a provisioning error, so fix the first reported error and restart again

Important Notes

Each provisioned entry must reference an existing organizationId. Complete first-run setup before enabling provisioning so you have a valid organization ID.

  • Changes to provisioning.json only apply on container restart
  • Provisioned resources appear in the normal UI and are marked as managed
  • Editing a provisioned resource in the UI is useful for testing, but the next provisioning sync can overwrite it