Pour la sécurité en cas de besoins de restauration des données:
Nous avons des sauvegardes locales journalières des données et du système sur le volume /mnt/backups/borgarchives de 1 To avec avec Borg App, plus une sauvegarde journalière (aussi avec Borg App), chiffrée sur un serveur Yunohost auto-hébergé où est installé Borg Server sur un disque dur de 2 To.
Il est tout de même conseillé malgré toutes ces précautions aux utilisateurs qui ont des données sur Nextcloud (Cloud Linux07) de bien faire des sauvegardes de temps à autres. Nous ne pouvons pas garantir à 100% de ne jamais rien perdre, mais nous faisons tout notre possible pour éviter de risquer de perdre vos données.
Fichier de configuration des sauvegardes distantes vers BorgServer (machine auto-hébergé à l'adresse de l'association Linux07)
/etc/yunohost/hooks.d/backup_method/05-borg_app
#!/bin/bash
set -eo pipefail
app="${0#"./05-"}"
app="${app%"_app"}"
BORG_PASSPHRASE="$(yunohost app setting $app passphrase)"
repo="$(yunohost app setting $app repository)" #$4
if ssh-keygen -F "[domain.tld]:<PORT_SSH>" >/dev/null ; then
BORG_RSH="ssh -i /root/.ssh/id_${app}_ed25519 -oStrictHostKeyChecking=yes "
else
BORG_RSH="ssh -i /root/.ssh/id_${app}_ed25519 -oStrictHostKeyChecking=no "
fi
do_need_mount() {
true
}
LOGFILE=/var/log/backup_borg.err
log_with_timestamp() {
sed -e "s/^/[$(date +"%Y-%m-%d_%H:%M:%S")] /" | tee -a $LOGFILE
}
do_backup() {
export BORG_PASSPHRASE
export BORG_RSH
export BORG_RELOCATED_REPO_ACCESS_IS_OK=yes
work_dir="$1"
name="$2"
repo="$3"
size="$4"
description="$5"
current_date=$(date +"%Y-%m-%d_%H:%M")
pushd "$work_dir"
set +e
if borg init -e repokey "$repo" ; then
#human_size=`echo $size | awk '{ suffix=" KMGT"; for(i=1; $1>1024 && i < length(suffix); i++) $1/=1024; print int($1) substr(suffix, i, 1), $3; }'`
# Speed in Kbps
#speed=1000
#evaluated_time=$(($size / ($speed * 1000 / 8) / 3600))
echo "Hello,
Your first backup on $repo is starting.
This is an automated message from your beloved YunoHost server." | /usr/bin/mail.mailutils -a "Content-Type: text/plain; charset=UTF-8" -s "[YNH] First backup is starting" "root"
fi
set -e
borg create "$repo::_${name}-${current_date}" ./ 2>&1 >/dev/null | log_with_timestamp
popd
# About thi _20 it's a crazy fix to avoid pruning wordpress__2
# if you prune wordpress
borg prune "$repo" -P "_${name}-" --keep-hourly 2 --keep-daily=7 --keep-weekly=8 --keep-monthly=12 2>&1 >/dev/null | log_with_timestamp
# Prune legacy archive name without error on wordpress/wordpress__2
borg prune "$repo" -P "${name}_" --keep-within 2m --keep-monthly=12 2>&1 >/dev/null | log_with_timestamp
# We prune potential manual backup older than 1 year
borg prune "$repo" --keep-within 1y 2>&1 >/dev/null | log_with_timestamp
}
do_mount() {
export BORG_PASSPHRASE
export BORG_RSH
work_dir="$1"
name="$2"
repo="$3"
size="$4"
description="$5"
borg mount "$repo::$name" "$work_dir" 2>&1 >/dev/null | log_with_timestamp
}
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
Fichier de configuration des sauvegardes locales
/etc/yunohost/hooks.d/backup_method/05-borg__2_app
#!/bin/bash
set -eo pipefail
app="${0#"./05-"}"
app="${app%"_app"}"
BORG_PASSPHRASE="$(yunohost app setting $app passphrase)"
repo="$(yunohost app setting $app repository)" #$4
if ssh-keygen -F "" >/dev/null ; then
BORG_RSH="ssh -i /root/.ssh/id_${app}_ed25519 -oStrictHostKeyChecking=yes "
else
BORG_RSH="ssh -i /root/.ssh/id_${app}_ed25519 -oStrictHostKeyChecking=no "
fi
do_need_mount() {
true
}
LOGFILE=/var/log/backup_borg.err
log_with_timestamp() {
sed -e "s/^/[$(date +"%Y-%m-%d_%H:%M:%S")] /" | tee -a $LOGFILE
}
do_backup() {
export BORG_PASSPHRASE
export BORG_RSH
export BORG_RELOCATED_REPO_ACCESS_IS_OK=yes
work_dir="$1"
name="$2"
repo="$3"
size="$4"
description="$5"
current_date=$(date +"%Y-%m-%d_%H:%M")
pushd "$work_dir"
set +e
if borg init -e repokey "$repo" ; then
#human_size=`echo $size | awk '{ suffix=" KMGT"; for(i=1; $1>1024 && i < length(suffix); i++) $1/=1024; print int($1) substr(suffix, i, 1), $3; }'`
# Speed in Kbps
#speed=1000
#evaluated_time=$(($size / ($speed * 1000 / 8) / 3600))
echo "Hello,
Your first backup on $repo is starting.
This is an automated message from your beloved YunoHost server." | /usr/bin/mail.mailutils -a "Content-Type: text/plain; charset=UTF-8" -s "[YNH] First backup is starting" "root"
fi
set -e
borg create "$repo::_${name}-${current_date}" ./ 2>&1 >/dev/null | log_with_timestamp
popd
# About thi _20 it's a crazy fix to avoid pruning wordpress__2
# if you prune wordpress
borg prune "$repo" -P "_${name}-" --keep-hourly 2 --keep-daily=7 --keep-weekly=8 --keep-monthly=12 2>&1 >/dev/null | log_with_timestamp
# Prune legacy archive name without error on wordpress/wordpress__2
borg prune "$repo" -P "${name}_" --keep-within 2m --keep-monthly=12 2>&1 >/dev/null | log_with_timestamp
# We prune potential manual backup older than 1 year
borg prune "$repo" --keep-within 1y 2>&1 >/dev/null | log_with_timestamp
}
do_mount() {
export BORG_PASSPHRASE
export BORG_RSH
work_dir="$1"
name="$2"
repo="$3"
size="$4"
description="$5"
borg mount "$repo::$name" "$work_dir" 2>&1 >/dev/null | log_with_timestamp
}
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
Tous les jours deux scripts sont lancés pour sauvegarder les bases de données, un pour les bases de données mysql et un autre pour les bases de données postgresql.
Pour voir les databases
mysql -e "show databases;" | grep -Ev '^(Database|information_schema|performance_schema|mysql|sys)$'
dolibarr
dolibarr__2
etherpad_mypads
my_webapp
nextcloud
opensondage
phpmyadmin
roundcube
Scripts pour sauvegarder les bases de données Mysql et garder des logs, auparavant créer les dossiers et fichiers scripts.
mkdir -p /mnt/backups/mysql_dumps
mkdir -p /root/Scripts/Sauv_Dumps_Logs/Dumps
touch /root/Scripts/run_mysql_backups.sh
touch /root/Scripts/mysql_backups.sh
/root/Scripts/mysql_backup.sh
#!/bin/sh
dest=/mnt/backups/mysql_dumps
echo "Sauvegarde bdd dolibarr à $(TZ=Europe/Paris date)"
mysqldump dolibarr > "$dest/dolibarr-dump-$( date '+%Y-%m-%d_%H-%M-%S' ).sql" -u root --password=''
echo "- Fin dump bdd dolibarr à $(TZ=Europe/Paris date)"
echo "Sauvegarde bdd dolibarr__2 à $(TZ=Europe/Paris date)"
mysqldump dolibarr__2 > "$dest/dolibarr__2-dump-$( date '+%Y-%m-%d_%H-%M-%S' ).sql" -u root --password=''
echo "- Fin dump bdd dolibarr__2 à $(TZ=Europe/Paris date)"
echo "Sauvegarde bdd etherpad_mypads à $(TZ=Europe/Paris date)"
mysqldump etherpad_mypads > "$dest/etherpad_mypads-dump-$( date '+%Y-%m-%d_%H-%M-%S' ).sql" -u root --password=''
echo "- Fin dump bdd etherpad_mypads à $(TZ=Europe/Paris date)"
echo "Sauvegarde bdd my_webapp à $(TZ=Europe/Paris date)"
mysqldump my_webapp > "$dest/my_webapp-dump-$( date '+%Y-%m-%d_%H-%M-%S' ).sql" -u root --password=''
echo "- Fin dump bdd my_webapp à $(TZ=Europe/Paris date)"
echo "Sauvegarde bdd nextcloud à $(TZ=Europe/Paris date)"
mysqldump nextcloud > "$dest/nextcloud-dump-$( date '+%Y-%m-%d_%H-%M-%S' ).sql" -u root --password=''
echo "- Fin dump bdd nextcloud à $(TZ=Europe/Paris date)"
echo "Sauvegarde bdd opensondage à $(TZ=Europe/Paris date)"
mysqldump opensondage > "$dest/opensondage-dump-$( date '+%Y-%m-%d_%H-%M-%S' ).sql" -u root --password=''
echo "- Fin dump bdd opensondage à $(TZ=Europe/Paris date)"
echo "Sauvegarde bdd phpmyadmin à $(TZ=Europe/Paris date)"
mysqldump phpmyadmin > "$dest/phpmyadmin-dump-$( date '+%Y-%m-%d_%H-%M-%S' ).sql" -u root --password=''
echo "- Fin dump bdd phpmyadmin à $(TZ=Europe/Paris date)"
echo "Sauvegarde bdd roundcube à $(TZ=Europe/Paris date)"
mysqldump roundcube > "$dest/roundcube-dump-$( date '+%Y-%m-%d_%H-%M-%S' ).sql" -u root --password=''
echo "- Fin dump bdd roundcube à $(TZ=Europe/Paris date)"
echo "Anciens dumps à supprimer (on garde les 16 derniers) :"
ls -t $dest/ | tail -n +17 | while read -r old_dump; do
echo "Suppression de $old_dump"
rm -f "$dest/$old_dump"
done
echo "- Contenu actuel du dossier :"
ls -l $dest/
Pour avoir les logs par dates dans un dossiers par mois, un autre fichier executable qui va être lancé avec un crontab.
/root/Scripts/run_mysql_backups.sh
#!/bin/bash
DATEMONTH="$(date +'%y-%m')"
DATE="$(date +'%y%m%d.%H%M')"
mkdir -p /root/Scripts/Sauv_Dumps_Logs/Dumps/${DATEMONTH}
/root/Scripts/mysql_backups.sh > /root/Scripts/Sauv_Dumps_Logs/Dumps/${DATEMONTH}/mysql_dumps_${DATE}_CRON.log 2>&1
Les rendre exécutables
chmod +x /root/Scripts/run_mysql_backups.sh
chmod +x /root/Scripts/mysql_backups.sh
Puis éditer le crontab, avec la commande crontab -e
0 1 * * * /root/Scripts/run_mysql_backups.sh
Et en prime un script qui automatise tout cela CRON_MYSQL_DUMPS.sh qui peut être exécuter pour mettre à jour si des changements dans les applications (ajouts/suppressions).
Trouver les bases Postgresql
grep -i 'type = "postgresql"' /etc/yunohost/apps/*/manifest.toml 2>/dev/null |
cut -d'/' -f5
forgejo
mattermost
mobilizon
Scripts pour sauvegarder les bases de données Postgresql et garder des logs, auparavant créer les dossiers et fichiers scripts.
mkdir -p /mnt/backups/pg_dumps
mkdir -p /root/Scripts/Sauv_Dumps_Logs/Dumps
touch /root/Scripts/run_mysql_backups.sh
touch /root/Scripts/mysql_backups.sh
/root/Scripts/pg_backup.sh
#!/bin/sh
dest=/mnt/backups/pg_dumps
echo "Sauvegarde bdd forgejo à $(TZ=Europe/Paris date)"
PGPASSWORD="$(yunohost app setting forgejo db_pwd)" pg_dump -U forgejo -Fc forgejo > $dest/forgejo-$(date '+%Y-%m-%d_%H-%M-%S').sql
echo "- Fin dump bdd forgejo à $(TZ=Europe/Paris date)"
echo "Sauvegarde bdd mattermost à $(TZ=Europe/Paris date)"
PGPASSWORD="$(yunohost app setting mattermost db_pwd)" pg_dump -U mattermost -Fc mattermost > $dest/mattermost-$(date '+%Y-%m-%d_%H-%M-%S').sql
echo "- Fin dump bdd mattermost à $(TZ=Europe/Paris date)"
echo "Sauvegarde bdd mobilizon à $(TZ=Europe/Paris date)"
PGPASSWORD="$(yunohost app setting mobilizon db_pwd)" pg_dump -U mobilizon -Fc mobilizon > $dest/mobilizon-$(date '+%Y-%m-%d_%H-%M-%S').sql
echo "- Fin dump bdd mobilizon à $(TZ=Europe/Paris date)"
echo "Anciens dumps à supprimer (on garde les 6 derniers) :"
ls -t $dest/ | tail -n +7 | while read -r old_dump; do
echo "Suppression de $old_dump"
rm -f "$dest/$old_dump"
done
echo "- Contenu actuel du dossier :"
ls -l $dest/
Pour avoir les logs par dates dans un dossiers par mois un fichier autre fichier executable qui va être lancé avce le cron.
/root/Scripts/run_pg_backups.sh
#!/bin/bash
DATEMONTH="$(date +'%y-%m')"
DATE="$(date +'%y%m%d.%H%M')"
mkdir -p /root/Scripts/Sauv_Dumps_Logs/Dumps/${DATEMONTH}
/root/Scripts/mysql_backups.sh > /root/Scripts/Sauv_Dumps_Logs/Dumps/${DATEMONTH}/pg_dumps_${DATE}_CRON.log 2>&1
Les rendre exécutables
chmod +x /root/Scripts/run_pg_backups.sh
chmod +x /root/Scripts/pg_backups.sh
Puis édité le crontab avec la commande crontab -e
0 1 * * * /root/Scripts/run_mysql_backups.sh
10 1 * * * /root/Scripts/run_pg_backups.sh
Et en prime un scripts qui automatise tout cela CRON_POSTGRESQL_DUMPS.sh qui peut être exécuter pour mettre à jour si des changements dans les applications (ajouts/suppressions).
0 1 * * * /root/Scripts/mysql_backup.sh >> /root/Sauv_mysqldump.log
10 1 * * * /root/Scripts/pg_backup.sh >> /root/Sauv_pgdump.log