I have a script that executes several commands in a user's home directory. The files are owned by the user and Apache (the www-data group) only has read privileges to them. The script needs to be executed on demand by PHP via exec(), and performs some deletions / untarring of files, which fail since Apache doesn't have write permissions to the directories.

I've tried editing the sudoers file like this :

www-data ALL=(user) NOPASSWD: /bin/su user -c /home/user/bin/script.sh

but it prompts me for the user's password

I've also tried

www-data ALL=(root) NOPASSWD: /usr/bin/sudo su user -c /home/user/bin/script.sh

but that prompts for www-data's sudo password

How to I get this to work without a password ?


Finally got it working with this line :

www-data ALL=(ALL) NOPASSWD: /usr/bin/sudo -u user /home/user/bin/script.sh

Since I needed arguments to my script, I had to add a "shell-style wildcard" at the end of the line :

www-data ALL=(ALL) NOPASSWD: /usr/bin/sudo -u user /home/user/bin/script.sh [[\:alpha\:]]*

It's not exactly what I was looking for, but it works (ie. it happens that my arguments start with alphabetic characters, but in fact I would like the expression to match only alphanumeric characters, dashes and periods).

I'm not at all familiar with shell wildcards and POSIX character classes, the one I use is basically copy-pasted from the sudoers manual. Anyone who knows how these apply to this kind of problem, please leave your comments !


Why are you running su inside sudo? (or worse, sudo inside sudo)

www-data ALL=(user) NOPASSWD: /bin/bash /home/user/bin/script.sh

This should work.

  • I've tried your solution before and the script is still being run by www-data, that's why I thought of using sudo su user to switch the user before running the script... – Andrei Jul 3 '10 at 16:28
  • 1
    Read man sudo and take a look at the parameter -u. – joschi Jul 3 '10 at 16:54
  • Thanks ! I've managed to get it working by adding this line to the sudoers file : www-data ALL=(ALL) NOPASSWD: /usr/bin/sudo -u user /home/user/bin/script.sh However, it doesn't work with arguments, and my script uses arguments... – Andrei Jul 3 '10 at 17:51
  • Nevermind, found the solution here : gratisoft.us/sudo/sudoers.man.html – Andrei Jul 3 '10 at 18:17
  • Ehm, running sudo in sudo is kind of fail. Why not call sudo -u $USER /home/user/bin/script.sh in the first place? – joschi Jul 4 '10 at 5:48

If it weren't a script, you could've just suid'd the executable, and set the group & permissions so only the webserver could execute it.

You can also use suExec (apache only) or CGIWrap (any webserver) to run CGIs under other users. There's also suPHP specifically for PHP in non-CGI mode on Apache.

They offer slightly different options (eg, CGIwrap can set resource limits), but in general, they'll run programs as alternate users.

  • Of all of those you mentioned, suPHP seems the easiest to setup and is best suited to my needs. suExec as I understand it requires modifications in the way Apache works with PHP, and I really only need this feature for one script for the moment. What are the advantages of using these other solutions vs editing the sudoers file ? In terms of security, perhaps ? – Andrei Jul 4 '10 at 21:53
  • @Andrei : For one script at a time, sudo should be fine, so long as you're only limiting it to a script with a fixed set of arguments and running it as a non-root user; the ones I mentioned are useful for when you've got a collection of scripts that all need to run as a single user, eg. installing something you've downlaoded and you don't want to open up everything to the webserver user. They're also useful for multi-user systems, so each user can install CGIs but can't mess with each other's scripts. – Joe H. Jul 4 '10 at 23:03
  • Thanks for this explanation ! I'm running this script on a dedicated server, my main concern is to keep www-data doing what's is supposed to be doing (reading some files, and writing only in some directories). I'm still having trouble with the shell wildcards required to enable arguments for commands in sudoers though...(see below) – Andrei Jul 5 '10 at 11:10
  • @Andrei : any of the solutions I mentioned should keep you from having to deal with the issue of arguments. You might also be able to allow the script to take any argument, and then do the argument checking in the script rather than the sudoers file. – Joe H. Jul 5 '10 at 14:21

I've made a different approach to this, to allow the apache user to sudo to a specified user that can then run all commands (or you can specify a list if you only need one or a few.

Defaults:APACHEUSER       targetpw
Defaults:APACHEUSER             !requiretty

this allows the password to be sent from code (eg read from database) using :

echo password | sudo -u username -S bash -c command_here arguments_here

Just make sure you use a dedicated user for this, and don't put that user in the wheel group.

see also here


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.