diff --git a/README.md b/README.md index 1c0dbb37..459d1d98 100644 --- a/README.md +++ b/README.md @@ -249,6 +249,14 @@ Zerobyte can use [rclone](https://rclone.org/) to support 40+ cloud storage prov + - ~/.config/rclone:/root/.config/rclone ``` + > **Note for non-root users:** If your container runs as a different user (e.g., TrueNAS apps), mount your config to the appropriate location and set `RCLONE_CONF_DIR`: + > ```yaml + > environment: + > - RCLONE_CONF_DIR=/home/appuser/.config/rclone + > volumes: + > - ~/.config/rclone:/home/appuser/.config/rclone:ro + > ``` + 5. **Restart the Zerobyte container**: ```bash @@ -257,9 +265,9 @@ Zerobyte can use [rclone](https://rclone.org/) to support 40+ cloud storage prov ``` 6. **Create a repository** in Zerobyte: - - Select "rclone" as the repository type - - Choose your configured remote from the dropdown - - Specify the path within your remote (e.g., `backups/zerobyte`) + - Select "rclone" as the repository type + - Choose your configured remote from the dropdown + - Specify the path within your remote (e.g., `backups/zerobyte`) For a complete list of supported providers, see the [rclone documentation](https://rclone.org/). diff --git a/app/server/core/capabilities.ts b/app/server/core/capabilities.ts index 8f7dc029..3c50f809 100644 --- a/app/server/core/capabilities.ts +++ b/app/server/core/capabilities.ts @@ -1,4 +1,5 @@ import * as fs from "node:fs/promises"; +import { RCLONE_CONF_DIR } from "./constants"; import { logger } from "../utils/logger"; export type SystemCapabilities = { @@ -34,14 +35,14 @@ async function detectCapabilities(): Promise { /** * Checks if rclone is available by: - * 1. Checking if /root/.config/rclone directory exists and is accessible + * 1. Checking if the rclone config directory exists and is accessible */ async function detectRclone(): Promise { try { - await fs.access("/root/.config/rclone"); + await fs.access(RCLONE_CONF_DIR); // Make sure the folder is not empty - const files = await fs.readdir("/root/.config/rclone"); + const files = await fs.readdir(RCLONE_CONF_DIR); if (files.length === 0) { throw new Error("rclone config directory is empty"); } @@ -49,7 +50,9 @@ async function detectRclone(): Promise { logger.info("rclone capability: enabled"); return true; } catch (_) { - logger.warn("rclone capability: disabled. " + "To enable: mount /root/.config/rclone in docker-compose.yml"); + logger.warn( + `rclone capability: disabled. ` + `To enable: mount rclone config at ${RCLONE_CONF_DIR} in docker-compose.yml`, + ); return false; } } diff --git a/app/server/core/constants.ts b/app/server/core/constants.ts index a98c54eb..d2178333 100644 --- a/app/server/core/constants.ts +++ b/app/server/core/constants.ts @@ -8,4 +8,6 @@ export const RESTIC_CACHE_DIR = process.env.RESTIC_CACHE_DIR || "/var/lib/zeroby export const DATABASE_URL = process.env.DATABASE_URL || "/var/lib/zerobyte/data/zerobyte.db"; export const RESTIC_PASS_FILE = process.env.RESTIC_PASS_FILE || "/var/lib/zerobyte/data/restic.pass"; +export const RCLONE_CONF_DIR = process.env.RCLONE_CONF_DIR || "/root/.config/rclone"; + export const DEFAULT_EXCLUDES = [DATABASE_URL, RESTIC_PASS_FILE, REPOSITORY_BASE];