Skip to content

Backing up and restoring Rhinvoice

5 min read

Rhinvoice backs up its whole database with restic: encrypted, deduplicated and compressed, daily and shortly after every issued or cancelled document, to a target you choose (S3, SFTP, Dropbox, Google Drive or a folder). The database holds everything: customers, articles, documents, the archived PDFs of issued documents, the logo and the settings.

  • When: daily (02:00 by default, BACKUP_DAILY_AT) and about two minutes after documents were issued or cancelled (several in a row give one backup). Settings → Backup → Back up now asks for one at once.
  • Kept: 7 daily, 4 weekly, 12 monthly and every yearly backup. Invoices must be kept for ten years (Art. 958f CO, GoBD, BAO); yearly backups are never deleted. Old backups are removed on Sundays, when a sample of 5 % of the data is also verified.
  • Not backed up: an installation without company data (a fresh one). Its empty database must never become the latest backup.
  • Shown: the overview warns when the last successful backup is older than 24 hours or backups are not set up. Settings → Backup lists the last backups.

Choose a target and write it to .env (next to compose.yml), then restart with docker compose up -d.

RESTIC_PASSWORD='a-long-random-password' # encrypts the backups
RESTIC_REPOSITORY=... # see below

Backblaze B2, Infomaniak Swiss Backup, AWS, Wasabi and others:

RESTIC_REPOSITORY=s3:https://s3.eu-central-003.backblazeb2.com/my-bucket/rhinvoice
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...

Use a key that may only access this bucket.

RESTIC_REPOSITORY=sftp:backup@nas.example:/backups/rhinvoice

The container needs the SSH key and the server’s host key (known_hosts). Mount them, e.g. in a compose.override.yml:

services:
backup:
volumes:
- ./ssh:/home/backup/.ssh:ro # id_ed25519 and known_hosts
Terminal window
ssh-keyscan nas.example > ssh/known_hosts
sudo chown -R 10001 ssh && chmod 700 ssh && chmod 600 ssh/id_ed25519 # the container's user

Dropbox, Google Drive and other cloud storage

Section titled “Dropbox, Google Drive and other cloud storage”

restic reaches them through rclone, which is part of the backup container. The first backup holds every archived PDF; later ones add only what changed, usually a few kilobytes.

  1. Allow access, once, on a computer with a web browser (it does not need to be the server): install rclone 1.75 or newer (rclone.org/downloads, on a Mac brew install rclone) and run

    Terminal window
    rclone authorize "dropbox"

    Log in to Dropbox in the browser that opens and allow access. The terminal then prints a token: one line starting with {"access_token":.

  2. Hand the token to the backup container, on the server, in the Rhinvoice folder. read keeps the token out of the screen and the shell history:

    Terminal window
    read -rs TOKEN # paste the token, press Enter
    docker compose run --rm --no-deps backup rclone config create dropbox dropbox \
    config_refresh_token false token "$TOKEN"
    unset TOKEN

    The configuration is kept, unencrypted, in the volume backup-rclone; rclone renews the access there by itself.

  3. Choose the folder in .env and restart (docker compose up -d):

    RESTIC_REPOSITORY=rclone:dropbox:Rhinvoice-Backup
  4. Try it: docker compose exec backup rhinvoice-backup backup. The folder Rhinvoice-Backup appears in your Dropbox; Settings → Backup shows the backup.

rclone’s own Dropbox app may access your whole Dropbox. For access to one folder only, create your own Dropbox app with “App folder” access (rclone.org/dropbox) and add its client_id and client_secret to both commands.

Google Drive works the same. Ask only for access to the files rclone creates itself (the scope must be chosen when authorizing):

Terminal window
rclone authorize "drive" --drive-scope drive.file
Terminal window
read -rs TOKEN
docker compose run --rm --no-deps backup rclone config create gdrive drive \
scope drive.file config_refresh_token false token "$TOKEN"
unset TOKEN

and RESTIC_REPOSITORY=rclone:gdrive:Rhinvoice-Backup.

For other providers (OneDrive, kDrive and other WebDAV storage) run docker compose run --rm --no-deps backup rclone config, answer “No” when asked whether to use a web browser automatically and follow the rclone documentation of the provider. Name the remote as you like and use it in RESTIC_REPOSITORY=rclone:<name>:<folder>.

An iCloud or Nextcloud folder, the Dropbox app’s folder or a USB disk:

RESTIC_REPOSITORY=/repository
BACKUP_LOCAL_DIR=/Users/me/Library/Mobile Documents/com~apple~CloudDocs/Rhinvoice-Backup

The container writes as user 10001; on Linux make the folder writable for it (sudo chown 10001 /path/to/folder). Without BACKUP_LOCAL_DIR the backups land in a Docker volume on the same disk: that protects against mistakes, not against a broken disk.

Terminal window
docker compose logs backup # what the container does
docker compose exec backup rhinvoice-backup snapshots # list the backups
docker compose exec backup rhinvoice-backup check # verify the repository
docker compose exec backup rhinvoice-backup backup # back up now
docker compose exec backup rhinvoice-backup rclone lsd dropbox: # an rclone target is reachable

Restoring replaces the whole database with the state of a backup. It runs in one transaction: if anything fails, nothing changes.

Terminal window
docker compose exec backup rhinvoice-backup snapshots # pick a snapshot ID
docker compose stop app backup
docker compose run --rm --no-deps backup restore latest # or the ID, e.g. 52365e00
docker compose start app backup

From the source folder: make restore SNAPSHOT=latest.

On a new machine: install Rhinvoice as in Installation with the same RESTIC_REPOSITORY and RESTIC_PASSWORD. Start only the database first (docker compose up -d db), then restore as above and start everything (docker compose up -d).

How often does Rhinvoice back up?

Daily, at 02:00 by default, and about two minutes after documents were issued or cancelled. Settings, Backup, Back up now asks for one at once.

How long are backups kept?

7 daily, 4 weekly, 12 monthly and every yearly backup. Yearly backups are never deleted, because invoices must be kept for ten years.

Can Rhinvoice back up to Dropbox or Google Drive?

Yes, through rclone, which is part of the backup container. The backups are encrypted before they leave the machine, so the cloud provider only stores unreadable blocks.

What happens if I lose the backup password?

Then nobody can restore the backups, not even you. Keep RESTIC_PASSWORD somewhere else too, for example in a password manager or printed in a safe.