Jump to content

Preventing to be logged out from Processwire Admin when using Debian/Ubuntu Linux


Edison
 Share

Recommended Posts

When I installed Processwire for the first time, I noticed that Admin sessions were not lasting for a long time and it was very common to be logged out. Reading this forum I found useful information, but I could not solve this issue. I tried to modify site/config.php adding $config->sessionExpireSeconds with different values, but without success (for your awareness sessionExpireSeconds default value is 86400 seconds, ie 1 day .. so quite enough!).

OK, I had no time to go deeper, so I kept doing what I had to do ... being happily logged out …  time to time. Few weeks later while studying Session.php in wire/core/ I got the hint (please read the commented text) which helped me to understand how to solve it:

if(ini_get('session.save_handler') == 'files') {
  if(ini_get('session.gc_probability') == 0) {
    // Some debian distros replace PHP's gc without fully implementing it,
    // which results in broken garbage collection if the save_path is set. 
    // As a result, we avoid setting the save_path when this is detected. 
  } else {
    ini_set("session.save_path", rtrim($this->config->paths->sessions, '/'));
  }
}

Uh! Yes, my VPS uses Debian 9 ! So I quickly did a test:

echo ini_get('session.gc_probability');
echo ini_get('session.gc_divisor');
echo ini_get('session.gc_maxlifetime');

The session.gc_maxlifetime was rightly set to 86400, but session.gc_probability was 0 ! As you can easily get from Session.php routine, if probability is 0 bye bye PHP's session garbage collection and of course PW will not set the save_path. But why probability is set to 0 ??

This is due to the fact Debian/Ubuntu Linux overrides standard PHP’s session garbage collection by setting  session.gc_probability to 0. As a consequence PHP’s standard session garbage collection will never run. Instead Debian/Ubuntu sets a specific Cron job for garbage collection with a duration of 1440 seconds, ie 24 minutes. This determines the max session duration.

If you try to change session.gc_maxlifetime through $config->sessionExpireSeconds=86400 or ini_set('session.gc_maxlifetime', 86400) it will have no effect and sessions will be deleted at intervals of 24 minutes (or within 54 minutes). The Cron job garbage collection duration is defined at php.ini level, and runtime changes to session.gc_maxlifetime will not affect the Cron job timeout. Uh!

Of course the simplest solution would be to change session.gc_maxlifetime in php.ini. However sometimes this is not possible (shared hosting). Another point to consider is that this change may affect multiple applications running on your server.

Instead of modifying php.ini, personally I preferred to enable PHP's session garbage collection locally for Processwire only. Majority of the code is already written in PW Session.php, we have just to take benefit of it. Let's go step by step.

Let's open site/config.php and do the following modifications (I choose to implement 14400 seconds session time, ie 4 hours):

/**
 * Reduce inactivity timeout (original 86400 = 1 day)
 * How many seconds of inactivity before session expires
 */
 $config->sessionExpireSeconds = 14400;

/**
 * Enable Session Garbage Collection
 * Garbage Collection is disabled in Debian as default (probability set to zero)
 * Enable session garbage collection with a 1% chance of running on each session_start();
 * Chance calculated as gc_probability/gc_divisor
 * Session path is defined inside wire/core/Session.php and points to site/assets/sessions
 * Thanks to this modification session now takes into account gc_maxlifetime set in config
 */
ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 100);

Do not forget to lock site/config.php after modifying it.

Here it is! We are done!

After we have set gc_maxlifetime (through sessionExpireSeconds), enabled the garbage collection (gc_probability=1), and set its intervention probability (gc_divisor=100 ie 1% chance), we can rely on Session.php where the a session path (session_save_path()) is defined, and session is started (session_start()).

In the development session of our browser let's look for our session cookie:

442548499_ScreenShot2019-07-19at18_36_05.thumb.png.bf089988bad819e2e1bf07276a208363.png

 

if you go to site/assets/sessions you will find your corresponding session:

1292194904_ScreenShot2019-07-19at18_35_27.png.58ac07dd1121c3ea35c237e764ff5195.png

 

Please note that during development phase, likely having little traffic, the number of sessions may grow and they will not be deleted. This depends from the 1% chance of deletion. If you want to test garbage collection is properly working or just to make sure sessions files are regularly cleaned during development, you can decrease gc_divisor to a lower rate(10=>10% ... 2=>50%). Do not forget to reestablish gc_divisor = 100 when moving to production.

I hope some can find that tutorial useful in the future ... and may save several log outs!

  • Like 9
  • Thanks 2
Link to comment
Share on other sites

  • 4 weeks later...
  • 5 months later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...