01 Nov 2015

PHP-FPM Socket Passing

As noted on the PHP and Systemd wikis, PHP-FPM uses the FPM_SOCKETS variable to allow socket inheritance during reloads. While those examples (and all others I was able to find) use domain sockets, it's also possible to pass arbitrary TCP sockets with minimal fuss.

All that's required to launch PHP-FPM this way is an environment variable in the format FPM_SOCKETS=<ipaddress>:<port>=<fileno> and a matching listen directive in PHP-FPM's configuration file. The match between the environment variable and configuration file is required as PHP-FPM only uses inherited sockets that have corresponding listen directives. This can be taken care of with a little bit of sed or by generating a configuration file template on-demand.

As an example, let's pass a random port opened initially in Python to PHP-FPM:

# Bind the initial socket (port 0 = auto-choose)
import socket
s = socket.socket()
s.bind(('', 0))

# Get socket/file descriptor information
addr, port = s.getsockname()
fd = s.fileno()

# Update configuration
subprocess.call(["/usr/bin/sed", "-i",
                 "s/^listen[ ]*=.*/listen = %s:%d/" % (addr, port),

# Exec PHP-FPM in-place
          {'FPM_SOCKETS': '%s:%d=%d' % (addr, port, fd)})