A session that disappears looks like a login problem and almost never is. The login worked; the proof of it was lost between one request and the next.

1. Something is cleaning the session files

On Debian and Ubuntu a timer sweeps PHP session files on a schedule of its own, using the DISTRIBUTION's idea of the lifetime - not the one your page sets with ini_set. A page that raises gc_maxlifetime at runtime changes nothing about that sweep.

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

The fix is a session directory of your own that the sweeper does not touch, with its lifetime set in the pool config rather than at runtime.

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

2. The cookie is not coming back

session.cookie_secure = 1
session.cookie_httponly = 1
session.cookie_samesite = Lax
cookie_secure on a site reachable over plain http means the cookie is never sent back, and the user is logged out instantly with no error anywhere. It is correct on an https-only site and fatal on a mixed one.

3. Two servers, one session

Behind a load balancer, request one lands on server A and writes a session file there; request two lands on B, which has no such file. The user is logged out at random, which is the hardest version to reproduce.

  • Sessions in Redis or the database, shared by both.
  • Or sticky sessions at the balancer, which works and does not survive a server being replaced.

Watch it happen

ls -la /var/lib/php/sessions/ | head\n# log in, then look again: your file should be there and should stay
If the file exists and the user is still logged out, it is the cookie. If the file vanishes, it is the sweeper. That single observation splits the problem in half.