Version: 2026-07-08 Server timezone: Europe/Vilnius ## 0. Goal This manual describes how to back up a Docker-based Calibre-Web installation from an Ubuntu VPS to pCloud using rclone. It includes: - rclone installation on Windows, Linux and macOS; - pCloud authentication from Windows for a headless Linux VPS; - server validation commands; - production backup script; - validation script; - restore script; - daily cron schedule; - troubleshooting. ## 1. Verified environment from this server The real server configuration found during our work: ```text Container: calibre-web Docker image: lscr.io/linuxserver/calibre-web:latest Library host path: /root/calibre-library Library path inside container: /books Calibre-Web config host path: /root/calibre-web/data Config path inside container: /config Published port: 8095 -> 8083 Restart policy: unless-stopped ``` Back up BOTH folders: ```text /root/calibre-library /root/calibre-web/data ``` The library contains books and `metadata.db`. The config directory contains Calibre-Web settings, users and application data. ## 2. Target pCloud structure ```text Backups/ Calibre/ library/ config/ versions/ ``` `library` and `config` are current mirrors. `versions` stores changed/deleted files from previous backups. ## 3. Install rclone on Windows ### Option A: download manually 1. Open the official rclone download page: https://rclone.org/downloads/ 2. Download the Windows AMD64 ZIP. 3. Extract it, for example to: ```powershell C:\Tools clone ``` 4. Add this folder to the Windows PATH, or run rclone using the full path: ```powershell C:\Tools clone clone.exe version ``` ### Option B: install with Chocolatey ```powershell choco install rclone rclone version ``` ### Option C: install with Scoop ```powershell scoop install rclone rclone version ``` Windows is needed mainly for browser-based pCloud authorization when the VPS has no browser. ## 4. Install rclone on Linux / Ubuntu VPS Recommended official install method: ```bash sudo -v curl https://rclone.org/install.sh | sudo bash rclone version ``` Alternative using apt, usually older: ```bash sudo apt update sudo apt install rclone -y rclone version ``` ## 5. Install rclone on macOS Using the official script: ```bash sudo -v curl https://rclone.org/install.sh | sudo bash rclone version ``` Using Homebrew: ```bash brew install rclone rclone version ``` ## 6. Configure pCloud remote on headless VPS using Windows browser On the VPS run: ```bash rclone config ``` Choose: ```text n) New remote name> pcloud Storage> pcloud client_id> [press Enter] client_secret> [press Enter] Edit advanced config? n Use web browser to automatically authenticate rclone with remote? n ``` rclone will print a command similar to: ```bash rclone authorize "pcloud" ``` On Windows PowerShell run the command exactly as shown by the VPS: ```powershell rclone authorize "pcloud" ``` A browser opens. Log in to pCloud and authorize rclone. PowerShell will print a large JSON token. Copy the entire JSON token and paste it into the VPS prompt. Validate on the VPS: ```bash rclone listremotes rclone lsd pcloud: ``` Expected result: ```text pcloud: ``` and a list of pCloud folders. ## 7. Validate Docker and Calibre-Web paths on the VPS Check running containers: ```bash docker ps ``` Check all containers, including stopped: ```bash docker ps -a | grep -i calibre ``` Check container mounts: ```bash docker inspect calibre-web --format '{{range .Mounts}}{{println .Source "->" .Destination}}{{end}}' ``` Expected: ```text /root/calibre-library -> /books /root/calibre-web/data -> /config ``` Check library file: ```bash ls -lah /root/calibre-library/metadata.db ``` Check config folder: ```bash ls -lah /root/calibre-web/data ``` ## 8. Create backup script on the VPS Create the script: ```bash sudo nano /usr/local/bin/backup-calibre-pcloud.sh ``` Paste this: ```bash #!/usr/bin/env bash set -euo pipefail # ========================================================== # Calibre-Web -> pCloud backup via rclone # Server: Ubuntu VPS # Container: calibre-web # Library: /root/calibre-library # Config: /root/calibre-web/data # ========================================================== SOURCE_LIBRARY="/root/calibre-library" SOURCE_CONFIG="/root/calibre-web/data" REMOTE_LIBRARY="pcloud:Backups/Calibre/library" REMOTE_CONFIG="pcloud:Backups/Calibre/config" REMOTE_VERSIONS="pcloud:Backups/Calibre/versions/$(date +%F_%H-%M-%S)" CONTAINER="calibre-web" LOG="/var/log/calibre-pcloud-backup.log" LOCK="/tmp/calibre-pcloud-backup.lock" exec 9>"$LOCK" if ! flock -n 9; then echo "$(date '+%F %T') ERROR: backup already running" >> "$LOG" exit 1 fi START_AGAIN=false finish() { local exit_code=$? if [ "$START_AGAIN" = true ]; then if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER}quot;; then echo "$(date '+%F %T') Starting container after backup/error: $CONTAINER" >> "$LOG" docker start "$CONTAINER" >> "$LOG" 2>&1 || true fi fi if [ $exit_code -eq 0 ]; then echo "$(date '+%F %T') Backup finished successfully" >> "$LOG" else echo "$(date '+%F %T') ERROR: backup failed with exit code $exit_code" >> "$LOG" fi echo "==================================================" >> "$LOG" echo "" >> "$LOG" exit $exit_code } trap finish EXIT echo "==================================================" >> "$LOG" echo "$(date '+%F %T') Backup started" >> "$LOG" # Basic checks command -v rclone >/dev/null 2>&1 || { echo "ERROR: rclone not installed" >> "$LOG"; exit 1; } command -v docker >/dev/null 2>&1 || { echo "ERROR: docker not installed" >> "$LOG"; exit 1; } rclone listremotes | grep -q '^pcloud: || { echo "ERROR: rclone remote pcloud: not found" >> "$LOG" exit 1 } [ -f "$SOURCE_LIBRARY/metadata.db" ] || { echo "ERROR: Calibre metadata.db not found in $SOURCE_LIBRARY" >> "$LOG" exit 1 } [ -d "$SOURCE_CONFIG" ] || { echo "ERROR: Calibre-Web config folder not found: $SOURCE_CONFIG" >> "$LOG" exit 1 } # Check pCloud access rclone lsd pcloud: >> "$LOG" 2>&1 # Stop Calibre-Web for a consistent SQLite metadata.db backup if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER}quot;; then echo "$(date '+%F %T') Stopping container: $CONTAINER" >> "$LOG" docker stop "$CONTAINER" >> "$LOG" 2>&1 START_AGAIN=true else echo "$(date '+%F %T') Container $CONTAINER is not running" >> "$LOG" fi # Backup library rclone sync "$SOURCE_LIBRARY" "$REMOTE_LIBRARY" \ --backup-dir "$REMOTE_VERSIONS/library" \ --create-empty-src-dirs \ --fast-list \ --transfers 4 \ --checkers 8 \ --retries 3 \ --low-level-retries 10 \ --stats 1m \ --log-file "$LOG" \ --log-level INFO # Backup Calibre-Web configuration rclone sync "$SOURCE_CONFIG" "$REMOTE_CONFIG" \ --backup-dir "$REMOTE_VERSIONS/config" \ --create-empty-src-dirs \ --fast-list \ --transfers 4 \ --checkers 8 \ --retries 3 \ --low-level-retries 10 \ --stats 1m \ --log-file "$LOG" \ --log-level INFO ``` Make it executable: ```bash sudo chmod +x /usr/local/bin/backup-calibre-pcloud.sh ``` ## 9. First manual backup test Run: ```bash sudo /usr/local/bin/backup-calibre-pcloud.sh ``` Read the log: ```bash tail -n 120 /var/log/calibre-pcloud-backup.log ``` Validate pCloud content: ```bash rclone lsd pcloud:Backups/Calibre rclone lsd pcloud:Backups/Calibre/library rclone lsd pcloud:Backups/Calibre/config rclone ls pcloud:Backups/Calibre/library/metadata.db ``` Check that the container is running again: ```bash docker ps | grep calibre-web ``` ## 10. Create validation script Create: ```bash sudo nano /usr/local/bin/check-calibre-pcloud-backup.sh ``` Paste: ```bash #!/usr/bin/env bash set -euo pipefail echo "1) Local Calibre library metadata.db" ls -lah /root/calibre-library/metadata.db echo echo "2) Local Calibre-Web config folder" ls -lah /root/calibre-web/data | head -n 30 echo echo "3) rclone remotes" rclone listremotes echo echo "4) pCloud root access" rclone lsd pcloud: echo echo "5) pCloud Calibre backup folders" rclone lsd pcloud:Backups/Calibre echo echo "6) metadata.db in pCloud backup" rclone ls pcloud:Backups/Calibre/library/metadata.db echo echo "7) Latest version folders" rclone lsd pcloud:Backups/Calibre/versions | tail -n 20 echo echo "8) Last backup log lines" tail -n 80 /var/log/calibre-pcloud-backup.log echo echo "Validation completed." ``` Make executable: ```bash sudo chmod +x /usr/local/bin/check-calibre-pcloud-backup.sh ``` Run: ```bash sudo /usr/local/bin/check-calibre-pcloud-backup.sh ``` ## 11. Configure daily cron backup Open root crontab: ```bash sudo crontab -e ``` Add this line: ```cron 30 3 * * * /usr/local/bin/backup-calibre-pcloud.sh ``` This runs every day at 03:30 server time. Validate cron: ```bash sudo crontab -l ``` Check after the next scheduled run: ```bash tail -n 120 /var/log/calibre-pcloud-backup.log ``` ## 12. Create restore script Create: ```bash sudo nano /usr/local/bin/restore-calibre-from-pcloud.sh ``` Paste: ```bash #!/usr/bin/env bash set -euo pipefail REMOTE_LIBRARY="pcloud:Backups/Calibre/library" REMOTE_CONFIG="pcloud:Backups/Calibre/config" TARGET_LIBRARY="/root/calibre-library" TARGET_CONFIG="/root/calibre-web/data" CONTAINER="calibre-web" SAFETY_DIR="/root/calibre-restore-safety" STAMP="$(date +%F_%H-%M-%S)" cat <<EOF WARNING: This will restore Calibre library and Calibre-Web config from pCloud. Local folders will be replaced by remote backup data: $TARGET_LIBRARY $TARGET_CONFIG A local safety archive will be created in: $SAFETY_DIR EOF read -rp "Type RESTORE to continue: " CONFIRM if [ "$CONFIRM" != "RESTORE" ]; then echo "Cancelled." exit 1 fi command -v rclone >/dev/null 2>&1 || { echo "ERROR: rclone not installed"; exit 1; } command -v docker >/dev/null 2>&1 || { echo "ERROR: docker not installed"; exit 1; } rclone lsd pcloud:Backups/Calibre >/dev/null mkdir -p "$SAFETY_DIR" echo "Stopping container if running..." docker stop "$CONTAINER" || true echo "Creating local safety archive..." tar -czf "$SAFETY_DIR/calibre-before-restore-$STAMP.tar.gz" \ "$TARGET_LIBRARY" "$TARGET_CONFIG" echo "Restoring library..." rclone sync "$REMOTE_LIBRARY" "$TARGET_LIBRARY" \ --create-empty-src-dirs \ --transfers 4 \ --checkers 8 \ --progress echo "Restoring config..." rclone sync "$REMOTE_CONFIG" "$TARGET_CONFIG" \ --create-empty-src-dirs \ --transfers 4 \ --checkers 8 \ --progress echo "Starting container..." docker start "$CONTAINER" echo "Restore finished. Open Calibre-Web and validate the library." ``` Make executable: ```bash sudo chmod +x /usr/local/bin/restore-calibre-from-pcloud.sh ``` Run only when restore is needed: ```bash sudo /usr/local/bin/restore-calibre-from-pcloud.sh ``` The script asks you to type `RESTORE` before it changes anything. ## 13. Manual restore without script Stop container: ```bash docker stop calibre-web ``` Create local safety archive: ```bash mkdir -p /root/calibre-restore-safety tar -czf /root/calibre-restore-safety/calibre-before-restore-$(date +%F_%H-%M-%S).tar.gz /root/calibre-library /root/calibre-web/data ``` Restore from pCloud: ```bash rclone sync pcloud:Backups/Calibre/library /root/calibre-library --create-empty-src-dirs --transfers 4 --checkers 8 --progress rclone sync pcloud:Backups/Calibre/config /root/calibre-web/data --create-empty-src-dirs --transfers 4 --checkers 8 --progress ``` Start container: ```bash docker start calibre-web ``` Open Calibre-Web: ```text http://SERVER_IP:8095 ``` ## 14. Optional: dry-run before real sync For safety, test what rclone would do: ```bash rclone sync /root/calibre-library pcloud:Backups/Calibre/library --backup-dir pcloud:Backups/Calibre/versions/test/library --dry-run ``` No files are changed with `--dry-run`. ## 15. Optional: encrypted backup with rclone crypt If you do not want pCloud to see filenames or content, create an encrypted rclone remote over pCloud. Run: ```bash rclone config ``` Choose: ```text n) New remote name> pcloudcrypt Storage> crypt remote> pcloud:Encrypted/Calibre filename_encryption> standard directory_name_encryption> true password> [generate or enter strong password] password2> [optional salt password] ``` Then replace in scripts: ```bash pcloud:Backups/Calibre ``` with: ```bash pcloudcrypt:Backups/Calibre ``` Important: save the crypt passwords offline. Without them you cannot restore. ## 16. Troubleshooting ### Error: config file not found / didn't find section pcloud Problem: pCloud remote is not configured. Fix: ```bash rclone config rclone listremotes rclone lsd pcloud: ``` ### Error: metadata.db not found Check actual library location: ```bash find / -name metadata.db 2>/dev/null ``` For your server the correct path is: ```text /root/calibre-library/metadata.db ``` ### Container does not start after backup Run: ```bash docker start calibre-web docker logs --tail=100 calibre-web ``` ### pCloud upload is slow Reduce transfers: ```bash --transfers 2 --checkers 4 ``` or limit bandwidth: ```bash --bwlimit 5M ``` ### Cron did not run Check crontab: ```bash sudo crontab -l ``` Check cron service: ```bash systemctl status cron ``` Check backup log: ```bash tail -n 120 /var/log/calibre-pcloud-backup.log ``` ## 17. Daily routine Normally nothing is needed. Once in a while run: ```bash sudo /usr/local/bin/check-calibre-pcloud-backup.sh ``` ## 18. Important final notes - Use `sync` only because `--backup-dir` is enabled. Deleted or changed files are moved to version folders. - Back up both library and config. - Do not edit `metadata.db` manually. - Keep the pCloud/rclone token secure. - If using `crypt`, keep the crypt passwords somewhere safe. ## 19. Official references - rclone home: https://rclone.org/ - rclone install: https://rclone.org/install/ - rclone documentation: https://rclone.org/docs/ - rclone pCloud backend: https://rclone.org/pcloud/