PHP-FPM Socket Ownership Issue: Why listen.owner and listen.group Parameters Are Ignored


9 views

When configuring PHP-FPM, many developers encounter this perplexing behavior: while listen.mode changes take effect immediately, the listen.owner and listen.group directives seem completely ignored. The socket stubbornly remains owned by root:

$ ls -l /run/php-fpm/www.sock
srw-rw---- 1 root root 0 Jan 1 12:00 /run/php-fpm/www.sock

The root cause (pun intended) lies in systemd's interaction with PHP-FPM. Since most modern distributions use systemd to manage PHP-FPM, the service unit file overrides our socket permissions. Here's how to verify:

$ systemctl cat php-fpm.service
# Look for these critical directives:
[Service]
...
PrivateTmp=true
ProtectSystem=full
User=root
Group=root

1. Modify the systemd service file (Recommended)

Create an override file:

$ sudo systemctl edit php-fpm.service

Add these directives:

[Service]
User=ben
Group=ben
UMask=0007

2. Alternative: Change socket creation location

Move the socket to a directory where 'ben' has write permissions:

[www]
listen = /var/lib/php-fpm/www.sock
listen.owner = ben
listen.group = ben
listen.mode = 0660

3. Using a tmpfiles.d configuration

Create /etc/tmpfiles.d/php-fpm.conf:

d /run/php-fpm 0770 ben ben -

Then apply changes:

$ sudo systemd-tmpfiles --create

After implementing any solution:

$ sudo systemctl restart php-fpm
$ ls -l /run/php-fpm/www.sock
srw-rw---- 1 ben ben 0 Jan 1 12:00 /run/php-fpm/www.sock

Systemd enforces strict security by default. The root ownership prevents privilege escalation vulnerabilities. While inconvenient for development, this design protects production systems where PHP-FPM might run multiple pools with different users.


When configuring PHP-FPM's socket file permissions, many developers encounter a puzzling situation where listen.owner and listen.group directives in www.conf appear to have no effect. Despite explicit configuration:

[www]
listen = /run/php-fpm/www.sock
listen.owner = ben
listen.group = ben
listen.mode = 0660

The socket file stubbornly remains owned by root:root after service restart.

Through testing, we can confirm these behaviors:

  • Working: listen.mode changes take effect immediately
  • Working: Modifying listen path creates new socket with correct permissions
  • Not Working: Owner/group changes through config file alone

This occurs because PHP-FPM must be started as root to bind to privileged ports (<1024). The master process runs as root, while worker processes drop privileges. The socket file inherits ownership from the master process.

Three solutions exist:

Solution 1: Use systemd tmpfiles

# /etc/tmpfiles.d/php-fpm.conf
z /run/php-fpm/www.sock 0660 ben ben -

This ensures proper ownership before PHP-FPM starts.

Solution 2: Post-start chown

# In your systemd service unit
[Service]
ExecStartPost=/bin/chown ben:ben /run/php-fpm/www.sock

Solution 3: Run master as target user

Modify systemd unit (not recommended for production):

[Service]
User=ben
Group=ben

For production systems, the tmpfiles approach is most reliable. Here's complete implementation:

  1. Create tmpfiles configuration:
  2. echo "z /run/php-fpm/www.sock 0660 ben ben -" | sudo tee /etc/tmpfiles.d/php-fpm.conf
  3. Apply configuration:
  4. sudo systemd-tmpfiles --create
  5. Restart PHP-FPM:
  6. sudo systemctl restart php-fpm

After this, your socket file should maintain correct ownership across reboots and service restarts.

Confirm the settings took effect:

$ ls -l /run/php-fpm/www.sock
srw-rw---- 1 ben ben 0 Jul 15 10:30 /run/php-fpm/www.sock