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.

Versions concernées
Dolibarr 22.0.5, 23.0.4 et 24.0.1 mis à jour vers 24.0.2 (archives officielles .tgz) · Debian 13, PHP 8.4, MariaDB 11.8
Ce qui a été vérifié
Tests du 19/10/2026 sur Debian 13 (PHP 8.4.26, MariaDB 11.8.6) avec les archives officielles de SourceForge : installations neuves de 22.0.5, 23.0.4 et 24.0.1 par l'assistant web, avec un tiers, une facture, une pièce jointe, une clé API et un dossier dans custom/ ; commandes de cette page exécutées sous un compte sudo ; script lancé depuis les trois versions ; migration en un seul appel, deuxième étape bloquée par upgrade.unlock, lancement depuis un autre dossier et sous un autre compte ; échec provoqué (droit ALTER retiré) pour tester le retour arrière ; structure de chaque base comparée colonne par colonne à une 24.0.2 neuve ; API REST appelée avant et après. Lecture du code de Dolibarr 24.0.2 (install/upgrade.php, upgrade2.php, step5.php, inc.php, check.php).

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 /install de nouveau bloquées, upgrade.unlock supprimé, conf.php toujours 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_amount de llx_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 ALTER retiré à 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.

À lire aussi

Dolibarrmise à jourscriptligne de commandeupgrade.phpupgrade2.phpstep5.phpupgrade.unlockinstall.lockSSH