diff --git a/README.md b/README.md index ae261fbb..4c4cc2a1 100644 --- a/README.md +++ b/README.md @@ -37,396 +37,6 @@ Zerobyte is a backup automation tool that helps you save your data across multip In order to run Zerobyte, you need to have Docker and Docker Compose installed on your server. Then, you can use the provided `docker-compose.yml` file to start the application. -### Configure Zerobyte via Config File - - -You can pre-configure backup sources (volumes), destinations (repositories), backup schedules, notification destinations and initial users using a config file (`zerobyte.config.json` by default (mounted in /app dir), or set `ZEROBYTE_CONFIG_PATH`). - -Config import is opt-in. Enable it by setting `ZEROBYTE_CONFIG_IMPORT=true`. - -Secrets/credentials in the config file can reference environment variables using `${VAR_NAME}` syntax for secure injection. - -> **ℹ️ Config File Behavior** -> -> The config file is applied on startup using a **create-only** approach: -> - Resources defined in the config are only created if they don't already exist in the database -> - Existing resources with the same name are **not overwritten** - a warning is logged and the config entry is skipped -> - Changes made via the UI are preserved across container restarts -> - To update a resource from config, either modify it via the UI or delete it first -> -> This means the config file serves as "initial setup" rather than "desired state sync". - -#### zerobyte.config.json Structure - -```json -{ - "recoveryKey": "${RECOVERY_KEY}", - "volumes": [ - // Array of volume objects. Each must have a unique "name" and a "config" matching one of the types below. - ], - "repositories": [ - // Array of repository objects. Each must have a unique "name" and a "config" matching one of the types below. - // Optionally, "compressionMode" ("auto", "off", "max") - ], - "backupSchedules": [ - // Array of backup schedule objects as described below. - ], - "notificationDestinations": [ - // Array of notification destination objects as described below. - ], - "users": [ - // Array of user objects. Each must have a unique "username". - // Note: Zerobyte currently supports a single user; only the first entry is applied. - ] -} -``` - -##### Volume Types - -- **Local Directory** - ```json - { - "name": "local-volume", - "config": { - "backend": "directory", - "path": "/data", - "readOnly": true - } - } - ``` - -- **NFS** - ```json - { - "name": "nfs-volume", - "config": { - "backend": "nfs", - "server": "nfs.example.com", - "exportPath": "/data", - "port": 2049, - "version": "4", - "readOnly": false - } - } - ``` - -- **SMB** - ```json - { - "name": "smb-volume", - "config": { - "backend": "smb", - "server": "smb.example.com", - "share": "shared", - "username": "user", - "password": "${SMB_PASSWORD}", - "vers": "3.0", - "domain": "WORKGROUP", - "port": 445, - "readOnly": false - } - } - ``` - -- **WebDAV** - ```json - { - "name": "webdav-volume", - "config": { - "backend": "webdav", - "server": "webdav.example.com", - "path": "/remote.php/webdav", - "username": "user", - "password": "${WEBDAV_PASSWORD}", - "port": 80, - "readOnly": false, - "ssl": true - } - } - ``` - -##### Repository Types - -- **Local Directory** - ```json - { - "name": "local-repo", - "config": { - "backend": "local", - "path": "/var/lib/zerobyte/repositories" - }, - "compressionMode": "auto" - } - ``` - > **Note for importing existing local repositories:** If you're migrating an existing repository (e.g., from a backup or another Zerobyte instance), include the `name` field in `config` with the original subfolder name, and set `isExistingRepository: true`. The actual restic repo is stored at `{path}/{name}`. - > - > **Example (migration):** - > ```json - > { - > "name": "my-local-repo", - > "config": { - > "backend": "local", - > "path": "/var/lib/zerobyte/repositories", - > "name": "abc123", - > "isExistingRepository": true - > } - > } - > ``` - > You can find the `config.name` value in an exported config under `repositories[].config.name`. This value must be unique across all repositories. - -- **S3-Compatible** - ```json - { - "name": "backup-repo", - "config": { - "backend": "s3", - "bucket": "mybucket", - "accessKeyId": "${ACCESS_KEY_ID}", - "secretAccessKey": "${SECRET_ACCESS_KEY}" - }, - "compressionMode": "auto" - } - ``` - -- **Google Cloud Storage** - ```json - { - "name": "gcs-repo", - "config": { - "backend": "gcs", - "bucket": "mybucket", - "projectId": "my-gcp-project", - "credentialsJson": "${GCS_CREDENTIALS}" - } - } - ``` - -- **Azure Blob Storage** - ```json - { - "name": "azure-repo", - "config": { - "backend": "azure", - "container": "mycontainer", - "accountName": "myaccount", - "accountKey": "${AZURE_KEY}" - } - } - ``` - -- **WebDAV, rclone, SFTP, REST, etc.** - (See documentation for required fields; all support env variable secrets.) - -##### Backup Schedules - -- **Example:** - ```json - { - "name": "local-volume-local-repo", - "volume": "local-volume", - "repository": "local-repo", - "cronExpression": "0 2 * * *", - "retentionPolicy": { "keepLast": 7, "keepDaily": 7 }, - "includePatterns": ["important-folder"], - "excludePatterns": ["*.tmp", "*.log"], - "enabled": true, - "notifications": ["slack-alerts", "email-admin"] - } - ``` -- **Fields:** - - `name`: Unique name of the schedule - - `volume`: Name of the source volume - - `repository`: Name of the destination repository - - `cronExpression`: Cron string for schedule - - `retentionPolicy`: Object with retention rules (e.g., keepLast, keepDaily) - - `includePatterns`/`excludePatterns`: Arrays of patterns - - `enabled`: Boolean - - `notifications`: Array of notification destination names (strings) or detailed objects: - - Simple: `["slack-alerts", "email-admin"]` - - Detailed: `[{"name": "slack-alerts", "notifyOnStart": false, "notifyOnSuccess": true, "notifyOnWarning": true, "notifyOnFailure": true}]` - -##### Notification Destinations - -- **Examples:** - - **Slack** - ```json - { - "name": "slack-alerts", - "config": { - "type": "slack", - "webhookUrl": "${SLACK_WEBHOOK_URL}", - "channel": "#backups", - "username": "zerobyte", - "iconEmoji": ":floppy_disk:" - } - } - ``` - - **Email** - ```json - { - "name": "email-admin", - "config": { - "type": "email", - "smtpHost": "smtp.example.com", - "smtpPort": 587, - "username": "admin@example.com", - "password": "${EMAIL_PASSWORD}", - "from": "zerobyte@example.com", - "to": ["admin@example.com"], - "useTLS": true - } - } - ``` - - **Discord** - ```json - { - "name": "discord-backups", - "config": { - "type": "discord", - "webhookUrl": "${DISCORD_WEBHOOK_URL}", - "username": "zerobyte", - "avatarUrl": "https://example.com/avatar.png", - "threadId": "1234567890" - } - } - ``` - - **Gotify** - ```json - { - "name": "gotify-notify", - "config": { - "type": "gotify", - "serverUrl": "https://gotify.example.com", - "token": "${GOTIFY_TOKEN}", - "path": "/message", - "priority": 5 - } - } - ``` - - **ntfy** - ```json - { - "name": "ntfy-notify", - "config": { - "type": "ntfy", - "serverUrl": "https://ntfy.example.com", - "topic": "zerobyte-backups", - "priority": "high", - "username": "ntfyuser", - "password": "${NTFY_PASSWORD}" - } - } - ``` - - **Pushover** - ```json - { - "name": "pushover-notify", - "config": { - "type": "pushover", - "userKey": "${PUSHOVER_USER_KEY}", - "apiToken": "${PUSHOVER_API_TOKEN}", - "devices": "phone,tablet", - "priority": 1 - } - } - ``` - - **Telegram** - ```json - { - "name": "telegram-notify", - "config": { - "type": "telegram", - "botToken": "${TELEGRAM_BOT_TOKEN}", - "chatId": "123456789" - } - } - ``` - - **Custom (shoutrrr)** - ```json - { - "name": "custom-shoutrrr", - "config": { - "type": "custom", - "shoutrrrUrl": "${SHOUTRRR_URL}" - } - } - ``` - -- **Fields:** - - `name`: Unique name for the notification config - - `config.type`: Notification type (email, slack, discord, gotify, ntfy, pushover, telegram, custom) - - `config`: Type-specific config with `type` field, secrets via `${ENV_VAR}` - -##### User Setup (Automated) - -Zerobyte currently supports a **single user**. If multiple entries are provided in `users[]`, only the first one will be applied. - -- **Example (new instance):** - ```json - { - "recoveryKey": "${RECOVERY_KEY}", - "users": [ - { - "username": "my-user", - "password": "${ADMIN_PASSWORD}" - } - ] - } - ``` - -- **Example (migration from another instance):** - ```json - { - "recoveryKey": "${RECOVERY_KEY}", - "users": [ - { - "username": "my-user", - "passwordHash": "$argon2id$v=19$m=19456,t=2,p=1$..." - } - ] - } - ``` - -- **Fields:** - - `recoveryKey`: Optional recovery key (can use `${ENV_VAR}`) - if provided, the UI prompt to download recovery key will be skipped - - `users[]`: List of users to create on first startup (create-only). Only the first user is applied. - - `users[].username`: Username - - `users[].password`: Plaintext password for new instances (can use `${ENV_VAR}`) - - `users[].passwordHash`: Pre-hashed password for migration (exported from another instance) - - `users[].hasDownloadedResticPassword`: Optional boolean; defaults to `true` when `recoveryKey` is provided - -> **Note:** Use either `password` OR `passwordHash`, not both. The `passwordHash` option is useful when migrating from another Zerobyte instance using an exported config with `includePasswordHash=true`. - -**On first startup, Zerobyte will automatically create users from the config file.** - -> **⚠️ About the Recovery Key** -> -> The recovery key is a 64-character hex string that serves two critical purposes: -> 1. **Restic repository password** - Used to encrypt all your backup data -> 2. **Database encryption key** - Used to encrypt credentials stored in Zerobyte's database -> -> **If you lose this key, you will lose access to all your backups and stored credentials.** -> -> **Generating a recovery key ahead of time:** -> ```bash -> # Using OpenSSL (Linux/macOS) -> openssl rand -hex 32 -> -> # Using Python -> python3 -c "import secrets; print(secrets.token_hex(32))" -> ``` -> -> **Retrieving from an existing instance:** -> - Download via UI: Settings → Download Recovery Key -> - Or read directly from the container: `docker exec zerobyte cat /var/lib/zerobyte/data/restic.pass` - ---- - -**Notes:** -- All secrets (passwords, keys) can use `${ENV_VAR}` syntax to inject from environment variables. -- All paths must be accessible inside the container (mount host paths as needed). -- `readOnly` is supported for all volume types that allow it, including local directories. - ```yaml services: zerobyte: @@ -444,7 +54,6 @@ services: volumes: - /etc/localtime:/etc/localtime:ro - /var/lib/zerobyte:/var/lib/zerobyte - - ./zerobyte.config.json:/app/zerobyte.config.json:ro # Mount your config file ``` > [!WARNING] @@ -493,6 +102,12 @@ If you need remote mount capabilities, keep the original configuration with `cap See [examples/README.md](examples/README.md) for runnable, copy/paste-friendly examples. +### Config file import (Infrastructure as Code) + +If you want Zerobyte to create volumes, repositories, schedules, notification destinations, and an initial user from a JSON file on startup, check the following example: + +- [examples/config-file-import/README.md](examples/config-file-import/README.md) + ## Adding your first volume Zerobyte supports multiple volume backends including NFS, SMB, WebDAV, and local directories. A volume represents the source data you want to back up and monitor. diff --git a/docker-compose.yml b/docker-compose.yml index 4a0f2578..90a43015 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,14 +12,11 @@ services: - SYS_ADMIN environment: - NODE_ENV=development - - ZEROBYTE_CONFIG_IMPORT=true ports: - "4096:4096" volumes: - /etc/localtime:/etc/localtime:ro - /var/lib/zerobyte:/var/lib/zerobyte - - ./mydata:/mydata:ro - - ./zerobyte.config.json:/app/zerobyte.config.json:ro - ./app:/app/app - ~/.config/rclone:/root/.config/rclone @@ -36,33 +33,7 @@ services: - SYS_ADMIN ports: - "4096:4096" - environment: - # Cloud storage credentials - - ACCESS_KEY_ID=your-access-key-id - - SECRET_ACCESS_KEY=your-secret-access-key - - GCS_CREDENTIALS=your-gcs-credentials-json - - AZURE_KEY=your-azure-key - # Volume credentials - - SMB_PASSWORD=your-smb-password - - WEBDAV_PASSWORD=your-webdav-password - # SFTP credentials (for repositories) - - SFTP_PRIVATE_KEY=your-sftp-private-key - # Notification credentials - - SLACK_WEBHOOK_URL=your-slack-webhook-url - - EMAIL_PASSWORD=your-email-password - - DISCORD_WEBHOOK_URL=your-discord-webhook-url - - GOTIFY_TOKEN=your-gotify-token - - NTFY_PASSWORD=your-ntfy-password - - PUSHOVER_USER_KEY=your-pushover-user-key - - PUSHOVER_API_TOKEN=your-pushover-api-token - - TELEGRAM_BOT_TOKEN=your-telegram-bot-token - - SHOUTRRR_URL=your-shoutrrr-url - # Admin credentials - - ADMIN_PASSWORD=your-admin-password - - RECOVERY_KEY=your-64-char-hex-recovery-key volumes: - /etc/localtime:/etc/localtime:ro - /var/lib/zerobyte:/var/lib/zerobyte - - ./zerobyte.config.json:/app/zerobyte.config.json:ro - - ./mydata:/mydata:ro - ~/.config/rclone:/root/.config/rclone diff --git a/examples/README.md b/examples/README.md index 8d2e7657..0ae69c9a 100644 --- a/examples/README.md +++ b/examples/README.md @@ -11,6 +11,7 @@ This folder contains runnable, copy/paste-friendly examples for running Zerobyte - [Bind-mount a local directory](directory-bind-mount/README.md) — back up a host folder by mounting it into the container. - [Mount an rclone config](rclone-config-mount/README.md) — use rclone-based repository backends by mounting your rclone config. - [Secret placeholders + Docker secrets](secrets-placeholders/README.md) — keep secrets out of the DB using `env://...` and `file://...` references. +- [Config file import (Infrastructure as Code)](config-file-import/README.md) — pre-configure volumes/repos/schedules/users on startup. ### Advanced setups diff --git a/examples/config-file-import/.env.example b/examples/config-file-import/.env.example new file mode 100644 index 00000000..d59d0377 --- /dev/null +++ b/examples/config-file-import/.env.example @@ -0,0 +1,23 @@ +# Copy to .env and fill values + +# Used by examples/config-file-import/zerobyte.config.example.json +RECOVERY_KEY=your-64-char-hex-recovery-key +ADMIN_PASSWORD=change-me + +# Optional: referenced by some config examples +ACCESS_KEY_ID= +SECRET_ACCESS_KEY= +GCS_CREDENTIALS= +AZURE_KEY= +SMB_PASSWORD= +WEBDAV_PASSWORD= +SFTP_PRIVATE_KEY= +SLACK_WEBHOOK_URL= +EMAIL_PASSWORD= +DISCORD_WEBHOOK_URL= +GOTIFY_TOKEN= +NTFY_PASSWORD= +PUSHOVER_USER_KEY= +PUSHOVER_API_TOKEN= +TELEGRAM_BOT_TOKEN= +SHOUTRRR_URL= diff --git a/examples/config-file-import/.gitignore b/examples/config-file-import/.gitignore new file mode 100644 index 00000000..9961ad53 --- /dev/null +++ b/examples/config-file-import/.gitignore @@ -0,0 +1,2 @@ +.env +zerobyte.config.json diff --git a/examples/config-file-import/README.md b/examples/config-file-import/README.md new file mode 100644 index 00000000..4bf1aa7d --- /dev/null +++ b/examples/config-file-import/README.md @@ -0,0 +1,388 @@ +# Config file import (Infrastructure as Code) + +Zerobyte supports **config file import** on startup. +This lets you pre-configure volumes, repositories, backup schedules, notification destinations, and an initial user. + +This example includes: + +- a runnable `docker-compose.yml` +- a comprehensive `zerobyte.config.example.json` template (trim it down to what you actually use) +- `.env.example` showing how to inject secrets via environment variables + +## Prerequisites + +- Docker + Docker Compose + +This example includes `SYS_ADMIN` and `/dev/fuse` because it’s compatible with remote volume mounts (SMB/NFS/WebDAV). + +## Setup + +1. Copy the env file: + +```bash +cp .env.example .env +``` + +2. Create a local directory to mount as a sample volume: + +```bash +mkdir -p mydata +``` + +3. Create a working config file (copy the example template): + +```bash +cp zerobyte.config.example.json zerobyte.config.json +``` + +This is the recommended workflow for quick testing: if you don't have your own JSON config yet, start from the template. + +4. Review/edit `zerobyte.config.json`. + + The example template is intentionally "kitchen-sink" (lots of volume/repository/notification types) so you can copy what you need. + Delete the entries you don't plan to use, and keep only the ones you have credentials/mounts for. + +5. Start Zerobyte: + +```bash +docker compose up -d +``` + +6. Access the UI at `http://localhost:4096`. + +## Notes + +### Enabling import + +Config import is opt-in and only runs when: + +- `ZEROBYTE_CONFIG_IMPORT=true` + +The config path defaults to `/app/zerobyte.config.json`, but you can override it via: + +- `ZEROBYTE_CONFIG_PATH=/app/your-config.json` + +### Secrets via env vars + +Zerobyte supports **two different mechanisms** that are easy to confuse: + +1. **Config import interpolation** (this example) +2. **Secret placeholders** (`env://...` and `file://...`) + +#### 1) Config import interpolation: `${VAR_NAME}` + +During config import, any string value in the JSON can reference an environment variable using `${VAR_NAME}`. + +Example: + +```json +{ + "recoveryKey": "${RECOVERY_KEY}", + "repositories": [ + { + "name": "s3-repo", + "config": { + "backend": "s3", + "accessKeyId": "${ACCESS_KEY_ID}", + "secretAccessKey": "${SECRET_ACCESS_KEY}" + } + } + ] +} +``` + +Important properties of `${...}` interpolation: + +- It runs **only during import**. +- Values are **resolved before** they are written to the database (meaning the actual secret ends up in the DB for fields that are stored as secrets). +- Because it reads `process.env`, Docker Compose must inject those variables into the container. + +This example uses: + +- `env_file: .env` + +So to make `${VAR_NAME}` work, put the variables in `.env` (or otherwise provide them in the container environment). + +#### 2) Secret placeholders: `env://...` and `file://...` + +Separately from config import, Zerobyte supports **secret placeholders** for *some sensitive fields*. +These placeholders are stored **as-is** in the database (the raw secret is not stored) and resolved at runtime. + +Supported formats: + +- `env://VAR_NAME` → reads `process.env.VAR_NAME` at runtime +- `file://secret_name` → reads `/run/secrets/secret_name` (Docker secrets) + +This is useful when you want to keep secrets out of the database and rotate them without editing Zerobyte’s stored config. + +See the runnable example: + +- [examples/secrets-placeholders/README.md](../secrets-placeholders/README.md) + +### Config file behavior (create-only) + +The config file is applied on startup using a **create-only** approach: + +- Resources defined in the config are only created if they don't already exist in the database +- Existing resources with the same name are **not overwritten** (a warning is logged and the config entry is skipped) +- Changes made via the UI are preserved across container restarts +- To update a resource from config, either modify it via the UI or delete it first + +This makes the config file better suited as "initial setup" than as a "desired state sync". + +--- + +## Config structure reference + +This example is intended to be the primary, copy/paste-friendly reference for config import. + +### `zerobyte.config.json` structure + +```json +{ + "recoveryKey": "${RECOVERY_KEY}", + "volumes": [ + "..." + ], + "repositories": [ + "..." + ], + "backupSchedules": [ + "..." + ], + "notificationDestinations": [ + "..." + ], + "users": [ + "..." + ] +} +``` + +### Volume types + +#### Local directory + +```json +{ + "name": "local-volume", + "config": { + "backend": "directory", + "path": "/mydata", + "readOnly": true + } +} +``` + +#### NFS + +```json +{ + "name": "nfs-volume", + "config": { + "backend": "nfs", + "server": "nfs.example.com", + "exportPath": "/data", + "port": 2049, + "version": "4", + "readOnly": false + } +} +``` + +#### SMB + +```json +{ + "name": "smb-volume", + "config": { + "backend": "smb", + "server": "smb.example.com", + "share": "shared", + "username": "user", + "password": "${SMB_PASSWORD}", + "vers": "3.0", + "domain": "WORKGROUP", + "port": 445, + "readOnly": false + } +} +``` + +#### WebDAV + +```json +{ + "name": "webdav-volume", + "config": { + "backend": "webdav", + "server": "webdav.example.com", + "path": "/remote.php/webdav", + "username": "user", + "password": "${WEBDAV_PASSWORD}", + "port": 80, + "readOnly": false, + "ssl": true + } +} +``` + +### Repository types + +#### Local + +```json +{ + "name": "local-repo", + "config": { + "backend": "local", + "path": "/var/lib/zerobyte/repositories" + }, + "compressionMode": "auto" +} +``` + +Note for importing existing local repositories (migration): + +- include `config.name` and set `config.isExistingRepository: true` +- the actual restic repo is stored at `{path}/{name}` + +```json +{ + "name": "my-local-repo", + "config": { + "backend": "local", + "path": "/var/lib/zerobyte/repositories", + "name": "abc123", + "isExistingRepository": true + } +} +``` + +#### S3-compatible + +```json +{ + "name": "backup-repo", + "config": { + "backend": "s3", + "bucket": "mybucket", + "accessKeyId": "${ACCESS_KEY_ID}", + "secretAccessKey": "${SECRET_ACCESS_KEY}" + }, + "compressionMode": "auto" +} +``` + +#### Google Cloud Storage + +```json +{ + "name": "gcs-repo", + "config": { + "backend": "gcs", + "bucket": "mybucket", + "projectId": "my-gcp-project", + "credentialsJson": "${GCS_CREDENTIALS}" + } +} +``` + +#### Azure Blob Storage + +```json +{ + "name": "azure-repo", + "config": { + "backend": "azure", + "container": "mycontainer", + "accountName": "myaccount", + "accountKey": "${AZURE_KEY}" + } +} +``` + +### Backup schedules + +```json +{ + "name": "local-volume-local-repo", + "volume": "local-volume", + "repository": "local-repo", + "cronExpression": "0 2 * * *", + "retentionPolicy": { "keepLast": 7, "keepDaily": 7 }, + "includePatterns": ["important-folder"], + "excludePatterns": ["*.tmp", "*.log"], + "enabled": true, + "notifications": ["slack-alerts", "email-admin"] +} +``` + +`notifications` can also be an array of objects: + +```json +[ + { + "name": "slack-alerts", + "notifyOnStart": false, + "notifyOnSuccess": true, + "notifyOnWarning": true, + "notifyOnFailure": true + } +] +``` + +### User setup (automated) + +Zerobyte currently supports a **single user**. +If multiple entries are provided in `users[]`, only the first one will be applied. + +New instance: + +```json +{ + "recoveryKey": "${RECOVERY_KEY}", + "users": [ + { + "username": "my-user", + "password": "${ADMIN_PASSWORD}" + } + ] +} +``` + +Migration: + +```json +{ + "recoveryKey": "${RECOVERY_KEY}", + "users": [ + { + "username": "my-user", + "passwordHash": "$argon2id$v=19$m=19456,t=2,p=1$..." + } + ] +} +``` + +Use either `password` OR `passwordHash`, not both. + +### Recovery key + +The recovery key is a 64-character hex string that serves two critical purposes: + +1. Restic repository password (encrypts your backup data) +2. Database encryption key (encrypts credentials stored in Zerobyte) + +Generating a recovery key ahead of time: + +```bash +# Using OpenSSL (Linux/macOS) +openssl rand -hex 32 + +# Using Python +python3 -c "import secrets; print(secrets.token_hex(32))" + +# Using Docker (prints the key, container is removed) +docker run --rm python:3.12-alpine sh -lc 'echo "Key is on the next line:"; python -c "import secrets; print(secrets.token_hex(32))"' +``` diff --git a/examples/config-file-import/docker-compose.yml b/examples/config-file-import/docker-compose.yml new file mode 100644 index 00000000..78792779 --- /dev/null +++ b/examples/config-file-import/docker-compose.yml @@ -0,0 +1,22 @@ +services: + zerobyte: + image: ghcr.io/nicotsx/zerobyte:latest + container_name: zerobyte + restart: unless-stopped + cap_add: + - SYS_ADMIN + devices: + - /dev/fuse:/dev/fuse + ports: + - "4096:4096" + env_file: + - .env + environment: + - TZ=${TZ:-UTC} + - ZEROBYTE_CONFIG_IMPORT=true + volumes: + - /etc/localtime:/etc/localtime:ro + - /var/lib/zerobyte:/var/lib/zerobyte + - ./zerobyte.config.json:/app/zerobyte.config.json:ro + - ./mydata:/mydata:ro + - ~/.config/rclone:/root/.config/rclone diff --git a/zerobyte.config.json b/examples/config-file-import/zerobyte.config.example.json similarity index 100% rename from zerobyte.config.json rename to examples/config-file-import/zerobyte.config.example.json