├── README.md ├── zabbix_agentd.d ├── borg-enc.conf └── borg.conf └── templates └── borg.xml /README.md: -------------------------------------------------------------------------------- 1 | Zabbix template for monitoring Borg backup repositories. Requires Borg binary to be available in the system being monitored. Monitoring occurs on the backup server, though it can be possible to invoke this by the client and connect to repository via Borg network capabilities. This setup is currently not supported by the plugin. 2 | 3 | # Installation 4 | 1. Copy `zabbix_agentd.d/borg.conf` to the Zabbix agent's configuration directory (usually located at `/etc/zabbix`). If using encrypted repositories, read the note below and use the file `zabbix_agentd.d/borg-enc.conf`. 5 | 2. Import template configuration `templates/borg.xml` to Zabbix web frontend. 6 | 7 | # Notes 8 | This plugin uses discovery capabilities provided by Zabbix to locate backup repositories. Since all commands are executed by `zabbix` user, appropriate permissions must be granted to all backup repositories. If encrypted, encryption keys should be provided to `zabbix` user. 9 | 10 | One possibility is to use `--umask=0027` parameter when invoking `borg` command to make created files group readable. Then add the user `zabbix` into the group of the SSH account used by backup client. In this case, the backup repository must be created with `--umask=0007` to make it group writable so that `zabbix` user can create lock files while polling the backup status. 11 | 12 | # Encrypted Repositories 13 | For encrypted repositories, a `borg info` command must be run right after the backup and output saved to a file `status.txt` located in the remote repository. Also the output of the `borg check -v` should be appended to `status.txt`. Since those commands are run right after the backup by the client, they will contain the latest status of the repository. This plugin can then reside in the remote host and read the status from `status.txt`. This effectively avoids making encryption keys available to `zabbix` user neither on backup client or remote storage server. 14 | 15 | To save the output of aforementioned commands, use something like: 16 | ``` 17 | borg info user@host:repo::backup | ssh user@host 'cat > repo/status.txt' 18 | borg check user@host:repo | ssh user@host 'cat >> repo/status.txt' 19 | ``` -------------------------------------------------------------------------------- /zabbix_agentd.d/borg-enc.conf: -------------------------------------------------------------------------------- 1 | UserParameter=borg.discover, dirname $(grep -silm1 "This is a Borg Backup" /home/*/*/README) | awk 'BEGIN{printf "{\"data\":["}; {i=split($1,path,"/"); printf c"{\"{#PATH}\":\""$1"\", \"{#HOST}\":\"" path[i-1] "\", \"{#DIR}\":\"" path[i] "\"}";c="," }; END{print "]}"}' 2 | 3 | UserParameter=borg.start_time[*], date -d "$(grep -i "time (start)" $1/status.txt | sed 's/^.*): //;s/$//')" 4 | UserParameter=borg.start_timestamp[*], date -d "$(grep -i "time (start)" $1/status.txt | sed 's/^.*): //;s/$//')" +%s 5 | UserParameter=borg.end_time[*], date -d "$(grep -i "time (end)" $1/status.txt | sed 's/^.*): //;s/$//')" 6 | UserParameter=borg.end_timestamp[*], date -d "$(grep -i "time (end)" $1/status.txt | sed 's/^.*): //;s/$//')" +%s 7 | 8 | UserParameter=borg.all_original[*], grep -i "all archives" $1/status.txt | awk '$$4~/^GB/{printf "%.f", $$3*1000*1000*1000}; $$4~/^MB/{printf "%u", $$3*1000*1000}; $$4~/^kB/{printf "%u", $$3*1000}; $$4~/^B/{print $$3};' 9 | UserParameter=borg.all_compressed[*], grep -i "all archives" $1/status.txt | awk '$$6~/^GB/{printf "%.f", $$5*1000*1000*1000}; $$6~/^MB/{printf "%u", $$5*1000*1000}; $$6~/^kB/{printf "%u", $$5*1000}; $$6~/^B/{print $$5};' 10 | UserParameter=borg.all_deduplicated[*], grep -i "all archives" $1/status.txt | awk '$$8~/^GB/{printf "%.f", $$7*1000*1000*1000}; $$8~/^MB/{printf "%u", $$7*1000*1000}; $$8~/^kB/{printf "%u", $$7*1000}; $$8~/^B/{print $$7};' 11 | 12 | UserParameter=borg.this_original[*], grep -i "this archive" $1/status.txt | awk '$$4~/^GB/{printf "%.f", $$3*1000*1000*1000}; $$4~/^MB/{printf "%u", $$3*1000*1000}; $$4~/^kB/{printf "%u", $$3*1000}; $$4~/^B/{print $$3};' 13 | UserParameter=borg.this_compressed[*], grep -i "this archive" $1/status.txt | awk '$$6~/^GB/{printf "%.f", $$5*1000*1000*1000}; $$6~/^MB/{printf "%u", $$5*1000*1000}; $$6~/^kB/{printf "%u", $$5*1000}; $$6~/^B/{print $$5};' 14 | UserParameter=borg.this_deduplicated[*], grep -i "this archive" $1/status.txt | awk '$$8~/^GB/{printf "%.f", $$7*1000*1000*1000}; $$8~/^MB/{printf "%u", $$7*1000*1000}; $$8~/^kB/{printf "%u", $$7*1000}; $$8~/^B/{print $$7};' 15 | 16 | UserParameter=borg.check[*], case $(grep -ci "no problems found" $1/status.txt) in 2*) echo 0;; *) echo 1;; esac 17 | -------------------------------------------------------------------------------- /zabbix_agentd.d/borg.conf: -------------------------------------------------------------------------------- 1 | UserParameter=borg.discover, dirname $(grep -silm1 "This is a Borg Backup" /home/*/*/README) | awk 'BEGIN{printf "{\"data\":["}; {i=split($1,path,"/"); printf c"{\"{#PATH}\":\""$1"\", \"{#HOST}\":\"" path[i-1] "\", \"{#DIR}\":\"" path[i] "\"}";c="," }; END{print "]}"}' 2 | 3 | UserParameter=borg.start_time[*], date -d "$(BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes borg info $1::$(borg list $1 --short | tail -n1) | grep -i "time (start)" | sed 's/^.*): //;s/$//')" 4 | UserParameter=borg.start_timestamp[*], date -d "$(BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes borg info $1::$(borg list $1 --short | tail -n1) | grep -i "time (start)" | sed 's/^.*): //;s/$//')" +%s 5 | UserParameter=borg.end_time[*], date -d "$(BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes borg info $1::$(borg list $1 --short | tail -n1) | grep -i "time (end)" | sed 's/^.*): //;s/$//')" 6 | UserParameter=borg.end_timestamp[*], date -d "$(BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes borg info $1::$(borg list $1 --short | tail -n1) | grep -i "time (end)" | sed 's/^.*): //;s/$//')" +%s 7 | 8 | UserParameter=borg.all_original[*], BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes borg info $1::$(borg list $1 --short | tail -n1) | grep -i "all archives" | awk '$$4~/^GB/{printf "%.f", $$3*1000*1000*1000}; $$4~/^MB/{printf "%u", $$3*1000*1000}; $$4~/^kB/{printf "%u", $$3*1000}; $$4~/^B/{print $$3};' 9 | UserParameter=borg.all_compressed[*], BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes borg info $1::$(borg list $1 --short | tail -n1) | grep -i "all archives" | awk '$$6~/^GB/{printf "%.f", $$5*1000*1000*1000}; $$6~/^MB/{printf "%u", $$5*1000*1000}; $$6~/^kB/{printf "%u", $$5*1000}; $$6~/^B/{print $$5};' 10 | UserParameter=borg.all_deduplicated[*], BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes borg info $1::$(borg list $1 --short | tail -n1) | grep -i "all archives" | awk '$$8~/^GB/{printf "%.f", $$7*1000*1000*1000}; $$8~/^MB/{printf "%u", $$7*1000*1000}; $$8~/^kB/{printf "%u", $$7*1000}; $$8~/^B/{print $$7};' 11 | 12 | UserParameter=borg.this_original[*], BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes borg info $1::$(borg list $1 --short | tail -n1) | grep -i "this archive" | awk '$$4~/^GB/{printf "%.f", $$3*1000*1000*1000}; $$4~/^MB/{printf "%u", $$3*1000*1000}; $$4~/^kB/{printf "%u", $$3*1000}; $$4~/^B/{print $$3};' 13 | UserParameter=borg.this_compressed[*], BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes borg info $1::$(borg list $1 --short | tail -n1) | grep -i "this archive" | awk '$$6~/^GB/{printf "%.f", $$5*1000*1000*1000}; $$6~/^MB/{printf "%u", $$5*1000*1000}; $$6~/^kB/{printf "%u", $$5*1000}; $$6~/^B/{print $$5};' 14 | UserParameter=borg.this_deduplicated[*], BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes borg info $1::$(borg list $1 --short | tail -n1) | grep -i "this archive" | awk '$$8~/^GB/{printf "%.f", $$7*1000*1000*1000}; $$8~/^MB/{printf "%u", $$7*1000*1000}; $$8~/^kB/{printf "%u", $$7*1000}; $$8~/^B/{print $$7};' 15 | 16 | UserParameter=borg.check[*], BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes borg check $1 2> /dev/null | wc -l 17 | -------------------------------------------------------------------------------- /templates/borg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 3.2 4 | 2017-01-30T20:26:47Z 5 | 6 | 7 | Templates 8 | 9 | 10 | 11 | 617 | 618 | 619 | --------------------------------------------------------------------------------