The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →To run GitLab CI on your own VPS, you need two connected pieces: a project-root .gitlab-ci.yml file that defines the pipeline, and GitLab Runner installed and registered on the VPS to execute its jobs. The shortest reliable path is to create a project runner in Settings > CI/CD > Runners, register it with the current authentication token, choose the shell or Docker executor, start the runner service, and trigger a pipeline to verify the job log.
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
This guide covers the complete setup, runner scope and tags, executor trade-offs, VPS sizing, security boundaries, maintenance commands, and the failure modes that leave a runner offline or unable to pick up jobs.
As an Amazon Associate I earn from qualifying purchases.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11What you are building
GitLab CI is the pipeline system; GitLab Runner is the worker that performs the pipeline’s jobs. A pipeline is described in a file named .gitlab-ci.yml at the root of the repository. The filename is case-sensitive. That file declares stages, jobs, scripts, variables, dependencies, and conditions.
GitLab schedules a job only when a suitable runner is available. Registering the runner links the VPS to GitLab so it can pick up jobs from the project pipeline. The runner’s executor then determines where each script runs:
#1 Best Overall
- Shell executor: commands run directly on the VPS operating system.
- Docker executor: each job runs inside a Docker container based on an image you select.
The VPS therefore becomes part of your build system. Its operating-system packages, disk, network access, credentials, and Docker daemon can all affect pipeline results.
Before you start
GitLab project access
You need a GitLab project in which you can add or manage a runner and commit .gitlab-ci.yml. Decide whether this runner should serve one project, several projects in a group, or an entire GitLab instance before creating it.
A supported Linux VPS
Provision a Linux VPS with an architecture supported by GitLab Runner. GitLab documents Linux support across multiple CPU architectures, but does not prescribe one universal CPU or RAM size for all CI workloads. Choose capacity from the jobs you expect to run: compiler-heavy builds, large test suites, Docker image builds, parallel jobs, and the size of your working directories all increase resource requirements.
- CPU: estimate how many jobs may run concurrently and whether they compile or perform other CPU-intensive work.
- Memory: account for the runner service, the operating system, package managers, test processes, and any containers running at the same time.
- Disk: leave room for repository checkouts, dependency caches, build artifacts, Docker images, and logs.
- Network: the VPS must reach your GitLab instance and any package registries, container registries, or external services required by your scripts.
Start with a modest machine for a lightly used project and observe actual utilization. Increase resources when jobs are queued because the runner is busy, processes are killed for lack of memory, or the disk fills.
Administrative access and a security plan
You need administrative access to install packages and run the runner service. Treat the runner authentication token and config.toml as secrets. Never commit either to the repository. Use protected and masked CI/CD variables for deployment credentials or API keys.
Do not expose a privileged shell runner to untrusted project code. For production workloads, GitLab recommends installing Runner on a separate machine for security and performance reasons. A dedicated VPS also prevents unrelated applications from sharing the runner’s host-level access.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #2
Step 1: Add a minimal pipeline
Create a file named exactly .gitlab-ci.yml in the repository root. This example defines sequential build and test stages, with one job in each stage:
stages:
- build
- test
build_app:
stage: build
script:
- echo "Building application"
- mkdir -p build
- printf 'build completen' > build/status.txt
artifacts:
paths:
- build/status.txt
test_app:
stage: test
script:
- echo "Running tests"
- test -f build/status.txt
Commit and push the file. GitLab reads the configuration when a pipeline is created. The test_app job waits for the preceding stage to complete, and the artifact from build_app is made available to the later job.
Replace the illustrative commands with your project’s real build and test commands. Keep secrets out of this file; reference CI/CD variables instead. If the YAML is rejected, correct the syntax before troubleshooting the runner—an invalid pipeline cannot be scheduled even when the runner is healthy.
Step 2: Provision and prepare the VPS
- Create the VPS. Select a supported Linux distribution and architecture, then choose CPU, memory, disk, and network capacity for your expected concurrency and job types.
- Apply operating-system updates. Use your distribution’s normal package-update process and configure time synchronization, a hostname, and administrative access.
- Limit access. Use key-based administration where possible, disable unnecessary services, and restrict inbound firewall rules to the ports required for administration and your own applications. The runner normally needs outbound access to GitLab and to dependencies used by jobs.
- Decide on the executor. Choose shell when direct host execution is intentional and simple. Choose Docker when jobs should run in containerized, repeatable environments.
Keep the runner host separate from databases, public web applications, and other sensitive services whenever untrusted code may execute. A shell job can read and modify files that the runner account can access; Docker adds a boundary but is not a substitute for careful permissions.
Free tools Windows power users keep installed
One-click scans. No signup required.
Step 3: Install GitLab Runner
Install GitLab Runner using GitLab’s official Linux package repository or another documented package or binary method appropriate for your distribution. Inspect installation scripts before executing them and keep the package source trusted. Installation normally provides the gitlab-runner command and a service definition.
After installation, verify that the binary is available:
Rank #3
gitlab-runner --version
If the command is not found, check that the package installed successfully and that its directory is on the service account’s PATH. Do not proceed to registration until the command runs on the VPS.
Step 4: Create the runner in GitLab
- Open the project in GitLab.
- Go to Settings > CI/CD.
- Open the Runners area and choose to create a project runner.
- Choose whether the runner accepts untagged jobs. Enable this only when it should be eligible for jobs that specify no tags.
- Set tags if this runner has a specialized capability, such as a particular operating system, toolchain, or hardware feature.
- Copy the generated runner authentication token. You will enter it on the VPS during registration.
Current GitLab workflows use runner creation and authentication tokens. Older registration-token workflows are deprecated in current documentation, so do not substitute an obsolete project registration token for the authentication token shown when you create the runner.
Step 5: Register the runner on the VPS
Registration records the GitLab instance, token, runner name, and executor in the runner configuration. Run the command as the account that owns the service configuration, commonly with administrative privileges:
sudo gitlab-runner register
The interactive prompts request these values:
- GitLab instance URL: enter the URL of the GitLab instance that hosts the project.
- Authentication token: paste the token generated in the project’s Runners settings.
- Runner description or name: use a name that identifies the VPS and its purpose, such as
linux-build-01. - Executor: enter
shellfor direct host execution ordockerfor containerized jobs.
The resulting configuration is stored in the runner’s config.toml. Protect that file and restrict access to it because it contains the runner’s credentials and operating parameters.
Registering a shell executor
Choose shell when your scripts must use tools installed directly on the VPS or when the setup is intentionally minimal. Install every required compiler, SDK, package manager, test tool, and system dependency on the host. Jobs then run with the permissions of the runner service account.
Shell execution is convenient for local caches and host resources, but it makes the host part of every job’s trust boundary. A job can affect other jobs through files, processes, installed packages, and environment settings that the runner account can access.
Recommended Free Tools
Registering a Docker executor
Choose docker when you want each job to use a declared image and a container boundary. Docker must be installed and the runner service account must be able to communicate with the Docker daemon. During registration, provide a default image when prompted, for example an image that contains the language runtime and tools your jobs need.
A Docker-based job still needs network access to pull its image and dependencies. Maintain the images you rely on, pin versions when reproducibility matters, and account for image storage in your disk sizing. Avoid granting more host access than the jobs require.
Step 6: Start the service and verify connectivity
Start the runner service using the service commands installed for your platform. The package commonly exposes these lifecycle operations:
sudo gitlab-runner start
sudo gitlab-runner status
sudo gitlab-runner restart
sudo gitlab-runner stop
If your distribution manages the runner through a native service manager, use that manager’s equivalent start, status, restart, and enable operations. The exact service integration depends on how Runner was installed.
Return to the project’s Settings > CI/CD > Runners page. The runner should appear online. Then trigger a pipeline and open its job log. A successful first run should show repository checkout, runner preparation, execution of each script command, artifact handling where configured, and a successful exit status.
Testing with a small pipeline first separates infrastructure problems from application-specific build failures. Once the minimal jobs succeed, replace the example scripts with your real workflow one job at a time.
Best Value
Step 7: Route jobs with tags
Tags are the routing filter for runners. GitLab’s runner guide states that “Tags are the only way to filter the list of available runners for a job.” Add a tag to the runner when it has a capability that should be selected explicitly, then use the same tag in a job:
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minutegpu_tests:
stage: test
tags:
- linux-build
script:
- ./run-tests.sh
A job that names tags can run only on a runner carrying all of those tags. A runner configured to accept untagged jobs may also run jobs with no tags. If a job remains pending, compare its tags with the runner’s tags character for character and confirm that the runner is allowed to accept untagged work when the job has no tags.
Choosing the right runner scope
| Scope | Best fit | Trade-off |
|---|---|---|
| Project runner | One project or a tightly controlled repository | Narrow blast radius and clear ownership, but it cannot be reused automatically by unrelated projects |
| Group runner | Several projects with a shared team and trust boundary | Reduces duplication while extending access to every eligible project in the group |
| Instance runner | Organization-wide shared infrastructure | Maximum reuse and centralized administration, but the broadest trust boundary and blast radius |
Use the narrowest scope that meets your sharing requirement. A project runner is usually the safest starting point for a single repository. Move to group or instance scope only when administration, capacity, and trust policies justify sharing.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Shell versus Docker executor
| Decision factor | Shell | Docker |
|---|---|---|
| Isolation | Commands run directly on the VPS; isolation depends on the service account and host permissions | Jobs run in containers, creating a stronger runtime boundary than direct host execution |
| Reproducibility | Depends on the packages and configuration currently installed on the host | Can be tied to a declared image and controlled image lifecycle |
| Startup overhead | Low; no container needs to be created | Requires container setup and image availability |
| Host access | Direct access to host files, tools, and processes available to the runner account | Container access is narrower unless you deliberately mount host paths or expose privileged capabilities |
| Maintenance | You maintain host dependencies and prevent jobs from contaminating one another | You maintain Docker, base images, image caches, registry access, and container permissions |
Choose shell for trusted code and a deliberately managed host environment. Choose Docker when consistent images and separation between jobs matter more than the additional Docker maintenance. Neither executor removes the need to review scripts and protect credentials.
Security practices that prevent costly mistakes
- Protect authentication material. Keep
config.toml, authentication tokens, deploy keys, and environment files readable only by the accounts that need them. Revoke and replace a token if it is exposed. - Use protected and masked variables. Store secrets in GitLab CI/CD variable settings rather than in YAML or source code. Restrict sensitive variables to protected branches or tags where appropriate.
- Separate trust zones. Do not share a runner between untrusted projects and production deployment jobs. A shared runner increases the consequences of a malicious or compromised job.
- Limit shell privileges. Run the service under the least-privileged account that can perform the build. Avoid giving that account unrestricted administrative access.
- Review Docker privileges. Membership in the Docker group can effectively grant broad control over the host. Grant it only when the executor requires it and keep the runner isolated from sensitive services.
- Keep software current. Update the operating system, GitLab Runner, Docker, and build images through trusted sources, then verify that your pipelines still produce the expected results.
Maintenance and lifecycle operations
Inspect the runner periodically from both sides: the project’s Runners page shows whether GitLab sees it online, while the VPS service status and logs show whether the process is running. Keep the runner package and its dependencies updated, remove unused images and work directories, and monitor disk usage before it blocks new jobs.
When changing executors or host capabilities, update the runner configuration deliberately and test a disposable pipeline. If the VPS is being retired, stop the service and remove or unregister the runner from GitLab so it cannot remain as a stale credentialed endpoint. If a token may have been copied, delete the affected runner and create a replacement rather than attempting to trust the exposed credential.
Troubleshooting: offline, pending, or failed jobs
The runner is offline
- Confirm the runner service is running with its status command.
- Check the VPS can reach the GitLab instance over the network and resolve its hostname.
- Verify that the configured instance URL is correct and has not been changed.
- Inspect the runner configuration for a damaged or unreadable
config.toml. - Confirm the authentication token has not been revoked and that the runner still exists in the project, group, or instance settings where it was created.
The job is stuck or pending
- Compare every job tag with the runner’s tags. A mismatch prevents scheduling.
- If the job has no tags, confirm the runner accepts untagged jobs.
- Check runner scope: a project runner cannot automatically execute jobs from another project, and a group or instance runner may be restricted by its settings.
- Look for another active job consuming the runner’s available concurrency or resources.
The job starts but commands fail immediately
- For shell, verify that the required executable is installed and visible in the runner service account’s
PATH. An interactive administrator shell may have a different environment. - For Docker, verify that the image exists, can be pulled, and contains the command or runtime used by the job.
- Check file permissions, working-directory assumptions, and required environment variables.
- Read the job log from checkout through script execution; the first failing command is usually more useful than the final summary.
The job fails because the VPS runs out of resources
Inspect CPU, memory, and disk use while a job runs. Reduce concurrency, split an oversized job, clean stale workspaces or images, or resize the VPS according to the workload. GitLab does not provide one universal VPS size because requirements vary with the projects and parallelism.
A repeatable operating checklist
- Create the project and commit a valid root-level
.gitlab-ci.yml. - Provision a supported Linux VPS sized for the expected workload.
- Install GitLab Runner from a trusted, documented source.
- Create a project, group, or instance runner in GitLab and copy its authentication token.
- Register the runner with the GitLab URL, token, name, and selected executor.
- Protect
config.tomland all authentication material. - Start the service and confirm the runner is online.
- Trigger a pipeline and inspect the complete job log.
- Add matching tags when jobs need routing to a specialized runner.
- Monitor resources, update software, and remove retired or exposed runners.
Once this checklist passes, GitLab can dispatch your project’s jobs to the VPS. The remaining work is operational: keep the runner’s trust boundary narrow, maintain its execution environment, and size it from observed workload rather than a generic CPU or memory number.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




