#907260 roundcube: database table `session` is never cleaned and grows without limit on nginx

#907260#5
Date:
2018-08-25 14:19:06 UTC
From:
To:
Dear Maintainer,

The table `session` of my roundcube database contained several months
worth of sessions, even though the lifetime of a session is 1200 seconds
(the default I think). This made this sole table more than 100MB.

Actual behavior: the last oldest row in the table is more than 8  months
old.
Expected behavior: the last oldest row in the table is not more than a
few days old (that is a few times $session_lifetime).

The reason of the problem seems to be the following: according to
https://github.com/roundcube/roundcubemail/issues/1864 roundcube relies
on vanilla php session gc. Debian disables it by setting
session.gc_probability to 0 and replaces it by a custom
phpsessionclean.{service,timer}. This script unfortunately only works on
sessions stored as files, and therefore does not clean roundcube
sessions.

I have implemented the following solution: roundcube ships a script to
gc manually: /usr/share/roundcube/bin/gc.sh
Unfortunately this script is slightly broken: when run I get
ERROR: Configuration error. Unsupported database driver:
According to strace, this script looks for roundcube's configuration
in /usr/share/roundcube/config/ instead of /etc/roundcube
Workaround:
ln -s /etc/roundcube/ /usr/share/roundcube/config
Similarly, I needed ln -s /tmp/ /usr/share/roundcube/temp
Then, bin/gc.sh works and I can make a systemd timer like
phpsessionclean:
# /etc/systemd/system/roundcube-gc.service
[Unit]
Description=Clean roundcube session table

[Service]
User=www-data
Type=oneshot
ExecStart=/usr/share/roundcube/bin/gc.sh
ProtectHome=true
ProtectSystem=true
PrivateTmp=true
# /etc/systemd/system/roundcube-gc.timer
[Unit]
Description=Clean roundcube session table every 30 mins

[Timer]
OnCalendar=*-*-* *:09,39:00
Persistent=true

[Install]
WantedBy=timers.target

I have been unable to trigger session gc by the vanilla php mechanism,
either in the nginx config or in /etc/php/7.2/fpm/php.ini, even with
session.gc_probability=1
session.gc_divisor=1

To sum up, it would be nice to fix bin/gc.sh and ship a timer to run it
periodically, possibly by default.

Thanks

#907260#10
Date:
2018-11-03 01:26:04 UTC
From:
To:
Hi,

Upstream's ‘.htaccess’ file sets it to one, however:

    $ grep -F session.gc_ .htaccess
    php_value   session.gc_maxlifetime   21600
    php_value   session.gc_divisor       500
    php_value   session.gc_probability   1

nginx doesn't honor that file, but it's not auto-configured by the
package's postinst script either, so nginx users are “on their own” in
that regard (hence lowering the severity to ‘wishlist’) :-P

I use the following snippet to pass these values to php-fpm and have one
every 500 requests (on average) trigger the GC and clean up expired
(>6h) sessions.

        location = /index.php {
            include snippets/fastcgi-php.conf;
            fastcgi_param PHP_VALUE "[…]
                                     session.gc_maxlifetime=21600
                                     session.gc_divisor=500
                                     session.gc_probability=1";
            […]
        }

Cf. also https://github.com/roundcube/roundcubemail/issues/3573 .

Cheers,

#907260#25
Date:
2022-06-28 18:59:01 UTC
From:
To:
Version: 1.4.1+dfsg.1-1
Control: forwarded 907260 https://github.com/roundcube/roundcubemail/issues/6560

Ooops that snippet disappeared from the upstream .htaccess since
1.4-rc1, didn't notice earlier…  But since that version Roundcube itself
sets session.gc_probability=1, so this should work on all backends.

That said, in retrospect a timer unit sounds like a good idea, that way
cleanup happens in the background and the less busy sites don't
accumulate stale sessions.