Jenkins normally runs shell commands as the jenkins user. However, some server-maintenance tasks require root privileges—for example, cleaning APT caches, removing old packages, or managing system files.
A common but unsafe approach is to give the Jenkins user unrestricted sudo access:
jenkins ALL=(ALL) NOPASSWD: ALL
This allows Jenkins jobs to execute arbitrary commands as root.
A much safer approach is to allow Jenkins to run only one specific maintenance script as root.
Approach: Allow Jenkins to Run Only One Script with sudo
In this example, we will create a cleanup script at:
/var/www/cleanup.sh
Jenkins will be allowed to execute this script as root, but it will not receive general root access.
1. Create the Root-Level Shell Script
Create the script on the server:
sudo nano /var/www/cleanup.sh
For example:
#!/bin/bash
set -e
echo "Running cleanup as:"
whoami
echo "------------ Check space before cleanup"
df -h
echo "------------ Clean the APT Cache"
du -sh /var/cache/apt/archives
apt-get clean
du -sh /var/cache/apt/archives
echo "------------ Remove Old Kernels"
apt-get autoremove -y
echo "------------ Check space after cleanup"
df -h
The important part is that the script contains the commands that require root privileges.
2. Set the Script Ownership and Permissions
Make the script executable:
sudo chmod 750 /var/www/cleanup.sh
Set the owner to root:
sudo chown root:root /var/www/cleanup.sh
You can verify the permissions:
ls -l /var/www/cleanup.sh
You should see something similar to:
-rwxr-x--- 1 root root ... /var/www/cleanup.sh
This prevents the Jenkins user from modifying the script itself.
That is important because if Jenkins could modify the script, restricting sudo to that script would provide little security benefit.
3. Create a Dedicated Sudoers Configuration
Instead of modifying the main /etc/sudoers file, create a dedicated configuration file:
sudo visudo -f /etc/sudoers.d/jenkins-cleanup
Add:
jenkins ALL=(root) NOPASSWD: /var/www/cleanup.sh
This rule means:
jenkins— applies to the Jenkins userALL— applies on the current host(root)— the command can run asrootNOPASSWD— Jenkins does not need to provide a password/var/www/cleanup.sh— Jenkins can run only this specific command
Save and exit.
Using visudo is recommended because it validates the sudoers syntax before installing the configuration.
4. Test the Sudo Permission
Before configuring Jenkins, test the command as the jenkins user:
sudo -u jenkins sudo /var/www/cleanup.sh
You can also run it with Bash tracing:
sudo -u jenkins sudo bash -x /var/www/cleanup.sh
You should see:
Running cleanup as:
root
This confirms that the script is actually being executed with root privileges.
Note: Running
sudo -u jenkins bash -x /var/www/cleanup.shby itself does not test the sudo permission. It only runs the script as thejenkinsuser. To test the root-level permission, usesudo -u jenkins sudo /var/www/cleanup.sh.
5. Configure Jenkins
In your Jenkins job, use an Execute shell build step:
#!/bin/bash
set -e
echo "Starting server cleanup..."
sudo /var/www/cleanup.sh
echo "Server cleanup completed."
Jenkins will execute:
sudo /var/www/cleanup.sh
The sudoers rule allows this command to run without requiring a password.
6. Verify That Jenkins Does Not Have General Root Access
The important security property of this setup is that Jenkins should not be able to execute arbitrary commands as root.
For example, this should fail:
sudo -u jenkins sudo whoami
While this should succeed:
sudo -u jenkins sudo /var/www/cleanup.sh
You can also check the permissions available to Jenkins:
sudo -u jenkins sudo -l
The output should show that Jenkins is allowed to run only the cleanup script.
7. Why This Approach Is Safer
Avoid giving Jenkins unrestricted sudo access:
jenkins ALL=(ALL) NOPASSWD: ALL
With unrestricted access, a compromised Jenkins job could potentially execute commands such as:
sudo rm -rf /
or modify system configuration, users, SSH keys, and other sensitive resources.
Instead, use a narrowly scoped rule:
jenkins ALL=(root) NOPASSWD: /var/www/cleanup.sh
This follows the principle of least privilege: Jenkins receives only the root permission it actually needs.
8. Important Security Considerations
Keep the Script Owned by Root
Do not allow Jenkins to modify the script:
sudo chown root:root /var/www/cleanup.sh
sudo chmod 750 /var/www/cleanup.sh
If Jenkins can write to a root-executable script, it could potentially insert arbitrary root commands into that script.
Use an Absolute Script Path
Use:
sudo /var/www/cleanup.sh
rather than:
sudo cleanup.sh
The absolute path makes the sudoers rule precise and avoids ambiguity around the executable being invoked.
Avoid User-Controlled Arguments
If you want Jenkins to run:
sudo /var/www/cleanup.sh
do not unnecessarily allow:
jenkins ALL=(root) NOPASSWD: /var/www/cleanup.sh *
The latter allows Jenkins to pass arbitrary arguments to the script, which can introduce additional security concerns.
Be Careful With Commands Inside the Script
Since the script runs as root, every command inside it effectively has root privileges.
For example:
rm -rf "$SOME_DIRECTORY"
should be carefully validated if the directory path can ever be influenced by external input.
Final Configuration
The resulting setup is simple:
Jenkins
|
| sudo /var/www/cleanup.sh
|
v
sudoers
|
| Allows only this command
v
/var/www/cleanup.sh
|
| runs as root
v
Server cleanup operations
The key configuration is:
Script:
sudo chown root:root /var/www/cleanup.sh
sudo chmod 750 /var/www/cleanup.sh
Sudoers:
jenkins ALL=(root) NOPASSWD: /var/www/cleanup.sh
Jenkins:
sudo /var/www/cleanup.sh
This gives Jenkins the ability to perform the required root-level maintenance task while avoiding unrestricted root access.
