0

I require a file at the top of my PHP scripts. The file just has connection object for MySQL:

$c->new mysqli('host','usr','pass','db')

The file has 400 permission: -r-------- and I keep it in /etc/mysql/ away from my webpage root (/var/www/html).

It works fine, except every night at midnight it stops and I will get a permission denied error for all of my pages:

Warning: require(/etc/mysql/.myfile.php): Failed to open stream: Permission denied in...

If I change permissions to 444, log in to my site, then change the permissions back to 400. It works until the next midnight. I can log in and log out of my site as many times as I want throughout the day, but when midnight comes, it will fail.

What causes this and how do I fix it?

Obviously I'd like to keep it so that only root can read the file since it has password in clear text.

2
  • 1
    Note: you can put also in /var/www/html. If someone has access to it, can also access the file in /etc (by just adding few line in PHP). In any case, I use either /root/ or /etc/local/ for my files (which should not be touched by maintenance scripts of other packages). Nov 29, 2023 at 8:42
  • ok thank you. I will try in /etc/local and see what happens.
    – bungee1980
    Nov 29, 2023 at 9:11

2 Answers 2

0

This should be a comment - but space is limited there and so is formatting.

You've not really provided a good explanation of the situation.

You've said you "lose permissions" and how you restore normal operations, but you've not said what the permissions are after the midnight event.

When determining access, permissions are meaningless without details of ownership. Presumably the file is initially owned by your webserver uid (although you didn't actually say that this was being accessed by scripts running from the webserver). Again, what are these before and after?

How did you determine that it stops at midnight? Knowing exactly when the event occurred is a useful stepping stone to resolving the issue. If it occurred (say) between 00:00:00 and 00:03:00 then there's a very high probability that this was due to some scheduled task. It also makes it a lot easier to cross reference the event with the system logs (as well as the webserver logs).

Kudos for thinking about permissions and access however....

Your choice of permissions is not ideal. Again assuming that this is for a webserver, then the file can only be managed by the root user. If you are the only person maintaining the server, then a better approach would be to set the ownership to bungee1980:wwwgrp (where wwwgrp is the defaul group for the webserver uid) and permissions -rw-r----- (0750).

Your choice of location is not ideal. Most modern OS restrict file access via mandatory access control mechanisms (SELinux on RHEL and derivatives, Apparmor elsewhere). It is common to restrict the webserver to a directory tree containing only its content. While you don't want this file to be inside the document root for obvious reasons, you also don't (usually) want to allow your scripts to read directly from a lot of the other files in /etc

A minor issue is that PHP provides a mechanism for setting the default credentials and database details (and for running additional boiler plate code in advance of the target script). Given that this can be set in your webserver config, that might be a more appropriate vehicle for the credentials.

2
  • The file ownership is root:root I will change it as you suggest. I'm interested in the links you sent but will take me a while to figure out what they mean. Even though my situation isn't critical, I want to know the right way to do this. I know for a fact that it happens at midnight because I tested it by logging in and out at 11:59 two nights in a row (I thought at first it was because of a cron job I run at 3am). I will try giving my user group access tonight. Where is such a file 'supposed' to be located?
    – bungee1980
    Nov 30, 2023 at 1:10
  • I chose this as the answer even though it doesn't really address why I lose permission. But changing my php.ini file to have a prepended file read as explained in your link was a real eye-opener. thanks for that. And it's 12:02 am right now and working.
    – bungee1980
    Dec 1, 2023 at 8:02
0

If I change permissions to 444, log in to my site, then change the permissions back to 400.

In other words: with permissions 400, your scripts cannot read the file, but with permissions 444, they can, and then some process will be either keeping the file open or keeping the credentials in RAM until midnight, when something triggers a restart or clean-up of some sort.

You did not mention the OS/distribution you're using, but I would start by checking /etc/cron.* and the crontabs of any relevant users (usually in /var/spool/cron[/crontabs] or similar) for any daily cron jobs running at midnight. Perhaps there's something that cleans up old PHP sessions? Or perhaps it's logrotate triggering a restart of something like php-fpm as part of a daily log rotation schedule?

If your system uses systemd, also check its timer units: systemctl list-units --type=timer to list all system-wide timers, and then systemctl cat <name>.timer to view them.


For example, in Debian 12, logrotate could be triggered by /etc/cron.daily/logrotate, which might run by anacron at the time specified in /etc/cron.d/anacron, by default the earliest time between 07:30 and 23:30 when the system is running... but this schedule will actually be used only if systemd is not in use, as the job specified in /etc/cron.d/anacron is conditional to /run/systemd/system not existing.

With systemd, logrotate.timer is used instead, and it is specified like this:

systemctl cat logrotate.timer 

# /lib/systemd/system/logrotate.timer
[Unit]
Description=Daily rotation of log files
Documentation=man:logrotate(8) man:logrotate.conf(5)

[Timer]
OnCalendar=daily
AccuracySec=1h
Persistent=true

[Install]
WantedBy=timers.target

As described in man systemd.time, OnCalendar=daily means *-*-* 00:00:00, i.e. every day exactly at midnight. The AccuracySec=1h allows coalescing this timer with other timers that trigger between 00:00 and 01:00, if any exist, to optimize power saving. On my system at least, the end result seems to be that the log rotation happens exactly at midnight, unless the system was down at that time.

With systemctl status logrotate.timer, you can see the next scheduled trigger time for the timer.

1
  • ty for the info. your answer tries to get the heart of WHY it is happening. But I selected the other answer because it solved my problem and I dont feel like changing anything in the system for something that could be fixed through php.ini
    – bungee1980
    Dec 1, 2023 at 8:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .