Mettre à jour Dolibarr en ligne de commande
Mettre à jour Dolibarr sans l'assistant web : upgrade.php, upgrade2.php et step5.php, une étape par version, le piège d'upgrade.unlock qui bloque la 2e étape sans erreur, et un script complet avec sauvegarde et retour arrière, testé de la 22 à la 24.
L’assistant web de Dolibarr (/install) fait la mise à jour en quelques clics. Mais si vous gérez
votre serveur en SSH, si vous avez plusieurs instances, ou si la page coupe avant la fin, vous
voudrez lancer la même chose en ligne de commande. Dolibarr le permet : ce sont les trois scripts
que l’assistant appelle, upgrade.php, upgrade2.php et step5.php.
Les commandes sont courtes. Les pièges, eux, ne se voient pas : ces scripts répondent « tout va bien » (code retour 0) même quand ils n’ont rien fait. Nous en avons provoqué trois le 19 octobre 2026, puis écrit un script qui les évite, testé en passant de la 22.0.5, de la 23.0.4 et de la 24.0.1 à la 24.0.2.
Cette page vise une installation faite avec l’archive .tgz, comme dans notre guide
Installer Dolibarr sur Ubuntu ou Debian : le code dans
/var/www/dolibarr, les documents dans /var/lib/dolibarr/documents. Avec l’image Docker
officielle, lisez plutôt Mettre à jour Dolibarr sous Docker.
Avant de commencer
La mise à jour elle-même casse rarement Dolibarr : ce sont les modules externes, la version de PHP et les personnalisations qui posent problème (voir Mettre à jour Dolibarr sans casse). Notre module gratuit Prêt pour la mise à jour fait ce contrôle avant, sans rien modifier.
Ensuite, notez la version de votre base, pas celle des fichiers : c’est elle qui décide des étapes.
sudo mariadb -N dolibarr -e "SELECT name, value FROM llx_const WHERE name LIKE 'MAIN_VERSION_LAST_%' AND entity = 0"
La plus haute des valeurs affichées est votre version actuelle. Remplacez dolibarr par le nom de votre
base, et llx_ par votre préfixe s’il est différent (les deux sont dans conf.php).
1. Sauvegarder
Faites-le même si vous comptez sur la sauvegarde de l’hébergeur : le retour arrière ci-dessous en a besoin.
sudo mariadb-dump --single-transaction --routines dolibarr > ~/dolibarr-base.sql
sudo tar -czf ~/dolibarr-documents.tgz -C /var/lib/dolibarr documents
Les anciens fichiers de Dolibarr seront gardés à l’étape suivante. Pour plus de détails : Sauvegarder et restaurer Dolibarr.
2. Remplacer les fichiers
Mettez la nouvelle version dans un dossier neuf plutôt que de la copier par-dessus l’ancienne : les
fichiers supprimés entre deux versions disparaissent ainsi vraiment, et l’ancien dossier sert de
retour arrière. On recopie ensuite deux choses : conf.php et le dossier custom des modules
externes.
cd /tmp
curl -fL -o dolibarr-24.0.2.tgz "https://sourceforge.net/projects/dolibarr/files/Dolibarr%20ERP-CRM/24.0.2/dolibarr-24.0.2.tgz/download"
sudo tar --no-same-owner -xzf /tmp/dolibarr-24.0.2.tgz -C /var/www
sudo mv /var/www/dolibarr /var/www/dolibarr-ancien
sudo mv /var/www/dolibarr-24.0.2 /var/www/dolibarr
sudo cp -a /var/www/dolibarr-ancien/htdocs/conf/conf.php /var/www/dolibarr/htdocs/conf/
sudo cp -a /var/www/dolibarr-ancien/htdocs/custom/. /var/www/dolibarr/htdocs/custom/
cp -a garde le propriétaire et les droits de conf.php (dans notre test, www-data, lecture
seule).
3. Migrer la base : une étape par version
Chaque étape passe d’une version majeure à la suivante, avec les trois scripts dans l’ordre. Les
numéros s’écrivent x.0.0 : le dernier chiffre de votre version (le 5 de 22.0.5) est ignoré par
Dolibarr, qui choisit le même fichier dans les deux cas.
De la 22 à la 24, deux étapes :
sudo touch /var/lib/dolibarr/documents/upgrade.unlock
cd /var/www/dolibarr/htdocs/install
sudo -u www-data php upgrade.php 22.0.0 23.0.0 > /tmp/etape1.html
sudo -u www-data php upgrade2.php 22.0.0 23.0.0 >> /tmp/etape1.html
sudo -u www-data php step5.php 22.0.0 23.0.0 auto upgrade_23.0.0 >> /tmp/etape1.html
sudo -u www-data php upgrade.php 23.0.0 24.0.0 > /tmp/etape2.html
sudo -u www-data php upgrade2.php 23.0.0 24.0.0 >> /tmp/etape2.html
sudo -u www-data php step5.php 23.0.0 24.0.0 >> /tmp/etape2.html
Depuis une 23.x ou une 24.0.x, une seule étape (c’est aussi celle d’une mise à jour mineure, 24.0.1 vers 24.0.2) :
sudo touch /var/lib/dolibarr/documents/upgrade.unlock
cd /var/www/dolibarr/htdocs/install
sudo -u www-data php upgrade.php 23.0.0 24.0.0 > /tmp/etape1.html
sudo -u www-data php upgrade2.php 23.0.0 24.0.0 >> /tmp/etape1.html
sudo -u www-data php step5.php 23.0.0 24.0.0 >> /tmp/etape1.html
Pour un écart plus grand, ajoutez une étape par version, sur le même modèle : toutes les étapes
sauf la dernière finissent par auto upgrade_ suivi de la version d’arrivée.
4. Contrôler, puis reverrouiller
grep -o '[0-9.]*-[0-9.]*\.sql' /tmp/etape*.html | sort -u
sudo mariadb -N dolibarr -e "SELECT value FROM llx_const WHERE name = 'MAIN_VERSION_LAST_UPGRADE' AND entity = 0"
La première commande doit afficher un fichier par étape (etape1.html:22.0.0-23.0.0.sql puis
etape2.html:23.0.0-24.0.0.sql ; avec une seule étape, juste 23.0.0-24.0.0.sql) : c’est le seul signe fiable que la migration a tourné. La seconde doit
afficher la nouvelle version. Puis remettez les protections du guide d’installation :
sudo rm -f /var/lib/dolibarr/documents/upgrade.unlock
sudo find /var/www/dolibarr/htdocs -path /var/www/dolibarr/htdocs/custom -prune -o -exec chmod a-w {} +
sudo chmod 400 /var/www/dolibarr/htdocs/conf/conf.php
Connectez-vous et vérifiez dans ConfigurationModules/Applications que vos modules externes
sont toujours actifs. Gardez /var/www/dolibarr-ancien quelques jours avant de le supprimer.
Les pièges que nous avons provoqués
| Ce qu’on fait | Ce qui se passe | Code retour |
|---|---|---|
Lancer upgrade.php alors que install.lock existe, sans upgrade.unlock |
Une phrase « The install/upgrade pages have been disabled… », la base n’est pas touchée | 0 |
Enchaîner deux étapes sans auto upgrade_23.0.0 à la fin de la première |
step5.php efface upgrade.unlock dès la 1re étape : la 2e est bloquée comme ci-dessus |
0 |
| Passer de la 22 à la 24 en un seul appel | Les deux fichiers SQL tournent, mais les trois migrations de données de la 23 sont sautées | 0 |
| Lancer le script depuis un autre dossier | Failed opening required '../filefunc.inc.php' |
255 |
Lancer le script sous un compte qui ne peut pas lire conf.php |
Permission denied sur conf.php |
255 |
Le deuxième est le plus dangereux. Dans notre test, la base affichait déjà « 24.0.2 » après la
première étape, alors que la seconde n’avait pas tourné : il lui manquait 3 tables et 37 colonnes de
la 24, et l’API REST répondait 401 avec une clé qui marchait avant. L’assistant web évite ce piège en
passant upgrade_23.0.0 aux étapes intermédiaires (c’est écrit dans install/check.php) : la base est
alors marquée 23.0.0, et upgrade.unlock reste en place jusqu’à la dernière étape.
Le troisième ne se voit pas tout de suite. En un seul appel 2224, la structure finale était
identique à celle des deux étapes, mais les migrations de données propres à la 23 n’ont pas tourné
(dans notre base, la clé API n’a pas été recopiée dans sa nouvelle table, et la clé de signature des
journaux inaltérables n’a pas été créée). Rien n’a cassé visiblement en 24.0.2 : c’est justement le
problème. Avec trois versions d’écart ou plus, c’est pire : d’après le code de upgrade.php, seuls le
premier et le dernier fichier SQL sont choisis, ce que notre test Docker de la 20 à la
24 avait montré (base incomplète, sans aucune erreur).
Les deux derniers cas, eux, s’arrêtent avec une erreur visible : placez-vous dans htdocs/install
et lancez les scripts avec le compte du serveur web (www-data sur Debian et Ubuntu).
Le script complet
Le script ci-dessous fait tout ce qui précède, dans l’ordre, et s’arrête au premier doute. Il lit les
paramètres de la base dans conf.php, calcule les étapes, sauvegarde, remplace les fichiers, migre
étape par étape, vérifie après chaque étape que le fichier SQL a bien tourné et que la base porte
la bonne version, puis reverrouille. En cas d’échec, il remet les anciens fichiers et recharge la
sauvegarde de la base.
Copiez-le dans un fichier maj-dolibarr.sh, adaptez les cinq lignes du haut, puis lancez-le :
sudo bash maj-dolibarr.sh
#!/bin/bash
# Mise à jour de Dolibarr en ligne de commande (installation par archive .tgz).
# Guide et explications : https://dolix.fr/notes/dolibarr-script-mise-a-jour/
# Testé le 19/10/2026 sur Debian 13 (PHP 8.4, MariaDB 11.8) : 22.0.5, 23.0.4 et 24.0.1 -> 24.0.2.
# À lancer en root (sudo bash maj-dolibarr.sh), en dehors des heures d'utilisation.
set -euo pipefail
# --- À adapter --------------------------------------------------------------
NOUVELLE=24.0.2 # version à installer
DOLI=/var/www/dolibarr # dossier qui contient htdocs/
DOCS=/var/lib/dolibarr/documents # dossier des documents ($dolibarr_main_data_root)
SAUV=/root/sauvegardes-dolibarr # où ranger les sauvegardes
WEB=www-data # utilisateur du serveur web
# -----------------------------------------------------------------------------
CONF=$DOLI/htdocs/conf/conf.php
DATE=$(date +%Y%m%d-%H%M%S)
TRAVAIL=$SAUV/$DATE
[ "$(id -u)" -eq 0 ] || { echo "À lancer en root (sudo)."; exit 1; }
[ -f "$CONF" ] || { echo "conf.php introuvable : $CONF"; exit 1; }
mkdir -p "$TRAVAIL"; chmod 700 "$SAUV" "$TRAVAIL"
# Paramètres de la base, lus dans conf.php
lire() { php -r 'include $argv[1]; echo ${$argv[2]}??"";' "$CONF" "$1"; }
DB_HOTE=$(lire dolibarr_main_db_host); DB_PORT=$(lire dolibarr_main_db_port)
DB_NOM=$(lire dolibarr_main_db_name); DB_USER=$(lire dolibarr_main_db_user)
DB_MDP=$(lire dolibarr_main_db_pass); PREFIXE=$(lire dolibarr_main_db_prefix)
case "$DB_MDP" in crypted:*|dolcrypt:*)
echo "Mot de passe chiffré dans conf.php : ce script ne sait pas le lire."; exit 1;; esac
MYCNF=$(mktemp); chmod 600 "$MYCNF"; trap 'rm -f "$MYCNF"' EXIT
printf '[client]\nhost=%s\nport=%s\nuser=%s\npassword="%s"\n' \
"$DB_HOTE" "${DB_PORT:-3306}" "$DB_USER" "$DB_MDP" > "$MYCNF"
SQL() { mariadb --defaults-extra-file="$MYCNF" -N "$DB_NOM" -e "$1"; }
# Version de la base (et non celle des fichiers)
ACTUELLE=$(SQL "SELECT value FROM ${PREFIXE:-llx_}const WHERE name IN
('MAIN_VERSION_LAST_UPGRADE','MAIN_VERSION_LAST_INSTALL') AND entity=0" | sort -V | tail -1)
[ -n "$ACTUELLE" ] || { echo "Version de la base introuvable."; exit 1; }
M=${ACTUELLE%%.*}; C=${NOUVELLE%%.*}
[ "$M" -le "$C" ] || { echo "La base ($ACTUELLE) est plus récente que $NOUVELLE."; exit 1; }
# Étapes : une par version majeure (22 -> 23, puis 23 -> 24), jamais 22 -> 24 d'un coup
ETAPES=()
if [ "$M" -eq "$C" ]; then ETAPES=("$((C - 1)).0.0 $C.0.0")
else for ((v = M; v < C; v++)); do ETAPES+=("$v.0.0 $((v + 1)).0.0"); done; fi
echo "Base en $ACTUELLE, cible $NOUVELLE. Étapes :"; printf ' %s\n' "${ETAPES[@]}"
read -r -p "Sauvegarde puis mise à jour. Continuer ? (o/N) " R; [ "$R" = o ] || exit 1
# 1. Télécharger et décompresser la nouvelle version (rien n'est encore modifié)
curl -fsSL -o "$TRAVAIL/dolibarr-$NOUVELLE.tgz" \
"https://sourceforge.net/projects/dolibarr/files/Dolibarr%20ERP-CRM/$NOUVELLE/dolibarr-$NOUVELLE.tgz/download"
tar --no-same-owner -xzf "$TRAVAIL/dolibarr-$NOUVELLE.tgz" -C "$TRAVAIL"
[ -f "$TRAVAIL/dolibarr-$NOUVELLE/htdocs/install/upgrade.php" ] || { echo "Archive incomplète."; exit 1; }
# 2. Sauvegardes : base, documents (les anciens fichiers sont gardés à l'étape 3)
mariadb-dump --defaults-extra-file="$MYCNF" --single-transaction --routines --skip-disable-keys "$DB_NOM" > "$TRAVAIL/base.sql"
tar -czf "$TRAVAIL/documents.tgz" -C "$(dirname "$DOCS")" "$(basename "$DOCS")"
echo "Sauvegardes dans $TRAVAIL"
# 3. Remplacer les fichiers : nouveau dossier, puis conf.php et modules externes
ANCIEN=$DOLI-ancien-$DATE
mv "$DOLI" "$ANCIEN"
mv "$TRAVAIL/dolibarr-$NOUVELLE" "$DOLI"
cp -a "$ANCIEN/htdocs/conf/conf.php" "$DOLI/htdocs/conf/conf.php"
cp -a "$ANCIEN/htdocs/custom/." "$DOLI/htdocs/custom/"
chown -R "$WEB:$WEB" "$DOLI/htdocs/custom"
retour() {
set +e
echo "ÉCHEC à l'étape $1 : retour à la version $ACTUELLE."
rm -rf "$DOLI"; mv "$ANCIEN" "$DOLI"; rm -f "$DOCS/upgrade.unlock"
echo "Anciens fichiers remis en place."
# Vider la base (les tables créées par la migration doivent partir aussi), puis recharger la sauvegarde
{ echo "SET FOREIGN_KEY_CHECKS=0;"
SQL "SELECT CONCAT('DROP TABLE \`', table_name, '\`;') FROM information_schema.tables
WHERE table_schema = DATABASE()"; } | mariadb --defaults-extra-file="$MYCNF" "$DB_NOM" \
&& mariadb --defaults-extra-file="$MYCNF" "$DB_NOM" < "$TRAVAIL/base.sql" \
&& echo "Base restaurée." \
|| echo "LA BASE N'A PAS PU ÊTRE RESTAURÉE : rechargez $TRAVAIL/base.sql à la main."
echo "Journaux de la migration : $TRAVAIL/*.html"; exit 1
}
# 4. Migrer la base, étape par étape, en tant qu'utilisateur du serveur web
cd "$DOLI/htdocs/install"
for E in "${ETAPES[@]}"; do
set -- $E
# step5.php efface upgrade.unlock quand la base atteint la version des fichiers : on le recrée à chaque étape
touch "$DOCS/upgrade.unlock"
if [ "$2" = "$C.0.0" ]; then FIN=""; ATTENDU=$NOUVELLE # dernière étape
else FIN="auto upgrade_$2"; ATTENDU=$2; fi # étape intermédiaire, comme l'assistant web
for P in upgrade.php upgrade2.php step5.php; do
A=""; [ "$P" = step5.php ] && A=$FIN
runuser -u "$WEB" -- php "$P" "$1" "$2" $A > "$TRAVAIL/$1-$2-$P.html" 2>&1 || retour "$P $1 -> $2"
done
# Codes retour à 0 même quand install.lock bloque tout : on contrôle le résultat
grep -q "$1-$2.sql" "$TRAVAIL/$1-$2-upgrade.php.html" || retour "$1 -> $2 (script SQL non lancé)"
V=$(SQL "SELECT value FROM ${PREFIXE:-llx_}const WHERE name='MAIN_VERSION_LAST_UPGRADE' AND entity=0")
[ "$V" = "$ATTENDU" ] || retour "$1 -> $2 (base en $V au lieu de $ATTENDU)"
echo "Étape $1 -> $2 : OK (base en $V)"
done
rm -f "$DOCS/upgrade.unlock"
# 5. Reverrouiller, comme après l'installation
[ -f "$DOCS/install.lock" ] || touch "$DOCS/install.lock"
find "$DOLI/htdocs" -path "$DOLI/htdocs/custom" -prune -o -exec chmod a-w {} +
chmod 400 "$DOLI/htdocs/conf/conf.php"
echo "Terminé. Anciens fichiers : $ANCIEN (à supprimer après contrôle)."
Ce qu’il ne fait pas : il ne contrôle pas les modules externes, il ne lit pas un mot de passe chiffré
dans conf.php (il s’arrête), et il utilise les commandes mariadb et mariadb-dump (sur un serveur
MySQL, elles s’appellent mysql et mysqldump : non testé).
Ce que nous avons vérifié avec ce script
- 22.0.524.0.2 (deux étapes), 23.0.424.0.2 et 24.0.124.0.2 : version de la base à
24.0.2, tiers, facture, pièce jointe et dossier de
custom/présents, clé API acceptée, pages/installde nouveau bloquées,upgrade.unlocksupprimé,conf.phptoujours en lecture seule. - Structure comparée colonne par colonne à une 24.0.2 installée à neuf : identique, à une colonne
près pour les bases venues de la 22 et de la 23 (
retained_warranty_amountdellx_facture, dont l’ajout est mis en commentaire dans le script officiel de la 24 et qu’aucun fichier PHP de la 24.0.2 n’utilise). - Échec provoqué (droit
ALTERretiré à l’utilisateur de la base) : le script s’est arrêté à la première étape, a remis les anciens fichiers et rechargé la base ; structure et contenu identiques à avant, API de nouveau en 22.0.5. - Durée sur notre base de test : 37 secondes, téléchargement compris. Une vraie base prendra plus longtemps : lancez-le en dehors des heures d’utilisation.
Revenir en arrière à la main
Si vous avez suivi les étapes à la main et que quelque chose ne va pas :
sudo rm -rf /var/www/dolibarr
sudo mv /var/www/dolibarr-ancien /var/www/dolibarr
sudo mariadb -e "DROP DATABASE dolibarr; CREATE DATABASE dolibarr CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"
sudo mariadb dolibarr < ~/dolibarr-base.sql
Vérifiez avant que votre base est bien en utf8mb4 (c’est le cas si vous avez suivi notre guide
d’installation).
Si la migration bloque
Lisez les fichiers /tmp/etape*.html (ou ceux du dossier de sauvegarde pour le script) : chaque
requête refusée y apparaît avec son message d’erreur. Si vous ne trouvez pas, le diagnostic à
90 € consiste à regarder votre instance avec vous pendant une heure, puis à
vous remettre par écrit la cause et ce que coûterait la correction.