Google Drive to VPS backup
Configure the run, then follow the steps.
Setup wizard
Only upfront values live here. Values discovered later appear in the relevant step.
Required values
Prepare the VPS target
Create the two directories the runtime uses: one for rclone config, one for copied data. The config directory stays writable to rclone so refreshed OAuth token metadata can be saved; the data directory is the backup target.
mkdir -p "/mnt/backupdrive/rclone-config" "/mnt/backupdrive/data"Make the config and data directories writable by 1000:1000 before running the non-root container.
chown -R 1000:1000 "/mnt/backupdrive/rclone-config" "/mnt/backupdrive/data"
chmod 700 "/mnt/backupdrive/rclone-config"Create the Google OAuth client
Create a dedicated OAuth client instead of relying on rclone's shared bundled credentials. Shared credentials are rate-limited and can produce 429 errors.
- Enable the Google Drive API for the Google Cloud project.
- Open Google credentials and create an OAuth client ID with application type Desktop app.
- Add
http://127.0.0.1:53682/as an authorized redirect URI, including the trailing slash. - Set the OAuth consent screen publishing status to In production before minting the final token. Testing-mode Drive refresh tokens expire after 7 days.
- For a one-person setup, authorize through the unverified-app warning with your own Google account. Google documents this as acceptable for personal use by you or a few known users.
Mint the rclone token
Do the OAuth approval from any workstation with Docker and a browser. The headless VPS does not need browser access.
docker run --rm -it -p 53682:53682 rclone/rclone authorize "drive" \
--drive-client-id "YOUR_CLIENT_ID" \
--drive-client-secret "YOUR_CLIENT_SECRET"The container may print an xdg-open error because no browser exists inside it. Open the printed http://127.0.0.1:53682/auth?... URL on the workstation, approve access, and copy the full token JSON that rclone prints.
Create the rclone remote
Run rclone config on the VPS with the config directory mounted writable. Backup runs keep it writable too, so token refreshes can be persisted without noisy save errors.
docker run --rm -it \
--user "1000:1000" \
-v "/mnt/backupdrive/rclone-config:/config/rclone" \
rclone/rclone confignnew remote, name itgdrive-backup.- Storage type:
drive. - Paste
client_idandclient_secret. - Scope:
2for read-only Drive access. service_account_file: blank, Enter.- Edit advanced config:
n. - Use auto config / browser:
n. - At
config_token>, paste the full token JSON from step 03. - Shared Drive / Team Drive:
n. Use My Drive when rclone asks about Shared Drive / Team Drive. - Keep this remote:
y, thenqto quit.
If the session exits before y and q, no config is saved.
Verify the remote
Confirm that the remote exists and that the spelling is exactly gdrive-backup. Keep the config mount writable so rclone can save refreshed token metadata.
# should print: gdrive-backup:
docker run --rm \
--user "1000:1000" \
-v "/mnt/backupdrive/rclone-config:/config/rclone" \
rclone/rclone listremotes
# list Drive root to confirm auth and folder spelling
docker run --rm \
--user "1000:1000" \
-v "/mnt/backupdrive/rclone-config:/config/rclone" \
rclone/rclone lsd gdrive-backup:Run the first copy manually
Run one manual copy before scheduling. The generated commands quote the source and destination, so folder names with spaces are safe.
docker run --rm \
--user "1000:1000" \
-v "/mnt/backupdrive/rclone-config:/config/rclone" \
-v "/mnt/backupdrive/data:/data" \
rclone/rclone \
copy "gdrive-backup:Drive Folder" "/data/Drive Folder" \
--progress --transfers=4 --checkers=8When it completes, ls -la "/mnt/backupdrive/data/Drive Folder" should show copied files for Drive Folder.
Create the Healthchecks check
Monitoring is enabled. Create the Healthchecks.io check before installing the script, then paste the check's base ping URL here.
- Period:
1 hour. - Grace:
20-30 min. - Integrations: add whichever alert channel will reach the operator.
The generated script will ping /start, the base success URL, and /fail with a log tail.
Install the script and cron
Create /mnt/backupdrive/backup.sh after the manual copy succeeds and the Healthchecks URL has been applied in step 07. The script wraps rclone, writes logs, and reports start, success, or failure.
#!/usr/bin/env bash
set -u -o pipefail
REMOTE_NAME="gdrive-backup"
REMOTE_FOLDER="Drive Folder"
BASE="/mnt/backupdrive"
HC="https://hc-ping.com/YOUR_UUID"
DOCKER_IMAGE="rclone/rclone"
RUN_AS="1000:1000"
TRANSFERS="4"
CHECKERS="8"
DOCKER_USER_ARGS=()
if [ -n "$RUN_AS" ]; then
DOCKER_USER_ARGS=(--user "$RUN_AS")
fi
curl -fsS -m 10 --retry 3 "$HC/start" >/dev/null 2>&1 || true
docker run --rm \
"${DOCKER_USER_ARGS[@]}" \
-v "$BASE/rclone-config:/config/rclone" \
-v "$BASE/data:/data" \
"$DOCKER_IMAGE" \
copy "$REMOTE_NAME:$REMOTE_FOLDER" "/data/$REMOTE_FOLDER" \
--log-file=/data/rclone.log \
--log-level INFO \
--transfers="$TRANSFERS" \
--checkers="$CHECKERS"
EXIT=$?
if [ $EXIT -eq 0 ]; then
curl -fsS -m 10 --retry 3 "$HC" >/dev/null 2>&1 || true
else
curl -fsS -m 10 --retry 3 \
--data-raw "$(tail -c 10000 "$BASE/data/rclone.log" 2>/dev/null)" \
"$HC/fail" >/dev/null 2>&1 || true
fi
exit $EXITchmod +x "/mnt/backupdrive/backup.sh"
"/mnt/backupdrive/backup.sh"Cron starts an ephemeral container. flock -n prevents overlap: if one run is still active, the next scheduled run exits immediately instead of starting a second writer.
crontab -ePaste this line into the crontab:
# Google Drive backup, lock-guarded
0 * * * * /usr/bin/flock -n "/mnt/backupdrive/.backup.lock" "/mnt/backupdrive/backup.sh" >> "/mnt/backupdrive/cron.log" 2>&1A skipped overlapping run sends no ping, but the long run that caused it still pings success when it finishes.
Set log rotation and review failure modes
weekly with rotate 4 keeps bounded history.
cat > /etc/logrotate.d/gdrive-backup <<'EOF'
/mnt/backupdrive/data/rclone.log /mnt/backupdrive/cron.log {
weekly
rotate 4
compress
missingok
notifempty
copytruncate
}
EOF# dry-run: show actions, change nothing
logrotate -d /etc/logrotate.d/gdrive-backup
# force a real rotation now
logrotate -f /etc/logrotate.d/gdrive-backupOAuth tokens include the client ID and client secret. If the secret has been exposed, delete it in Google Cloud Console, generate a new one, and rewrite the rclone config.
Drive refresh tokens expire after seven days while an external OAuth app is in Testing. For unattended use, move the OAuth consent screen to In production before minting the final token. If you already minted a Testing token, mint a new token and update the rclone remote.
gdrive-backup must match in the config, commands, and script. If unsure, listremotes is canonical.
copy adds and updates files but never deletes local files. Add restic, borg, or --backup-dir if point-in-time recovery matters.