How do I create a safe and secure cron job for running PHP scripts of my website?

I'm creating a PHP installation script for Ubuntu 16.04.3 LTS Server. The script copies files from my installation package to /var/www/mysite and sets appropriate read/write permissions for default Apache web user account, which is www-data:

setfacl -R -m u:www-data:rX /var/www/mysite
setfacl -R -m u:www-data:rwX /var/www/mysite/storage /var/www/mysite/bootstrap/cache
setfacl -dR -m u:www-data:rwX /var/www/mysite/storage /var/www/mysite/bootstrap/cache

Now, as the final step of my installation script I have to install cron jobs that call PHP commands on my site, for example, like this one:

php /var/www/mysite/artisan notifications:send

I have done some research and found multiple options and possible complications, so I'm not sure what would be the most correct and error free way to create a cron job in my situation.

Specific thoughts and questions:

  • it seems, the best place to install cron jobs that do not belong to a specific user but to services running in background would be /etc/cron.d, right? It also seems safe choice for automated installation process because I won't have to change any existing cron config file from my installation script but just add a new file, if it doesn't exist yet.

  • I don't want to run my jobs as root; that might be not good idea for websites, right? So I will need a dedicated user. At first I thought - hey, I already have www-data user created for Apache server and with all required permissions for my site, so I could use that, right? But I've read that www-data user actually has no permissions to execute shell commands! So, I would have to change the permissions of www-data (which seems not a good idea) or I should create a new user account specifically for my cron jobs, such as mysite-jobs. But how do I safely check existence of this user and if it does not exist then create the user from my installation script? And how do I specify its permissions so cron can run php /some/command as this user but the user itself does not have /home nor password and cannot normally login?

  • also, I've read that environment variables are not automatically available for jobs in cron.d, so I have to specify them in my cron file. Technically, it might look like this, right?

    SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

My guess is that this might also automatically fix the problem of launching PHP commands in the previous point, but I'm not sure if I'm not giving too much permissions here - I don't want the user to execute any shell command or any command from those bin and sbin directories but php /some/command only. And also this makes me wonder - if I have to specify SHELL and PATH variables for cron to use for this job only, then maybe it's safe to use www-data after all - those environment variables won't leak out of the cron job, right? But I'm not sure if they will be effective for www-data at all, considering that it is a "special" account.

  • after I create a cron job in /etc/cron.d, will it be picked up by cron immediately or do I have to somehow notify cron about new (or possibly updated when I update websites) file?

So, considering all of the above, how should the final cron job look and how do I specify user account with minimal permissions to run my php commands?

  • do you need to run this as a oneoff or every so often? – Journeyman Geek Nov 19 '17 at 12:35
  • The installation script will be run many times to deliver updates, which means that new cron jobs might be added in new versions of my website. – JustAMartin Nov 19 '17 at 12:44

No need to over-think it. Since you are using Ubuntu, the crontab takes the id under which to run the cron job (www-data). On my server (that runs a MyBB forum) I added this to /etc/crontab:

# Run DB backups every morning at 06:00 UTC.
0  6 * * *   www-data /usr/bin/php /var/www/theforum/task.php 4

No need to worry about PATH contents if you give a full path to the PHP executable.

  • I've read that it's not good idea to modify /etc/crontab directly because it might be unsafe to update & merge using automatic tools; see the comment by kasperd under this answer: serverfault.com/a/801261/87638 therefore I chose cron.d option, where I could put a file which I'm sure will have entries created only by my installation script. But thanks for the direct /usr/bin/php part - I guess, with direct php execution www-data will not need any PATH or SHELL settings, right? – JustAMartin Nov 19 '17 at 17:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.