Anexgohan

Backup Script for PBS

Aug 10th, 2025
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 10.05 KB | None | 0 0
  1. #!/bin/env bash
  2.  
  3. # This script is used to backup from Proxmox Virtual Environment (PVE) to the Proxmox Backup Server (PBS).
  4. # Can be run manually or scheduled using cron with no user input. Provides output to the terminal and logs to a file.
  5. # Must have a valid API token for the user on the Proxmox Backup Server (PBS) to run this script.
  6. # Avoid spaces in the names and paths and use full paths.
  7.  
  8. # =x=x=x=x=x=x=x=x=x=x= Configuration =x=x=x=x=x=x=x=x=x=x= #
  9. # ==================== Define variables (Edit Below) ==================== #
  10. DRY_RUN=false    # true/false, for testing purposes true (only logs will be generated), for production false (actual run)
  11. CLIENT_HOSTNAME="$(hostname)" # This automatically gets the hostname of the machine its running on, or replace with your own
  12. PBS_USER="<PBS_USER>"  # Replace with your PBS username, e.g. "root"
  13. PBS_TOKEN_NAME="<PBS_TOKEN_NAME>"  # Replace with your PBS token name, e.g. "pbs-token"
  14. PBS_NAMESPACE="${CLIENT_HOSTNAME}/node" # This should already exist in PBS, e.g. "pve-thor/node" or "pve-loki/backup", where "pve-thor" is the hostname of the PVE server and "node" is the sub-namespace.
  15. BACKUP_PATH="/"  # No trailing slash, use full path and no spaces in the path, eg "/home/user", ("/" is host backup), exclude mnt,etc below if needed.
  16.  
  17. # On Proxmox Backup Server UI, PBS>Datastore>"Show Connection Information"
  18. PBS_SERVER_IP="<PBS_SERVER_IP>"  # Replace with your PBS server IP address, e.g. "
  19. PBS_SERVER_PORT="8007"  # Default port is 8007
  20. PBS_DATASTORE="<pbs-datastore-name>"  # Replace with your PBS datastore name, e.g. "pbs-tank"
  21. PBS_FINGERPRINT="<PBS_FINGERPRINT_Long_String>"  # Replace with your PBS fingerprint, e.g. "A1:B2:C3:D4:E5:F6:G7:H8:I9:J0:K1:L2:M3:N4:O5:P6:Q7:R8:S9:T0:U1:V2:W3:X4:Y5:Z6"
  22. PBS_PASSWORD_FILE_LOCATION="/etc/pve/priv/storage/${PBS_DATASTORE}.pw" # "/path/to/key/.secrets/pbskey"
  23. # PBS_PASSWORD_FILE_LOCATION="/etc/pve/priv/storage/${PBS_DATASTORE}.pw"
  24. PATH_FOR_LOGS="/path/to/logs/pbs/${CLIENT_HOSTNAME}/${PBS_NAMESPACE}" # "/path/to/logs"
  25.  
  26. # if you want to force include a path, set the path below, else leave it empty,
  27. # separate multiple paths with a space, enclosed in single quotes:
  28. # DO NOT REMOVE THE DOUBLE QUOTES ""
  29. FORCE_INCLUDE_PATH="'/etc/pve' '/boot/efi'" # No trailing slash, use full path and no spaces in the path, e.g. "'/etc/pve' '/var/lib/vz'", pbs excludes /etc/pve and /boot by default, so you need to include them if you want to backup those directories.
  30. # ==================== End of Define variables ==================== #
  31. # =x=x=x=x=x=x=x=x=x=x= Configuration Complete (Do not Edit Below) =x=x=x=x=x=x=x=x=x=x= #
  32.  
  33. # ==================== Guides & Reading ==================== #
  34. # NOTE:
  35. # example of empty path and multiple paths respectively:
  36. # FORCE_INCLUDE_PATH=""
  37. # FORCE_INCLUDE_PATH="'/etc/pve' '/var/lib/vz'"
  38. # https://pbs.proxmox.com/docs/backup-client.html#creating-backups
  39.  
  40. # Links:
  41. # API Tokens:
  42. # https://pbs.proxmox.com/docs/user-management.html#api-tokens
  43. # generate token for user:
  44. # proxmox-backup-manager user generate-token <user> <token-name>
  45.  
  46. # Excluding Files/Directories from a Backup: (the .pxarexclude file)
  47. # https://pbs.proxmox.com/docs/backup-client.html#excluding-files-directories-from-a-backup
  48.  
  49. # the backup command syntax:
  50. # "proxmox-backup-client backup ${CLIENT_HOSTNAME}.pxar:${BACKUP_PATH} --ns ${PBS_NAMESPACE} --include-dev '/path/to/include'"
  51.  
  52. # Run the following commands in pbs shell to get the required information:
  53. # List Users:
  54. # proxmox-backup-manager user list
  55. # List Tokens:
  56. # proxmox-backup-manager user list-token <user>
  57. # Result <PBS_USER>@pbs!<PBS_TOKEN_NAME>
  58. # List Datastores:
  59. # proxmox-backup-manager datastore list
  60.  
  61.  
  62. # ==================== Start of Script (Do not Edit Below) ==================== #
  63. # ------------------- export PBS Environment Secrets: ------------------- #
  64. export PBS_PASSWORD_FILE=${PBS_PASSWORD_FILE_LOCATION}
  65. export PBS_FINGERPRINT=${PBS_FINGERPRINT}
  66. export PBS_REPOSITORY=${PBS_USER}@pbs!${PBS_TOKEN_NAME}@${PBS_SERVER_IP}:${PBS_SERVER_PORT}:${PBS_DATASTORE}
  67.  
  68. # Initialize the backup command
  69. PBS_BACKUP_COMMAND="proxmox-backup-client backup ${CLIENT_HOSTNAME}.pxar:${BACKUP_PATH} --ns ${PBS_NAMESPACE}"
  70.  
  71. # If FORCE_INCLUDE_PATH is not empty, add --include-dev for each path
  72. if [ -n "$FORCE_INCLUDE_PATH" ]; then
  73.     # Use eval to handle paths enclosed in quotes
  74.     eval "set -- $FORCE_INCLUDE_PATH"
  75.     for path in "$@"; do
  76.         PBS_BACKUP_COMMAND="${PBS_BACKUP_COMMAND} --include-dev ${path}"
  77.     done
  78. fi
  79.  
  80. # get the current date and time and store it
  81. date=$(date)
  82. # Get the current time zone in "Region/City" format
  83. current_time_zone=$(timedatectl show --property=Timezone --value)
  84. # get the current date and time in IST and store it, to use as filename for the log file
  85. date_Filename=$(TZ=${current_time_zone} date +'%Y-%m-%d_%I-%M-%S-%p')
  86. # get the current date and time in IST and store it, for display in terminal and printing to the log file
  87. start_date_formatted=$(TZ=${current_time_zone} date +'%Y-%m-%d | %I:%M:%S %p')
  88.  
  89. # ------------------- Set paths ------------------- #
  90. # format the variable PBS_NAMESPACE to replace "/" or any other symbols with "-"
  91. PBS_NAMESPACE_FORMATED=$(echo $PBS_NAMESPACE | sed 's/[/\|]/-/g')
  92. # create a variable for path to the log file
  93. log_file_path="${PATH_FOR_LOGS}/${date_Filename}_${PBS_NAMESPACE_FORMATED}.log"
  94. # Redirect stdout and stderr to tee
  95. exec > >(tee -a "$log_file_path") 2>&1
  96.  
  97. # ------------------- Functions ------------------- #
  98. # create a separator function to print a separator line, # Usage: log_separator
  99. log_separator() {
  100.     echo "========================================"
  101.     echo ""
  102. }
  103. # create a separator function to print a separator line, # Usage: single_separator
  104. single_separator() {
  105.     echo "========================================"
  106. }
  107. # create a smaller separator function to print a smaller separator line, # Usage: small_separator
  108. small_separator() {
  109.     echo "--------------------"
  110. }
  111.  
  112. # print starting date and time
  113. log_separator
  114. echo "Starting Update at: $start_date_formatted"
  115. log_separator
  116.  
  117. # ------------------- Start of backup script ------------------- #
  118. echo
  119. # print stuff:
  120. echo "Backup Source             -    [$CLIENT_HOSTNAME]"
  121. echo "Backup Directory          -    [$BACKUP_PATH]"
  122. small_separator
  123. echo "Backup Destination        -    [Proxmox Backup Server] @ [$PBS_SERVER_IP:$PBS_SERVER_PORT]"
  124. echo "Destination Datastore     -    [$PBS_DATASTORE] @ [$PBS_SERVER_IP:$PBS_SERVER_PORT]"
  125. small_separator
  126. echo "Repository                -    [${PBS_USER}@pbs!${PBS_TOKEN_NAME}@${PBS_SERVER_IP}:${PBS_SERVER_PORT}:${PBS_DATASTORE}]"
  127. echo "Datastore                 -    [$PBS_DATASTORE]"
  128. echo "Namespace                 -    [$PBS_NAMESPACE]"
  129. echo "Environment Variables     -    [PBS_PASSWORD_FILE], [PBS_FINGERPRINT], [PBS_REPOSITORY]"
  130. small_separator
  131. echo "Directories Excluded      -    [mnt/**], [var/lib/vz**], [**tmp**], [/etc/pve/**] and all mounted drives by Default."
  132. echo "Force Included            -    [$FORCE_INCLUDE_PATH]"
  133. echo "Ignore List               -    [.pxarexclude] #Edit this file to exclude patterns."
  134. # echo "Include in .pxarexclude   -    [nothing]"
  135. small_separator
  136. echo "Skipped mount points      -    [dev], [proc], [run], [sys], [var/lib/lxcfs] by Default."
  137. echo ""
  138. single_separator
  139. echo "Running the following command:"
  140. small_separator
  141. echo "${PBS_BACKUP_COMMAND}"
  142. log_separator
  143. echo "running backup, please wait..."
  144.  
  145. # if DRY_RUN is true, run ${PBS_BACKUP_COMMAND} --dry-run, else run ${PBS_BACKUP_COMMAND}, echo the command before running
  146. if [ "$DRY_RUN" = true ]; then
  147.    
  148.     echo "Dry Running: "
  149.     # Countdown from 3 to 1
  150.     for i in {3..1}; do
  151.         echo -ne " --dry-run -> $i\r"
  152.         sleep 1
  153.         echo -ne "                \r"
  154.     done
  155.     echo "${PBS_BACKUP_COMMAND} --dry-run"
  156.     ${PBS_BACKUP_COMMAND} --dry-run
  157. elif [ "$DRY_RUN" = false ]; then
  158.     echo "running backup, please wait..."
  159.     # Countdown from 3 to 1
  160.     for i in {3..1}; do
  161.         echo -ne " Starting -> $i\r"
  162.         sleep 1
  163.         echo -ne "               \r"
  164.     done
  165.     echo "${PBS_BACKUP_COMMAND}"
  166.     ${PBS_BACKUP_COMMAND}
  167. else
  168.     echo "Invalid value for DRY_RUN. Exiting."
  169.     # Countdown from 3 to 1
  170.     for i in {3..0}; do
  171.         echo -ne " Exiting, -> $i\r"
  172.         sleep 1
  173.         echo -ne "              \r"
  174.     done
  175.     exit 1
  176. fi
  177.  
  178. sleep 2.0s
  179. echo ""
  180.  
  181. single_separator
  182. echo "Started Update at: $start_date_formatted"
  183. single_separator
  184. # convert the date to IST with format "YYYY-MM-DD | I:MM:SS p" and add it to the log file
  185. finish_date_formatted=$(TZ=${current_time_zone} date +'%Y-%m-%d | %I:%M:%S %p')
  186. echo "Finished Update at: $finish_date_formatted"
  187. single_separator
  188.  
  189. # since "|" creates issues in the date command, we need to remove it for the math to work
  190. start_date_for_math=$(echo $start_date_formatted | sed 's/| //')
  191. finish_date_for_math=$(echo $finish_date_formatted | sed 's/| //')
  192. # total time taken in the format "H:M:S"
  193. echo "Total time taken: $(date -d @$(( $(date -d "$finish_date_for_math" +%s) - $(date -d "$start_date_for_math" +%s) )) -u +%H:%M:%S)"
  194. log_separator
  195.  
  196. # print "Please check the log file for more details" to the console along with the path to the log file
  197. echo "Please check the log file for more details:"
  198. small_separator
  199. echo "$log_file_path"
  200. log_separator
  201.  
  202. # delete the log files older than 30 days and print the files that are being deleted
  203. log_file_dir=$(dirname "$log_file_path")/
  204. echo "Log files older than 30 days, under '$log_file_dir' that were deleted:"
  205. small_separator
  206. find $log_file_dir -type f -mtime +30 -exec sh -c 'echo "$1"; rm -f "$1"' _ {} \;
  207. small_separator
  208.  
  209. # exit the script
  210. echo ""
  211. echo "exiting"
  212. echo ""
  213. # clear the variables and clear the export variables to avoid any conflicts with other scripts or commands that may use the same variables
  214. unset PBS_PASSWORD_FILE PBS_FINGERPRINT PBS_REPOSITORY date_Filename date start_date_formatted finish_date_formatted start_date_for_math finish_date_for_math log_file_path log_file_dir log_separator single_separator small_separator FORCE_INCLUDE_PATH
  215. exit 0
  216.  
Advertisement
Add Comment
Please, Sign In to add comment