How to backup automatically with borg on a local harddrive without encryption

en

#1

Backup on local disk without encryption

Warning: this kind of backup don’t protect you from fire, flood, theft because the backup is only on one place. This backup don’t protect your server from cryptolocker virus and some big manual mistakes.

This kind of backup can protect your server from some kinds of manual mistakes, hard drive/ssd/sd end of life, because your usb hard drive is an other storage.

Setup borg

apt-get install python3-pip python3-dev libacl1-dev libssl-dev liblz4-dev
pip3 install borgbackup

Create your local repository

Your disk should be mounted on server start

mkdir /media/DISK/backup
borg init --encryption=none /media/DISK/backup

Activate custom backup methods

mkdir -p /etc/yunohost/hooks.d/backup_method
mkdir -p /usr/share/yunohost/backup_method

Add the mylocalborg hooks

Don’t forget to replace DISK by your directory
/etc/yunohost/hooks.d/backup_method/05-mylocalborg

#!/bin/bash

set -e

repo=/media/DISK/backup

do_need_mount() {
    true
}

do_backup() {
    
    work_dir=$1
    name=$2
    repo=$3
    size=$4
    description=$5
    LOGFILE=/var/log/backup_borg.log
    ERRFILE=/var/log/backup_borg.err
    current_date=$(date +"%d_%m_%y_%H:%M")
    pushd $work_dir
    borg create $repo::${name}_${current_date} ./ >> $LOGFILE 2>> $ERRFILE
    popd

    borg prune $repo -P ${name} --keep-daily=7 --keep-weekly=8 --keep-monthly=12 >> $LOGFILE 2>> $ERRFILE
}

do_mount() {
    work_dir=$1
    name=$2
    repo=$3
    size=$4
    description=$5
    LOGFILE=/var/log/backup_borg.log
    ERRFILE=/var/log/backup_borg.err
    borg mount $repo::$name $work_dir >> $LOGFILE 2>> $ERRFILE
}

work_dir=$2
name=$3

size=$5
description=$6

case "$1" in
  need_mount)
    do_need_mount $work_dir $name $repo $size $description
    ;;
  backup)
    do_backup $work_dir $name $repo $size $description
    ;;
  mount)
    do_mount
    ;;
  *)
    echo "hook called with unknown argument \`$1'" >&2
    exit 1
    ;;
esac

exit 0

Test

yunohost backup create --ignore-apps --system conf_ldap -n test --method mylocalborg --debug --verbose

Run the backup each night

If it’s ok you can create a cron to run the command each night
/etc/cron.daily/yunohost-99-backup

#!/bin/bash
if yunohost -v | grep "version: 2." > /dev/null; then
    ignore_apps="--ignore-apps"
    ignore_system="--ignore-system"
else
    ignore_apps=""
    ignore_system=""
fi
filter_hooks() {
    ls /usr/share/yunohost/hooks/backup/ /etc/yunohost/hooks.d/backup/ | grep "\-$1_" | cut -d"-" -f2 | uniq
}

# Backup system part conf
yunohost backup create $ignore_apps -n auto_conf --methods mylocalborg --system $(filter_hooks conf)

# Backup system data
yunohost backup create $ignore_apps -n auto_data --methods mylocalborg --system $(filter_hooks data)

# Backup all apps independently
for app in $(yunohost app list --installed -b | grep id: | cut -d: -f2); do
    backup_methods=$(yunohost app setting $app backup_methods)

    if [ -z "$backup_methods" ]; then
        backup_methods=mylocalborg
    fi

    if [ "$backup_methods" != "none" ]; then
        yunohost backup create $ignore_system -n auto_$app --methods $backup_methods --apps $app
    fi
done

Don’t forget to give rights to execute !

chmod a+x /etc/cron.daily/yunohost-99-backup

Disable the backup for a particular app

yunohost app setting strut backup_methods -v none


How to backup your YunoHost server on another server
Borg & Nextcloud
Déplacer sauvegardes / Move backup files
Borg backup local et distants
#2

@ljf
Thanks for this guide.


#3

Est-ce qu’on peut choisir à quelle heure il se lance ?


#4

@ljf friend for the guidance its really knowledgeable thread. :slightly_smiling_face:


#5

Salutations, j’ai une erreur de pip3 (Egg_info) lorsque je tente d’installer Borg Backup depuis une réinstall (avec restauration de backup config & data).

Versions :
Yunohost : 2.7.12
Borg :1.1.5

Une personne peut-elle tester de son côté avec les même versions et voir si elle rencontre la même erreur ?

Le log :

Running setup.py (path:/tmp/pip-build-y7k7x5yh/borgbackup/setup.py) egg_info for package borgbackup
    Traceback (most recent call last):
      File "<string>", line 17, in <module>
      File "/tmp/pip-build-y7k7x5yh/borgbackup/setup.py", line 846, in <module>
        extras_require=extras_require,
      File "/usr/lib/python3.4/distutils/core.py", line 108, in setup
        _setup_distribution = dist = klass(attrs)
      File "/usr/lib/python3/dist-packages/setuptools/dist.py", line 266, in __init__
        _Distribution.__init__(self,attrs)
      File "/usr/lib/python3.4/distutils/dist.py", line 280, in __init__
        self.finalize_options()
      File "/usr/lib/python3/dist-packages/setuptools/dist.py", line 301, in finalize_options
        ep.load()(self, ep.name, value)
      File "/tmp/pip-build-y7k7x5yh/borgbackup/setuptools_scm-2.1.0-py3.4.egg/setuptools_scm/integration.py", line 10, in version_keyword
      File "/tmp/pip-build-y7k7x5yh/borgbackup/setuptools_scm-2.1.0-py3.4.egg/setuptools_scm/version.py", line 44, in _warn_if_setuptools_outdated
    setuptools_scm.version.SetuptoolsOutdatedWarning: your setuptools is too old (<12)
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):

  File "<string>", line 17, in <module>

  File "/tmp/pip-build-y7k7x5yh/borgbackup/setup.py", line 846, in <module>

    extras_require=extras_require,

  File "/usr/lib/python3.4/distutils/core.py", line 108, in setup

    _setup_distribution = dist = klass(attrs)

  File "/usr/lib/python3/dist-packages/setuptools/dist.py", line 266, in __init__

    _Distribution.__init__(self,attrs)

  File "/usr/lib/python3.4/distutils/dist.py", line 280, in __init__

    self.finalize_options()

  File "/usr/lib/python3/dist-packages/setuptools/dist.py", line 301, in finalize_options

    ep.load()(self, ep.name, value)

  File "/tmp/pip-build-y7k7x5yh/borgbackup/setuptools_scm-2.1.0-py3.4.egg/setuptools_scm/integration.py", line 10, in version_keyword

  File "/tmp/pip-build-y7k7x5yh/borgbackup/setuptools_scm-2.1.0-py3.4.egg/setuptools_scm/version.py", line 44, in _warn_if_setuptools_outdated

setuptools_scm.version.SetuptoolsOutdatedWarning: your setuptools is too old (<12)

----------------------------------------
Cleaning up...
Command python setup.py egg_info failed with error code 1 in /tmp/pip-build-y7k7x5yh/borgbackup
Exception information:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/pip/basecommand.py", line 122, in main
    status = self.run(options, args)
  File "/usr/lib/python3/dist-packages/pip/commands/install.py", line 290, in run
    requirement_set.prepare_files(finder, force_root_egg_info=self.bundle, bundle=self.bundle)
  File "/usr/lib/python3/dist-packages/pip/req.py", line 1230, in prepare_files
    req_to_install.run_egg_info()
  File "/usr/lib/python3/dist-packages/pip/req.py", line 326, in run_egg_info
    command_desc='python setup.py egg_info')
  File "/usr/lib/python3/dist-packages/pip/util.py", line 716, in call_subprocess
    % (command_desc, proc.returncode, cwd))
pip.exceptions.InstallationError: Command python setup.py egg_info failed with error code 1 in /tmp/pip-build-y7k7x5yh/borgbackup

Édit: pip3 et/ou setuptools (de pip) n’étaient pas à jours, j’ai effectué la mise-à-jour avec ces commandes -en sachant qu’un reboot a été nécessaire-

sudo pip install -U pip
sudo pip3 install --upgrade setuptools

Puis j’ai pu install Borg Backup avec un

sudo pip3 install borgbackup


#6

J’avais mis en place cette solution de backup sur un DD externe, qui marchait très bien. Je viens de la tester après la migration vers stretch, et ça ne marche plus :

root@lamo:/etc/cron.daily# yunohost backup create --system conf_ldap -n test --method myborg --debug
139  DEBUG loading actions map namespace 'yunohost'
154  DEBUG extra parameter classes loaded: ['ask', 'password', 'required', 'pattern']
154  DEBUG initializing base actions map parser for cli
155  DEBUG registering new callback action 'yunohost.utils.packages.ynh_packages_version' to ['-v', '--version']
207  DEBUG lock has been acquired
247  DEBUG loading python module yunohost.backup took 0.040s
247  INFO processing action [18417.1]: yunohost.backup.create with args={'description': None, 'apps': None, 'system':
 ['conf_ldap'], 'output_directory': None, 'methods': ['myborg'], 'no_compress': False, 'name': 'test'}
248  DEBUG custom hook folder not found for action 'backup' in /etc/yunohost/hooks.d/
248  DEBUG Exécution des scripts de sauvegarde...
253  DEBUG custom hook folder not found for action 'backup' in /etc/yunohost/hooks.d/
253  DEBUG Exécution de la commande « sh -c YNH_BACKUP_DIR=/home/yunohost.backup/tmp/test YNH_BACKUP_CSV=/tmp/backupc
sv_kz3Bff YNH_CWD=/home/yunohost.backup/tmp/test BASH_XTRACEFD=7 /bin/bash -x "/usr/share/yunohost/hooks/backup/05-co
nf_ldap" /home/yunohost.backup/tmp/test 7>&1 »...
264  DEBUG + set -eu
265  DEBUG + source /usr/share/yunohost/helpers.d/filesystem
265  DEBUG ++ CAN_BIND=1
265  DEBUG + backup_dir=/home/yunohost.backup/tmp/test/conf/ldap
266  DEBUG + ynh_backup /etc/ldap/slapd.conf /home/yunohost.backup/tmp/test/conf/ldap/slapd.conf
266  DEBUG + local SRC_PATH=/etc/ldap/slapd.conf
266  DEBUG + local DEST_PATH=/home/yunohost.backup/tmp/test/conf/ldap/slapd.conf
266  DEBUG + local IS_BIG=0
267  DEBUG + BACKUP_CORE_ONLY=0
267  DEBUG + '[' 0 == 1 ']'
267  DEBUG + [[ -e /etc/ldap/slapd.conf ]]
267  DEBUG ++ realpath /etc/ldap/slapd.conf
267  DEBUG + SRC_PATH=/etc/ldap/slapd.conf
268  DEBUG + [[ -z /home/yunohost.backup/tmp/test/conf/ldap/slapd.conf ]]
268  DEBUG + [[ / == \/ ]]
268  DEBUG + DEST_PATH=conf/ldap/slapd.conf
268  DEBUG + [[ c == \/ ]]
268  DEBUG + [[ f == \/ ]]
268  DEBUG + [[ ! -e conf/ldap/slapd.conf ]]
269  DEBUG + local REL_DIR=
269  DEBUG + REL_DIR=/
269  DEBUG + DEST_PATH=/conf/ldap/slapd.conf
269  DEBUG + DEST_PATH=conf/ldap/slapd.conf
269  DEBUG ++ echo /etc/ldap/slapd.conf
269  DEBUG ++ sed -r 's/"/\"\"/g'
269  DEBUG + local SRC=/etc/ldap/slapd.conf
270  DEBUG ++ echo conf/ldap/slapd.conf
270  DEBUG ++ sed -r 's/"/\"\"/g'
270  DEBUG + local DEST=conf/ldap/slapd.conf
270  DEBUG + echo '"/etc/ldap/slapd.conf","conf/ldap/slapd.conf"'
270  DEBUG ++ dirname /home/yunohost.backup/tmp/test/conf/ldap/slapd.conf
270  DEBUG + mkdir -p /home/yunohost.backup/tmp/test/conf/ldap
270  DEBUG + sudo slapcat -b cn=config -l /home/yunohost.backup/tmp/test/conf/ldap/cn=config.master.ldif
322  DEBUG + sudo slapcat -b dc=yunohost,dc=org -l /home/yunohost.backup/tmp/test/conf/ldap/dc=yunohost-dc=org.ldif
369  DEBUG custom hook folder not found for action 'restore' in /etc/yunohost/hooks.d/
381  DEBUG Envoi de tous les fichiers dans la sauvegarde dans de référentiel borg-backup…
381  DEBUG system hook folder not found for action 'backup_method' in /usr/share/yunohost/hooks/
382  DEBUG Exécution de la commande « sh -c YNH_CWD=/etc/yunohost/hooks.d/backup_method BASH_XTRACEFD=7 /bin/bash -x "./05-myborg" need_mount /home/yunohost.backup/tmp/test test /home/yunohost.backup/archives 120425 '' 7>&1 »...
389  DEBUG + set -e
390  DEBUG + repo=/media/DD2T/Sauvegardes/sauvyunohost/borg
390  DEBUG + work_dir=/home/yunohost.backup/tmp/test
390  DEBUG + name=test
390  DEBUG + size=120425
391  DEBUG + description=
391  DEBUG + case "$1" in
391  DEBUG + do_need_mount /home/yunohost.backup/tmp/test test /media/DD2T/Sauvegardes/sauvyunohost/borg 120425
391  DEBUG + true
391  DEBUG + exit 0
499  DEBUG system hook folder not found for action 'backup_method' in /usr/share/yunohost/hooks/
500  DEBUG Exécution de la commande « sh -c YNH_CWD=/etc/yunohost/hooks.d/backup_method BASH_XTRACEFD=7 /bin/bash -x "./05-myborg" backup /home/yunohost.backup/tmp/test test /home/yunohost.backup/archives 120425 '' 7>&1 »...
520  DEBUG + set -e
522  DEBUG + repo=/media/DD2T/Sauvegardes/sauvyunohost/borg
523  DEBUG + work_dir=/home/yunohost.backup/tmp/test
523  DEBUG + name=test
524  DEBUG + size=120425
524  DEBUG + description=
524  DEBUG + case "$1" in
525  DEBUG + do_backup /home/yunohost.backup/tmp/test test /media/DD2T/Sauvegardes/sauvyunohost/borg 120425
525  DEBUG + work_dir=/home/yunohost.backup/tmp/test
526  DEBUG + name=test
526  DEBUG + repo=/media/DD2T/Sauvegardes/sauvyunohost/borg
527  DEBUG + size=120425
527  DEBUG + description=
528  DEBUG + LOGFILE=/var/log/backup_borg.log
528  DEBUG + ERRFILE=/var/log/backup_borg.err
528  DEBUG ++ date +%d_%m_%y_%H:%M
529  DEBUG + current_date=26_06_18_11:13
529  DEBUG + pushd /home/yunohost.backup/tmp/test
530  DEBUG /home/yunohost.backup/tmp/test /etc/yunohost/hooks.d/backup_method
530  DEBUG + borg create /media/DD2T/Sauvegardes/sauvyunohost/borg::test_26_06_18_11:13 ./
829  ERROR Échec de l’exécution du script « /etc/yunohost/hooks.d/backup_method/05-myborg »
Traceback (most recent call last):
  File "/usr/lib/moulinette/yunohost/hook.py", line 283, in hook_callback
    no_trace=no_trace, raise_on_error=True, user="root")
  File "/usr/lib/moulinette/yunohost/hook.py", line 381, in hook_exec
    errno.EIO, m18n.n('hook_exec_failed', path=path))
MoulinetteError: [Errno 5] Échec de l’exécution du script « /etc/yunohost/hooks.d/backup_method/05-myborg »
836  DEBUG action [18417.1] executed in 0.589s
837  DEBUG lock has been released
837  ERROR Échec de la méthode de sauvegarde personnalisée à l’étape « backup »

Mais je ne comprends pas ce qui plante… @ljf, est-ce que tu pourrais remettre le tuto à jour pour un fonctionnement post migration ?


#7

I had updated the script to run with 2.7 or 3.x


#8

Je viens de vérifier mes backups, et je n’ai qu’une partie des apps qui est bien sauvegardée, sans réussir à comprendre pourquoi.
Par exemple, le backup de zerobin fonctionne, et pas celui de mailman :

La sauvegarde classique marche :

admin@lamo:/media/DD2T/Sauvegardes/sauvyunohost/borgmount$ sudo yunohost backup create --apps mailman
Succès ! Sauvegarde terminée
name: 20180720-114813
results:
  apps:
    mailman: Success
  system:
size: 16806999

Et la sauvegarde avec la méthode borg non :

admin@lamo:/media/DD2T/Sauvegardes/sauvyunohost/borgmount$ sudo yunohost backup create --apps mailman -n test --method myborg --debug
[...]
1739 DEBUG + borg create /media/DD2T/Sauvegardes/sauvyunohost/borg::test_20_07_18_11:45 ./
4549 ERROR Échec de l’exécution du script « /etc/yunohost/hooks.d/backup_method/05-myborg »
Traceback (most recent call last):
  File "/usr/lib/moulinette/yunohost/hook.py", line 283, in hook_callback
    no_trace=no_trace, raise_on_error=True, user="root")
  File "/usr/lib/moulinette/yunohost/hook.py", line 381, in hook_exec
    errno.EIO, m18n.n('hook_exec_failed', path=path))
MoulinetteError: [Errno 5] Échec de l’exécution du script « /etc/yunohost/hooks.d/backup_method/05-myborg »
4771 DEBUG action [31130.1] executed in 4.543s
4772 DEBUG lock has been released
4773 ERROR Échec de la méthode de sauvegarde personnalisée à l’étape « backup »

Une idée de ce qui bloque ?


#9

Salut, j’ai toujours un bug dans mon backup, avec pas mal d’app qui ne sont pas sauvegardées, sans que je comprenne pourquoi.
Quand je le lance à la main, j’ai cette erreur qui revient plusieurs fois (une fois par app je pense) :

Erreur : Le dossier de sortie n’est pas vide

Ce qui est bizarre : si je lance le backup de mailman par exemple avec la méthode myborg, ça marche. Par contre, elle n’est pas sauvegardée si je lance le script. Est-ce que quelqu’un a une idée de ce que ça peut être que ce dossier de sortie ?


#10

@tomdereub
Il semble qu’il y a des dossiers temporaires qui n’ont pas été éffacés dans /home/yunohost.backup/tmp/

Mais attention ! Logiquement yunohost s’occupe de les supprimer si ils sont toujours présents. Il y a une façon précise de les enlever, il ne faut pas supprime rle contenu car il s’agit de la vraie copie en cours d’utilisation des fichiers.

En debug tu devrais voir le dossier en question avec un message comme celui-ci:
“temporary directory for backup CHEMIN_DU_DOSSIER already exists”


#11

Quand tu dis en debug, c’est en lançant le backup d’une appli à la main ? Comme je disais, pour celles qui foirent, si je le lance à la main ça marche. J’ai testé avec mailman, opensondage, et je suis en train de le tester avec nextcloud (le backup a l’air de marcher, mais il va prendre un peu de temps).

En gros, si je lance le script de backup :
sudo ./yunohost-99-backup
j’ai les 3/4 de mes apps qui ne se backup pas, avec comme seule erreur " Le dossier de sortie n’est pas vide"
Si je les backups à la main : sudo yunohost backup create -n test_nextcloud --method myborg --apps nextcloud -» ça marche.


#12

Est-ce que tu peux mettre une copie du script yunohost-99-backup


#13

Le voici :

#!/bin/bash
yunohost app setting nextcloud backup_core_only -d

filter_hooks() {
    ls /usr/share/yunohost/hooks/backup/ /etc/yunohost/hooks.d/backup/ | grep "\-$1_" | cut -d"-" -f2 | uniq
}

# Backup system part conf
yunohost backup create -n auto_conf --method myborg --system $(filter_hooks conf)

# Backup system data
yunohost backup create -n auto_data --method myborg --system $(filter_hooks data)

# Backup all apps independently
for app in $(yunohost app list --installed -b | grep id: | cut -d: -f2); do
    backup_methods=$(yunohost app setting $app backup_methods)

    if [ -z "$backup_methods" ]; then
        backup_methods=myborg
    fi

    if [ "$backup_methods" != "none" ]; then
        yunohost backup create -n auto_$app --method $backup_methods --apps $app
    fi
done

Et pour mes deux wordpress j’ai une autre erreur, qui a plutôt l’air liée à une histoire de version de php :

3608 WARNING !!! Source path '/etc/php/7.0/fpm/conf.d/20-wordpress.ini' does not exist !!!
3608 DEBUG + local SRC_PATH=/etc/nginx/conf.d/santequilibre.lamonerie.net.d/wordpress.conf
3609 WARNING !!
3609 DEBUG + local DEST_PATH=
3609 WARNING   wordpress's script has encountered an error. Its execution was cancelled.
3610 DEBUG + local IS_BIG=0
3610 WARNING !!
3610 DEBUG + BACKUP_CORE_ONLY=0
3611 WARNING

#14

Met --debug à la fin des commandes yunohost dans ton script et fait tourner le script pour voir ce qu’il dit.

Pour wordpress, pas sûr que tu sois à jour sur l’app, mais si c’est le cas tente

touch  /etc/php/7.0/fpm/conf.d/20-wordpress.ini

#15

Pour wordpress, pas de réponse sur le touch. À priori je suis à jour, en tout cas je n’ai aucune màj de proposée…

Pour le backup avec debug, ça me donne ça :

652  INFO processing action [16663.1]: yunohost.backup.create with args={'description': None, 'apps': None, 'system':
 ['conf_ldap', 'conf_ssh', 'conf_ynh_mysql', 'conf_ssowat', 'conf_ynh_firewall', 'conf_ynh_certs', 'conf_xmpp', 'conf
_nginx', 'conf_cron', 'conf_ynh_currenthost'], 'output_directory': None, 'methods': ['myborg'], 'no_compress': False,
 'name': 'auto_conf'}
759  DEBUG temporary directory for backup '/home/yunohost.backup/tmp/auto_conf' already exists
760  DEBUG action [16663.1] executed in 0.108s
761  DEBUG lock has been released
761  ERROR Le dossier de sortie n’est pas vide
ls: impossible d'accéder à '/etc/yunohost/hooks.d/backup/': Aucun fichier ou dossier de ce type
130  DEBUG loading actions map namespace 'yunohost'

Et dans le dossier /etc/yunohost.backup/tmp j’ai ça :

admin@lamo:/home/yunohost.backup/tmp$ ls
20170429-235549  20170701-030035  20170708-012532  20170816-030025  20180720-115543  auto_mastodon     auto_rainloop
20170608-034506  20170704-030030  20170710-030035  20170818-134245  auto_conf        auto_nextcloud
20170608-034623  20170707-030036  20170711-000405  20180711-123248  auto_data        auto_opensondage
20170628-030016  20170708-003403  20170807-030025  20180720-115318  auto_mailman     auto_peertube

Du coup je comprends mieux pourquoi mes backups à la main marchent, c’est juste une question de nom. Comment est-ce que je peux nettoyer ce dossier tmp ?


#16

Bon, j’ai réglé temporairement le problème en changeant le nom donné aux backups dans le script (auto1 à la place de auto), donc mes backups marchent.
Par contre j’aimerais bien une solution pour nettoyer ce dossier tmp, si quelqu’un sait comment faire. J’ai bien compris qu’il ne fallait pas tout supprimer comme un bourrin…


#17

Petit up, si quelqu’un pouvait me dire comment nettoyer ce dossier tmp sans perdre de données…