PHP session mounted as tempfs

It used to be recommended back with Nextcloud 11 that you mount your php session as a tempfs in ram to speed things up. Does anyone know if this is still recommended for Nextcloud 16? If you have Redis installed doesn’t that already sort of take care of caching the session in RAM?

I’d start with tuning of your caching via redis and database. Especially the database can make huge difference compared to standard setups. In the temp-folder, I think during the partial upload some files snippets are stored there. But before you put everything on RAMdisk, I’d do a few large uploads and check the system performance with iotop. Mostly it is the database which creates too much i/o-load which can be reduced with redis and proper caching settings.

Thanks @tflidd
I’m familiar with tuning the innodb_buffer_file_size as well as the opcache and apc.shm_size for APCu. Other than running redis over a socket I’m not sure of any other tuning I can do.
When you monitor with iotop are you mostly just checking to make sure nothing is going into swap?

What you did already covers all I wound recommend: APCu + Redis + MariaDB cache tuning.

Not sure what you initially meant by running the session in RAM:

  • Webserver and PHP are already running in RAM, the environment and sockets etc. The only thing that could be additionally done is moving the tmp PHP upload dir to RAM, if not yet the case, however that can fill RAM based on the size of uploaded files and I am not even sure if/how this is used by Nextcloud, at least I could never monitor any writes to the tmp upload dir when uploading files via web UI, but to the Nextcloud data dir directly instead. (EDIT: At least when uploading via desktop client, each uploaded file is indeed temporarily created in upload_tmp_dir, which defaults to /tmp already.)
  • The database itself should not be moved to RAM (and e.g. synced to disk as shutdown task) to avoid loss of data (calendar, file tags/meta data/index, …) in case of server crash. Instead keep it on a fast drive, e.g. SSD.

Thanks for explaining all that. I feel like I understand a bit more.
The PHP Session I was referring to is the one referenced here, not the database itself:
https://docs.nextcloud.com/server/11/admin_manual/installation/deployment_recommendations.html

Ah I guess you’re referring to the session.save_path, which indeed defaults to /tmp, which is a tmpfs by default on Debian. Since the default systemd unit for Apache and PHP-FPM used private-tmp=true, you’ll find the actual dir in some /tmp/apache-<random_string> sub dir.

In my Ubuntu I can find private-tmp=true in /lib/systemd/system/apache2.service file.
However, in /etc/php/7.2/apache2/php.ini I find session.save_path = "/var/lib/php/sessions"
So shouldn’t it be defaulting to /var/lib/php/sessions directory?

You are right, I did not have a close enough look at this. Indeed in my case as well I see session files being created in that dir. This is strange since due to PHP docs, /tmp is default:
https://www.php.net/manual/en/session.configuration.php#ini.session.save-path
And in my case all settings are commented, so the default should apply :thinking:

2019-08-08 12:40:04 root@micha:/var/lib/php/sessions# grep -r 'session.save_path' /etc/php/
/etc/php/7.3/apache2/php.ini:;     session.save_path = "N;/path"
/etc/php/7.3/apache2/php.ini:;     session.save_path = "N;MODE;/path"
/etc/php/7.3/apache2/php.ini:;session.save_path = "/var/lib/php/sessions"
/etc/php/7.3/apache2/php.ini:;       (see session.save_path above), then garbage collection does *not*
/etc/php/7.3/cli/php.ini:;     session.save_path = "N;/path"
/etc/php/7.3/cli/php.ini:;     session.save_path = "N;MODE;/path"
/etc/php/7.3/cli/php.ini:;session.save_path = "/var/lib/php/sessions"
/etc/php/7.3/cli/php.ini:;       (see session.save_path above), then garbage collection does *not* 

Reading a bid it seems that it is by distro not moved to /tmp by default, since this can be a security issue when other processes are able to read those. However since Apache has provate-tmp, this is not an issue, so session.save_path=/tmp is something that can and should be set. I just do on my system and verify behaviour.

EDIT: Jep as it should, session files are created in /tmp/systemd-private-<random_string>-apache2.service-<random_string>/tmp now. Confused why this is not default. But to be true these session files are small (single line) and neither performance nor disk I/O should significantly enhance by this.

Thank you for spending the time to clarify all that @MichaIng
I think I found the same info about the session.save_path locations here:


So since it doesn’t really impact performance I guess there is no reason to recommend setting it to /tmp in the Nextcloud Admin Manual.

On the other hand many guides about PHP tuning mention that these should be set to a tmpfs or handled via Redis for larger multi system environments. I guess it depends on how heavy the server is in use, thus how many files are actually created between the 30 minutes when the phpsessionclean systemd timer cleans them. And as it does not hurt, at least with private-tmp it definitely makes sense and has no downside.

I’m going to summarize everything here in case anyone else is wondering about this. Maybe something should be added to the Nextcloud Admin Manual on this.

PHP Session Files

PHP Sessions allow web pages to be treated as a group, allowing variables to be shared between different pages.
Session files offer a secure alternative to cookies and even work when the user has disabled the browser’s cookie support.
Many performance/tuning guides recommend storing session files in a RAM file or using redis as a session handler.

Recommendations for Nextcloud:

Single-server Deployment: Store sessions in files on a tmpfs so they reside in RAM.
Multi-server Deployment: Use redis as it offers both a RAM cache and persistence on disk. In a multi-server environment redis allows the same session data to be available regardless of which application server serves an individual request.

PHP session files on tmpfs

Linux distros can have various default locations for the session.save_path found in the php.ini files.
If php is compiled from source the default location will be /tmp
In some distros /tmp is mounted as as a tmpfs in RAM.
if this is the case you can just set the session.save_path to /tmp in your php.ini files.
To check for tmpfs mounts:

mount | grep -i tmp

Note: storing session files in /tmp can be a security concern if other users can access those files.
Apache’s default systemd unit sets private-tmp=true in /lib/systemd/system/apache2.service
This setting keeps these files private.

If /tmp is not mounted as a tmpfs (as in the case of Ubuntu 18.04) then one solution is to find the current session.save_path and mount it as tmpfs
To find the default session.save_path you can create a phpinfo() file in your webroot directory or use the following command:

grep -R 'session.save_path' /etc/php*

In the output look for the apache2/php.ini file if using apache.
The session.save_path will likely be commented out with a ; but this is still the default location.
Under Ubuntu 18.04 this will be /var/lib/php/sessions
Add the following to your /etc/fstab and then reboot the system:

tmpfs /var/lib/php/sessions tmpfs defaults,noatime,mode=1777 0 0

To check that correct permissions were set after reboot:

stat -c "%a %n" /var/lib/php/sessions

PHP session handled by redis socket

If you are connecting multiple servers to your redis server you will not be using a socket. This site might help: https://www.digitalocean.com/community/tutorials/how-to-set-up-a-redis-server-as-a-session-handler-for-php-on-ubuntu-16-04

To set up with a socket, add the following to /etc/php/7.0/mods-available/redis.ini
Make sure to replace redis.sock and your-password with the values from your system.

session.save_handler = redis
session.save_path = "unix:///var/run/redis/redis.sock?auth=your-password&persistent=1&weight=1&database=0"

Restart apache and redis.

1 Like

Great summary.
Btw about the last part: You don’t need to edit both, php.ini and redis.ini since the latter just overrides the first. Add those lines to redis.ini only, to have is enabled/disabled together with the required module and leave php.ini untouched. Or use an own drop-in config or mod to manage custom settings and leave all default files untouched.

Thanks. I made that change.

I found a reason why PHP session files in /tmp does not work well on most systems:

  • The Apache and PHP-FPM systemd units (services) contain PrivateTmp=true.
  • This protects their tmp files from other services and prevents double uses, but it means that no other process sees the same files when looking in /tmp.
  • phpsessionclean.service now has no chance to find and clean PHP session files. It has PrivateTmp=true itself, hence PHP handler and phpsessionclean both need to have this removed, which then again breaks the security and isolation benefit…

So the only chance I see then is to use another or own tmpfs instead and either mount it or chown a subdir with root:root 1733 to only allow root full access and www-data write access only (like default /var/lib/php/sessions).

1 Like