<pre style="background-color:#ffffff;">
<span style="color:#63a35c;">version</span><span style="color:#323232;">: </span><span style="color:#183691;">"1"
</span><span style="color:#323232;">
</span><span style="font-style:italic;color:#969896;"># Schedules (https://www.freedesktop.org/software/systemd/man/systemd.time.html#Calendar%20Events)
</span><span style="color:#323232;">{{ </span><span style="color:#183691;">$SCHEDULE_RESTIC_BACKUP := "*-*-* 22:00:00" </span><span style="color:#323232;">}} </span><span style="font-style:italic;color:#969896;"># Daily at 10PM
</span><span style="color:#323232;">{{ </span><span style="color:#183691;">$SCHEDULE_RESTIC_CHECK := "Sat *-*-* 04:00:00" </span><span style="color:#323232;">}} </span><span style="font-style:italic;color:#969896;"># Weekly at 4AM on Saturday
</span><span style="color:#323232;">{{ </span><span style="color:#183691;">$SCHEDULE_SYNC_BACKUP := "Sun *-*-* 21:30:00" </span><span style="color:#323232;">}} </span><span style="font-style:italic;color:#969896;"># Weekly at 11.30PM on Sunday
</span><span style="color:#323232;">{{ </span><span style="color:#183691;">$SCHEDULE_POSTGRES_BACKUP := "Fri *-*-* 20:00:00" </span><span style="color:#323232;">}} </span><span style="font-style:italic;color:#969896;"># Weekly at 8PM on Friday
</span><span style="color:#323232;">
</span><span style="font-style:italic;color:#969896;"># Directories
</span><span style="color:#323232;">{{ </span><span style="color:#183691;">$LOCATION_RESTIC_BINARY := "/home/deck/Desktop/.config/restic/bin/restic_0.15.2_linux_arm64" </span><span style="color:#323232;">}}
</span><span style="color:#323232;">{{ </span><span style="color:#183691;">$LOCATION_RESTIC_REPO := "/home/deck/Desktop/restic-repo" </span><span style="color:#323232;">}}
</span><span style="color:#323232;">{{ </span><span style="color:#183691;">$LOCATION_RESTIC_LOG := "/home/deck/Desktop/.config/restic/logs" </span><span style="color:#323232;">}}
</span><span style="color:#323232;">{{ </span><span style="color:#183691;">$LOCATION_RESTIC_STATUS := "/home/deck/Desktop/.config/restic/logs/statuses" </span><span style="color:#323232;">}}
</span><span style="color:#323232;">{{ </span><span style="color:#183691;">$LOCATION_RESTIC_BLOCKED_FILE := "/home/deck/Desktop/.config/restic/BLOCKED" </span><span style="color:#323232;">}}
</span><span style="color:#323232;">{{ </span><span style="color:#183691;">$LOCATION_RCLONE_BINARY := "/home/deck/Desktop/.config/restic/bin/rclone_1.63.1_linux_arm64" </span><span style="color:#323232;">}}
</span><span style="color:#323232;">{{ </span><span style="color:#183691;">$LOCATION_RCLONE_REPO := "bucket:restic-backup-12345" </span><span style="color:#323232;">}}
</span><span style="color:#323232;">{{ </span><span style="color:#183691;">$LOCATION_RCLONE_CONFIG := "/home/deck/Desktop/.config/restic/config/rclone.conf" </span><span style="color:#323232;">}}
</span><span style="color:#323232;">{{ </span><span style="color:#183691;">$LOCATION_RESTICPROFILE_LOCK := "/tmp/resticprofile-default.lock" </span><span style="color:#323232;">}}
</span><span style="color:#323232;">{{ </span><span style="color:#183691;">$LOCATION_POSTGRES_DUMP := "/home/deck/Desktop/dumps" </span><span style="color:#323232;">}}
</span><span style="color:#323232;">{{ </span><span style="color:#183691;">$LOCATION_PRIMARY_BACKUP_SOURCE := "/home/deck/Desktop/" </span><span style="color:#323232;">}}
</span><span style="color:#323232;">
</span><span style="font-style:italic;color:#969896;"># Configs
</span><span style="color:#323232;">{{ </span><span style="color:#183691;">$CONFIG_CURRENT_TIME := .Now.Format "20060102T150405" </span><span style="color:#323232;">}}
</span><span style="color:#323232;">{{ </span><span style="color:#183691;">$CONFIG_RESTIC_PASSWORD := "/home/deck/Desktop/.config/restic/config/password.txt" </span><span style="color:#323232;">}}
</span><span style="color:#323232;">{{ </span><span style="color:#183691;">$CONFIG_RESTIC_EXCLUDE := "/home/deck/Desktop/.config/restic/excludes.txt" </span><span style="color:#323232;">}}
</span><span style="color:#323232;">
</span><span style="color:#63a35c;">global</span><span style="color:#323232;">:
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">default-command</span><span style="color:#323232;">: </span><span style="color:#183691;">snapshots </span><span style="font-style:italic;color:#969896;"># Run 'snapshots' when no command is specified
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">initialize</span><span style="color:#323232;">: </span><span style="color:#0086b3;">false </span><span style="font-style:italic;color:#969896;"># Do not initialize a repository if none exists
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">priority</span><span style="color:#323232;">: </span><span style="color:#183691;">low </span><span style="font-style:italic;color:#969896;"># Use priority class on Windows and "nice" on Unixes
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">min-memory</span><span style="color:#323232;">: </span><span style="color:#0086b3;">100 </span><span style="font-style:italic;color:#969896;"># Minimum required RAM for Resticprofile to start
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">restic-lock-retry-after</span><span style="color:#323232;">: </span><span style="color:#183691;">5m </span><span style="font-style:italic;color:#969896;"># Retry failed restic command acquisition every 5 minutes
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">restic-stale-lock-age</span><span style="color:#323232;">: </span><span style="color:#183691;">10h </span><span style="font-style:italic;color:#969896;"># Unlock stale lock if age exceeds 10 hours
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">restic-binary</span><span style="color:#323232;">: </span><span style="color:#183691;">'{{ $LOCATION_RESTIC_BINARY }}' </span><span style="font-style:italic;color:#969896;"># Location of the Restic binary
</span><span style="color:#323232;">
</span><span style="color:#63a35c;">default</span><span style="color:#323232;">:
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">lock</span><span style="color:#323232;">: </span><span style="color:#183691;">'{{ $LOCATION_RESTICPROFILE_LOCK }}' </span><span style="font-style:italic;color:#969896;"># Local lockfile to prevent concurrent profile runs
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">force-inactive-lock</span><span style="color:#323232;">: </span><span style="color:#0086b3;">true </span><span style="font-style:italic;color:#969896;"># Detect and remove stale locks
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">initialize</span><span style="color:#323232;">: </span><span style="color:#0086b3;">true </span><span style="font-style:italic;color:#969896;"># Initialize repository if it doesn't exist
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">repository</span><span style="color:#323232;">: </span><span style="color:#183691;">'{{ $LOCATION_RESTIC_REPO }}' </span><span style="font-style:italic;color:#969896;"># Path to Restic repository
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">password-file</span><span style="color:#323232;">: </span><span style="color:#183691;">'{{ $CONFIG_RESTIC_PASSWORD }}' </span><span style="font-style:italic;color:#969896;"># File containing repository password
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">status-file</span><span style="color:#323232;">: </span><span style="color:#183691;">'{{ $LOCATION_RESTIC_STATUS }}/{{ $CONFIG_CURRENT_TIME }}-restic-status.json' </span><span style="font-style:italic;color:#969896;"># Output status file
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">compression</span><span style="color:#323232;">: </span><span style="color:#183691;">'max' </span><span style="font-style:italic;color:#969896;"># Maximum compression level
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">run-after-fail</span><span style="color:#323232;">: </span><span style="font-style:italic;color:#969896;"># Block syncing if there was a failure. TODO: Add an email
</span><span style="color:#323232;"> - </span><span style="color:#183691;">'echo "The command ${PROFILE_COMMAND} has failed in ${PROFILE_NAME}. Please check the logs." > {{ $LOCATION_RESTIC_BLOCKED_FILE }}'
</span><span style="color:#323232;">
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">backup</span><span style="color:#323232;">:
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">run-before</span><span style="color:#323232;">: </span><span style="font-style:italic;color:#969896;"># Bring down Docker before backup
</span><span style="color:#323232;"> - </span><span style="color:#183691;">'systemctl stop docker.socket'
</span><span style="color:#323232;"> - </span><span style="color:#183691;">'systemctl stop docker'
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">run-finally</span><span style="color:#323232;">:
</span><span style="color:#323232;"> - </span><span style="color:#183691;">'grep --invert-match -E "^unchanged|(0 B added, 0 B stored)|(0 B added)" {{ tempFile "backup.log" }} > {{ $LOCATION_RESTIC_LOG }}/{{ $CONFIG_CURRENT_TIME }}-restic-backup.log' </span><span style="font-style:italic;color:#969896;"># Copy log file, stripping out any unchanced files
</span><span style="color:#323232;"> - </span><span style="color:#183691;">'systemctl start docker' </span><span style="font-style:italic;color:#969896;"># Bring Docker back online after backup
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">one-file-system</span><span style="color:#323232;">: </span><span style="color:#0086b3;">false </span><span style="font-style:italic;color:#969896;"># Exclude other file systems
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">no-error-on-warning</span><span style="color:#323232;">: </span><span style="color:#0086b3;">true </span><span style="font-style:italic;color:#969896;"># Don't consider warnings as backup failures
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">source</span><span style="color:#323232;">: </span><span style="font-style:italic;color:#969896;"># Directories to back up
</span><span style="color:#323232;"> - </span><span style="color:#183691;">'{{ $LOCATION_PRIMARY_BACKUP_SOURCE }}'
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">exclude-file</span><span style="color:#323232;">: </span><span style="color:#183691;">'{{ $CONFIG_RESTIC_EXCLUDE }}' </span><span style="font-style:italic;color:#969896;"># File containing exclude patterns
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">exclude-caches</span><span style="color:#323232;">: </span><span style="color:#0086b3;">true </span><span style="font-style:italic;color:#969896;"># Exclude cache files
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">schedule</span><span style="color:#323232;">: </span><span style="color:#183691;">'{{ $SCHEDULE_RESTIC_BACKUP }}' </span><span style="font-style:italic;color:#969896;"># Backup schedule
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">schedule-permission</span><span style="color:#323232;">: </span><span style="color:#183691;">system </span><span style="font-style:italic;color:#969896;"># Schedule permission
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">schedule-lock-wait</span><span style="color:#323232;">: </span><span style="color:#183691;">10m </span><span style="font-style:italic;color:#969896;"># Wait time for the lock during schedule
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">schedule-log</span><span style="color:#323232;">: </span><span style="color:#183691;">'{{ tempFile "backup.log" }}' </span><span style="font-style:italic;color:#969896;"># Log file to /tmp. This contains all information, including unchanged files which we do not care about
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">verbose</span><span style="color:#323232;">: </span><span style="color:#0086b3;">2 </span><span style="font-style:italic;color:#969896;"># Log details about processed files
</span><span style="color:#323232;">
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">check</span><span style="color:#323232;">:
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">schedule</span><span style="color:#323232;">: </span><span style="color:#183691;">'{{ $SCHEDULE_RESTIC_CHECK }}' </span><span style="font-style:italic;color:#969896;"># Verification schedule
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">schedule-permission</span><span style="color:#323232;">: </span><span style="color:#183691;">system </span><span style="font-style:italic;color:#969896;"># Schedule permission
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">schedule-lock-wait</span><span style="color:#323232;">: </span><span style="color:#183691;">10m </span><span style="font-style:italic;color:#969896;"># Wait time for the lock during schedule
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">schedule-log</span><span style="color:#323232;">: </span><span style="color:#183691;">'{{ $LOCATION_RESTIC_LOG }}/{{ $CONFIG_CURRENT_TIME }}-restic-check.log' </span><span style="font-style:italic;color:#969896;"># Log file
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">read-data</span><span style="color:#323232;">: </span><span style="color:#0086b3;">true </span><span style="font-style:italic;color:#969896;"># Verify data during check
</span><span style="color:#323232;">
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">prune</span><span style="color:#323232;">:
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">dry-run</span><span style="color:#323232;">: </span><span style="color:#0086b3;">true </span><span style="font-style:italic;color:#969896;"># Only prune if safe to do so, change manually
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">repack-uncompressed</span><span style="color:#323232;">: </span><span style="color:#0086b3;">true </span><span style="font-style:italic;color:#969896;"># Repack all uncompressed data
</span><span style="color:#323232;">
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">forget</span><span style="color:#323232;">:
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">dry-run</span><span style="color:#323232;">: </span><span style="color:#0086b3;">true </span><span style="font-style:italic;color:#969896;"># Only forget if safe to do so, change manually
</span><span style="color:#323232;">
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">rewrite</span><span style="color:#323232;">:
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">dry-run</span><span style="color:#323232;">: </span><span style="color:#0086b3;">true </span><span style="font-style:italic;color:#969896;"># Only rewrite if safe to do so, change manually
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">forget</span><span style="color:#323232;">: </span><span style="color:#0086b3;">true </span><span style="font-style:italic;color:#969896;"># Remove original snapshots after creating new ones
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">exclude-file</span><span style="color:#323232;">: </span><span style="color:#183691;">'{{ $CONFIG_RESTIC_EXCLUDE }}' </span><span style="font-style:italic;color:#969896;"># File containing exclude patterns
</span><span style="color:#323232;">
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">mount</span><span style="color:#323232;">:
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">allow-other</span><span style="color:#323232;">: </span><span style="color:#0086b3;">true </span><span style="font-style:italic;color:#969896;"># Allow other users to access the mount point
</span><span style="color:#323232;">
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">rebuild-index</span><span style="color:#323232;">:
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">read-all-packs</span><span style="color:#323232;">: </span><span style="color:#0086b3;">true </span><span style="font-style:italic;color:#969896;"># Read all pack files to generate new index from scratch
</span><span style="color:#323232;">
</span><span style="font-style:italic;color:#969896;"># The following shell profiles are simply to run other shell scripts at a scheduled time
</span><span style="font-style:italic;color:#969896;"># We do not actually run the primary Restic commands listed, as we exit the process early
</span><span style="color:#323232;">
</span><span style="color:#63a35c;">shell-postgres</span><span style="color:#323232;">: </span><span style="font-style:italic;color:#969896;"># Profile to run shell scripts only. We exit the current process before Restic can run.
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">backup</span><span style="color:#323232;">:
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">schedule</span><span style="color:#323232;">: </span><span style="color:#183691;">'{{ $SCHEDULE_POSTGRES_BACKUP }}' </span><span style="font-style:italic;color:#969896;"># Postgres backup schedule
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">schedule-permission</span><span style="color:#323232;">: </span><span style="color:#183691;">system </span><span style="font-style:italic;color:#969896;"># Schedule permission
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">schedule-lock-mode</span><span style="color:#323232;">: </span><span style="color:#183691;">ignore </span><span style="font-style:italic;color:#969896;"># Ignore locks, if any
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">schedule-log</span><span style="color:#323232;">: </span><span style="color:#183691;">'{{ $LOCATION_RESTIC_LOG }}/{{ $CONFIG_CURRENT_TIME }}-postgres-backup.log' </span><span style="font-style:italic;color:#969896;"># Log file
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">dry-run</span><span style="color:#323232;">: </span><span style="color:#0086b3;">true </span><span style="font-style:italic;color:#969896;"># Don't write data
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">run-before</span><span style="color:#323232;">: </span><span style="font-style:italic;color:#969896;"># Dump postgres databases
</span><span style="color:#323232;"> - </span><span style="color:#183691;">'chmod 777 /var/run/docker.sock'
</span><span style="color:#323232;"> - </span><span style="color:#183691;">'docker exec -t immich-postgres pg_dumpall -c -U postgres | gzip > "{{ $LOCATION_POSTGRES_DUMP }}/immich-dump-{{ $CONFIG_CURRENT_TIME }}.sql.gz" && echo "Dumped Immich database: {{ $LOCATION_POSTGRES_DUMP }}/immich-dump-{{ $CONFIG_CURRENT_TIME }}.sql.gz"'
</span><span style="color:#323232;"> - </span><span style="color:#183691;">'docker exec -t joplin-postgres pg_dumpall -c -U joplin | gzip > "{{ $LOCATION_POSTGRES_DUMP }}/joplin-dump-{{ $CONFIG_CURRENT_TIME }}.sql.gz" && echo "Dumped Joplin database: {{ $LOCATION_POSTGRES_DUMP }}/joplin-dump-{{ $CONFIG_CURRENT_TIME }}.sql.gz"'
</span><span style="color:#323232;"> - </span><span style="color:#183691;">'kill $$'
</span><span style="color:#323232;">
</span><span style="color:#63a35c;">shell-sync</span><span style="color:#323232;">:
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">backup</span><span style="color:#323232;">:
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">schedule</span><span style="color:#323232;">: </span><span style="color:#183691;">'{{ $SCHEDULE_SYNC_BACKUP }}' </span><span style="font-style:italic;color:#969896;"># Sync backup schedule
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">schedule-permission</span><span style="color:#323232;">: </span><span style="color:#183691;">system </span><span style="font-style:italic;color:#969896;"># Schedule permission
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">schedule-lock-mode</span><span style="color:#323232;">: </span><span style="color:#183691;">ignore </span><span style="font-style:italic;color:#969896;"># Ignore locks, if any
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">schedule-log</span><span style="color:#323232;">: </span><span style="color:#183691;">'{{ $LOCATION_RESTIC_LOG }}/{{ $CONFIG_CURRENT_TIME }}-rsync-backup.log' </span><span style="font-style:italic;color:#969896;"># Log file
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">dry-run</span><span style="color:#323232;">: </span><span style="color:#0086b3;">true </span><span style="font-style:italic;color:#969896;"># Don't write data
</span><span style="color:#323232;"> </span><span style="color:#63a35c;">run-before</span><span style="color:#323232;">: </span><span style="font-style:italic;color:#969896;"># Sync the Restic repo, after checking if the repository is in good health
</span><span style="color:#323232;"> - </span><span style="color:#183691;">'if [ -f "{{ $LOCATION_RESTIC_BLOCKED_FILE }}" ]; then echo "There has been a problem with the Restic repository, please check the logs. If everything is okay, delete the BLOCKED file." && kill $$; fi'
</span><span style="color:#323232;"> - </span><span style="color:#183691;">'{{ $LOCATION_RCLONE_BINARY }} -v sync {{ $LOCATION_RESTIC_REPO }} {{ $LOCATION_RCLONE_REPO }} --config={{ $LOCATION_RCLONE_CONFIG }} --b2-hard-delete'
</span><span style="color:#323232;"> - </span><span style="color:#183691;">'{{ $LOCATION_RCLONE_BINARY }} cleanup {{ $LOCATION_RESTIC_REPO }} --config={{ $LOCATION_RCLONE_CONFIG }}'
</span><span style="color:#323232;"> - </span><span style="color:#183691;">'kill $$'
</span>
Resticprofile doesn’t let me run other shell commands on a schedule, and because I wanted everything in a single configuration, I just created two new profiles which call the backup command. I then made the shell commands run before Restic, and then finally killed the instance before it got to actually run, which effectively does what I needed.