From 4c7bd31b88b354a40843c884bd762083f5ee30b0 Mon Sep 17 00:00:00 2001 From: Nico <47644445+nicotsx@users.noreply.github.com> Date: Sun, 1 Feb 2026 10:24:09 +0100 Subject: [PATCH] feat: custom rclone conf dir env variable (#432) * feat: custom rclone conf dir env variable Closes #238 * chore: rename RCLONE_CONF_DIR -> RCLONE_CONFIG_DIR --- README.md | 30 ++++++++++++++++++++---------- app/server/core/capabilities.ts | 11 +++++++---- app/server/core/constants.ts | 2 ++ docker-compose.yml | 9 ++++++--- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 1c0dbb37..55f7b759 100644 --- a/README.md +++ b/README.md @@ -89,16 +89,17 @@ Zerobyte can be customized using environment variables. Below are the available ### Environment Variables -| Variable | Description | Default | -| :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------------- | :--------- | -| `BASE_URL` | **Required.** The base URL of your Zerobyte instance (e.g., `https://zerobyte.example.com`). See [Authentication](#authentication) below. | (none) | -| `APP_SECRET` | **Required.** A random secret key (32+ chars) used to encrypt sensitive data in the database. Generate with `openssl rand -hex 32`. | (none) | -| `PORT` | The port the web interface and API will listen on. | `4096` | -| `RESTIC_HOSTNAME` | The hostname used by Restic when creating snapshots. Automatically detected if a custom hostname is set in Docker. | `zerobyte` | -| `TZ` | Timezone for the container (e.g., `Europe/Paris`). **Crucial for accurate backup scheduling.** | `UTC` | -| `TRUSTED_ORIGINS` | Comma-separated list of extra trusted origins for CORS (e.g., `http://localhost:3000,http://example.com`). | (none) | -| `LOG_LEVEL` | Logging verbosity. Options: `debug`, `info`, `warn`, `error`. | `info` | -| `SERVER_IDLE_TIMEOUT` | Idle timeout for the server in seconds. | `60` | +| Variable | Description | Default | +| :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------------- | :--------------------- | +| `BASE_URL` | **Required.** The base URL of your Zerobyte instance (e.g., `https://zerobyte.example.com`). See [Authentication](#authentication) below. | (none) | +| `APP_SECRET` | **Required.** A random secret key (32+ chars) used to encrypt sensitive data in the database. Generate with `openssl rand -hex 32`. | (none) | +| `PORT` | The port the web interface and API will listen on. | `4096` | +| `RESTIC_HOSTNAME` | The hostname used by Restic when creating snapshots. Automatically detected if a custom hostname is set in Docker. | `zerobyte` | +| `TZ` | Timezone for the container (e.g., `Europe/Paris`). **Crucial for accurate backup scheduling.** | `UTC` | +| `TRUSTED_ORIGINS` | Comma-separated list of extra trusted origins for CORS (e.g., `http://localhost:3000,http://example.com`). | (none) | +| `LOG_LEVEL` | Logging verbosity. Options: `debug`, `info`, `warn`, `error`. | `info` | +| `SERVER_IDLE_TIMEOUT` | Idle timeout for the server in seconds. | `60` | +| `RCLONE_CONFIG_DIR` | Path to the rclone config directory inside the container. Change this if running as a non-root user. | `/root/.config/rclone` | ### Secret References @@ -249,6 +250,15 @@ 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_CONFIG_DIR=/home/appuser/.config/rclone + > volumes: + > - ~/.config/rclone:/home/appuser/.config/rclone:ro + > ``` + 5. **Restart the Zerobyte container**: ```bash diff --git a/app/server/core/capabilities.ts b/app/server/core/capabilities.ts index 8f7dc029..ca1efae6 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_CONFIG_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_CONFIG_DIR); // Make sure the folder is not empty - const files = await fs.readdir("/root/.config/rclone"); + const files = await fs.readdir(RCLONE_CONFIG_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_CONFIG_DIR} in docker-compose.yml`, + ); return false; } } diff --git a/app/server/core/constants.ts b/app/server/core/constants.ts index a98c54eb..0eff834f 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_CONFIG_DIR = process.env.RCLONE_CONFIG_DIR || "/root/.config/rclone"; + export const DEFAULT_EXCLUDES = [DATABASE_URL, RESTIC_PASS_FILE, REPOSITORY_BASE]; diff --git a/docker-compose.yml b/docker-compose.yml index d0b7bfac..ca0029e3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,17 +10,20 @@ services: - /dev/fuse:/dev/fuse cap_add: - SYS_ADMIN + env_file: + - .env.local environment: - NODE_ENV=development - - APP_SECRET=94bad4678ce84a60b9789bd2114a6bf780aeb38df426f7352c941c66e25d5c2b - - BASE_URL=http://localhost:4096 + - APP_SECRET=${APP_SECRET} + - BASE_URL=${BASE_URL:http://localhost:3000} ports: - - "4096:4096" + - "3000:3000" volumes: - /etc/localtime:/etc/localtime:ro - /var/lib/zerobyte:/var/lib/zerobyte - ./app:/app/app - ~/.config/rclone:/root/.config/rclone + - ./tmp/:/test-data zerobyte-prod: # image: ghcr.io/nicotsx/zerobyte:v0.22.0