NAS Backup Pipeline: Backrest, Restic & Google Drive#
Complete configuration guide for backing up isolated TrueNAS/DSM network shares from the headless Ubuntu VM (HP1Docker) to an encrypted Google Drive repository using Backrest (a Web UI wrapper for Restic) and Rclone. For baseline Rclone installation, remote management, and CLI commands, see the RClone Guide.
1. System Architecture Overview#
- Source Data: 8 explicit network shares mounted via CIFS/SMB on the host VM at
/mnt/<ShareName>. - Backup Host: Ubuntu VM (
HP1Docker-10.1.2.202). - Backup Agent: Backrest Docker Container running Restic 0.18.1.
- Target Backend: Google Drive (
proxmox.app@gmail.com) via a dedicated Rclone remote. - Security Model: Client-side, zero-knowledge encryption via a dedicated repository password before data leaves the local host.
- Rate-Limit Protections: Powered by a custom Google Cloud Project ID to bypass global multi-user API query restrictions during multi-terabyte data transfers.
2. Directory Structure Setup#
All configuration and container runtime files are centralized on the host under the user deployment directory.
# Navigate to the project directory
cd /home/marc/docker-compose/backrest
# Create required persistent local storage volumes
mkdir -p data config cache tmp rclone repos
# Restrict permissions on the rclone directory to secure credentials
chmod 700 rclone3. Docker Compose Configuration#
The full docker-compose.yml file maps the 8 network shares explicitly as Read-Only (:ro) to insulate source data against accidental software manipulation or deletion.
services:
backrest:
image: ghcr.io/garethgeorge/backrest:latest
container_name: backrest
hostname: backrest
volumes:
- ./data:/data
- ./config:/config
- ./cache:/cache
- ./tmp:/tmp
- ./rclone:/root/.config/rclone
- ./repos:/repos
# Explicitly isolated network shares mapped to internal workspace
- /mnt/Books:/userdata/Books:ro
- /mnt/Documents:/userdata/Documents:ro
- /mnt/HomesDSM:/userdata/HomesDSM:ro
- /mnt/Immich:/userdata/Immich:ro
- /mnt/Musique:/userdata/Musique:ro
- /mnt/Nadine:/userdata/Nadine:ro
- /mnt/Photos:/userdata/Photos:ro
- /mnt/Software:/userdata/Software:ro
environment:
- BACKREST_DATA=/data
- BACKREST_CONFIG=/config/config.json
- XDG_CACHE_HOME=/cache
- TMPDIR=/tmp
- TZ=America/Toronto
ports:
- "9898:9898"
restart: unless-stopped4. Headless Rclone Authentication & Custom API Access#
To circumvent global Google API 403 RATE_LIMIT_EXCEEDED bottlenecks during large baseline backups, Rclone must communicate using a personal Client ID and Client Secret generated inside your Google Cloud Console project.
Step 1: Obtain Google Cloud Credentials#
- Navigate to your Google Cloud Credentials Console under the
GDriveAccessproject. - Verify that the Google Drive API is marked as Enabled.
- Click + CREATE CREDENTIALS -> OAuth client ID.
- Set the Application type to Desktop app.
- Complete creation, then copy the resulting Client ID and Client Secret into your 1Password vault.
Step 2: Generate Token on Desktop Machine#
Open your local desktop terminal (PC/Mac with Rclone installed) and pass your custom client variables into the authorization loop:
rclone authorize "drive" --drive-client-id "YOUR_CUSTOM_CLIENT_ID" --drive-client-secret "YOUR_CUSTOM_CLIENT_SECRET"Note: If your system default web browser opens with an incorrect Google profile signed in, copy the full authentication web URL out of that browser, paste it into an active Firefox session where proxmox.app@gmail.com is verified, and approve permissions.
Copy the completed JSON string token block {...} returned in the terminal.
Step 3: Write Config File on Host Server#
On HP1Docker, write the credential file inside the persistent configuration directory:
nano rclone/rclone.confPaste the layout below, inserting your personal credentials dynamically:
[gdrive-backups]
type = drive
scope = drive
client_id = YOUR_CUSTOM_CLIENT_ID
client_secret = YOUR_CUSTOM_CLIENT_SECRET
token = {"access_token":"...","token_type":"Bearer","refresh_token":"...","expiry":"..."}Ensure the massive JSON array block stays entirely on a single continuous token = string line.
Save and exit nano (Ctrl+O, Enter, Ctrl+X). Secure the host file permissions:
chmod 600 rclone/rclone.conf5. Web UI Initialization#
Deploy the stack from /home/marc/docker-compose/backrest:
docker compose up -dAccess the web portal at http://10.1.2.202:9898 and finalize the parameter options.
Step 1: Initialize Restic Repository#
Navigate to Repositories -> Add Repository:
- Repo Name:
proxmox.app-unas-backup - Repository URI:
rclone:gdrive-backups:restic-nas-backups - Password: [Generate and save a strong random cryptographic key in 1Password. This acts as the exclusive recovery key for data decryption.]
Step 2: Configure the Backup Plan#
Navigate to Plans -> + Add Plan:
- Plan Name:
UNAS - Repository: Select
proxmox.app-unas-backup - Target Paths (Include Scopes):
/userdata/Books/userdata/Documents/userdata/HomesDSM/userdata/[Immich](Immich.md)/userdata/Musique/userdata/Nadine/userdata/Photos/userdata/Software
6. Automation & Scheduling Policy#
Cron Configuration#
To avoid metadata resource starvation bottlenecks across network mounts and stay comfortably inside API limits, automation is bound to a single comprehensive daily loop.
- Schedule Expression: Daily at 18:00 (6:00 PM)
- Cron syntax:
0 18 * * *
Operational Notes#
- Initial Backup: Processes ~2.2 TiB of baseline data. High runtime and storage block validation duration are expected on the first execution pass while parsing through the file catalog.
- Subsequent Backups: Content-defined deduplication policies ensure subsequent passes are fully incremental, scanning blocks for differentials and uploading changes within minutes.
7. Restore Procedure#
Restic backups are completely non-destructive and can be recovered either directly through the Backrest Web UI or via the command line using the underlying Restic binary inside the container.
Method 1: Via the Backrest Web UI (Recommended)#
-
Open the Web UI (
http://10.1.2.202:9898) and navigate to Repositories in the left sidebar. -
Click on
proxmox.app-unas-backupand navigate to the Snapshots tab (or browse via the Tree View). -
Expand the date folders to find the exact snapshot you want to recover files from.
-
Click Browse Files to navigate the nested share structures (e.g.,
/userdata/Documents). -
Select the checkboxes next to the files or folders you need to recover, then click the Restore button.
-
Configure the Restore dialog based on your scenario:
-
Scenario A: Safe Isolated Testing / Verification
- Destination Path: Type
/tmp/restore-landing. - How it works: This avoids overwriting live production data. Because the compose file maps
./tmpon the host to/tmpinside the container, files securely land on your server’s host filesystem at/home/marc/docker-compose/backrest/tmp/restore-landing/.
- Destination Path: Type
-
Scenario B: Direct-to-NAS Recovery (Disaster Recovery / Large Data Pulls)
- Use this scenario if your data exceeds your server’s local 100 GB storage limit.
- Step 1: On your server host, open
docker-compose.ymland temporarily remove the:roflag from the specific network share(s) you need to restore to make them writeable.- Example change:
- /mnt/Books:/userdata/Books
- Example change:
- Step 2: Apply the configuration changes in your terminal:
docker compose up -d - Step 3: In the Restore dialog box, set the Restore to path to exactly:
/ - How it works: Restic reads the original absolute path of the backup metadata (e.g.,
/userdata/Books). By using/as the root target, it streams files directly into the writeable NAS mount point, consuming 0 GB of your server’s host storage drive.
-
Method 2: Command-Line Failsafe (Emergency Bypass)#
If the Backrest container’s web interface is ever down, you can execute raw Restic restore operations directly through the container’s CLI backend using your host’s mapped Rclone configuration.
-
Verify Repository Access: Run a test command to list all snapshots directly from the Google Drive repository (you will be prompted to enter your Restic repository encryption password from 1Password):
docker exec -it backrest restic -r rclone:gdrive-backups:restic-nas-backups snapshots -
Perform an Emergency Restore: To restore a specific share (e.g.,
Documents) from the most recent snapshot into your local host’s scratch/tmp directory:docker exec -it backrest restic -r rclone:gdrive-backups:restic-nas-backups restore latest \ --target /tmp/emergency-recovery \ --include /userdata/Documents -
Retrieve the Data: The unencrypted, recovered data will immediately be accessible on your Ubuntu host filesystem at:
ls -la /home/marc/docker-compose/backrest/tmp/emergency-recovery/userdata/Documents
8. Deactivate and Wipe This Backup Process#
This procedure permanently deletes the Backrest/Restic backup repository and all of its Google Drive data. It must not be used to delete the separate
Proxmox-Backupsfolder, which belongs to the PBS backup process. The eight source shares under/mnt/are not deleted by these steps.
Run the local commands below on HP1Docker (10.1.2.202) as the deployment user, unless otherwise noted.
8.1 Disable the scheduled backup#
-
Inspect the current crontab and confirm the Backrest schedule:
crontab -l -
Edit the crontab:
crontab -e -
Remove or comment out the Backrest entry:
0 18 * * * -
Confirm that no active cron entry still launches Backrest, Restic, or an rclone sync for this repository:
crontab -l grep -RInE 'backrest|restic|gdrive-backups|restic-nas-backups' /etc/cron* /var/spool/cron 2>/dev/null
8.2 Stop the Backrest stack#
From the deployment directory, stop and remove the containers and network:
cd /home/marc/docker-compose/backrest
docker compose downConfirm that no related container or process remains:
docker ps -a --format '{{.Names}}' | grep -Ei 'backrest|restic' || true
pgrep -af 'backrest|restic|rclone' || true8.3 Preserve anything required before deletion#
Before wiping the configuration, export any information required for auditing or future recovery, such as the repository name, source paths, and retention policy. Do not export or print OAuth tokens, client secrets, or the Restic repository password.
8.4 Delete the local Backrest data#
After confirming that the containers are stopped and no recovery is required, delete the local process data:
cd /home/marc/docker-compose/backrest
rm -rf data config cache tmp repos rcloneThis removes the local Backrest database, plans, cache, temporary restore data, repository staging data, and rclone configuration. It does not remove the /mnt/Books, /mnt/Documents, /mnt/HomesDSM, /mnt/Immich, /mnt/Musique, /mnt/Nadine, /mnt/Photos, or /mnt/Software source shares.
Optionally remove the now-unused project directory only after reviewing its contents:
find /home/marc/docker-compose/backrest -maxdepth 2 -print8.5 Delete all data at the Google Drive target#
In the proxmox.app@gmail.com Google Drive account:
- Open the
restic-nas-backupsfolder. - Delete the entire folder, not just visible snapshot directories.
- Empty the Google Drive trash if permanent deletion is intended.
- Confirm that
Proxmox-Backupsis not selected or deleted; it is a separate PBS target.
The deleted target includes all Restic snapshots, encrypted repository data, indexes, pack files, configuration metadata, and hidden files within restic-nas-backups.
8.6 Revoke cloud authorization#
-
Revoke the rclone OAuth authorization for
proxmox.app@gmail.comfrom the Google Account security settings. -
Disable or delete the custom OAuth client in the Google Cloud
GDriveAccessproject if it is no longer used by another process. -
Remove any remaining local copy of
rclone.conf:find /home/marc/docker-compose/backrest -name 'rclone.conf' -print
8.7 Verify that the process is fully deactivated#
Run the following checks:
crontab -l
docker ps -a
pgrep -af 'backrest|restic|rclone' || true
find /home/marc/docker-compose/backrest -maxdepth 2 -print 2>/dev/nullConfirm that the source shares still exist and are mounted:
findmnt /mnt/Books /mnt/Documents /mnt/HomesDSM /mnt/Immich /mnt/Musique /mnt/Nadine /mnt/Photos /mnt/Software