5 Backup/Google Drive
Stefano Pigozzi edited this page 2025-10-21 03:53:00 +02:00

First time setup

  1. Create a new directory somewhere on your system to use to store data related to GA Backup; it can be anywhere, but for the purposes of this guide, it'll be referred to as $ga_config_dir, and will be located in /srv/docker/ga_backup:

    ga_config_dir="/srv/docker/ga_backup"
    mkdir --verbose --parents "$ga_config_dir"
    
  2. Create a directory for storing secrets, and make sure you're the only user with access to it:

    mkdir --verbose --parents "$ga_config_dir/secrets"
    chmod go-rwx "$ga_config_dir/secrets"
    
  3. Generate the encryption password and store it in the secrets directory as a file with the name of ga_passphrase.txt:

    cat "/dev/urandom" | LC_ALL="C" tr --delete --complement '[:graph:]' | head --bytes 32 > "$ga_config_dir/secrets/ga_passphrase.txt"
    
  4. Use the Google Cloud Console to create new OAuth credentials for a Desktop Application, then download the resulting JSON credential file and move it inside the secrets directory with the name ga_gdrive_client_secret.json:

    # Example. Source file location might vary depending on your system.
    mv --verbose ./client_secret* "$ga_config_dir/secrets/ga_gdrive_client_secret.json"
    
  5. Create a new Docker volume with the name ga_cache, which will be used to temporarily store previous backups in a series:

    docker volume create "ga_cache"
    
  6. Create a new Docker volume with the name ga_credentials, which will be use to store Google Drive API credentials:

    docker volume create "ga_credentials"
    
  7. Open the ga_gdrive_client_secret.json and copy somewhere the value of .installed.client_id; let's call this $ga_gdrive_client_id:

    {
        "installed": {
            "client_id": "641079776729-da3fi7a2kgk5jkutsjdcnhugqolu40mo.apps.googleusercontent.com",
            //            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            //                                         copy this part                             
            // [...]
        }
    }
    
  8. Find in your browser the Google Drive directory you want to store backups in, open it, and copy the final part of the URL; let's call this $ga_gdrive_directory:

    https://drive.google.com/drive/u/0/folders/1_AAAAAAAAAA-BBBBBBBBBBBBBBBBBBBB
                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                                         copy this part         
    
  9. Create a compose.include.yml file in the $ga_config_dir directory with the following contents, taking care to manually replace $ga_gdrive_client_id and $ga_gdrive_directory with the values you've acquired in the previous steps:

    # Must be volumes to be able to import this from other compose files
    volumes:
        ga_credentials:
            name: &ga_credentials "ga_credentials"
            external: true
        ga_cache:
            name: &ga_cache "ga_cache"
            external: true
    
    # Since they are sensitive files, they should be secrets
    secrets:
        ga_passphrase:
            name: &ga_passphrase "ga_passphrase"
            file: "./secrets/ga_passphrase.txt"
        ga_gdrive_client_secret:
            name: &ga_gdrive_client_secret "ga_gdrive_client_secret"
            file: "./secrets/ga_gdrive_client_secret.json"
    
    services:
        # The backup utility itself
        ga:
            image: "forge.steffo.eu/steffo/ga-backup:latest"
            restart: unless-stopped
    
            network_mode: host
    
            stdin_open: true
            tty: true
    
            volumes:
            - # Mount the credentials volume
                type: volume
                source: *ga_credentials
                target: "/var/lib/duplicity"
            - # Mount the cache volume
                type: volume
                source: *ga_cache
                target: "/usr/lib/duplicity/.cache/duplicity"
            - # Mount the current working directory to backup it.
                # Note that this breaks if launching the compose project from outside the working directory.
                type: bind
                source: "${PWD}"
                target: "/mnt"
    
            secrets:
            - 
                source: *ga_passphrase
            - 
                source: *ga_gdrive_client_secret
    
            environment:
            MODE: "backup"
            DUPLICITY_TARGET_URL: "gdrive://$ga_gdrive_client_id/${COMPOSE_PROJECT_NAME}?myDriveFolderID=$ga_gdrive_directory"
            DUPLICITY_PASSPHRASE_FILE: "/run/secrets/ga_passphrase"
            GOOGLE_CLIENT_SECRET_JSON_FILE: "/run/secrets/ga_gdrive_client_secret"
            GOOGLE_CREDENTIALS_FILE: "/var/lib/duplicity/google_credentials"
            GOOGLE_OAUTH_LOCAL_SERVER_HOST: "localhost"
            GOOGLE_OAUTH_LOCAL_SERVER_PORT: "8080"
    
  10. Briefly launch a shell in the container:

    docker compose run --interactive --rm --entrypoint=sh ga
    
  11. Pretend to launch a backup to trigger the Google Drive authentication flow, then complete the authentication and immediately terminate the shell:

    /etc/periodic/daily/backup.sh
    
    Please visit this URL to authorize this application: https://accounts.google.com/o/oauth2/auth
    

    Note

    For authentication to work correctly after Google's removal of the OOB Flow, your http://localhost:8080 address might be required to match the http://localhost:8080 of the GA Backup container.

    This is not an issue if you can launch a browser on the same machine you're configuring GA Backup on, but it might be troublesome for non-graphical servers, where this is not possible.

    To bypass the issue, you can temporarily set up an SSH tunnel towards the server for the duration of the setup process:

    ssh -L 8080:8080 yourserver
    
  12. You should be done! Make sure backups are appearing in the Google Drive directory you've configured.

Backing up Compose project directories

Tip

The basic idea is to store all files related to a project in the directory containing compose.yml, then backing that up.

  1. Add the following to your compose.yml file:

    include:
    - path: "/srv/docker/realms_duplicity/compose.include.yml"
    
  2. Take up the project:

    docker compose up
    

    Warning

    For the backup to work properly, you MUST be in the directory of the project to backup when running the command.