The deployment of a continuous integration and continuous delivery (CI/CD) pipeline requires a robust execution environment where the GitLab Runner can perform high-level system operations without manual intervention. In a standard installation on Ubuntu 22.04 LTS, the GitLab Runner is installed as a service that operates under a dedicated system user named gitlab-runner. By default, this user lacks the administrative privileges necessary to perform tasks such as installing software packages, modifying system configurations, or managing other system services via the sudo command. To bridge this gap, the gitlab-runner user must be explicitly added to the sudoers file. This process ensures that the runner can execute privileged commands during a pipeline job, which is critical for automated deployments, infrastructure as code (IaC) updates, and system-level testing. Without this configuration, jobs that require root access will fail with permission denied errors, effectively halting the automation pipeline.
Installation and Environment Setup for GitLab Runner
Before addressing the sudoers configuration, the GitLab Runner must be correctly installed on the Ubuntu 22.04 LTS environment. This process involves adding the official repository to ensure the system receives the latest stable updates and security patches.
The initial step requires the execution of the official installation script to configure the repository:
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
Following the repository setup, the runner is installed via the advanced package tool:
sudo apt-get install gitlab-runner
For environments requiring a specific version of the runner, such as version 10.0.0, the following sequence is utilized:
apt-cache madison gitlab-runner
sudo apt-get install gitlab-runner=10.0.0
Once installed, the version can be verified using the version command:
sudo gitlab-runner -version
As of the current documented state, the version is identified as 15.7.2, running on the 15-7-stable branch with Go version 1.18.9 on a linux/amd64 architecture.
The operational status of the service can be monitored and managed using the following administrative commands:
- To check status:
sudo gitlab-runner status - To start the service:
sudo gitlab-runner start - To stop the service:
sudo gitlab-runner stop - To restart the service:
sudo gitlab-runner restart
Granting Sudo Permissions to the GitLab Runner User
Upon the successful installation of the runner, the system automatically creates a dedicated user account named gitlab-runner. This user is located within the /home directory, as can be verified by navigating to the home path:
cd /home
ls
The output will confirm the existence of the gitlab-runner and ubuntu users. To enable this user to execute commands with root privileges without requiring a password—which is essential because CI/CD jobs are non-interactive—the visudo utility must be used.
The administrator must execute the following command to open the sudoers configuration file:
sudo visudo
Within the sudoers file, specific entries must be added to grant the gitlab-runner user full administrative access. The following lines are required:
gitlab-runner ALL=(ALL:ALL) ALL
gitlab-runner ALL=(ALL) NOPASSWD: ALL
The impact of adding NOPASSWD: ALL is significant. In a standard Linux environment, sudo prompts the user for a password. However, a GitLab Runner executes scripts automatically; there is no human present to type a password. Without the NOPASSWD directive, any pipeline step attempting to use sudo would hang or fail immediately, as the process cannot provide the required authentication. This configuration creates a seamless transition where the runner can elevate its privileges instantly to perform system tasks.
Registration and Configuration of the Runner
After configuring the sudoers file, the runner must be registered with the GitLab server to begin picking up jobs. This requires the Server URL and a Registration Token, both of which are found by navigating to Settings > CI/CD > Runners in the GitLab project interface.
The registration can be performed through a standard interactive command:
sudo gitlab-runner register
Alternatively, for a non-interactive setup using the Docker executor, the following command structure is used:
sudo gitlab-runner register \
--non-interactive \
--url "GITLAB_SERVER_URL" \
--registration-token "REGISTRATION_TOKEN" \
--description "docker-runner" \
--executor "docker" \
--docker-image ubuntu:latest
The use of the Docker executor changes the permission landscape. In a Docker-based runner, each job runs in an ephemeral virtual machine or container. This means the sudoers configuration on the host machine may not apply to the container.
Sudo Behavior in Shared and Containerized Runners
There is a critical distinction between a shell runner installed on a private VM and a shared runner provided by GitLab.com.
In the case of GitLab.com shared runners, the system utilizes autoscaling Docker executors. Each job runs in an isolated, ephemeral container. This environment is stripped down to the essentials, and sudo is often not installed.
When a user attempts to run a command like:
sudo usermod -aG docker $USER
They may encounter the error /bin/bash: line 125: sudo: command not found. This occurs because the container does not include the sudo binary. However, shared runners typically execute as the root user by default. Therefore, the use of sudo is redundant. Users can simply run the command without the sudo prefix:
usermod -aG docker $USER
This highlights a fundamental architectural difference: on a private Ubuntu 22.04 LTS runner, sudo is required because the runner starts as a low-privilege user. In a shared Docker runner, the process is already root, making the sudoers file on the host irrelevant to the job execution.
Troubleshooting Execution and User Switching
Users may encounter issues when attempting to switch users during the execution of a pipeline using the su command. A common problem is that running su - in a script does not persist the user change for subsequent lines in the CI configuration.
If a user executes su - and then checks whoami, they may find they are still the original user. This is because each line in a GitLab CI YAML file is often executed as a separate shell process. To correctly switch users and execute a command, the command must be passed in the same process line.
The following formats are recommended for successful user switching:
sudo "your command"su -;"your command"su -||"your command"
Dealing with Job Stagnation and Tags
A common failure after installing and granting sudo permissions is the "Job is stuck" error. This typically occurs when the project does not have any runners online assigned to it, or there is a mismatch between the runner's tags and the job's tags.
If a runner is registered with specific tags, the job in the .gitlab-ci.yml file must also specify those tags. If the job has no tags but the runner does, the runner will not pick up the job. To resolve this, the administrator should:
- Navigate to Settings > CI/CD > Runners.
- Expand the Runners section.
- Check the box labeled "Indicates whether this runner can pick jobs without tags".
Enabling this option allows the runner to act as a general-purpose worker regardless of the specific tags assigned to a job, ensuring that the sudo-enabled runner is utilized effectively.
MacOS Specific Runner Execution Issues
While primarily focused on Ubuntu, the interaction between sudo and the GitLab Runner also manifests on MacOS. Users may find that the runner appears as "sleeping" in the process list (top | grep gitlab) and does not pick up jobs when run in user space.
Warnings regarding running only in user space often occur when the gitlab-runner run command is used without elevation. The resolution is to execute the runner with root privileges:
sudo gitlab-runner run
This confirms that certain setup and execution phases of the runner require root access to interact with the system's process management and network sockets.
Comprehensive Uninstallation Process
If the GitLab Runner needs to be removed from the Ubuntu 22.04 LTS system, a complete purge is necessary to prevent orphaned files or users from cluttering the system.
The removal process follows these steps:
First, remove the package:
sudo apt purge --autoremove -y gitlab-runner
Second, delete the GPG key associated with the repository:
sudo apt-key del 51312F3F
Third, remove the repository list file:
sudo rm -rf /etc/apt/sources.list.d/runner_gitlab-runner.list
Fourth, delete the system user and their home directory:
sudo deluser --remove-home gitlab-runner
Finally, remove the configuration directory:
sudo rm -rf /etc/gitlab-runner
Summary of Configuration Requirements
The following table summarizes the configuration states for different GitLab Runner environments:
| Component | Private Ubuntu Runner | Shared Docker Runner | MacOS Runner |
|---|---|---|---|
| Default User | gitlab-runner |
root |
User-dependent |
| Sudo Requirement | Mandatory via visudo |
Not available/Not needed | Mandatory for run |
| Password Prompt | Disabled via NOPASSWD |
N/A | N/A |
| Persistence | Permanent on Host | Ephemeral Container | Permanent on Host |
| User Switching | Requires same-line command | N/A | N/A |
Conclusion
The integration of the gitlab-runner user into the sudoers file is a pivotal step in transitioning from a basic installation to a fully functional automation server. By applying the NOPASSWD: ALL directive in the /etc/sudoers file via visudo, administrators eliminate the interactive bottleneck of password prompts, allowing the CI/CD pipeline to perform critical system-level operations. However, this power must be balanced with the understanding of the execution environment. In private Ubuntu 22.04 LTS deployments, the sudoers configuration is the primary mechanism for privilege escalation. In contrast, in shared Docker environments, the ephemeral nature of the container and the default root execution render traditional sudo configurations obsolete. Ultimately, the ability of a runner to pick up jobs depends not only on these permissions but also on the correct alignment of tags within the GitLab CI/CD settings. Failing to align tags or improperly configuring the sudoers file results in a broken pipeline, whereas a correctly configured system ensures that the automation remains seamless, secure, and autonomous.