Abstract
L’auto-hébergement consiste à héberger ses services Internet personnels sur ses propres machines locales, voire sur un serveur dédié virtuel. Cette approche offre plusieurs avantages : souveraineté sur les données, réduction de la dépendance aux services tiers, ou encore personnalisation avancée de l’infrastructure.
Dans un cadre professionnel, on parle plutôt de solutions on-premise. Cette pratique peut être vue comme l’opposé du cloud, bien qu’elle n’exclue pas l’adoption de ses bonnes pratiques, appliquées à une infrastructure locale.
Que l'on parle d'auto-hébergement ou de solution on-premise, la pérennité des données reste un enjeu crucial. Cela implique la capacité à restaurer rapidement ses données, par exemple en cas de perte de bases de données — omniprésentes dans la majorité des applications web auto-hébergées.
Dans cet article, nous allons explorer un exemple de système simple et automatisé permettant d’assurer cette pérennité.
Un mot sur les outils

La mise en place de ce système se base sur la stack suivante :
Ansible est un outil d’infrastructure as code, généralement utilisé pour automatiser la configuration des machines, qu'elles soient physiques ou virtuelles. Dans notre cas, il est principalement utilisé pour déployer des fichiers basés sur des modèles (templates), ce qui permet d’unifier la configuration et d’avoir une source de vérité unique.

Restic est un outil de sauvegarde incrémentielle, chiffrée, et compatible avec plusieurs backends de stockage. Il crée ce qu’on appelle des repositories, c’est-à-dire des répertoires contenant les sauvegardes, les métadonnées associées, ainsi que les clés de chiffrement.
The place where your backups will be saved is called a “repository”. This is simply a directory containing a set of subdirectories and files created by restic to store your backups, some corresponding metadata and encryption keys. (source)

MinIO est un service de stockage d’objets compatible avec l’API S3 d’AWS. Couplé à Restic, il permet d’envoyer les sauvegardes sur des destinations locales ou distantes, y compris sur des serveurs tiers.
L'idée de base
La majorité des services auto-hébergeables utilisent des bases de données PostgreSQL (ou parfois MySQL) pour le stockage relationnel. Dans notre cas, nous utilisons PostgreSQL. Chaque service dispose de sa propre base, isolée dans un conteneur Docker décrit via un fichier docker-compose.yml
.
Voici un exemple de structure de dossier pour un service (Grafana) :
user@DB_Server:/docker/grafana$ tree
.
├── docker-compose.yml
├── dump.sh
├── postgres [error opening dir]
├── postgres_backup
│ ├── grafana.dump.sql
├── restic.sh
└── restore.sh
Trois scripts .sh
sont présents dans chaque dossier :
dump.sh
: effectue un export de la base de donnéesrestore.sh
: restaure une base à partir d’un dump SQLrestic.sh
: envoie le dump dans un dépôt Restic
Ces scripts sont générés par Ansible à partir de templates, ce qui permet une standardisation et une gestion automatisée.
Exemple de script Restic Dockerisé
#! /bin/bash
docker run --net=host --rm -v /docker/grafana/.passfile:/pass \
-v /docker/grafana/postgres_backup:/postgres_backup \
--env-file /docker/grafana/.s3_credentials \
-e RESTIC_REPOSITORY=s3:https://min.io/grafana-backup \
restic/restic:latest -p /pass "$@"
Ce script garantit que la même version de Restic est utilisée sur tous les hôtes, via un conteneur Docker.
Automatisation avec Ansible
Structure des rôles
L’automatisation s'appuie sur trois rôles Ansible personnalisés :
- postgres : prépare l’environnement de base de données
- cron : crée les tâches planifiées pour les sauvegardes
- restic : configure les accès aux dépôts de sauvegarde
Rôle PostgreSQL
Ce rôle :
- Copie le fichier
docker-compose.yml
- Crée les dossiers nécessaires (
postgres_backup
) - Déploie les scripts
dump.sh
etrestore.sh
configurés avec les identifiants
- name: Deploy PostgreSQL database for application {{ service_name }} - {{ service_instance }}
hosts: DB_Server
vars:
service_name: '{{ service }}'
service_instance: "{{ instance }}"
service_home: '{{ home_docker }}/{{ service_instance }}'
roles:
- role: postgres
postgres_home: "{{ service_home }}"
postgres_version: "{{ _services[service_instance].database.version if _services[service_instance].database.version is defined else '15.2-alpine' }}"
postgres_container_name: "{{ service_instance }}-db"
postgres_user: "{{ _services[service_instance].database.user }}"
postgres_password: "{{ _services[service_instance].database.password }}"
postgres_db: "{{ _services[service_instance].database.db }}"
postgres_port: "{{ _services[service_instance].database.port }}"
postgres_host: "{{ _services[service_instance].database.host }}"
Rôle Cron
Ce rôle crée les tâches cron pour automatiser les sauvegardes et leur nettoyage :
- name: Configure Restic and backup schedules for application {{ service_name }} - {{ service_instance }}
hosts: DB_Server
vars:
service_name: '{{ service }}'
service_instance: "{{ instance }}"
service_home: '{{ home_docker }}/{{ service_instance }}'
roles:
- role: cron
cron_name: "{{ service_instance }} backup database"
cron_job: "{{ service_home }}/dump.sh && {{ service_home }}/restic.sh backup /postgres_backup"
cron_hour: "2"
cron_minute: "0"
cron_user: "root"
hc_tags:
- "{{ service_instance }}"
- "backup"
- role: cron
cron_name: "Restic clean up - {{ service_instance }}"
cron_job: "{{ restic_default_cleanup_command }}"
cron_minute: "30"
cron_hour: "1"
cron_user: "root"
hc_tags:
- "{{ service_instance }}"
- "backup clean"
- "restic"
La commande de nettoyage utilisée par défaut :
./restic.sh --group-by paths --prune \
--keep-yearly 1 \
--keep-monthly 3 \
--keep-weekly 4 \
--keep-daily 7
Rôle Restic
Ce rôle configure :
- Le script
restic.sh
- Les fichiers de credentials pour accéder aux buckets
- name: Configure Restic and backup schedules for application {{ service_name }} - {{ service_instance }}
hosts: DB_Server
vars:
service_name: '{{ service }}'
service_instance: "{{ instance }}"
service_home: '{{ home_docker }}/{{ service_instance }}'
roles:
- role: restic
restic_passphrase: "{{ _services[service_instance].restic.minio_passphrase }}"
restic_aws_access_key_id: "{{ _services[service_instance].restic.minio_access_key }}"
restic_aws_secret_access_key: "{{ _services[service_instance].restic.minio_secret_key }}"
bucket_name: "{{ service_instance }}-backup"
volumes: "{{ _services[service_instance].restic.volumes }}"
Les volumes désignent ici les répertoires locaux à sauvegarder, comme postgres_backup
.
Conclusion
Avec cette architecture simple, modulaire et automatisée, il est possible d’assurer la pérennité des données tout en limitant les efforts de maintenance.
Grâce à Ansible, les rôles peuvent être réutilisés facilement sur plusieurs projets. Les sauvegardes sont automatisées, chiffrées et stockées dans des dépôts compatibles S3. Le système ne se limite pas aux bases de données : tout type de volume peut être sauvegardé, comme :
- des fichiers PDF (ex. : Paperless)
- des configurations domotiques (Home Assistant)
- des fichiers utilisateurs (Nextcloud)
Une solution efficace, évolutive et auto-hébergeable pour toute organisation soucieuse de ses données.