For a long time my server backed itself up every night, carefully, to… itself. Database dumps, config snapshots, project archives, all neatly stored in a folder on the same disk as the data they protected. If that disk had died, or the server had been hacked, or I'd fat-fingered a delete command, the backups would have gone down with the ship.

Meanwhile I had a Google account with 2 TB of storage, mostly empty. This post is how I connected the two: every night my server sends an encrypted copy of its backups to Google Drive, automatically, in a way that even a compromised server can't use to wreck my Drive.

Why Google Drive (and when not to use it)

The 3-2-1 rule says at least one copy of your data should live off-site, ideally with a different company. My VPS host and Google are about as "different company" as it gets. And if you already pay for Google storage, the off-site copy costs you nothing extra.

Honest caveats before you copy me:

  • Drive isn't built for this. It works well for nightly backups of a few hundred megabytes, like mine. For hundreds of gigabytes, purpose-built storage (Backblaze B2, Wasabi, S3) is a better fit.
  • Your Google account becomes critical. Turn on two-factor authentication. If you ever lost access to that account, you'd lose this copy, which is why it's one of my copies, not the only one.
  • Google can technically read what you upload. That's why we encrypt first. More on that below.

The tool: rclone

rclone is a free command-line program that talks to more than 70 storage services, Google Drive included. Think of it as "copy and paste, but between your server and the cloud." Install it with your package manager or the one-line installer from their site, then check:

rclone version

Step 1: a connection that can't see your whole Drive

This is the part most tutorials skip, and the one I care about most. By default, rclone asks Google for full access to your entire Drive. That means if your server were ever hacked, the attacker would be holding a key to your tax returns, your family photos, everything.

Instead, use the drive.file scope. It gives rclone access only to files rclone itself created. The server can manage its backup folder and nothing else. When rclone asks about "scope" during setup, pick the option described as access to files created by rclone.

rclone config
# n) New remote → name it: gdrive-backup
# Storage: drive
# scope: drive.file   ← the important one

Optional but recommended: rclone's built-in Google connection is shared by every rclone user in the world, so it can get slow at busy times. Making your own free "client ID" in Google Cloud Console takes about ten minutes, and rclone's docs walk you through it.

Step 2: signing in from a server with no browser

Here's where everyone gets stuck. Google wants you to sign in through a web browser, but your server doesn't have one. The trick is that you do the browser part on your own computer and hand the result to the server.

  1. When rclone config asks "Use web browser to automatically authenticate?", answer n.
  2. rclone prints a command that starts with rclone authorize "drive" …. Copy it.
  3. On your laptop or desktop (install rclone there too), paste and run that command. A browser opens.
  4. Sign in to Google and click Allow. If you made your own client ID, Google may warn it's an "unverified app". That's you, so click Advanced → Go to….
  5. Your laptop's terminal prints a token: a long line of text starting with {"access_token":. Copy the whole line.
  6. Paste it into the server's waiting rclone config prompt. Done.

Test it:

rclone lsd gdrive-backup:

No errors means the server can talk to Drive.

Step 3: encrypt before anything leaves the server

My backups include database dumps, and database dumps include things like user accounts. I don't want those sitting readable in a Google folder. rclone has a built-in encryption layer called crypt that wraps another remote: files are encrypted on the server before upload, and even the filenames are scrambled.

rclone config
# n) New remote → name it: gdrive-crypt
# Storage: crypt
# remote: gdrive-backup:vps-offsite
# filename_encryption: standard
# password + password2: let rclone generate strong ones

Now anything you copy to gdrive-crypt: lands in a vps-offsite folder on Drive as unreadable gibberish, and comes back readable when you copy it out through rclone.

Save both passwords in your password manager right now. If your server dies, those two passwords are the only way to decrypt your backups. Store them on the server alone and you've built a safe and locked the key inside it.

Step 4: a nightly sync that can't wipe itself out

rclone has two main ways to send files:

  • rclone copy uploads new and changed files and never deletes anything on Drive. Safe, but Drive fills up forever.
  • rclone sync makes Drive an exact mirror, including deletions. Tidy, but if your server's backup folder is ever emptied, by accident or by an attacker, sync faithfully empties Drive too.

I use sync with a safety net: --backup-dir. Anything that would be deleted or overwritten on Drive is moved to a dated "deleted" folder instead, and I keep that for 30 days. I also cap the number of deletions per run, so a mass deletion stops the job instead of going through.

#!/bin/bash
# /root/maint/offsite-sync.sh: nightly encrypted copy to Google Drive
DEST=gdrive-crypt:
STAMP=$(date +%Y%m%d)
OPTS=(--backup-dir "${DEST}deleted/$STAMP" --max-delete 100)

rclone sync /root/backups/db    "${DEST}db"            "${OPTS[@]}"
rclone sync /home/admin/backups "${DEST}admin-backups" "${OPTS[@]}"

# Permanently remove "deleted" items after 30 days
rclone delete "${DEST}deleted" --min-age 30d --rmdirs

My real version also logs every run and emails me if either sync fails. The upload is small: about 21 MB of database dumps plus a couple hundred megabytes of other backups. And because sync only sends what changed, most nights it moves far less than that.

Step 5: put it on a schedule

One cron line, timed to run after the nightly backups and cleanup have finished (I explain the five-star format in my cron post):

30 4 * * *  root  /root/maint/offsite-sync.sh

I also have a health check, running every 15 minutes, that alerts me if the last successful upload is more than 26 hours old. That way I hear about it if the job stops running entirely, not just when it runs and fails.

Step 6: prove you can get it back

This is the step that turns "I have backups" into "I have backups that work". Pull one file back down and open it:

# See what's up there (decrypted names)
rclone ls gdrive-crypt:db | head

# Download one dump and peek inside
rclone copy gdrive-crypt:db/20261015/mysql.sql.gz /tmp/restore-test/
zcat /tmp/restore-test/mysql.sql.gz | head -20

If you see readable SQL, everything works: upload, encryption and decryption. For the real test, set up rclone on a different computer using only the passwords from your password manager and try it there. That's exactly the situation you'll be in on the worst day.

What I'd tell myself a year ago

The whole setup took an afternoon, most of it spent understanding the sign-in step. It costs nothing on top of storage I already had. And it turned my backups from "copies on the same disk" into something that would survive the server disappearing completely. Of all the things I've automated, this is the one I'd do first.