Une session qui disparaît ressemble à un problème de connexion et n'en est presque jamais un. La connexion a marché ; c'est la preuve de cette connexion qui s'est perdue entre une requête et la suivante.

1. Quelque chose nettoie les fichiers de session

Sur Debian et Ubuntu, une minuterie balaie les fichiers de session PHP selon son propre calendrier, avec l'idée que la DISTRIBUTION se fait de la durée de vie - pas celle que votre page fixe avec ini_set. Une page qui relève gc_maxlifetime à l'exécution ne change rien à ce balayage.

systemctl list-timers | grep phpsessionclean
php -i | grep -E "session.save_path|session.gc_maxlifetime"

Le remède est un répertoire de sessions à vous, que le balayeur ne touche pas, avec sa durée de vie fixée dans la configuration du pool et non à l'exécution.

php_admin_value[session.save_path] = /var/lib/php/sessions-mysite
php_admin_value[session.gc_maxlifetime] = 86400

2. Le cookie ne revient pas

session.cookie_secure = 1
session.cookie_httponly = 1
session.cookie_samesite = Lax
cookie_secure sur un site joignable en http tout nu veut dire que le cookie n'est jamais renvoyé, et que l'utilisateur est déconnecté aussitôt, sans erreur nulle part. C'est juste sur un site tout en https et fatal sur un site mixte.

3. Deux serveurs, une session

Derrière un répartiteur de charge, la première requête tombe sur le serveur A et y écrit un fichier de session ; la deuxième tombe sur B, qui n'a pas ce fichier. L'utilisateur est déconnecté au hasard : la version la plus difficile à reproduire.

  • Des sessions dans Redis ou dans la base, partagées par les deux.
  • Ou des sessions collantes au répartiteur : cela marche, et cela ne survit pas au remplacement d'un serveur.

Regardez la chose se produire

ls -la /var/lib/php/sessions/ | head
# log in, then look again: your file should be there and should stay
Si le fichier existe et que l'utilisateur est quand même déconnecté, c'est le cookie. Si le fichier disparaît, c'est le balayeur. Cette seule observation coupe le problème en deux.