This is the preparation, the final goal is to have the pipeline to test Ansible roles with Molecule.
Host: zd-runner.my-domain.com
The runner VM initiates HTTPS connections to your GitLab host: it asks for jobs, checks out the repository, and sends logs and results back. GitLab does not need to SSH into the runner or open an inbound connection to it.
Once registered, the runner uses its own token to request jobs; each job gets a temporary token for repository checkout.
# Installed OCI OL 10.2 to be runner, test https connection to GitLab
$ curl -I https://gitlab-server.my-domain.com
HTTP/2 302
server: nginx
date: Mon, 28 Sep 2026 05:38:47 GMT
content-type: text/html; charset=utf-8
content-length: 0
location: https://gitlab-server.my-domain.com/explore/projects
cache-control: no-cache
content-security-policy:
nel: {"max_age": 0}
permissions-policy: interest-cohort=()
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-gitlab-meta: {"correlation_id":"01M3K8BQ72CG93CZHZ3DK4S4J0","version":"1"}
x-permitted-cross-domain-policies: none
x-request-id: 01M3K8BQ72CG93CZHZ3DK4S4J0
x-runtime: 0.017794
x-ua-compatible: IE=edge
x-xss-protection: 1; mode=block
strict-transport-security: max-age=63072000
referrer-policy: strict-origin-when-cross-origin
On zd-runner host, download program to setup gitlab yum repo.
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh" -o script.rpm.sh
bash script.rpm.sh
dnf install gitlab-runner
$ rpm -qi gitlab-runner
Name : gitlab-runner
Version : 19.4.1
Release : 1
Architecture: x86_64
Install Date: Mon 28 Sep 2026 03:49:35 PM GMT
Group : default
Size : 124663831
License : MIT
Signature :
RSA/SHA512, Thu 24 Sep 2026 04:55:27 AM GMT, Key ID 6c57c29c6ba75a4e
Source RPM : gitlab-runner-19.4.1-1.src.rpm
Build Date : Thu 24 Sep 2026 04:55:16 AM GMT
Build Host : runner-owtqbnqe-project-250833-concurrent-20
Relocations : /
Packager : GitLab Inc. <support@gitlab.com>
Vendor : GitLab Inc.
URL : https://gitlab.com/gitlab-org/gitlab-runner
Summary : GitLab Runner
Description :
GitLab Runner
# The local account is created:
gitlab-runner:x:990:990:GitLab Runner:/home-local/gitlab-runner:/bin/bash
dnf install podman
podman --version
podman version 5.8.2
Registration creates a runner record in GitLab and saves its authentication token on your VM.
In your GitLab project, open **Settings → CI/CD → Runners → Create project runner**.
You need Maintainer access for this. Set a description such as `zd-runner OL10 lab`, add the tag `molecule`, and leave **Run untagged** off.
We’ll give test jobs that tag later.
1. After selecting **Create runner**, GitLab shows an authentication token. Keep it private. On the runner VM, start interactive registration:
sudo gitlab-runner register
2. At the prompts, enter `https://gitlab-server.my-domain.com`, paste the token **at the token prompt**, and choose `shell` as the executor.
The shell executor will let jobs use the tools installed on this VM.
GitLab job → shell on OL 10 VM → Molecule → Podman test container
3. Run `sudo gitlab-runner verify`. Tell me whether it reports the runner as alive.
The example:
[root@zd-runner ~] gitlab-runner register --url https://gitlab-server.my-domain.com --token [REDACTED_RUNNER_TOKEN]
Runtime platform arch=amd64 os=linux pid=33108 revision=3c39fceb version=19.4.1
Running in system-mode.
Enter the GitLab instance URL (for example, https://gitlab.com/):
[https://gitlab-server.my-domain.com]:
Verifying runner... is valid correlation_id=01M3MQY0QP8M509FRNW2R77W9S runner=[REDACTED] runner_name=zd-runner
Enter a name for the runner. This is stored only in the local config.toml file:
[zd-runner]:
Enter an executor: docker+machine, kubernetes, ssh, parallels, custom, instance, docker, virtualbox, shell, docker-windows, docker-autoscaler:
shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
Configuration (with the authentication token) was saved in "/etc/gitlab-runner/config.toml"
[root@zd-runner ~]cat "/etc/gitlab-runner/config.toml"
concurrent = 1
check_interval = 0
connection_max_age = "15m0s"
shutdown_timeout = 0
[session_server]
session_timeout = 1800
[[runners]]
name = "zd-runner"
url = "https://gitlab-server.my-domain.com"
id = 3728
token = "[REDACTED_RUNNER_TOKEN]"
token_obtained_at = 2026-09-28T19:30:10Z
token_expires_at = 0001-01-01T00:00:00Z
executor = "shell"
[runners.cache]
MaxUploadedArchiveSize = 0
[runners.cache.s3]
AssumeRoleMaxConcurrency = 0
[runners.cache.gcs]
[runners.cache.azure]
$ gitlab-runner verify
Runtime platform arch=amd64 os=linux pid=33159 revision=3c39fceb version=19.4.1
Running in system-mode.
Verifying runner... is valid correlation_id=01M3MR5F9T57XK7CBMTANAGN0G runner=[REDACTED] runner_name=zd-runner
If home is auto mounted from NFS, create /home-local directory and use for gitlab-runner service account. Use this new home in /etc/systemd/system/gitlab-runner.service
Install glab package on your host where you do the work.
This is the GitLab CLI tool, it brings GitLab to your command line.
In GitLab, with Web UI, go to Access - Personal Access token - create the token with api and write_repository permissions.
Token can be as environmental variable, to check access.
read -rsp 'GitLab token: ' GITLAB_TOKEN; echo
export GITLAB_TOKEN
glab auth status --hostname gitlab-server.my-domain.com
Or store in ~/.config/glab-cli/config.yml
$ glab auth status --hostname gitlab-server.my-domain.com
gitlab-server.my-domain.com
✓ Logged in to gitlab-server.my-domain.com as zdudic (~/.config/glab-cli/config.yml)
✓ Git operations for gitlab-server.my-domain.com configured to use https protocol.
✓ API calls for gitlab-server.my-domain.com are made over https protocol.
✓ REST API Endpoint: https://gitlab-server.my-domain.com/api/v4/
✓ GraphQL Endpoint: https://gitlab-server.my-domain.com/api/graphql/
✓ Token found: **************************
Create the file .gitlab-ci.yml in Git repo, the file triggers the pipeline. We want to be triggered only when push to certain branch, and execute some simple commands.
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "ci-learn"'
# That last line is an explicit “deny everything else.” It’s optional here.
- when: never
runner_smoke:
tags:
- molecule
script:
- whoami
- hostname -f
- uname -a
- echo "branch=$CI_COMMIT_BRANCH"
To verify and lint the file run:
$ glab ci lint .gitlab-ci.yml
Validating...
✓ CI/CD YAML is valid!
Stage the change, commit and push to the branch, to start the pipeline.
$ git status
On branch ci-learn
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitlab-ci.yml
nothing added to commit but untracked files present (use "git add" to track)
$ git add .gitlab-ci.yml
$ git commit -m "Add first .gitlab-ci.yml file"
[ci-learn bf4a5f9] Add first .gitlab-ci.yml file
1 file changed, 19 insertions(+)
create mode 100644 .gitlab-ci.yml
$ git push origin ci-learn
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 619 bytes | 309.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)
remote:
remote: To create a merge request for ci-learn, visit:
remote: https://gitlab-server.my-domain.com/zdudic/conf-mgmt/-/merge_requests/new?merge_request%5Bsource_branch%5D=ci-learn
remote:
To gitlab-server.my-domain.com:zdudic/conf-mgmt.git
* [new branch] ci-learn -> ci-learn
In GitLab Web UI, see the pipeline logs.