seolcu notes

Unattended offsite backups with the official Proton Drive CLI

Run the official proton-drive CLI from systemd on headless servers: log hosts in as a separate editor account (Proton has no scoped tokens), store the session in pass with a passphrase-less GPG key, set a readable working directory, and purge the owner’s trash yourself.

Status
working
Verified
(0 days before this build)
How
Running in production since 2026-10-02 on four Ubuntu 24.04 / Debian 13 hosts (x86_64 and arm64), daily and weekly uploads of 1 MB–4.4 GB archives.
Applies to
  • init systemd
  • os Ubuntu 24.04 LTS, Debian 13
  • proton-drive cli 0.8.0 (linux-x64, linux-arm64)

Summary

The official Proton Drive CLI works for unattended server backups, but four things are not obvious from its help text:

  1. Any CLI session is a full-account session. Proton has no scoped tokens, app passwords or service accounts. Do not log servers in with your main account.
  2. Use a second (free) account as an editor of one shared folder. Files it uploads are owned by, and counted against, the folder owner.
  3. The session store needs pass, and pass needs a GPG key that an unattended job can decrypt. Give root a passphrase-less key and rely on file permissions.
  4. An editor’s deletions land in the owner’s trash, and Proton never empties trash on its own. Something holding the owner’s session has to purge it.

Environment

Account model

MachineLogged-in accountCan do
Backup hostssecondary account, editor on /my-files/<folder> onlyupload, list, trash inside that folder
One private helper hostmain account (owner)everything; used only to purge trash

A compromised backup host can read and trash backups, nothing else: not mail, not Pass, not personal Drive files.

Verified: after a 4.1 GB upload by the editor account, the editor account’s own storage usage still read 0. The upload counted against the owner.

Paths as each side sees them:

Install on a host

# CLI (check the sha512 first)
sudo install -m 0755 proton-drive /usr/local/bin/proton-drive

# pass without recommends; with recommends Debian/Ubuntu pull ~80 X11/Mesa packages
sudo apt-get install -y --no-install-recommends pass

# Passphrase-less GPG key for root, then initialise pass with it
sudo -H bash -c 'cd /root && gpg --batch --pinentry-mode loopback --passphrase "" \
  --quick-gen-key "backup proton <root@$(hostname)>" default default never \
  && pass init "$(gpg --list-secret-keys --with-colons | awk -F: "/^fpr/{print \$10; exit}")"'

# Log in as the SECONDARY account; open the printed URL in any browser
sudo -H bash -c 'cd /root && PROTON_DRIVE_CREDENTIALS_STORE=pass proton-drive auth login'

# First time only: accept the share invitation
sudo -H bash -c 'cd /root && PROTON_DRIVE_CREDENTIALS_STORE=pass proton-drive invitation list'
sudo -H bash -c 'cd /root && PROTON_DRIVE_CREDENTIALS_STORE=pass proton-drive invitation accept <id>'

systemd unit essentials

[Service]
Type=oneshot
Environment=PROTON_DRIVE_CREDENTIALS_STORE=pass
Environment=HOME=/root
WorkingDirectory=/root
ExecStart=/usr/local/sbin/offsite-upload.sh

HOME and WorkingDirectory are required. proton-drive spawns pass from its current working directory, and the run fails with EACCES if that directory is not readable by the user.

Upload, prune, restore

export PROTON_DRIVE_CREDENTIALS_STORE=pass
proton-drive filesystem upload -f skip ./world-20261002-032715.tar.gz /shared-with-me/homelab/minecraft/
proton-drive filesystem list /shared-with-me/homelab/minecraft
proton-drive filesystem trash /shared-with-me/homelab/minecraft/world-20260901-031500.tar.gz
proton-drive filesystem download -f remove /shared-with-me/homelab/minecraft/<archive> /tmp

Purging the owner’s trash

The trash belongs to the owner, so the purge has to run with the owner’s session. Run it on a private host with no public services. Rules that keep it from destroying personal data:

Throughput (measured)

Not working / rejected

Failure visibility

An expired or revoked session is not silent only if you make it loud. Here the uploader touches a stamp file after each successful upload, and the service’s update job refuses to run when the stamp is stale (see Gate automatic updates on backup freshness). The CLI’s session lifetime was not documented at the time of writing.

Search terms

  • proton-drive auth login
  • PROTON_DRIVE_CREDENTIALS_STORE=pass
  • EACCES
  • Trashed node not found
  • Wrong key usage
  • rclone protondrive

Written and verified by Gyuwon Seol (seolcu). If this page solved your problem, you can support the work.

Published 2026-11-09 · last changed 2026-11-09 · Markdown source