I changed my server; the old one ran Centos 8
, the new runs Ubuntu 20.4
. Now my php scripts have a problem with permissions — why?
Example:
current user: root
script was executed under user: nobody
Message: fopen(/tmp/RebuildCat_sequence.cnt): failed to open stream: Permission denied
Actually this file is owned by nobody
, so I should not get this warning at all:
CS-1 01:47:22 :/tmp# ls -latr /tmp/RebuildCat_sequence.cnt
--wxrwxrwT+ 1 nobody nogroup 480 Oct 23 00:02 /tmp/RebuildCat_sequence.cnt
This php file is called by cron (root
), as a rule, and as I noticed that some similar cron triggered files are owned by systemd-timesync
, I issued
setfacl -m u:systemd-timesync:rwX /tmp
setfacl -m u:nobody:rwX /tmp
and even
setfacl -R -m u:nobody:rwX /tmp
setfacl -R -m u:systemd-timesync:rwX /tmp
to no avail. How do I understand this?
In my understanding both users systemd-timesync
and nobody
should be able to read and write files in /tmp
without problem due to acl
. I think someone has to educate me here.
/tmp
resides on /dev/md2
CS-1 01:32:34 :/tmp# tune2fs -l /dev/md2 | grep "Default mount options:"
Default mount options: user_xattr acl
No problem here, I guess.
CS-1 01:46:09 :/tmp# getfacl /tmp
getfacl: Removing leading '/' from absolute path names
# file: tmp
# owner: root
# group: root
# flags: --t
user::rwx
user:systemd-timesync:rwx
user:nobody:rwx
group::rwx
mask::rwx
other::rwx
Looks OK to me, as well. Clueless.
Addendum
OK, I set chmod 777 /tmp
, but still I get a PHP
error fopen(/tmp/RebuildCat_sequence.cnt): failed to open stream: Permission denied
, but file_put_contents
works with 777
— how do I understand this? Why does fopen
throw an error, but file_put_contents
does not?
2
Answers
Well, it looks like I was kind of silly. I'm sure I double checked permissions on
/tmp
inWinSCP
(1777
), but I am unsure if I did it in the console.Now I issued
chmod 777 /tmp
in the console and there it is! This problem is gone.chmod 666 /tmp
reintroduces the problem.chmod 676 /tmp
is OK as well.I googled quite a bit to educate myself about this topic, but frankly I don't understand it. In particular why did I have the problem in the first place and why did ACL not solve the problem? I'd appreciate some enlightenment.
Alas,
chmod 777 /tmp
in the console is not the answer. It is much more complicated than that. So I wasn’t silly at all.How to reproduce?
In my case, I have 2 docker
PHP
containers writing to a number of case specific log files, one of them usingapache
, the othernginx
. Both have a mapping/tmp:/tmp
, so we can look at a file from the host or from inside a container.From inside the containers, the owner is
apache:apache
if created in theapache
container ornginx:nginx
in thenginx
container, but from the host’s perspective it issystemd-timesync:systemd-journal
for the same file in both cases.Of course, the
apache
container does not have a usernginx
and vice versa (neither does the host). So if myPHP
script wants to write to a file created by the other container, I have said permission problem.Fix
The remedy is easy, if at creation time the owner is changed to
nobody
and permissions to666
.If not, we cannot change the owner from the other container and get
failed to open stream: Permission denied
. See https://serverfault.com/questions/772227/chmod-not-working-correctly-in-docker (also see the discussion about changing permissions from host viasystem
call below).So I wrote a wrapper function
str_to_file
to add this manipulation:This works for both the
apache
andnginx
containers.Explanation
How did I get into this mess anyway?
It looks like either I didn’t mess it up when on
CentOS
, so in this case most probably it has nothing to do with my switch toUbuntu
. I cannot remember what I did but I don’t remember I had this kind of permission problem onCentOS
.Or
CentOS
handles files created in a container differently thanUbuntu
. I am sure I never saw a usersystemd-timesync:systemd-journal
onCentOS
. Unfortunately I cannot investigate without too much effort what userCentOS
would substitute from the host point of view and which consequences this has.Oh wait, I remember I do have another server running
PHP
andnginx
onCentOS
. Creating a file in/tmp
from within the container reveals that the owner from both inside the container and from the host isnobody
. So there is a significant difference between both Linux versions.What’s more, this insight explains why I experienced this permission problem only after the switch from
CentOS
toUbuntu
, to which I was forced due to the fact that my provider does not offerCentOS
anymore for obvious reasons.By the way, I first tried the
CentOS
substitutesAlmaLinux
andRockyLinux
with bad results of different nature which finally forced me to useUbuntu
. This switch in turn revealed lots of problems, this one being the last, which cost me several weeks so far. I hope that this nightmare ends now.Acting from
cron
, theapache
version is and was used exclusively, so no problem here.Testing from the browser lately, I switched by chance and for no particular reason from the
apache
version to thenginx
version and vice versa, creating those described problems.Actually I don’t know why the containers write on behalf of those users. The user of the container is
root
in both cases, as is standard withdocker
. I guess it is the browser engine which introduces these users.Interestingly, when trying to change permissions and ownership via
system
call after creation, I failed, if I remember correctly, although the user then should beroot
androot
should be capable of doing that.It turns out that on
apache
thesystem
user [system(‘whoami’)] is notroot
butapache
, but the file owner isapache
where as onnginx
the system user isnobody
and the file owner isnginx
. So changing permissions withsystem
should work onapache
[system("chmod 0666 $filename"); system("chown nobody:nobody $filename");], but not onnginx
. Alas, it does not work onapache
either.Quick check in
apache
container:Sorry, I can’t understand this. And no idea about ACL.
apache vs. nginx
Why do I use both web server versions in the first place?
Well, the process I invoke processes random data which may take a long time, so chances are that
nginx
times out. This is a well-knownnginx
feature.Despite all my studies and obvious instructions, I could not manage
nginx
to behave. Geez!Finally, as an appropriate workaround, I introduced
apache
, which does not have this problem. For decent runtimes it makes no difference, of course.