Running Splunk forwarder on a FreeBSD 14 host

Few months ago I discovered that Splunk did not bother updating its forwarder to support FreeBSD 14. It’s a real PITA for many users, including myself. After asking around for support about that problem and seeing Splunk quietly ignoring the voice of its users, I’ve decided to try and run the Linux version on FreeBSD.

Executive summary: it works great on both FreeBSD 14 and 13, but with some limitations.

A user like me has few options:

  1. (re)check if you really need a local log forwarder (for everything that is not handled by syslog), if you don’t, just ditch the Splunk forwarder and tune syslogd to send logs to a Splunk indexer directly
  2. find an alternate solution that suits you: very hard is you have a full Splunk ecosystem or if, like me, you really are addicted to Splunk
  3. Run the Linux version on FreeBSD: needs some skills but works great so far

Obviously, I’m fine with the latest.

Limitations

You will run a proprietary Linux binary on a totally unsupported environment: you are on your own & it can break anytime, either because of FreeBSD, or because of Splunk.

You will run the Splunk forwarder inside a chroot environment: your log files will have to be available inside the chroot, or Splunk won’t be able to read them. Also, no ACL residing on your FreeBSD filesystem will be available to the Linux chroot, so you must not rely on ACLs to grant Splunk access to your log files.

How to

Below you’ll find a quick&dirty step by step guide that worked for me. Not everything will be detailed or explained and YMMV.

First step is to install a Linux environment. You must activate the Linux compatibility feature. I’ve used both Debian and Devuan successfully. Here is what I’ve done for Devuan:

zfs create -o mountpoint=/compat/devuan01 sas/compat_devuan01 
curl -OL https://git.devuan.org/devuan/debootstrap/raw/branch/suites/unstable/scripts/ceres
mv ceres /usr/local/share/debootstrap/scripts/daedalus
curl -OL https://files.devuan.org/devuan-archive-keyring.gpg
mv devuan-archive-keyring.gpg /usr/local/share/keyrings/
ln -s /usr/local/share/keyrings /usr/share/keyrings
debootstrap daedalus /compat/devuan01

This last step should fail, it seems that it’s to be expected. Following that same guide:

chroot /compat/devuan01 /bin/bash
dpkg --force-depends -i /var/cache/apt/archives/*.deb
echo "APT::Cache-Start 251658240;" > /etc/apt/apt.conf.d/00chroot
exit

Back on the host, add what you need to /etc/fstab:

# Device        Mountpoint              FStype          Options                      Dump    Pass#
devfs           /compat/devuan01/dev      devfs           rw,late                      0       0
tmpfs           /compat/devuan01/dev/shm  tmpfs           rw,late,size=1g,mode=1777    0       0
fdescfs         /compat/devuan01/dev/fd   fdescfs         rw,late,linrdlnk             0       0
linprocfs       /compat/devuan01/proc     linprocfs       rw,late                      0       0
linsysfs        /compat/devuan01/sys      linsysfs        rw,late                      0       0

and mount all, then finish install:

mount -al
chroot /compat/devuan01 /bin/bash
apt update
apt install openrc
exit

Make your log files available inside the chroot:

mkdir -p /compat/debian_stable01/var/hostnamedlog
mount_nullfs /var/named/var/log /compat/debian_stable01/var/hostnamedlog
mkdir -p /compat/debian_stable01/var/hostlog
mount_nullfs /var/log /compat/debian_stable01/var/hostlog

Note: /var/named/var/log and /var/log are ZFS filesystems. You’ll have to make the nullfs mounts permanent by adding them in /etc/fstab.

Now you can install the Splunk forwarder:

chroot /compat/devuan01 /bin/bash
useradd -m splunkfwd
export SPLUNK_HOME="/opt/splunkforwarder"
mkdir $SPLUNK_HOME
echo /opt/splunkforwarder/lib >/etc/ld.so.conf.d/splunk.conf 
ldconfig
apt install curl
dpkg -i splunkforwarder_package_name.deb
/opt/splunkforwarder/bin/splunk enable boot-start -systemd-managed 0 -user splunkfwd
exit

Note: splunk enable boot-start -systemd-managed 0 activates the Splunk service as an old-school init.d service. systemd is not available in the context of a Linux chroot on FreeBSD.

Now from the host, grab your config files and copy them in your Linux chroot:

cp /opt/splunkforwarder/etc/system/local/{inputs,limits,outputs,props,transforms}.conf /compat/devuan01/opt/splunkforwarder/etc/system/local/

Then edit /compat/devuan01/opt/splunkforwarder/etc/system/local/inputs.conf accordingly: in my case it means I must replace /var/log by /var/hostnamedlog and /var/named/var/log by /var/hostnamedlog.

Go back to your Devuan and start Splunk:

chroot /compat/devuan01 /bin/bash
service splunk start
exit

To do

I still need to figure out how to properly start the service from outside the chroot (when FreeBSD boots). No big deal.

Related posts

Borg, Kopia, Restic : sauvegarde et utilisation des ressources

Je vais m'intéresser dans cet article un peu plus en détail aux métriques relatives aux sauvegardes. Notamment celles qui sont faciles à mesurer : le temps d'exécution d'une sauvegarde et les volumétrie des transferts réseau. La consommation CPU n'est pas évidente à mesurer sur la plate-forme de test et dans mon contexte, c'est quelque chose qui a assez peu d’importance. La mesure des I/O sur le stockage aurait pu être intéressante, mais comme le disque de destination des sauvegardes est partagés avec d'autres usages ce n'était pas une métrique récupérable lors de mes tests.

Sans m'étendre trop sur la méthodologie, voici rapidement comment j'ai procédé à ces mesures. Côté client le script de sauvegarde place des lignes horodatées dans un fichier de log (début de sauvegarde pour Borg, fin de sauvegarde pour Borg, début de purge pour Borg, etc.). Côté serveur, tcpdump m'a permis d'enregistrer le traffic réseau. Les fichiers PCap ont été transformés dans tshark pour obtenir la liste des conversations réseaux. La liste horodatée et le fichier de log du client ont ensuite été injectés dans Splunk. J'obtiens donc les traces horodatées correspondant au début et à la fin de chaque tâche de sauvegarde avec, en sandwich, les nombres de paquets et volumes de données échangés entre client et serveur.
Je collecte aussi, à chaque itération du script de sauvegarde, les volumétrie des dépôts de ces sauvegardes.

Les premières statistiques que je voudrais détailler ici sont relatives à la création de la première sauvegarde. Cette création révèle déjà une différence importante entre les trois solutions :

Pour un volume initial de 145 Go

durée vol in vol out stockage
Borg 1118 s 1,2 Go 52 Go 62 Go
Kopia 716 s 1 Go 39 Go 75 Go
Restic 583 s 0,7 Go 32,2 Go 58 Go

Pour la durée de création nous avons une variation du simple au double entre Restic et Borg. C’est assez significatif. Restic est configuré pour ouvrir quatre flux de lecture concurrents, ce qui va bien évidemment maximiser l’utilisation de toutes les ressources (réseau, IO). Restic utilise aussi son serveur HTTP pour le transport. Cela lui permet une taille de paquets supérieure et donc d'en envoyer moins que Borg ou Kopia (33,1 millions pour Restic contre 54,6 millions pour Kopia). Il en résulte une quantité de données transitant inférieure aux deux autres (moins de paquets = moins d’overhead).
Notez qu’à ce stade de mon expérimentation je n’avais pas activé la compression de Kopia (inactive par défaut) mais a priori le client ssh intégré compresse les flux. La compression est aussi désactivée sur le stockage ZFS de destination.

J’ai quelques théories mais pas de vraie explication pour la différence de volume à l’arrivée, entre les logiciels d’une part et avec le volume de données qui transite d’autre part.

Les sauvegardes suivantes sont bien plus courtes puisque seules les données modifiées depuis la sauvegarde précédente sont envoyées sur le serveur. Au long cours, Restic perd son avantage face à Kopia et se rapproche des temps constatés pour Borg.

Avg Median perc98
Borg 30,54 s 30,00 s 38,86 s
Kopia 8,53 s 8,00 s 13,86 s
Restic 24,96 s 25,00 s 30,00 s

L’avantage de Kopia est réellement impressionnant.

Sur environ un mois de mesures on note même une tendance haussière pour la durée moyenne des sauvegardes Borg et Restic et baissière pour celles de Kopia (4 périodes de 7 jours, 1 de 4 jours, 295 sauvegardes pour chaque logiciel) :

Borg Kopia Restic
2024-02-19 29,07 8,76 23,72
2024-02-26 31,28 9,08 25,57
2024-03-04 31,59 8,26 25,29
2024-03-11 31,36 7,77 26,34
2024-03-18 32,38 8,38 26,09

Sur les durées des sauvegardes, Kopia est donc très largement meilleur que ses concurrents. Sur les volumes d’échange réseau il est aussi le meilleur, mais avec une marge bien moins importante. Il se place juste devant Borg et loin devant Restic. Je n’ai pas agrégé de statistiques chiffrées car ma collecte tcpdump n’était pas suffisamment «maniable» sur une longue période. J'ai par contre quelques graphiques sur une période de 4 jours, dont j’ai vérifié manuellement les données.

L’évolution de la volumétrie du stockage des sauvegardes est intéressante à plusieurs titres. Elle permet bien sûr de faire un peu de prévision en terme de capacité. Elle permet aussi de déterminer quel logiciel est le plus efficace pour empiler un maximum de sauvegardes dans un minimum d’espace. Pour finir elle met en exergue une différence absolument fondamentale dans la gestion des rétentions entre Kopia et ses 2 concurrents. Différence qui m’a vraiment pris par surprise.

Sur le graphique suivant, l’évolution du volume des sauvegardes est visible du 17 février au 21 mars. L’axe des ordonnées est en octets, l’abréviation B est pour l’anglais «billion» : 60B est donc équivalent à 60 Go.

Dès les premiers jours, Borg est bon élève, avec une approche très efficace. Kopia et Restic par contre voient les volumétries s’envoler. Restic infléchi finalement sa trajectoire avec les premières tâches de purges visant à respecter la politique de rétention.
Le repère 1 marque le moment où j’ai activé la compression pour Kopia, sans cela je craignais que mon test soit écourté par la saturation du stockage de destination.
Le repère 2 marque la première purge de sauvegardes obsolètes pour Kopia, le motif en dents de scie descendant est du au fait que Kopia purge des sauvegardes non-compressées et les remplace par des sauvegardes compressées.
Le repère 3 marque le soir du 5 mars. À ce moment les archives Borg sont au nombre de 68, les snapshots Restic au nombre de 52, et ceux de Kopia au nombre de 24. Pourtant les politiques de rétention ont été alignées :

Options de purge de Borg :

--keep-last 10 --keep-hourly 48 --keep-daily 7 --keep-weekly 4 --keep-monthly 24 --keep-yearly 3

Options de purge de Restic :

--keep-last 10 --keep-hourly 48 --keep-daily 7 --keep-weekly 4 --keep-monthly 24 --keep-yearly 3 

Options de rétention de Kopia :

	  Annual snapshots:                     3  
	  Monthly snapshots:                   24 
	  Weekly snapshots:                     4  
	  Daily snapshots:                      7
	  Hourly snapshots:                    48
	  Latest snapshots:                    10

La différence entre Borg et Restic s’explique très simplement. Borg conserve une archive sur un unique critère de rétention : une archive pourra être conservée parce qu’elle correspond à une rétention horaire (hourly) ou à une rétention journalière (daily), mais jamais les deux. Restic par contre étiquette les snapshots avec différentes rétentions : un snapshot peut être horaire et journalier et hebdomadaire, etc. De plus, il va étiqueter à l’avance les rétentions longues (annuelles, mensuelles…). Au 5 mars Restic stocke l’équivalent de 74 snapshots, même si en réalité il n’a que 52 points de restauration.
Globalement on s’y retrouve.

Borg :

(rule: daily #5):        20240222.1708642488
(rule: daily #6):        20240221.1708553824
(rule: daily #7):        20240220.1708469744
(rule: weekly #1):       20240218.1708295990
(rule: weekly[oldest] #2): 20240217.1708164925

Restic :

2024-02-17 11:35:05                monthly snapshot  /Users/patpro
                                   yearly snapshot
2024-02-18 23:41:20                weekly snapshot   /Users/patpro
2024-02-25 23:40:46                weekly snapshot   /Users/patpro
2024-02-28 19:45:29                daily snapshot    /Users/patpro
2024-02-29 12:46:31                hourly snapshot   /Users/patpro
../..
2024-02-29 19:23:42                hourly snapshot   /Users/patpro
                                   daily snapshot
                                   monthly snapshot

Dans le cas de Kopia, l’histoire est très différente. Il ne calcule tout simplement pas la rétention comme les deux autres. Pour Borg et Restic --keep-hourly 48 signifie «conserve les 48 dernières archives/snapshots horaires». Pour Kopia Hourly snapshots: 48 signifie «conserve les snapshots horaires au maximum 48 heures». C’est extrêmement différent. Souvenez-vous, dans le premier article de la série j’indiquais qu’en raison de l’utilisation de Launchd avec StartInterval «le script est réellement lancé un peu moins d'une fois par heure. Par exemple si chaque exécution dure 5 minutes, alors il faut 26h et non 24h pour qu’il soit lancé 24 fois». J’indiquais aussi que le client dort la nuit, causant une interruption dans les sauvegardes. Par ailleurs, à partir du 27 février j’ai encore réduit la plage de sauvegarde, passant ainsi de 17 ou 18 sauvegardes par jour à 8 ou 9.
Sur cette fenêtre réduite, Kopia ne peut plus faire que 8 à 9 sauvegardes par jour. Après 48h il aura donc pris l’équivalent de 16 à 18 snapshots horaires, une heure plus tard le plus vieux dépassera sa durée de vie et sera purgé. Dans la même situation Borg va garder 48 archives «horaires» s’étalant sur à peu près 6 jours.
Ajoutons à cela que Kopia gère ses snapshots comme Restic : chacun peut avoir plusieurs étiquettes de rétention.

Kopia :

  2024-02-18 23:38:41 CET ../.. (weekly-4)
  2024-02-25 23:43:54 CET ../.. (weekly-3)
  2024-02-28 19:46:56 CET ../.. (daily-7)
  2024-02-29 19:20:29 CET ../.. (daily-6,monthly-2)
  2024-03-01 19:02:51 CET ../.. (daily-5)
  2024-03-02 19:55:36 CET ../.. (daily-4)

Pour finir, Kopia n’hésite pas à supprimer les snapshots les plus anciens là où Borg et Restic vont précieusement les conserver. Au 5 mars, Kopia a déjà supprimé le tout premier snapshot. Au 20 mars le plus ancien disponible est celui du 29 février.

Voici la situation au 20 mars :

nombre de points de restauration par date et par programme

Borg Kopia Restic
2024-02-17 1 1
2024-02-18 1
2024-02-25 1
2024-02-29 1 1 1
2024-03-03 1 1 1
2024-03-06 1
2024-03-07 1
2024-03-08 1
2024-03-09 1
2024-03-10 1 1 1
2024-03-11 1
2024-03-12 1
2024-03-13 4
2024-03-14 8 1 1
2024-03-15 8 1 8
2024-03-16 8 1 8
2024-03-17 8 1 8
2024-03-18 8 1 8
2024-03-19 8 8 8
2024-03-20 7 8 7
total 71 24 52

Pour conclure, si on privilégie des tâches de sauvegardes très rapides et économes en bande passante au détriment d’une rétention garantie et lisible, Kopia est le meilleur candidat. Si à l’inverse on souhaite maximiser le nombre de points de restauration au détriment du temps de sauvegarde et de l’utilisation de la bande passante Borg l’emporte haut-la-main. L’utilisateur de Kopia pourra néanmoins utiliser Latest snapshots pour assurer une rétention minimale pour un client qui n’est pas toujours allumé pour sa sauvegarde périodique.

Borg Kopia Restic
durée des sauvegardes - + -
volume réseau + + -
gestion de la rétention + - +
Related posts

Borg, Kopia, Restic: from configuration to first backup

[This is the English translation by DeepL]
[Version originale en français]

All backup solutions require a minimum of configuration to do the job. These three solutions are no exception.
What Borg, Restic and Kopia have in common is the use of a repository into which they push backups. This repository must be initialized before the first backup can be made. In practice, here's how I proceeded with each of these programs.

Borg

Borg relies on an SSH key to open the communication tunnel between Borg on the server and Borg on the client. For this purpose, I use a dedicated SSH key and configuration. If you've mastered SSH configuration on the client side, this opens the door to fairly fine-tuning of the tunnel between client and server. We're back in familiar territory, and it's quite comfortable.

$ borg init --encryption=repokey-blake2 --rsh "ssh -F .ssh/config_bkp" bkppat@192.168.0.22:/backupmaison/bench-borg

Creating the first backup, on the other hand, is a completely different story. The number of parameters is so great that, in my scripts, I define them as variables which I then use in the various commands:

$ SSH="ssh -F .ssh/config_bkp"
$ HOMEREPO="bkppat@192.168.0.22:/backupmaison/bench-borg"
$ HOMEOPTIONS="--stats --exclude-caches --exclude-if-present .nobench-bkup"
$ SOURCEROOT="/Users/patpro"
$ ARCHIVENAME=$(date "+%Y%m%d.%s")
$ export BORG_PASSPHRASE="foobar"
$ borg create ${HOMEOPTIONS} --rsh "${SSH}" ${HOMEREPO}::${ARCHIVENAME} ${SOURCEROOT}

With Borg, all parameterization is done in this way. There is no configuration file. Fortunately, a backup task is supposed to be automated, i.e. to reside in one form or another in a script that doesn't need to be retyped manually at the command line. The disadvantage is therefore rather minor.

Kopia

If you're using SFTP transport, then Kopia works in much the same way as Borg, except that Kopia uses its own SSH implementation by default. This requires you to specify the location of the known_hosts file, for example. Nor will it take into account the configuration file of the machine's native SSH client. Unfortunately, Kopia's native implementation of the SSH protocol does not support all key types. This bug has been identified but not yet corrected. The use of Elliptic Curve keys remains possible if the Kopia client is told to use an external SSH client. For my part, I chose to create an RSA key to get around the bug.

$ kopia repository create sftp --path=/backupmaison/bench-kopia --host=192.168.0.22 --username=patpro --keyfile=/Users/patpro/.ssh/kopia_rsa --known-hosts=/Users/patpro/.ssh/known_hosts-kopia

Unlike Borg, Kopia's configuration is largely deported to the repository. This involves using policy management commands to set a certain number of parameters for use by the Kopia client.
Here's how it works in my case :

$ kopia policy list
85bf7bc7688d5819433aad9ba1c84f6b (global)

$ kopia policy set --add-dot-ignore .nobench-bkup 08c59f69009c88ee463de6acbbc59a3a
Setting policy for patpro@cassandre:/Users/patpro/08c59f69009c88ee463de6acbbc59a3a
 - adding ".nobench-bkup" to "dot-ignore filenames"

$ kopia policy set --compression=zstd --global
Setting policy for (global)
 - setting compression algorithm to zstd

These policies are inherited, from the most general to the most specific:

$ kopia policy show --global| head
Policy for (global):

Retention:
  Annual snapshots:                     3   (defined for this target)
  Monthly snapshots:                   24   (defined for this target)
  Weekly snapshots:                     4   (defined for this target)
  Daily snapshots:                      7   (defined for this target)
  Hourly snapshots:                    48   (defined for this target)
  Latest snapshots:                    10   (defined for this target)
  Ignore identical snapshots:       false   (defined for this target)

$ kopia policy show 08c59f69009c88ee463de6acbbc59a3a| head
Policy for patpro@cassandre:/Users/patpro/08c59f69009c88ee463de6acbbc59a3a:

Retention:
  Annual snapshots:                     3   inherited from (global)
  Monthly snapshots:                   24   inherited from (global)
  Weekly snapshots:                     4   inherited from (global)
  Daily snapshots:                      7   inherited from (global)
  Hourly snapshots:                    48   inherited from (global)
  Latest snapshots:                    10   inherited from (global)
  Ignore identical snapshots:       false   inherited from (global)

As the various client parameters used to define backup and purge tasks are deported, the command line for the various actions is greatly simplified. You still need to to connect the client to the backup server. This is done with a command like :

$ kopia -p foobar repository connect sftp --path=/backupmaison/bench-kopia --host=192.168.0.22 --username=patpro --keyfile=/Users/patpro/.ssh/kopia_rsa --known-hosts=/Users/patpro/.ssh/known_hosts-kopia

Disconnection is then carried out as follows:

$ kopia repository disconnect

It's important to understand that this connection and disconnection doesn't have to be done systematically. It's a mistake I made myself: in the early days of running my backup scripts, for each Kopia task I would connect, perform the task and then disconnect. The side effects are minimal, but I'll come back to that later. In any case, a connection at time T persists, because it's not a network connection. It's best to think of this as a pre-configuration of the client, enabling it to use the server's login, password and contact details to carry out backup tasks. In the rest of my tests, I simply made a connection once and never disconnected my client again. As a result, creating a backup is as simple as this trivial command:

$ kopia snapshot create /Users/patpro

The difference with Borg is obvious.

Restic

To test Restic, I decided to use the REST-server. Transport is over HTTP and the command is relatively trivial. On the server side, configuration is fairly basic, since I've simply specified the storage path, interface and TCP port for listening and the --no-auth parameter, as I don't need authentication.

$ restic -r rest:http://192.168.0.22:8000/ init

Like Borg, backup and purge tasks require all parameters to be passed on the command line:

$ export RESTIC_PASSWORD=foobar
$ restic -r rest:http://192.168.0.22:8000/ backup --verbose --exclude-if-present .nobench-bkup --one-file-system --exclude-caches --no-scan --read-concurrency 4 /Users/patpro

There's not much more to say about Restic, which behaves much like Borg in terms of settings and command line. Even if the number of parameters were to multiply, it would all take place in a perfectly readable shell script.

To conclude

I really like the readability of a command line with or without variables: it allows me to analyze a backup script in any editor and in any context. Nevertheless, I have to admit that I'm quite taken with the elegance of Kopia's policy system, even if accessing the policy content requires access to the Kopia command in a terminal as well as to the backup repository (which is a drawback). I think we're faced with a choice criterion that will depend solely on the end-user's preference.

Related posts

Borg, Kopia, Restic : de la configuration à la première sauvegarde

Toute solution de sauvegarde nécessite un minimum de configuration pour faire le travail attendu. Ces trois solutions ne font pas exception.
Borg, Restic et Kopia ont comme point commun d’utiliser un dépôt dans lequel ils poussent les sauvegardes. Ce dépôt doit être initialisé avant de pouvoir faire une première sauvegarde. En pratique, voilà comment j'ai procédé pour chacun de ses logiciels.

Borg

Le fonctionnement de Borg s’appuie sur une clé SSH pour ouvrir le tunnel de communication entre Borg sur le serveur et Borg sur le client. À cette fin, j’utilise une clé et une configuration SSH dédiées. Si on maîtrise la configuration SSH côté client, cela ouvre la porte à un paramétrage assez fin du tunnel entre le client et le serveur. On se retrouve en terrain connu et c'est plutôt confortable.

$ borg init --encryption=repokey-blake2 --rsh "ssh -F .ssh/config_bkp" bkppat@192.168.0.22:/backupmaison/bench-borg

La création de la première sauvegarde par contre est une toute autre histoire. Le nombre de paramètres est plus important, au point que dans mes scripts, je les défini sous forme de variables que j'utilise ensuite dans les différentes commandes :

$ SSH="ssh -F .ssh/config_bkp"
$ HOMEREPO="bkppat@192.168.0.22:/backupmaison/bench-borg"
$ HOMEOPTIONS="--stats --exclude-caches --exclude-if-present .nobench-bkup"
$ SOURCEROOT="/Users/patpro"
$ ARCHIVENAME=$(date "+%Y%m%d.%s")
$ export BORG_PASSPHRASE="foobar"
$ borg create ${HOMEOPTIONS} --rsh "${SSH}" ${HOMEREPO}::${ARCHIVENAME} ${SOURCEROOT}

Avec Borg, tout le paramétrage se fait de cette manière. Il n'y a pas de fichier de configuration. Heureusement, une tâche de sauvegarde est supposée être automatisée, donc résider sous une forme sous une autre dans un script qu'il ne sera pas nécessaire de retaper manuellement à la ligne de commandes. L'inconvénient est donc plutôt mineur.

Kopia

Si l'on utilise le transport SFTP, alors le fonctionnement de Kopia est à peu près similaire à celui de Borg, à ceci près que Kopia utilise par défaut sa propre implémentation SSH. Cela nécessite de lui préciser l'emplacement du fichier known_hosts par exemple. Il ne prendra donc pas en compte non plus le fichier de configuration du client SSH natif de la machine. Malheureusement, l'implémentation native du protocole SSH dans Kopia ne supporte pas tous les types de clés. Il s'agit d'un bug identifié mais pas encore corrigé. L'utilisation de clés de type Elliptic Curve reste possible si on dit au client Kopia d'utiliser un client SSH externe. J'ai, pour ma part, choisi de créer une clé RSA pour contourner le bug.

$ kopia repository create sftp --path=/backupmaison/bench-kopia --host=192.168.0.22 --username=patpro --keyfile=/Users/patpro/.ssh/kopia_rsa --known-hosts=/Users/patpro/.ssh/known_hosts-kopia

À l'inverse de Borg, le paramétrage de Kopia est très largement déporté dans une configuration côté dépôt. Il s'agit, au travers de commandes de gestion de politiques, de régler un certain nombre de paramètres qui seront utilisables par le client Kopia.
Voici ce que cela donne dans mon cas de figure :

$ kopia policy list
85bf7bc7688d5819433aad9ba1c84f6b (global)

$ kopia policy set --add-dot-ignore .nobench-bkup 08c59f69009c88ee463de6acbbc59a3a
Setting policy for patpro@cassandre:/Users/patpro/08c59f69009c88ee463de6acbbc59a3a
 - adding ".nobench-bkup" to "dot-ignore filenames"

$ kopia policy set --compression=zstd --global
Setting policy for (global)
 - setting compression algorithm to zstd

Ces politiques fonctionnent avec une notion d'héritage, de la politique la plus générale à la plus particulière :

$ kopia policy show --global| head
Policy for (global):

Retention:
  Annual snapshots:                     3   (defined for this target)
  Monthly snapshots:                   24   (defined for this target)
  Weekly snapshots:                     4   (defined for this target)
  Daily snapshots:                      7   (defined for this target)
  Hourly snapshots:                    48   (defined for this target)
  Latest snapshots:                    10   (defined for this target)
  Ignore identical snapshots:       false   (defined for this target)

$ kopia policy show 08c59f69009c88ee463de6acbbc59a3a| head
Policy for patpro@cassandre:/Users/patpro/08c59f69009c88ee463de6acbbc59a3a:

Retention:
  Annual snapshots:                     3   inherited from (global)
  Monthly snapshots:                   24   inherited from (global)
  Weekly snapshots:                     4   inherited from (global)
  Daily snapshots:                      7   inherited from (global)
  Hourly snapshots:                    48   inherited from (global)
  Latest snapshots:                    10   inherited from (global)
  Ignore identical snapshots:       false   inherited from (global)

Les différents paramètres du client permettant de définir les tâches de sauvegarde et de purge étant déportés, la ligne de commandes pour les différentes actions s’en trouve grandement simplifiée. Il reste néanmoins à connecter le client au serveur de sauvegarde. Cela se fait avec une commande de ce style :

$ kopia -p foobar repository connect sftp --path=/backupmaison/bench-kopia --host=192.168.0.22 --username=patpro --keyfile=/Users/patpro/.ssh/kopia_rsa --known-hosts=/Users/patpro/.ssh/known_hosts-kopia

La déconnexion se faisant alors de cette façon :

$ kopia repository disconnect

Il est important de comprendre que cette connexion et cette déconnexion ne doivent pas nécessairement être faites de manière systématique. C'est une erreur que j'ai moi-même commise : lors des premiers jours d'exécution de mes scripts de sauvegarde, pour chaque tâche de Kopia, je faisais la connexion, la tâche puis la déconnexion. Les effets de bord sont minimes, mais j'y reviendrai. Dans tous les cas, une connexion à un instant T persiste, car ce n'est pas une connexion réseau. Il vaut mieux voir cela comme une pré-configuration du client, lui permettant d'utiliser notamment les login, mot de passe et coordonnées du serveur pour dérouler les tâches de sauvegarde. Dans la suite de mes tests, j'ai simplement fait une connexion une fois et je n'ai plus déconnecté mon client. Si bien que la création d'une sauvegarde se résume à cette commande triviale :

$ kopia snapshot create /Users/patpro

La différence avec Borg saute aux yeux.

Restic

Pour tester Restic, j'ai souhaité utiliser le REST-server. Le transport se fait sur HTTP et la commande est relativement triviale. Côté serveur, la configuration est assez basique, puisque j'ai simplement précisé le chemin du stockage, l'interface et le port TCP pour l'écoute et le paramètre --no-auth car je n'ai pas besoin d'authentification.

$ restic -r rest:http://192.168.0.22:8000/ init

Tout comme Borg, les tâches de sauvegarde ou de purge nécessitent le passage de l'intégralité des paramètres dans la ligne de commandes :

$ export RESTIC_PASSWORD=foobar
$ restic -r rest:http://192.168.0.22:8000/ backup --verbose --exclude-if-present .nobench-bkup --one-file-system --exclude-caches --no-scan --read-concurrency 4 /Users/patpro

Pas grand-chose à ajouter du côté de Restic, qui se comporte à peu de chose près comme Borg en terme de paramétrage et de ligne de commandes. Même si les paramètres venaient à se multiplier, le tout prendrait place dans un script shell parfaitement lisible.

Pour conclure

J'aime beaucoup la lisibilité d'une ligne de commandes avec ou sans variables : elle me permet d'analyser un script de sauvegarde dans n'importe quel éditeur et dans n'importe quel contexte. Néanmoins je dois admettre que je suis assez séduit par l'élégance du système de politiques de Kopia, même si accéder au contenu de la politique nécessite d'accéder à la commande Kopia dans un terminal ainsi qu’au dépôt de sauvegarde (c'est un inconvénient). Je crois que nous sommes face à un critère de choix qui dépendra uniquement de la préférence de l'utilisateur final.

Related posts

Borg, Kopia, Restic : périmètre fonctionnel et généralités

Le périmètre fonctionnel des trois solutions de sauvegarde est relativement équivalent. Chacune fonctionne sur le mode «push», c'est-à-dire que c'est le client qui initie la sauvegarde vers le serveur. Ce mode de fonctionnement est sans doute le plus adapté aux personnes qui gèrent une poignée de machines. Le mode «pull» est disponible pour Borg, mais requiert quelques aménagements.
Les trois programmes utilisent les mécanismes de duplication et de compression pour limiter les volumétries transmises et stockées. Attention cependant, avec Kopia, la compression n'est pas activée par défaut. Ils implémentent aussi tous trois une gestion de la rétention et de l'expiration des sauvegardes, des mécanismes d'entretien du dépôt, etc.

Borgbackup

logo BorgbackupBorgbackup, ou Borg pour les intimes, est une solution développée en langage python. Elle s'installe plutôt simplement mais ne permet pas la sauvegarde des postes Windows. Sa documentation est relativement exhaustive et son écosystème inclut des solutions d'automatisation et d'interfaces graphiques. Elle évolue régulièrement. Les tests ont été faits avec la version 1.2.7. La branche 1.4 (beta) est disponible et la branche 2 est en cours de développement actif.

Pour utiliser Borg, il est nécessaire que le logiciel souhaite aussi installer sur le serveur de destination. C'est une contrainte qui pourra bloquer certaines personnes. La sauvegarde distante passe par une connexion SSH. De plus, l'accès au dépôt de sauvegarde est exclusif (verrou), c'est-à-dire qu'il n'est pas possible de sauvegarder plusieurs machines dans le même dépôt en même temps. Par ailleurs, la sauvegarde de plusieurs clients sur le même dépôt est découragée pour différentes raisons.

En cas de compromission de la machine cliente, on peut s'inquiéter du fait que le logiciel de sauvegarde présent sur la machine permette la destruction des archives distantes. Par défaut c'est bien le cas. Néanmoins, le fonctionnement client-serveur de Borg permet d'ajouter des contrôles. Il est possible par exemple de configurer le client pour qu'il ne puisse faire que des ajouts et des restaurations de fichiers, mais pas de suppression d'archives.

Tout le paramétrage de Borg se fait avec des arguments en ligne de commande. Il n'y a pas de fichier de paramètres, même si on peut déporter dans des fichiers dédiés comme les listes d'exclusions et d’inclusions par exemple.

Site officiel : https://www.borgbackup.org/
Documentation officielle : https://borgbackup.readthedocs.io/en/stable/
Plate-forme de développement coopératif : https://github.com/borgbackup/borg

Kopia

logo KopiaKopia est une solution codée en GO. La version utilisée ici est la 0.15.0 et le projet est actif. Il s'agit d'un binaire monolithique disponible pour différentes architectures et systèmes d'exploitation. Kopia est compatible Windows et propose une version graphique. Il fonctionne aussi avec de nombreux stockages distants différents comme par exemple les stockages de type S3, Azure blob Storage, Backblaze B2, WebDAV, SFTP, etc. Il n'est pas nécessaire d'installer des composants côté serveur pour utiliser Kopia.
Il est aussi possible de sauvegarder plusieurs machines dans le même dépôt. La déduplication pourra alors être mise en commun.

Kopia dispose tout de même d'un mode «serveur» facultatif qu'il est possible de configurer pour ajouter une gestion d'utilisateurs, lorsque ces derniers partagent un même dépôt par exemple. C'est aussi grâce à cette fonctionnalité qu'il est possible de limiter les droits du client sur les archives stockées, par exemple en interdisant leur suppression. Si vous n'utilisez pas la partie serveur de Kopia, vous ne pourrez pas empêcher qu’un client compromis supprime ses sauvegardes.

Kopia permet de gérer des politiques de sauvegarde qui sont enregistrés et ensuite applicables à des tâches de sauvegarde (ou de nettoyage, puisque ces politiques incluent aussi la notion de rétention). Cette gestion de politiques de sauvegarde est plutôt élégante et permet de limiter le nombre d'arguments de la ligne de commande à chaque lancement d'une tâche.

Site officiel : https://kopia.io/
Documentation officielle : https://kopia.io/docs/
Plate-forme de développement coopératif : https://github.com/kopia/kopia/

Restic

logo ResticRestic est aussi codé en GO. La version utilisée ici est la 0.16.4 et le projet est actif. il est disponible pour différentes architectures et systèmes d'exploitation, y compris Windows. L'éventail de solutions de stockage distant supporté par Restic est à peu près similaire à celui de Kopia. Restic propose en plus son propre serveur HTTP haute performance qui implémente l’API REST de Restic. Cela permet, comme dans le cas de Kopia et de Borg, d'assurer une sécurisation des sauvegardes en limitant les droits du client.

Ce protocole de sécurisation des sauvegardes, communément appelé «append-only», pose des contraintes d'utilisation qui peuvent être décourageantes pour l'utilisateur. En effet, sauvegarder des machines vers des dépôts sur lesquels on ne peut pas supprimer les anciennes sauvegardes pose un problème de gestion de volumétrie. Pour ma part, je préfère de loin que le client ait tous les droits sur les sauvegardes, mais que le dépôt de ces sauvegardes soit stockés sur un système de fichiers qui permet de générer des snapshots réguliers. Dans mon cas, toutes les sauvegardes sont écrites sur un système de fichiers ZFS et des snapshots automatiques sont pris tous les jours avec des rétentions relativement longues.

Tout comme Borg, Restic s'appuie exclusivement sur des paramètres de ligne de commande pour assurer la configuration des différentes tâches.

Site officiel : https://restic.net/
Documentation officielle : https://restic.readthedocs.io/en/stable/index.html
Plate-forme de développement coopératif : https://github.com/restic/restic

Pour résumer

Chacun doit se faire sa propre idée à l’aune de ses propres besoins, mais si l’on n’exclue aucun scénario (sauvegarde de client Windows, dépôt partagé ou encore stockage S3…), Borg n’a pas l’avantage. Si comme moi vous sauvegardez une poignée de machines macOS/FreeBSD/Linux à destinations de serveurs sur lesquels vous pouvez installer des logiciels et auxquels vous pouvez vous connecter en SSH alors Borg fait jeu égal avec Kopia et Restic.

Borg Kopia Restic
Portabilité - + +
Options de stockage - + +
Options de transport - + +
Dépôt multi-client - + +
Related posts

Borg, Kopia, Restic : un comparatif

[English translation by DeepL]
Depuis plusieurs années, j'utilise Borg Backup. Cependant, fin 2023, j'ai rencontré des problèmes importants avec la sauvegarde d'une de mes machines. J'ai donc décidé d'explorer des pistes alternatives. Une recherche rapide m'a permis de trouver des solutions relativement équivalentes à Borg Backup : Restic et Kopia.

En absence d'un comparatif de ces trois solutions (il existe un comparatif «ancien» entre Borg et Restic mais il ne va pas aussi loin et ne mentionne pas Kopia), j'ai décidé de me lancer dans des tests moi-même, pour pouvoir comparer des métriques simples et communes aux trois logiciels.

Finalement, une fois qu'une sauvegarde régulière est automatisée, les métriques importantes sont pour moi : la durée d'une sauvegarde, la volumétrie des échanges réseau et la volumétrie de stockage sur le serveur de sauvegarde. Des métriques similaires sont intéressantes à explorer sur les opérations de restauration d’une sauvegarde et sur les opérations de maintenance du serveur de sauvegardes.

Mon environnement de test est constitué de ces différentes briques :

  • machine cliente : macmini M2 Pro sous macOS 13.6.3, 32 Go RAM
  • serveur de sauvegarde : PC à base de Intel(R) Core(TM) i3-3220T, sous FreeBSD 14, 16 Go RAM, stockage ZFS sur SSD
  • réseau ethernet 1Gbps «switché»
  • une instance Splunk pour ingérer les logs et produire des statistiques et des graphiques

Pour m'assurer de travailler sur des données représentatives, j'ai décidé de sauvegarder une partie de mon répertoire utilisateur. J'ai exclu un immense répertoire de photos numériques qui ne bouge que très rarement, ainsi que de nombreux répertoires de cache qu’il n’est pas pertinent de sauvegarder. La volumétrie finale de ma cible de sauvegarde avoisine les 140Go.

Je me suis basé pour mon protocole de sauvegarde sur mon expérience acquise avec Borg. Néanmoins, chaque logiciel ayant ses spécificités, un temps de documentation et d'adaptation a été nécessaire. Malgré ces préparatifs, le déroulement des sauvegardes m'a réservé quelques surprises.

L'automatisation des sauvegardes s'est faite par un script bash unique permettant de lancer dans un ordre aléatoire la création des sauvegardes via Borg, Restic et Kopia. J’avais dans l'idée que la première tâche de sauvegarde serait potentiellement pénalisée par l'accès à des fichiers sur le poste client qui ne seraient pas dans le cache du système, mais après 15 jours de test, j'ai constaté qu'il n'y a aucune différence visible de temps de sauvegarde qui soit imputable à l'ordre des tâches de sauvegarde. J'ai donc décidé ultérieurement de figer l’ordre des tâches de sauvegarde, ce qui me permet aussi de suivre les métriques bien plus facilement.
La machine cliente a des périodes de sommeil planifié la nuit. Pendant ces périodes de sommeil, aucune sauvegarde n'a lieu. De plus, la planification du script est faite dans Launchd via l’argument StartInterval à 3600 secondes. Contrairement à une planification de type crontab, par exemple, celle-ci assure un délai incompressible d'une heure entre deux exécutions du script. C'est-à-dire qu'il doit s'écouler une heure entre la fin de l'exécution précédente et le début de la nouvelle exécution. Ainsi, le script est réellement lancé un peu moins d'une fois par heure. Par exemple si chaque exécution dure 5 minutes, alors il faut 26h et non 24h pour qu’il soit lancé 24 fois.

Note importante : je ne vais pas aborder en détails dans ces articles les différences d'ergonomie de ces logiciels, la disponibilité ou non d'une interface graphique de gestion, etc. Certaines des solutions présentées ici disposent de plusieurs interfaces graphiques différentes, les fonctionnalités des trois produits varient, et je ne souhaite pas faire un catalogue qui comparerait chaque logiciel point par point.

Voici le sommaire de mon comparatif. Le lien vers chaque article deviendra actif à sa publication.

Related posts

Borgbackup: it’s complicated

As I wrote in a previous article, I'm using Borgbackup to back up some servers and workstations. And most of the time it's going OK. Unfortunately, when it's not OK, it can be very (very) hard to recover. Spoiler alert: one of my backup repositories had a problem, it took me 16 days and 1131 connections to the repository to fix it.

Few weeks ago, I've noticed that the Borg repository for the backups of my MacBook Pro was holding way too many backups. The pruning process was not doing its job properly. So I’ve started to investigate, and discovered that every attempt to prune older backups failed.
Trying to check the repository failed too: every single time the connection was reset. Apparently the remote server was dropping the SSH connection after a while (between 20 and 90 minutes). Client-side the error message was Connection closed by remote host.
I started to wonder if the problem was the very large number of backups, so I tried to delete backups manually. Some of them were easy to delete but most of the older backups needed delete --force and even delete --force --force, which is pretty bad.
Basically, I destroyed two years worth of backups, but it was still impossible to check and repair the repository. Also, the use of --force and --force --force makes it impossible to reclaim the space until you repair the repository.

Digging in the (mis)direction of a connection problem I’ve tried everything I could. It failed every single time:

  • tune ClientAliveInterval and ClientAliveCountMax server-side
  • tune ServerAliveInterval and ServerAliveCountMax client side
  • using and not using multiplexed ssh connections
  • moving the client to another physical network
  • using caffeinate to launch the borg command
  • using Amphetamine
  • upgrading ssh on the client
  • upgrading borg
  • giving mosh a try (nope)
  • running ssh with -vvv
  • using ktrace server-side to find the cause

None of this helped at all. Not to find a cause, not to make it work properly.
Eventually I stumbled upon this blog post: Repair Badly Damaged Borg Repository.

The repair method described failed too:
- step check --repair --repository-only worked
- but check --repair --archives-only died with the same Connection closed by remote host.
As a workaround attempt I’ve scripted a loop that would do check --repair --archives-only on every archive individually (~630).
After 3 full days and more than 600Go transferred from the repo to the client, every archives were checked and none was faulty.
Next step was to attempt check --repair again on the whole repository. About 15 hours later the output was

2851697 orphaned objects found!
Archive consistency check complete, problems found.

Full working solution for me:

export BORG_CHECK_I_KNOW_WHAT_I_AM_DOING=YES 
borg check -p --repair --repository-only LOGIN@HOST:/path/to/repo
borg -p list LOGIN@HOST:/path/to/repo | awk '{print $1}' > listborg
cat listborg | while read i; do 
	borg -vp check --repair --archives-only LOGIN@HOST:/path/to/repo::$i
done
borg -p check --repair LOGIN@HOST:/path/to/repo

Final step was to reclaim space on the server with compact:

$ borg compact -p --verbose path/to/repo/
compaction freed about 376.22 GB repository space.

Boy that was painful!

I’m pretty sure it’s not really an ssh issue. Something is causing the connection to drop but I have ssh connections opened for days between that client and that server, so I guess ssh is not the problem here. Also, borgbackup’s github is loaded with issues about failing connections. In the end it boils down to:
- borg repositories can break badly without warning
- repairing a repo might not worth the bandwidth/CPU/IOs

Related posts

Recherche Administrateur/trice Systèmes

Au sein du Service Opérations de la DSI de l'Université Lyon 2, nous cherchons un ou une Administrateur/trice Systèmes pour renforcer notre équipe et nous aider à relever des défis au quotidien.
Lieu de travail : campus de Bron (arrêt de tram T2 Europe Université).

  • Vous habitez la région Lyonnaise ou êtes mobile ;
  • Vous êtes motivée par les enjeux de la gestion d’un parc de plus de 600 serveurs Linux RedHat/CentOS (70%), Windows, FreeBSD ;
  • Les problématiques d’une ferme de virtualisation multi-site avec balance de charge, PRA, sauvegardes croisées ne vous font pas peur ;
  • Les infrastructures à fort enjeu de disponibilité, les outils d’automatisation, de monitoring et les SIEM vous intéressent ;
  • Vous êtes passionnée par les problématiques système et souhaitez évoluer dans un environnement riche et varié ;
  • Vous êtes curieuse, très rigoureuse et vous avez le sens du service.

Si vous vous reconnaissez dans ce profil, contactez-moi !

terminal - édition d'un script shell

Édition d'un script shell dans le terminal

Related posts