pm2
pm2 copied to clipboard
startup script: SELinux prevents PM2 from starting up on CentOS 8
What's going wrong?
On CentOS 8, pm2 startup
generates a systemd
service that is incompatible with the default security policy enforced by SELinux. Because of that, the service won't start.
How could we reproduce this issue?
On CentOS 8, just run pm2 startup
. After following the instructions, start the service. It won't be able to start.
Supporting information
I've opened a StackExchange issue that explains the problem. I think the issue is that the PIDFile
property of the service is a path to the home directory :
PIDFile=/home/john/.pm2/pm2.pid
I think this drifts away from the convention of having PID files in the /run
directory, and this is probably why I get this error when I start the service
SELinux is preventing systemd from read access on the file pm2.pid.
To me, the reason is due to the mismatch between these two contexts
Source Context system_u:system_r:init_t:s0
Target Context system_u:object_r:user_home_t:s0
I believe the problem would be solved by having the PID file generated in the /run
directory (actually I checked, and it worked).
I personally gave up on pm2 startup
because of this issue, and that pm2 startup
doesn't write PM2_* variables into the environment of the service file it generates. PID file and log file path should be flags for pm2 startup
, or at a bare minimum, transcribe PM2_PID_FILE_PATH
and PM2_LOG_FILE_PATH
into the service file generated. It should default to what the system expects, however, instead of what it is currently doing.
I get that pm2 wanted to be tidy and keep everything in one place, but violating system conventions asks for trouble. PIDs of systemd registered services are typically supposed to go in to /var/run, logs in /var/log. pm2 startup
should respect system conventions and default to what the system expects. Otherwise you run up against other system built in features like SELinux which expect conventions to be followed, and cause great misery for your users.
I am working around this issue with ansible to create the service myself, but it's a headache I have to maintain now.
Have two big thumbs up fellow sufferer.
👍 👍
I could solve my issue by lifting restrictions, but as you said it would be way better if PM2 followed system conventions in the first place. I'm setting up an execution environment and PM2 is the only thing that doesn't go smoothly.
Related issue #4776
Allowing the user to specify the location of the PID file would be a potential workaround. However, if you edit the generated unit file for systemd, specifying an alternate location for PIDFile, PM2 still writes the file at PM2_HOME/pm2.pid. The SELinux error goes away, but systemd is unaware that PM2 has successfully started and will continually try to start it until this file exists. Manually copying the file from PM2_HOME to the more sensible location (/var/run) makes everything happy until the next reboot.
The issue, as I see it, is that, regardless of the value chosen for PIDFile, PM2 ignores it. From what I can tell, paths.js has this hardcoded to PM2_HOME/pm2.pid. If this was changed so that it could be decoupled from PM2_HOME, at least there would be an acceptable workaround.
In the absence of a real solution to this problem, the following is the workaround that I've devised. It's far from elegant, but it'll get the job done until this is properly addressed. In the systemd service file for pm2, change the value for PIDFile as follows:
PIDFile=/run/pm2.pid
Because pm2 ignores this and writes the PID file to PM2_HOME anyway, we will also need the following:
ExecStartPre=/usr/bin/rm -f /run/pm2.pid
ExecStartPost=/usr/bin/cp /root/.pm2/pm2.pid /run/pm2.pid
Be sure that ExecStartPost
references the correct location of PM2_HOME for your installation.
This method is the best at the moment:
Edit file: /etc/systemd/system/pm2-root.service
-
Add new line:
Environment=PM2_PID_FILE_PATH=/run/pm2.pid
-
And replace:
PIDFile=/root/.pm2/pm2.pid
to:PIDFile=/run/pm2.pid
Versions:
- CentOS 8.3.2011
- Node.js 14.16.0
- NPM 7.7.5
- PM2 4.5.5
Original answer. Thanks Alec!
Just wanted to mention that only root can write in /run. If you want to run it as a non-root user, you need to add the entry RuntimeDirectory=pm2
and Environment=PM2_PID_FILE_PATH=/run/pm2/pm2.pid
. Then replace the entry for PIDFile
with /run/pm2/pm2.pid
.