Back to posts

Running Jenkins Pipeline with sudo

How to seamlessly run scripts as root in a Jenkins Pipeline? (sudoers & sudo -H guide) Struggling with the "sudo: a password is required" error in Jenkins? This brief guide solves the permission issue for non-privileged users. You'll learn why you should use sudo -H bash to run scripts (and how it saves your SSH connections!), and how to avoid a common mistake in sudoers configurations that keeps the system asking for a password.


Running Jenkins Pipeline Steps as Root — sudoers & sudo -H Guide

Problem

Jenkins agents run as a non-privileged user (e.g., jenkins).
Scripts that require root access (certbot, SSH to remote hosts using /root/.ssh/) will fail with:

ERROR: This script must be run as root

or:

sudo: a terminal is required to read the password
sudo: a password is required

Solution Overview

Two things are needed:

  1. sudo -H bash in the Jenkinsfile — to execute the script as root
  2. /etc/sudoers.d/jenkins-certbot — to allow passwordless sudo for those specific commands

Part 1 — sudo -H bash in Jenkinsfile

Why sudo bash and not just sudo ./script.sh?

When Jenkins runs sh '...', it launches a non-interactive shell without a TTY.
The cleanest way to run a script as root is:

sudo -H bash /path/to/script.sh [arguments]

What does -H do?

The -H flag tells sudo to set the HOME environment variable to the target user's home directory (root → /root).

Without -H:

HOME=/var/lib/jenkins    # jenkins user's home
SSH looks for keys in: /var/lib/jenkins/.ssh/   ← does not exist

With -H:

HOME=/root               # root's home
SSH looks for keys in: /root/.ssh/              ← correct location

This is critical when scripts use SSH/SCP to connect to remote hosts — they rely on /root/.ssh/config and /root/.ssh/id_* files.

Jenkinsfile example

steps {
    sh '''
        set -e
        sudo -H bash /var/jenkins/_workdir/01-letsencrypt-renewal.sh --force
    '''
}

Part 2 — sudoers Configuration

Why does sudo ask for a password?

By default, sudo requires a password for every user.
In a non-interactive Jenkins shell there is no TTY, so sudo cannot prompt — and fails.

How sudoers matching works

Sudoers matches the actual binary being executed, not the script path.

When Jenkins runs:

sudo -H bash /var/jenkins/_workdir/01-letsencrypt-renewal.sh --force

sudo sees:

command:   /bin/bash
arguments: /var/jenkins/_workdir/01-letsencrypt-renewal.sh --force

This means the sudoers rule must reference /bin/bash, not the script itself.

Common mistake

# WRONG — sudo sees /bin/bash, not the script path
jenkins ALL=(root) NOPASSWD: /var/jenkins/_workdir/01-letsencrypt-renewal.sh

This rule will never match and sudo will still ask for a password.

Correct configuration

Create /etc/sudoers.d/jenkins-certbot:

# Allow jenkins to run certbot scripts as root via "sudo -H bash /path/to/script"
jenkins ALL=(root) NOPASSWD: /bin/bash /var/jenkins/_workdir/01-letsencrypt-renewal.sh *
jenkins ALL=(root) NOPASSWD: /bin/bash /var/jenkins/_workdir/02-copy-cert.sh
jenkins ALL=(root) NOPASSWD: /bin/bash /var/jenkins/_workdir/03-restart-haproxy.sh

Rule breakdown:

Part Meaning
jenkins The user running the command (Jenkins agent user)
ALL=(root) Can run as root on any host
NOPASSWD: No password required
/bin/bash The actual binary sudo checks
/var/jenkins/_workdir/01-...sh * Specific script path; * allows any arguments (e.g., --force)
/var/jenkins/_workdir/02-...sh No * — script takes no arguments, so rule is strict

Installation

# Create the file
cat << 'EOF' > /etc/sudoers.d/jenkins-certbot
jenkins ALL=(root) NOPASSWD: /bin/bash /var/jenkins/_workdir/01-letsencrypt-renewal.sh *
jenkins ALL=(root) NOPASSWD: /bin/bash /var/jenkins/_workdir/02-copy-cert.sh
jenkins ALL=(root) NOPASSWD: /bin/bash /var/jenkins/_workdir/03-restart-haproxy.sh
EOF

# Set correct permissions (required by sudo)
chmod 440 /etc/sudoers.d/jenkins-certbot

# Validate syntax before applying
visudo -c -f /etc/sudoers.d/jenkins-certbot

Always validate with visudo -c before saving.
A syntax error in sudoers can lock you out of sudo on the system.


Verification

After configuration, test from the Jenkins agent user:

# Switch to jenkins user
su - jenkins

# Test each command
sudo -H bash /var/jenkins/_workdir/01-letsencrypt-renewal.sh --force
sudo -H bash /var/jenkins/_workdir/02-copy-cert.sh
sudo -H bash /var/jenkins/_workdir/03-restart-haproxy.sh

None of these should prompt for a password.


Security Notes

Practice Why
Limit rules to specific script paths Avoids granting unrestricted root bash access
Use * only where arguments are needed Minimizes attack surface
Set file permissions to 440 Required by sudo; world-readable sudoers files are rejected
Validate with visudo -c Prevents locking yourself out
Avoid ALL=(root) NOPASSWD: ALL Never grant unrestricted root sudo to service accounts

Quick Reference

Problem: Jenkins can't run script as root
  └─► Add: sudo -H bash /path/to/script.sh in Jenkinsfile sh block

Problem: sudo asks for a password in Jenkins
  └─► Add sudoers rule for /bin/bash /path/to/script.sh (not the script directly)

Problem: SSH fails even after sudo (wrong keys / no config)
  └─► Use sudo -H (sets HOME=/root so SSH finds /root/.ssh/)