When managing Linux servers, you often need to grant limited sudo privileges for specific scripts while maintaining system security. The common pitfall is assuming directory-level permissions will work, when sudo actually requires explicit file paths.
The entry jsmith ALL=(ALL) NOPASSWD: /usr/local/tomcat7/bin
doesn't work because:
- Sudo validates exact file paths, not directories
- Wildcards have special requirements in sudoers
- Directory permissions don't imply execution rights
For Tomcat scripts, use this format in /etc/sudoers
:
# Grant passwordless access to specific scripts
jsmith ALL=(root) NOPASSWD: /usr/local/tomcat7/bin/startup.sh
jsmith ALL=(root) NOPASSWD: /usr/local/tomcat7/bin/shutdown.sh
jsmith ALL=(root) NOPASSWD: /usr/local/tomcat7/bin/catalina.sh
If you need to match multiple scripts safely:
# Allow all scripts in bin/ but with strict naming
jsmith ALL=(root) NOPASSWD: /usr/local/tomcat7/bin/[a-z]*.sh
Important: Avoid broad wildcards like *
or .*
which create security holes.
After editing sudoers, always verify with:
sudo visudo -c
sudo -u jsmith sudo -l
- Use full absolute paths
- Restrict scripts to read-only locations
- Audit scripts for potential privilege escalation
- Consider creating a dedicated system group instead
For complex cases, create a C wrapper:
#include <unistd.h>
int main() {
setuid(0);
system("/usr/local/tomcat7/bin/your_script.sh");
return 0;
}
Compile with: gcc wrapper.c -o wrapper
then chmod u+s wrapper
When you need to grant passwordless sudo access to specific scripts while maintaining system security, the sudoers file provides the most reliable solution. Here's the proper syntax:
# Allow user 'jsmith' to run all scripts in /usr/local/tomcat7/bin without password
jsmith ALL=(root) NOPASSWD: /usr/local/tomcat7/bin/*.sh
Several important considerations when implementing this:
- Wildcards must be explicit (like *.sh) - directory paths alone won't work
- Specify the target user (root in this case) for security
- Test with
sudo -l
before implementation
For a concrete example with Tomcat control scripts:
# /etc/sudoers.d/tomcat-user
jsmith ALL=(root) NOPASSWD: /usr/local/tomcat7/bin/startup.sh
jsmith ALL=(root) NOPASSWD: /usr/local/tomcat7/bin/shutdown.sh
jsmith ALL=(root) NOPASSWD: /usr/local/tomcat7/bin/catalina.sh
To enhance security while maintaining convenience:
# Create a dedicated group
sudo groupadd tomcatadmins
# Set script ownership
sudo chown root:tomcatadmins /usr/local/tomcat7/bin/*.sh
sudo chmod 750 /usr/local/tomcat7/bin/*.sh
# Group-based sudo rule
%tomcatadmins ALL=(root) NOPASSWD: /usr/local/tomcat7/bin/*.sh
If your configuration isn't working:
- Check syntax with
visudo -c
- Ensure no conflicting rules exist
- Verify file permissions on both scripts and sudoers file
- Check SELinux/AppArmor contexts if applicable
For more complex scenarios, consider wrapper scripts:
#!/bin/bash
# /usr/local/bin/tomcat-control
case "$1" in
start)
sudo /usr/local/tomcat7/bin/startup.sh
;;
stop)
sudo /usr/local/tomcat7/bin/shutdown.sh
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
esac
Then grant sudo only to the wrapper:
jsmith ALL=(root) NOPASSWD: /usr/local/bin/tomcat-control