GitLab Runner for Windows Integration and Deployment

The architectural integration of GitLab Runner on Windows environments represents a critical component for organizations seeking to implement robust Continuous Integration and Continuous Delivery (CI/CD) pipelines within a Microsoft-centric ecosystem. GitLab Runner serves as the essential agent that facilitates the communication between the GitLab instance and the computing infrastructure where the actual job execution occurs. By acting as a listener, the runner connects to the GitLab server and remains in a dormant state until a pipeline triggers a job. Upon receiving a signal, the runner pulls the necessary code, executes the defined tasks, and reports the results back to the GitLab interface. This mechanism allows developers to automate the lifecycle of their software, including the execution of tests, the compilation of binaries, and the deployment of code to target environments, ensuring that Windows-specific applications are validated in their native environment.

Operational Infrastructure Requirements

Establishing a functional GitLab Runner on Windows requires specific environmental prerequisites to ensure stability and prevent runtime errors. The infrastructure can be flexible, accommodating various hardware and virtualization strategies.

The primary requirement is a Windows server. This may be a physical machine or a virtual machine (VM). Modern deployments often utilize Windows Server 2022, though the system is compatible with older server versions or even script servers being phased out. The choice between physical and virtual infrastructure depends on the need for scalability and snapshots.

Beyond the OS, the following technical requirements must be satisfied:

  • Git installation: The system must have Git installed from the official site to allow the runner to clone repositories and manage source code.
  • User Account Configuration: If the runner is not utilizing the Built-in System Account, a specific user account password is required for the service to authenticate.
  • System Locale: The system locale must be explicitly set to English (United States). This is a critical requirement to avoid character encoding issues that can lead to job failures or corrupted logs, specifically linked to issue 38702.

Installation Procedures and System Setup

Installing the GitLab Runner on Windows involves moving the binary into a permanent directory and configuring it as a system service.

The process begins with the creation of a dedicated folder to house the application, such as C:\GitLab-Runner. The binary is then downloaded based on the hardware architecture of the server, with options available for x86 64-bit, ARM 64-bit, or x86 32-bit. Once the file is placed in the folder, it is recommended to rename the binary to gitlab-runner.exe for ease of command execution.

A critical security step involves the management of directory permissions. Administrators must restrict Write permissions on the GitLab Runner directory and the executable file itself. Failure to implement these restrictions creates a security vulnerability where regular users could replace the official executable with a malicious one, potentially executing arbitrary code with elevated privileges.

The installation is finalized through an elevated command prompt, where the runner is installed as a service. This allows the runner to start automatically upon boot. Users have two primary options for service execution:

  • Built-in System Account: This is the recommended approach for most installations.
  • User Account: This is used when specific user permissions are required for the jobs.

It is important to note that Windows services do not provide interactive desktop sessions, which means any GUI-based tests or applications will not be visible or interactive.

Registration and Connection to GitLab

Once the binary is installed and the service is initialized, the runner must be registered to the specific GitLab instance to receive jobs.

The registration process can be initiated through the GitLab admin portal. By navigating to Settings -> CI/CD -> Runners and clicking the three dots menu, the administrator can select "Show runner installation and registration instructions." This menu provides a set of specific commands tailored to the server's instance, with options for Linux, MacOS, or Windows.

To perform the registration on the Windows server, the following command is executed in a PowerShell window:

gitlab-runner.exe register

This command initiates a prompt-based sequence where the runner is linked to the GitLab instance via a token, defining the executor and the tags that will be used to route specific jobs to this runner.

Hosted Runners on Windows (SaaS)

For users of GitLab.com, GitLab provides hosted runners on Windows, which are currently in a beta phase. This eliminates the need for users to manage their own infrastructure.

The available machine types for these hosted runners are summarized in the following table:

Runner Tag vCPUs Memory Storage
saas-windows-medium-amd64 2 7.5 GB 75 GB

The supported Windows version for these hosted runners is Windows 2022, which is currently in General Availability (GA).

Because these runners are in beta, users should be aware of specific performance characteristics. The average provisioning time for a new Windows virtual machine in the fleet is approximately five minutes. Consequently, users may experience slower start times for builds compared to Linux-based runners.

Configuration and the .gitlab-ci.yml File

The interaction between the GitLab Runner and the pipeline is defined in the .gitlab-ci.yml file. For Windows runners, the shell is configured as PowerShell. All commands listed in the script section of the YAML file must be valid PowerShell commands.

An example configuration for a Windows job is structured as follows:

```yaml
.windowsjob:
tags:
- saas-windows-medium-amd64
before
script:
- Set-Variable -Name "time" -Value (date -Format "%H:%m")
- echo ${time}
- echo "started by ${GITLABUSERNAME} / @${GITLABUSERLOGIN}"

build:
extends:
- .windows_job
stage: build
script:
- echo "running scripts in the build job"

test:
extends:
- .windows_job
stage: test
script:
- echo "running scripts in the test job"
```

In this configuration, the tags section ensures the job is routed to the correct Windows runner. The before_script uses PowerShell syntax to capture the current time and identify the user who triggered the pipeline.

Advanced Troubleshooting and Technical Fixes

Operating a GitLab Runner on Windows introduces specific technical challenges related to shell execution, permissions, and Git configurations.

Solving Git Configuration Issues

In some runner versions, regressions may affect Git system-level settings. Specifically, the core.longpaths setting may be disabled. To re-enable this and ensure long file paths are handled correctly, users can utilize the pre_get_sources_script to unset GIT_CONFIG_NOSYSTEM.

This can be achieved by adding the following to the .gitlab-ci.yml:

yaml build: hooks: pre_get_sources_script: - $env:GIT_CONFIG_NOSYSTEM=''

Alternatively, a custom gitlab-runner-helper image can be built using a Dockerfile:

dockerfile FROM registry.gitlab.com/gitlab-org/gitlab-runner/gitlab-runner-helper:x86_64-v17.8.3-servercore21H2 ENV GIT_CONFIG_NOSYSTEM=

Handling Batch Script Errors

A common error encountered when executing Windows batch scripts is "The system cannot find the batch label specified." This occurs when a .bat file is called directly. To resolve this, the call command must be prepended to the batch file path in the .gitlab-ci.yml file.

Example of the correct implementation:

yaml before_script: - call C:\path\to\test.bat

Resolving Service Logon Failures

During the installation of the runner service, a "FATA[0000] Failed to start GitLab Runner: The service did not start due to a logon failure" error may appear. This typically happens when the service is installed with a specific password:

gitlab-runner install --password WINDOWS_MACHINE_PASSWORD
gitlab-runner start

The root cause of this failure is that the user account designated to run the service lacks the SeServiceLogonRight permission. This permission must be granted to the user account via the Local Security Policy of the Windows server.

Managing ANSI Color Output

The GitLab web interface emulates a UNIX ANSI terminal. To see colored output in the logs, the program output must contain ANSI color codes.

On older versions of Windows (prior to version 1511), the command prompt did not support ANSI codes and used win32 (ANSI.SYS) calls. Many cross-platform libraries, such as Colorama, automatically convert ANSI codes to win32 calls when they detect a Windows environment. For CI builds, this conversion must be disabled so that the ANSI codes remain in the string and are correctly interpreted by the GitLab web interface.

Software Management on Shared Runners

For users employing shared Windows runners on GitLab.com, managing software dependencies requires a different approach since the environment is containerized.

The available pre-installed software for Windows containers is maintained in a public "cookbooks" repository provided by GitLab. This allows users to verify if a specific tool is already available before attempting to install it.

To install additional software such as Python, Ruby, or Perl on a shared runner, users must utilize PowerShell scripts within their pipeline. Many installers, such as the Python Windows Installer, support headless installation modes that do not require administrator privileges, allowing them to be executed directly within the job script.

An example of a basic job using a shared Windows runner:

yaml test_windows: stage: test tags: - shared-windows script: - dir

Analysis of Windows Runner Deployment Strategies

The deployment of GitLab Runners on Windows necessitates a balance between security, performance, and maintainability. The shift toward using Windows Server 2022 as the primary image for hosted runners ensures that the environment is aligned with modern enterprise standards. However, the inherent overhead of Windows virtual machines is evident in the five-minute provisioning time observed in the SaaS beta, which is significantly higher than the near-instantaneous start times of Linux containers.

From a security perspective, the requirement to restrict write access to the C:\GitLab-Runner directory highlights a critical vulnerability in the Windows service model where privilege escalation could occur if the binary is writable by non-admin users.

The reliance on PowerShell as the default shell for Windows runners further emphasizes the need for developers to be proficient in scripting. The transition from legacy Batch scripts to PowerShell provides more robust error handling and object-oriented output, although the necessity of using the call keyword for .bat files indicates that legacy support remains a priority for GitLab.

The integration of the gitlab-runner-helper allows for deeper customization of the environment, particularly regarding how Git handles the Windows file system. The use of the pre_get_sources_script to manipulate environment variables like GIT_CONFIG_NOSYSTEM demonstrates the flexibility available to administrators to bypass system-level restrictions and ensure that large-scale projects with deep directory structures can be cloned without failure.

Sources

  1. Randriksen - Windows GitLab Runner Setup
  2. GitLab Docs - Hosted Runners on Windows
  3. GitLab Docs - Install GitLab Runner on Windows
  4. GitLab Docs - GitLab Runner Overview
  5. GitLab Forum - GitLab CI Windows Runner Discussion

Related Posts