RedHat9 php-fpm restart of the base version deletes all .sock files for all php versions

Do we? Do we need to modify systemd units? Is this what I said earlier?

Yes, we could just undo it, but that alone wouldn’t be a step forward.

You understand this is technically a sideways step, right? Though I don’t mind having a Virtualmin-specific directory for these files while dealing with the EL systems’ mess. In this case, if we go this way, I think the right directory would be /var/virtualmin, and for PHP-FPM, /var/virtualmin/php-fpm consequently.

Yes, this would be another option, but it would be more complicated because we still don’t have SELinux support provided by default. It may confuse users if we include a policy file in the package without SELinux turned on by default.

Oh, but why /var/virtualmin and not a run directory as the OS packages do it (e.g. /run/virtualmin/php-fpm or /var/run/virtualmin/php-fpm )? That seems non-standard, and I don’t like non-standard.

Something needs to recreate this runtime directory after reboots, and systemd already handles that nicely. That’s why I still think we should follow what the system already does instead of adding custom SELinux policies or using custom paths for socket files like in the old days.


In my perspective, using systemd drop-ins is a simpler and better choice for keeping PHP-FPM socket files in /run/php-fpm on EL systems, without the extra complexity. Simply put, we can just include it in our virtual-server RPM package with a 00-virtualmin.conf override for known PHP packages (which we already target and support). The change to our spec RPM file would be as simple as:

# 00-virtualmin.conf (systemd drop-in override)
tmp="$(mktemp)"
cat > "$tmp" <<'EOF'
[Service]
RuntimeDirectory=php-fpm
RuntimeDirectoryMode=0755
RuntimeDirectoryPreserve=yes
EOF

# PHP-FPMs
for unit in php-fpm php70-php-fpm php71-php-fpm php72-php-fpm php73-php-fpm php74-php-fpm \
           php80-php-fpm php81-php-fpm php82-php-fpm php83-php-fpm php84-php-fpm
do
  install -d -m 0755 "%{buildroot}%{_unitdir}/$unit.service.d"
  install -m 0644 "$tmp" "%{buildroot}%{_unitdir}/$unit.service.d/00-virtualmin.conf"
done
rm -f "$tmp"

# Post install
%post
/bin/systemctl daemon-reload >/dev/null 2>&1 || :

# Post uninstall
%postun
/bin/systemctl daemon-reload >/dev/null 2>&1 || :

# Files included
%files
%dir %{_unitdir}/php-fpm.service.d
%{_unitdir}/php-fpm.service.d/00-virtualmin.conf
%dir %{_unitdir}/php*-php-fpm.service.d
%{_unitdir}/php*-php-fpm.service.d/00-virtualmin.conf

…easy to support, and we have full control over the process.

We could even create a separate recommended package named virtualmin-php-fpm-systemd-dropins to handle this separately from virtual-server package.

in my experience only the base/default php version needs help, whatever php that might be — any of my REMI packages do not affect the contents of /run/php-fpm as their systemd configs don’t use that directory – only Virtualmin uses that for REMI versions.

Yes, that’s correct. REMI packages and their systemd configs don’t use that directory. I believe they do this because the person who supports php-fpm doesn’t do it right—if the php-fpm package systemd unit simply set RuntimeDirectoryPreserve=yes, REMI could use the /run/php-fpm directory too easily. It would be much better and simpler than what they are doing now.

And, I don’t want socket paths to change depending on the PHP package. Since it might involve SELinux, we shouldn’t change it from /run/php-fpm for that reason and because we care about standards.

Ideally, someone should convince the php-fpm package supporter to add RuntimeDirectoryPreserve=yes to their php-fpm.service file. Then it wouldn’t be impossible to convince REMI to do the same.

Debian and Ubuntu do it right despite the packages’ source and always use /run/php. And for some reason, EL chooses to shoot themselves in the foot, for probably the most popular package on their system.


Alternatively, a simpler solution than I suggested in my previous comment would be to create a oneshot type of unit distributed with our virtual-server RPM package that would look something like this:

# /etc/systemd/system/virtualmin-php-fpm-rundir.service
[Unit]
Description=Create /run/php-fpm
DefaultDependencies=no
Before=sysinit.target

[Service]
Type=oneshot
ExecStart=/usr/bin/install -d -m 0755 /run/php-fpm

[Install]
WantedBy=sysinit.target

And then, we could create an override for only the default php-fpm package, which currently deletes the /run/php-fpm directory used by other sockets every time it’s restarted.


Thinking more about it, this is better than my previous suggestion, because we don’t assume what additional PHP versions the user might install.

So, to sum up for Jamie and Joe—I think here is the simplest and most accurate solution for this problem:

  1. Supply a oneshot service to always re-create /run/php-fpm after reboot
  2. Create a systemd drop-in for php-fpm only with:
    [Service]
    RuntimeDirectoryPreserve=yes
    

That’s it—no other changes on the Virtualmin side would be needed, and we would stick to the standards as we always have.

If we do this, do we also need to re-create /run/php-fpm? Seems like that one won’t help, as the issue is deletion of .sock files from other PHP versions.

Also, by “drop-in” do you mean to modify the default unit, or is this a separate file that overrides some options in it? That seems pretty reasonable to me.

It’s easier to show how it’s done with the code. Check out this PR.

To answer your question, it will solve both issues: first, it will tell the default php-fpm.service unit not to delete /run/php-fpm upon restart or stop, and second, it will create /run/php-fpm as soon as the system boots, before any other PHP-FPM services start.

Yes, of course, it’s a separate file. We don’t modify the package file. It can even exist if php-fpm package is uninstalled.

Actually, we don’t need a one-shot unit! There is a much better way to do it:

To be clear, it’s just one file under /etc/tmpfiles.d to always have it created with the correct SELinux context if enabled:

# /etc/tmpfiles.d/virtualmin-php-fpm.conf
d /run/php-fpm 0755 root root -
Z /run/php-fpm - - - -

Just curious, if we configure systemd to not delete that directory, why do we need to re-create it on boot?

because /run/ lives in a memory resident (temp) file system that does not survive a reboot :smiley:

and in REMI’s defense, perhaps he wanted to use his own directory so if his package deletes it, no other php versions would be affected ?

It might worth raising this issue with Remi as they’re also the maintainer for RH/Fedora PHP packages.

Hey Paul, I’m a bit puzzled now to hear that the same people are behind both projects, as it doesn’t quite make sense to me; the SELinux policy for /run/php-fpm is part of the default, while anything else isn’t. So, I’m genuinely confused about this decision.

If you know those guys and could invite one of them to come here and comment on it, that would be good.

Nevertheless, in the end, we’ve solved this issue for the upcoming Virtualmin 7.40.0, so it won’t be a problem for anyone anymore.

I agree, it’s interesting - as far as I am aware they are one and the same person!

I have only interacted with Remi around why the RHEL PHP module packages do not package third party software, only in the base PHP package (i.e. Imagick, Redis and Sodium packages) and that was through the RHEL Issue tracker:

I’d guess you’d get a clear explanation if the issue is posted there?

I was interested in how REMI did stuff as the socket file on my system /var/opt/remi/php84/run/php-fpm/www.sock has the proper SELinux context of httpd_var_run_t

so I did –

yumdownloader php84-runtime
rpm -qpR --scripts php84-runtime-8.4-1.el9.remi.x86_64.rpm

to find (among other cmds) –

postinstall scriptlet (using /bin/sh):
# Simple copy of context from system root to SCL root.
semanage fcontext -a -e / /opt/remi/php84/root &>/dev/null || :
semanage fcontext -a -e /etc /etc/opt/remi/php84 &>/dev/null || :
semanage fcontext -a -e /var /var/opt/remi/php84 &>/dev/null || :

so when php84 as an alternate php is installed, it adds its own SELinux configuration that duplicates the default located in those standard directories — pretty smart actually.

and that shows up as –

semanage fcontext -l | grep /var/opt/remi/php84
/var/opt/remi/php84 = /var

and in REMI’s defense, perhaps he wanted to use his own directory so if his package deletes that directory, no other php versions would be affected ?

Have you looked at the Remi packages? I would assume they’re shipping policy for their directories.

I think you’re the one being weird about paths here, insisting on stomping on the system php-fpm path and demanding it behave differently from what’s packaged. We can make our own path, and we can ship a policy to get the right SELinux context on that path.

This is the right thing. I mean, we’re not exactly adhering to The Right Thing, because we don’t put our stuff in /opt even tough we’re a third party package (for historic reasons), but not depending on system paths and their behavior for our own FPM processes is obviously better. This is new behavior, there is no historic reason for us to do this wrong.

Yes, I checked, and they are not shipping it. REMI packages are covered by the default selinux-policy-targeted package.

No need. The simpler solutions are usually the better ones.