diff --git a/.gitignore b/.gitignore
index 810227f4e038ae2522c8789b1f0d8117aa5c5adf..f7fb54ad93da07c3f614f543795851a5ddac4392 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,8 @@ etc/cron.d/backupninja
 etc/logrotate.d/backupninja
 examples/Makefile
 handlers/Makefile
+handlers/borg
+handlers/borg.helper
 handlers/dup
 handlers/dup.helper
 handlers/ldap
diff --git a/AUTHORS b/AUTHORS
index 2b2db911e41eecca3f51c1914f3fa0efef6c94a7..b450b84b6f8874cff8dc1abfdaacadb600216b57 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -59,3 +59,5 @@ Daniel Lo Nigro <daniel@dan.cx> -- Dropbox support for Duplicity
 Matthijs Wensveen <matthijs.wensveen@gmail.com> -- fix symmetric encryption in dup handler
 ulrich <ulrich@habmalnefrage.de> -- Added validation check for when
 Romain Dessort <romain@univers-libre.net> -- Fix list of devices when dumping partition tables
+Guillaume Subiron <ben@wainei.net> -- borg handler
+Jerome Charaoui <jerome@riseup.net> -- borg handler
diff --git a/ChangeLog b/ChangeLog
index 0748bf6e6b002ecf535d9013b05c68a01fe8b2be..77f3f7b61862f976aa10a82df2c2e4cba531651d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,9 @@ version 1.0.3 -- UNRELEASED
 
     documentation changes
 	 ยท Fix typos in README.md and manpages. Thank you, Lintian!
+    handler changes
+	borg:
+	 . Added initial support
 
 version 1.0.2 -- September 05, 2017
     handler changes
diff --git a/INSTALL.md b/INSTALL.md
index 0356ee2267f70f3c9d21303a73c2ad6602704dc7..4ea811273161000a9485250a4035cda63d43978f 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -15,7 +15,7 @@ Requirements:
 
 Recommended:
 
-        rdiff-backup duplicity rsync gzip hwinfo sfdisk cryptsetup flashrom hwinfo
+        rdiff-backup duplicity rsync borgbackup gzip hwinfo sfdisk cryptsetup flashrom hwinfo
 
 To install backupninja, simply do the following:
 
diff --git a/README.md b/README.md
index 7749cc9d61ce4c27e3785463f4aa9740103f7ee2..61a255edd1b90b6d09c95f3392b0155ae705f15a 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,7 @@ The following backup types are supported:
    with an unpriviledged backup user
  - backup of mysql databases (via mysqlhotcopy and mysqldump)
  - basic system and hardware info
- - encrypted remote backups (via duplicity)
+ - encrypted remote backups (via duplicity or borgbackup)
  - backup of subversion repositories
 
 Installation
@@ -107,6 +107,7 @@ file in `/etc/backup.d` according to the file's suffix:
  - `.sh`: run this file as a shell script.
  - `.rdiff`: filesystem backup (using rdiff-backup)
  - `.dup`: filesystem backup (using duplicity)
+ - `.borg`: filesystem backup (using borg)
  - `.mysql`: backup mysql databases
  - `.pgsql`: backup PostgreSQL databases
  - `.sys`: general hardware, partition, and system reports.
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 89bd56b22aa0244485a9a9d01bbfbdc6b0763896..c33a8fbe66d6f195f0f0258ef92e4efdce318c39 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -1,7 +1,7 @@
 
-EXAMPLES = example.dup example.maildir example.makecd example.mysql \
-		example.pgsql example.rdiff example.rsync example.sh  \
-		example.svn example.sys example.trac
+EXAMPLES = example.borg example.dup example.maildir example.makecd \
+		example.mysql example.pgsql example.rdiff example.rsync \
+		example.sh example.svn example.sys example.trac
 
 EXTRA_DIST = $(EXAMPLES)
 
diff --git a/examples/example.borg b/examples/example.borg
new file mode 100644
index 0000000000000000000000000000000000000000..b49598d0ab7f9a7bf3dc96cd36eb708412642eb6
--- /dev/null
+++ b/examples/example.borg
@@ -0,0 +1,182 @@
+##
+## This is an example borgbackup configuration file.
+##
+## Here you can find all the possible borgbackup options, details of
+## what the options provide and possible settings. The defaults are set
+## as the commented out option, uncomment and change when
+## necessary. Options which are uncommented in this example do not have
+## defaults, and the settings provided are recommended.
+##
+## The defaults are useful in most cases, just make sure to configure the
+## destination host and user.
+##
+
+## default is 0, but set to 19 if you want to lower the priority.
+## an example setting would be:
+## nicelevel = 19
+##
+## Default
+# nicelevel = 0
+
+## default is yes. set to no to skip the test if the remote host is alive
+##
+## Default:
+# testconnect = yes
+
+## default is not to limit bandwidth. 
+## set to a number in kiBytes/second to limit bandwidth usage. 
+##
+## Default:
+# bwlimit = 0
+
+######################################################
+## source section
+## (where the files to be backed up are coming from)
+
+[source]
+
+## default is to initialize the backup repository if absent
+## set to no to skip this step
+##
+## Default:
+# init = yes
+
+## A few notes about includes and excludes:
+## 1. include paths do not support any kind of pattern matching
+## 2. exclude paths support several types of pattern matching, the default being
+##    shell-style matching, where, for example, '*' matches any number of
+##    characters. for more info, see : borg help patterns
+## 3. Symlinks are preserved (not followed).
+##
+## for more info see : borg help patterns
+##
+## files to include in the backup
+include = /opt
+include = /srv
+include = /etc
+include = /root
+include = /home
+include = /usr/local
+include = /var
+
+## files to exclude from the backup
+exclude = /var/lock
+exclude = /var/run
+exclude = /var/cache
+exclude = /var/tmp
+exclude = /var/lib/mongodb/journal
+exclude = /var/lib/clamav
+exclude = /var/lib/mlocate
+exclude = /var/lib/postgresql
+exclude = /var/lib/mysql
+
+## define extra command-line options for the "borg create" operation.
+##
+## Example:
+## create_options = --exclude-caches
+##
+## for more info see : borg help create
+##
+## Default:
+# create_options =
+
+## whether to prune (remove) older backups
+##
+## Default:
+# prune = yes
+
+## keep all backups within this time frame.
+## must be defined as a number followed by one of the
+## following characters: "H", "d", "w", "m", "y"
+##
+## this option will be ignored if set to 0
+##
+## the default is to keep all backups made within the
+## last 30 days
+##
+## Default:
+# keep = 30d
+
+## define extra command-line options for the "borg prune" operation.
+##
+## Example:
+## prune_options = --keep-daily=7 --keep-weekly=4 --keep-monthly=6
+##
+## for more info see : borg help prune
+##
+## Default:
+# prune_options =
+
+######################################################
+## destination section
+## (where the files are copied to)
+
+[dest]
+
+## put the backups under this directory, this must be set!
+## an example setting would be:
+## directory = /backups
+##
+## Default:
+# directory =
+
+## the machine which will receive the backups.
+## an example setting would be:
+## host = backuphost
+##
+## set host = localhost for local backups (no ssh)
+##
+## Default
+# host =
+
+## make the files owned by this user. you must be able to
+## `su -c "ssh backupuser@backhost"` without specifying a password.
+## an example setting would be:
+## user = backupuser
+##
+## Default:
+# user =
+
+## archive name, should be unique every day.
+## Format tags available :
+## {now}, {utcnow}, {fqdn}, {hostname}, {user}, {pid}
+##
+## for more info see : borg help create
+##
+## Default:
+# archive = {now:%Y-%m-%dT%H:%M:%S} 
+
+## compression algorithm
+## can be "none", "lz4", "zstd[,L]", "zlib[,L]", "lzma[,L]", "auto,C[,L]".
+## - "none" stands for "no compression"
+## - "lz4" offers very high speed, very low compression
+## - "zstd" is a modern wide-range algorithm
+## - "zlib" offers medium speed, medium compression
+## - "lzma" offers low speed, high compression
+## - "auto,C" will use a heuristic to decide whether to compress using
+##            selected algorithm C
+##
+## for more info see : borg help compression
+##
+## Default:
+# compression = lz4
+
+## encryption mode to use for repository creation
+##
+## common options are "none", "repokey" or "keyfile"
+## - "none" = no encryption
+## - "repokey" = encryption with key stored inside the repository
+## - "keyfile" = encryption with key stored in ~/.config/borg/keys/
+##
+## for other options and more info, see : borg help init
+##
+## Default:
+# encryption = none
+
+## passphrase of the key used for repository encryptions
+##
+## must be set if encryption is not "none"
+## encryption is disabled by default
+##
+## Default:
+# passphrase =
diff --git a/handlers/Makefile.am b/handlers/Makefile.am
index bad53bbe857b9ffb5d833033e9b5b1ca50a7e9ff..e9526450dbd9259055b097726b3ce7a9743c52b3 100644
--- a/handlers/Makefile.am
+++ b/handlers/Makefile.am
@@ -1,9 +1,9 @@
 
-HANDLERS = dup dup.helper maildir makecd		\
+HANDLERS = borg borg.helper dup dup.helper maildir makecd	\
          makecd.helper mysql mysql.helper pgsql pgsql.helper rdiff	\
          rdiff.helper rsync sh svn sys sys.helper trac tar tar.helper
 
-DIST_HANDLERS = dup.in dup.helper.in maildir.in makecd.in		\
+DIST_HANDLERS = borg.in borg.helper.in dup.in dup.helper.in maildir.in makecd.in	\
          makecd.helper.in mysql.in mysql.helper.in pgsql.in pgsql.helper.in rdiff.in	\
          rdiff.helper.in rsync.in sh.in svn.in sys.in sys.helper.in trac.in tar.in tar.helper.in wget
 
@@ -18,6 +18,14 @@ edit = sed \
 
 pkgdata_DATA = $(HANDLERS)
 
+borg: $(srcdir)/borg.in
+	rm -f borg
+	$(edit) $(srcdir)/borg.in > borg
+
+borg.helper: $(srcdir)/borg.helper.in
+	rm -f borg.helper
+	$(edit) $(srcdir)/borg.helper.in > borg.helper
+
 dup: $(srcdir)/dup.in
 	rm -f dup
 	$(edit) $(srcdir)/dup.in > dup
diff --git a/handlers/borg.helper.in b/handlers/borg.helper.in
new file mode 100644
index 0000000000000000000000000000000000000000..d042198fe569397a83eaae0d0264ed787e783071
--- /dev/null
+++ b/handlers/borg.helper.in
@@ -0,0 +1,389 @@
+# -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*-
+# vim: set filetype=sh sw=3 sts=3 expandtab autoindent:
+#
+# Copyright 2016 Benjamin Maisonnas <ben@wainei.net>
+#
+# This work is free. You can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+
+HELPERS="$HELPERS borg:deduplicated_archive_based_backup"
+
+declare -a borg_includes
+declare -a borg_excludes
+
+# FUNCTIONS
+
+do_borg_host_includes() {
+   set -o noglob
+   # choose the files to backup
+   REPLY=
+   while [ -z "$REPLY" ]; do
+      formBegin "$borg_title - host system: includes"
+         for ((i=0; i < ${#borg_includes[@]} ; i++)); do
+            formItem include ${borg_includes[$i]}
+         done
+         formItem include
+         formItem include
+         formItem include
+         formItem include
+         formItem include
+         formItem include
+         formItem include
+         formItem include
+      formDisplay
+      [ $? = 0 ] || return
+      unset borg_includes
+      borg_includes=($REPLY)
+   done
+   set +o noglob
+}
+
+do_borg_excludes() {
+   set -o noglob
+   formBegin "$borg_title: host system: excludes"
+     for ((i=0; i < ${#borg_excludes[@]} ; i++))
+     do
+       formItem exclude ${borg_excludes[$i]}
+     done
+     formItem exclude
+     formItem exclude
+     formItem exclude
+     formItem exclude
+     formItem exclude
+     formItem exclude
+     formItem exclude
+     formItem exclude
+   formDisplay
+   [ $? = 0 ] || return
+   unset borg_excludes
+   borg_excludes=($REPLY)
+   set +o noglob
+}
+
+do_borg_src() {
+   do_borg_host_includes
+   [ $? = 0 ] || return 1
+
+   do_borg_excludes
+   [ $? = 0 ] || return 1
+
+   _src_done="(DONE)"
+   setDefault dest
+}
+
+do_borg_dest() {
+   declare -a tmp_array
+
+   set -o noglob
+   REPLY=
+   while [ -z "$REPLY" -o -z "$borg_directory" -o -z "$borg_host" -o -z "$borg_user" -o -z "$borg_archive" -o -z "$borg_compression" ]
+   do
+     formBegin "$borg_title - destination"
+        formItem "directory" "$borg_directory"
+        formItem "host" "$borg_host"
+        formItem "user" "$borg_user"
+        formItem "archive_name" "$borg_archive"
+        formItem "compression" "$borg_compression"
+
+        formDisplay
+     [ $? = 0 ] || return
+     tmp_array=($REPLY)
+     borg_directory=${tmp_array[0]}
+     borg_host=${tmp_array[1]}
+     borg_user=${tmp_array[2]}
+     borg_archive=${tmp_array[3]}
+     borg_compression=${tmp_array[4]}
+  done
+  set +o noglob
+
+  _dest_done="(DONE)"
+  setDefault conn
+}
+
+do_borg_enc() {
+   radioBox "$borg_title" "Encryption mode" \
+       "none"     "no encryption and no authentication" on \
+       "repokey"  "encryption with a passphrase" off
+   [ $? = 1 ] && return;
+   borg_encryption="$REPLY"
+
+   if [ "$borg_encryption" = "repokey" ]; then
+      local question="Enter the passphrase needed to encrypt/decrypt the repository:"
+      REPLY=
+      while [ -z "$REPLY" -o -z "$borg_passphrase" ]; do
+         passwordBox "$borg_title - " "$question"
+         [ $? = 0 ] || return 1
+         borg_passphrase="$REPLY"
+      done
+   fi
+
+  _enc_done="(DONE)"
+  setDefault prune
+}
+
+do_borg_local_dir() {
+   local dir_status="ok"
+
+   IFS=$' \t\n'
+   if [ "$_dest_done" = "" ]; then
+      msgBox "$borg_title: error" "You must first configure the destination."
+      return 1
+   fi
+
+   echo "Testing to see if the borg backup directory exists and is writable"
+   if [ test -d "$borg_directory" ]; then
+      if [ test -w "$borg_directory" ]; then
+         msgBox "destination directory is not writable!" "The destination directory is not writable by the user you specified. Please fix the permissions on the directory and then try again."
+         dir_status=failed
+      fi
+   else
+      booleanBox "Destination does not exist" "The destination backup directory does not exist, do you want me to create it for you?"
+      if [ $? = 0 ]; then
+         if mkdir -p "$borg_directory"; then
+            msgBox "$borg_title: success" "Creation of the destination directory was a success!"
+         else
+            msgBox "$borg_title: error" "Creation of the destination directory failed, check the directory permissions."
+            dir_status=failed
+         fi
+      fi
+   fi
+
+   [ "$dir_status" = "ok" ] || return 1
+}
+
+do_borg_ssh_con() {
+   local remote_status="ok"
+
+   IFS=$' \t\n'
+   if [ "$_dest_done" = "" ]; then
+      msgBox "$borg_title: error" "You must first configure the destination."
+      return 1
+   elif [ "$borg_user" = "" ]; then
+      msgBox "$borg_title: error" "You must first configure the destination user."
+      return 1
+   elif [ "$borg_host" = "" ]; then
+      msgBox "$borg_title: error" "You must first configure the destination host."
+      return 1
+   else
+      booleanBox "$borg_title" "This step will create a ssh key for the local root user with no passphrase (if one does not already exist), and attempt to copy root's public ssh key to authorized_keys file of $borg_user@$borg_host. This will allow the local root to make unattended backups to $borg_user@$borg_host.\n\n\nAre you sure you want to continue?"
+      [ $? = 0 ] || return 1
+   fi
+
+   if [ ! -f /root/.ssh/id_dsa.pub -a ! -f /root/.ssh/id_rsa.pub ]; then
+      echo "Creating local root's ssh key"
+      ssh-keygen -t rsa -b 4096 -f /root/.ssh/id_rsa -N ""
+      echo "Done. hit return to continue"
+      read
+   fi
+
+   ssh -o PreferredAuthentications=publickey $borg_host -l $borg_user "exit" 2> /dev/null
+   if [ $? -ne 0 ]; then
+      echo "Copying root's public ssh key to authorized_keys of $borg_user@$borg_host. When prompted, specify the password for user $borg_user@$borg_host."
+      pubkeys=( /root/.ssh/id_[rd]sa.pub )
+      if ! ssh-copy-id -i ${pubkeys[0]} $borg_user@$borg_host; then
+         echo "FAILED: Couldn't copy root's public ssh key to authorized_keys of $borg_user@$borg_host."
+         ssh $borg_user@$borg_host 'test -w .ssh || test -w .'
+         result=$?
+         echo "Hit return to continue."
+         read
+         case $result in
+            0 )   msgBox "$borg_title: error" "Directories are writable: Probably just a typo the first time." ;;
+            1 )   msgBox "$borg_title: error" "Connected successfully to $borg_user@$borg_host, but unable to write. Check ownership and modes of ~$borg_user on $borg_host." ;;
+            255 ) msgBox "$borg_title: error" "Failed to connect to $borg_user@$borg_host. Check hostname, username, and password. Also, make sure sshd is running on the destination host." ;;
+            * )   msgBox "$borg_title: error" "Unexpected error (return code ${result})." ;;
+         esac
+         return
+      else
+         echo "Done. hit return to continue"
+         read
+      fi
+   else
+      echo "root@localhost is already in authorized_keys of $borg_user@$borg_host."
+      echo "Hit return to continue."
+      read
+   fi
+
+   # test to see if the remote borg backup directory exists and is writable
+   echo "Testing to see if remote borg backup directory exists and is writable"
+   ssh $borg_user@$borg_host "test -d ${borg_directory}"
+   if [ $? = 0 ]; then
+      ssh $borg_user@$borg_host "test -w $borg_directory"
+      if [ $? != 0 ]; then
+         msgBox "destination directory is not writable!" "The remote destination directory is not writable by the user you specified. Please fix the permissions on the directory and then try again."
+         remote_status=failed
+      fi
+   else
+      booleanBox "Remote directory does not exist" "The destination backup directory does not exist, do you want me to create it for you?"
+      if [ $? = 0 ]; then
+         ssh $borg_user@$borg_host "mkdir -p ${borg_directory}"
+         result=$?
+         case $result in
+            0) msgBox "$borg_title: success" "Creation of the remote destination directory was a success!";;
+            1) msgBox "$borg_title: error" "Connected successfully to $borg_user@$borg_host, but was unable to create the destination directory, check the directory permissions."
+               remote_status=failed;;
+            255) msgBox "$borg_title: error" "Failed to connect to $borg_user@$borg_host. Check hostname, username, and password. Also, make sure sshd is running on the destination host."
+               remote_status=failed;;
+            *) msgBox "$borg_title: error" "Unexpected error."
+               remote_status=failed;;
+         esac
+      fi
+   fi
+
+   [ "$remote_status" = "ok" ] || return 1
+}
+
+do_borg_con() {
+   echo "Checking for local install of borg"
+   which borg
+   if [ $? != 0 ]; then
+      msgBox "$borg_title: error" "borg executable not found, please install borg ($borg_docs/installation.html)."
+      return
+   fi
+
+   if [ "$borg_host" != "localhost" ]; then
+      do_borg_ssh_con
+   else
+      do_borg_local_dir
+   fi
+
+   [ $? = 0 ] || return
+
+   echo "SUCCESS: Everything looks good!"
+   echo "Hit return to continue."
+   read
+
+   _con_done="(DONE)"
+   setDefault enc
+}
+
+do_borg_prune() {
+   radioBox "$borg_title" "pruning (how many backups to keep" \
+       "yes" "regularly prune old backups" on \
+       "no"  "keep all backups" off
+   [ $? = 1 ] && return;
+   borg_prune="$REPLY"
+
+   if [ "$borg_prune" = "yes" ]; then
+      declare -a tmp_array
+      set -o noglob
+      REPLY=
+      formBegin "$borg_title - keep all backups made within this number of days"
+         formItem "keep" "$borg_keep"
+         formDisplay
+
+      [ $? = 0 ] || return
+      tmp_array=($REPLY)
+      borg_keep=${tmp_array[0]}
+
+      set +o noglob
+   fi
+
+  _prune_done="(DONE)"
+   setDefault finish
+}
+
+do_borg_finish() {
+   get_next_filename $configdirectory/90.borg
+   cat > $next_filename <<EOF
+## for more options see
+## - example.borg
+## - $borg_docs
+
+[source]
+EOF
+   ## includes ##
+   set -o noglob
+   for ((i=0; i < ${#borg_includes[@]} ; i++)); do
+      echo "include = ${borg_includes[$i]}" >> $next_filename
+   done
+   set +o noglob
+
+   ## excludes ##
+   set -o noglob
+   for ((i=0; i < ${#borg_excludes[@]} ; i++)); do
+     echo exclude = ${borg_excludes[$i]} >> $next_filename
+   done
+   set +o noglob
+   cat >> $next_filename <<EOF
+
+## for more info see : borg prune -h
+prune = $borg_prune
+keep = "${borg_keep}d"
+
+[dest]
+directory = $borg_directory
+host = $borg_host
+user = $borg_user
+archive = $borg_archive
+compression = $borg_compression
+encryption = $borg_encryption
+passphrase = $borg_passphrase
+EOF
+
+   chmod 600 $next_filename
+}
+
+borg_main_menu() {
+   while true; do
+      srcitem="choose files to include & exclude $_src_done"
+      destitem="configure backup destination $_dest_done"
+      conitem="test connection and destination dir $_con_done"
+      encitem="configure encryption mode $_enc_done"
+      pruneitem="configure pruning (optional) $_prune_done"
+      menuBox "$borg_title" "choose a step:" \
+         src "$srcitem" \
+         dest "$destitem" \
+         conn "$conitem" \
+         enc "$encitem" \
+         prune "$pruneitem" \
+         finish "finish and create config file"
+      [ $? = 0 ] || return
+      result="$REPLY"
+      case "$result" in
+         "src") do_borg_src;;
+         "dest") do_borg_dest;;
+         "conn") do_borg_con;;
+         "enc") do_borg_enc;;
+         "prune") do_borg_prune;;
+         "finish")
+            if [[ "$_con_done$_dest_done$_enc_done$_src_done" != "(DONE)(DONE)(DONE)(DONE)" ]]; then
+               msgBox "$borg_title" "You cannot create the configuration file until mandatory steps are completed."
+            else
+               do_borg_finish
+               return
+            fi
+            ;;
+      esac
+   done
+}
+
+borg_wizard() {
+   # Global variables
+   borg_title="borg action wizard"
+   borg_docs="http://borgbackup.readthedocs.io/en/stable"
+
+   _src_done=
+   _dest_done=
+   _enc_done=
+   _con_done=
+
+   borg_directory=/backup/`hostname`
+   borg_user=root
+   borg_host=localhost
+   borg_archive='{now:%Y-%m-%dT%H:%M:%S}'
+   borg_compression=lz4
+   borg_encryption=none
+   borg_passphrase=
+   borg_keep=30
+
+   # Global variables whose '*' shall not be expanded
+   set -o noglob
+   borg_includes=(/var/spool/cron/crontabs /var/backups /etc /root /home /usr/local/*bin)
+   borg_excludes=(/home/*/.gnupg /home/*/.local/share/Trash /home/*/.Trash /home/*/.thumbnails)
+   set +o noglob
+
+   borg_main_menu
+}
diff --git a/handlers/borg.in b/handlers/borg.in
new file mode 100644
index 0000000000000000000000000000000000000000..df500a80bacb6daf26c61625d01eca6d558e27db
--- /dev/null
+++ b/handlers/borg.in
@@ -0,0 +1,169 @@
+# -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*-
+# vim: set filetype=sh sw=3 sts=3 expandtab autoindent:
+#
+# borg handler script for backupninja
+# requires borgbackup
+#
+# Guillaume Subiron, Sysnove, 2016
+#
+# Copyright 2016 Guillaume Subiron <guillaume@sysnove.fr>
+#
+# This work is free. You can redistribute it and/or modify it under the
+# terms of the Do What The Fuck You Want To Public License, Version 2,
+# as published by Sam Hocevar. See the http://www.wtfpl.net/ file for more details.
+#
+#
+
+export BORG_RELOCATED_REPO_ACCESS_IS_OK=yes
+export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes
+
+### GET CONFIG ###
+
+getconf testconnect yes
+getconf nicelevel 0
+getconf bwlimit
+
+setsection source
+getconf init yes
+getconf include
+getconf exclude
+getconf create_options
+getconf prune yes
+getconf keep 30d
+getconf prune_options
+
+setsection dest
+getconf user
+getconf host
+getconf directory
+# strip trailing /
+directory=${directory%/}
+getconf archive {now:%Y-%m-%dT%H:%M:%S}
+getconf compression lz4
+getconf encryption none
+getconf passphrase
+
+export BORG_PASSPHRASE="$passphrase"
+
+### CHECK CONFIG ###
+
+# destination specific checks
+[ "$directory" != "" ] || fatal "Destination directory not set"
+if [ "$host" != "localhost" ]; then
+  execstr_repository="ssh://${user}@${host}${directory}"
+else
+  execstr_repository="$directory"
+fi
+execstr_archive="$archive"
+
+# check the connection at the source and destination
+[ -n "$test" ] || test=0
+if [ "$host" != "localhost" ] && ([ "$testconnect" = "yes" ] || [ "${test}" -eq 1 ]); then
+   debug "ssh -o PasswordAuthentication=no $host -l $user 'echo -n 1'"
+   local ret=`ssh -o PasswordAuthentication=no $host -l $user 'echo -n 1'`
+   if [ "$ret" = 1 ]; then
+      debug "Connected to $host as $user successfully"
+   else
+      teststr="borg list --show-rc -v $execstr_repository"
+      debug "$teststr"
+      output=`su -c "$teststr" 2>&1`
+      if echo "$output" | grep "terminating with success status" ; then
+         debug "Connected to $host as $user successfully (forced command)"
+      else
+         if echo "$output" | grep -E "Repository.+does not exist" ; then
+            debug "Connected to $host as $user successfully (forced command)"
+         else
+            fatal "Can't connect to $host as $user."
+         fi
+      fi
+   fi
+fi
+
+### INIT IF NEEDED ###
+
+if [ "$init" == "yes" ]; then
+   initstr="borg init --encryption=$encryption $execstr_repository"
+   debug "$initstr"
+   if [ $test = 0 ]; then
+      output="`su -c "$initstr" 2>&1`"
+      if [ $? = 2 ]; then
+         debug $output
+         info "Repository was already initialized"
+      else
+         warning $output
+         warning "Repository has been initialized"
+      fi
+   fi
+fi
+
+### EXECUTE ###
+
+execstr="borg create --stats --compression $compression"
+
+set -o noglob
+
+# includes
+SAVEIFS=$IFS
+IFS=$(echo -en "\n\b")
+for i in $include; do
+   includes="${includes} '$i'"
+done
+IFS=$SAVEIFS
+
+# excludes
+SAVEIFS=$IFS
+IFS=$(echo -en "\n\b")
+for i in $exclude; do
+   excludes="${excludes} --exclude '$i'"
+done
+IFS=$SAVEIFS
+
+set +o noglob
+
+if [ ! -z $bwlimit ]; then
+   execstr="${execstr} --remote-ratelimit=${bwlimit}"
+fi
+
+if [ ! -z $create_options ]; then
+   execstr="${execstr} ${create_options}"
+fi
+
+# include client-part and server-part
+execstr="${execstr} ${excludes} $execstr_repository::$execstr_archive ${includes}"
+debug "$execstr"
+
+if [ $test = 0 ]; then
+   output=`nice -n $nicelevel su -c "$execstr" 2>&1`
+   if [ $? = 0 ]; then
+      debug $output
+      info "Successfully finished backing up source $label"
+   else
+      error $output
+      fatal "Failed backuping up source $label"
+   fi
+fi
+
+### REMOVE OLD BACKUPS ###
+
+# borg prune
+if [ "$prune" == "yes" ]; then
+   if [ ! "$keep" == "0" ]; then
+      prune_options="${prune_options} --keep-within=${keep}"
+   fi
+   prunestr="borg prune $prune_options $execstr_repository"
+   debug "$prunestr"
+   if [ $test = 0 ]; then
+      output="`su -c "$prunestr" 2>&1`"
+      if [ $? = 0 ]; then
+         debug $output
+         info "Removing old backups succeeded."
+      else
+         warning $output
+         warning "Failed removing old backups."
+      fi
+   fi
+fi
+
+unset BORG_PASSPHRASE
+
+return 0
diff --git a/man/backup.d.5 b/man/backup.d.5
index df2063e5bd82fa99ad4cb1f0ef75f9e78a12aec8..5b7a62625641b2c6ca146943848a567ebbcf064c 100644
--- a/man/backup.d.5
+++ b/man/backup.d.5
@@ -33,6 +33,8 @@ run this file as a shell script.
 backup action for rdiff-backup.
 .IP .dup
 backup action for duplicity.
+.IP .borg
+backup action for borgbackup.
 .IP .maildir
 backup action for slow, incremental rsyncs of tens of thousands of maildirs.
 .IP .mysql