diff --git a/home/.chezmoi.yaml.tmpl b/home/.chezmoi.yaml.tmpl
index bc2469e8..20d7d88b 100644
--- a/home/.chezmoi.yaml.tmpl
+++ b/home/.chezmoi.yaml.tmpl
@@ -140,6 +140,15 @@ data:
     docker:
       doRegion: nyc1
     domain: "{{ $domain }}"
+    gitlabRunners:
+      - glurl: "https://gitlab.com/"
+        runnerDescription: "Docker executor"
+        runnerImage: "alpine:latest"
+        runnerTags: ""
+      - glurl: "https://gitlab.com/"
+        baseVM: "debian"
+        runnerDescription: "VirtualBox executor - Debian, OpenJDK 20"
+        runnerTags: "bash,openjdk20,linux"
     headless: {{ $headless }}
     home: "{{ .chezmoi.homeDir }}"
     homeParentFolder: "{{ if eq .chezmoi.os "linux" }}/home{{ else if eq .chezmoi.os "darwin" }}/Users{{ else }}C:\Users{{ end }}"
diff --git a/home/.chezmoiscripts/universal/run_onchange_after_46-gitlab-runner.sh.tmpl b/home/.chezmoiscripts/universal/run_onchange_after_46-gitlab-runner.sh.tmpl
new file mode 100644
index 00000000..1aa98f78
--- /dev/null
+++ b/home/.chezmoiscripts/universal/run_onchange_after_46-gitlab-runner.sh.tmpl
@@ -0,0 +1,110 @@
+{{- if eq .host.distro.family "linux" -}}
+#!/usr/bin/env bash
+# @file GitLab Runner Configuration
+# @brief Registers GitLab Runner(s) with the given GitLab instance
+# @description
+#     This script registers the runner(s) with the given GitLab instance. SaaS GitLab can also be provided as the GitLab instance to register
+#     the runners with. The script configures the runners to use either Docker or VirtualBox Executor. Refer to
+#     [this page](https://docs.gitlab.com/runner/executors/docker.html) and [this page](https://docs.gitlab.com/runner/executors/virtualbox.html)
+#     for details about the available configuration settings.
+#
+#     Runners are always tagged with these 2 values: `hostname` and `docker`/`virtualbox` depending on the type of executor. If a list of tags is provided,
+#     the runner is tagged with these values in addition to the above mentioned values. If the list of tags is empty, no additonal tags are added and the
+#     runner is configured to pickup `untagged` jobs.
+#
+#     Configuring other type of executors is not supported by this script.
+#
+#     ## Secrets
+#
+#     The following chart details the secret(s) that are needed to configure the runner:
+#
+#     | Secret                 | Description                                                |
+#     |------------------------|------------------------------------------------------------|
+#     | `GITLAB_RUNNER_TOKEN`  | The token generated when the runner was created in GitLab  |
+#
+#     For more information about storing secrets like SSH keys and API keys, refer to our Secrets documentation provided below
+#
+#     ## Configuration Variables
+#
+#     The following chart details the input variable(s) that are used to determine the configuration of the runner:
+#
+#     | Variable            | Description                                                                                              |
+#     |---------------------|----------------------------------------------------------------------------------------------------------|
+#     | `glurl`             | The URL of the Gitlab instance to associate the Runner with                                              |
+#     | `runnerImage`       | Docker image to use to configure the runner. Needed only when configuring `Docker` executor              |
+#     | `runnerDescription` | Description of this runner                                                                               |
+#     | `runnerTags`        | Comma separated list of tags for this runner. See details in the description for more info               |
+#     | `baseVM`            | Name of the VirtualBox VM to use for creating runner. Needed only when configuring `VirtualBox` executor |
+#
+#     ## Links
+#
+#     * [Secrets / Environment variables documentation](https://install.doctor/docs/customization/secrets)
+
+{{ includeTemplate "universal/profile" }}
+{{ includeTemplate "universal/logg" }}
+
+### Check if Docker is installed and operational so Docker executor(s) can be registered
+if command -v docker > /dev/null && docker run --rm hello-world > /dev/null; then
+    HAS_DOCKER=1
+else
+    logg warn 'Docker is not installed or it is not operational'
+fi
+
+### Check if VirtualBox is installed and operational so VirtualBox executor(s) can be registered
+if command -v VirtualBox > /dev/null; then
+    HAS_VIRTUALBOX=1
+else
+    logg warn 'VirtualBox is not installed'
+fi
+
+### Configure runners if Docker or VirtualBox is installed
+if [ $HAS_DOCKER -eq 0 ] && [ $HAS_VIRTUALBOX -eq 0 ]; then
+    logg warn 'Docker and VirtualBox are not installed. Not registering runner(s).'
+else
+    ### Run logic if gitlab-runner is installed
+    if command -v gitlab-runner > /dev/null; then
+      ### Check if Runner Token value is present before attempting to register runner(s)
+      if [ -v $GITLAB_RUNNER_TOKEN ]; then
+          ### Registering runners
+          {{ $cmd := `gitlab-runner register \
+              --non-interactive \
+              --token $GITLAB_RUNNER_TOKEN \` }}
+          ### Register Docker based runners if Docker is installed and operational
+          if [ $HAS_DOCKER -eq 1 ]; then
+          logg info 'Registering GitLab Runner(s) that use Docker executor'
+              {{- range .host.gitlabRunners }}
+              {{- if .runnerImage }}
+              {{- $cmd }}
+              --url {{ .glurl }} \
+              --executor "docker" \
+              --description "{{ .runnerDescription }} - on {{ .chezmoi.hostname }}" \
+              --docker-image {{ .runnerImage }} \
+              {{ if and .runnerTags (gt (len .runnerTags) 0) }}--tag-list "{{ .runnerTags }},{{ .chezmoi.hostname }},docker"
+              {{ else }}--tag-list "{{ .chezmoi.hostname }},docker" --run-untagged{{ end }} || echo 'Runner registration failed"
+              {{ end -}}
+              {{ end }}
+          fi
+          ### Register VirtualBox based runners if VirtualBox is installed
+          if [ $HAS_VIRTUALBOX -eq 1 ]; then
+              logg info 'Registering GitLab Runner(s) that use VirtualBox executor'
+              {{- range .host.gitlabRunners }}
+              {{- if .baseVM }}
+              {{- $cmd }}
+              --url {{ .glurl }} \
+              --executor "virtualbox" \
+              --description "{{ .runnerDescription }} - on {{ .chezmoi.hostname }}" \
+              --virtualbox-base-name "{{ .baseVM }}" \
+              {{ if and .runnerTags (gt (len .runnerTags) 0) }}--tag-list "{{ .runnerTags }},{{ .chezmoi.hostname }},virtualbox"
+              {{ else }}--tag-list "{{ .chezmoi.hostname }},virtualbox" --run-untagged{{ end }} || echo 'Runner registration failed"
+              {{ end -}}
+              {{ end }}
+          fi
+      else
+        logg warn 'GITLAB_RUNNER_TOKEN is not set. Not registering runner(s)'
+      fi
+    else
+      logg warn 'gitlab-runner is not installed or is not available in PATH'
+    fi
+fi
+
+{{ end -}}
diff --git a/home/dot_config/shell/private_private.sh.tmpl b/home/dot_config/shell/private_private.sh.tmpl
index 8dba229c..b2d53aaa 100644
--- a/home/dot_config/shell/private_private.sh.tmpl
+++ b/home/dot_config/shell/private_private.sh.tmpl
@@ -43,6 +43,7 @@ export GITHUB_TOKEN="$GH_TOKEN"
 ### GitLab
 export GL_TOKEN="{{ if (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "GITLAB_TOKEN")) }}{{ includeTemplate "secrets/GITLAB_TOKEN" | decrypt | trim }}{{ else }}{{ env "GITLAB_TOKEN" }}{{ end }}"
 export GITLAB_TOKEN="$GL_TOKEN"
+export GITLAB_RUNNER_TOKEN="{{ if (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "GITLAB_RUNNER_TOKEN")) }}{{ includeTemplate "secrets/GITLAB_RUNNER_TOKEN" | decrypt }}{{ else }}{{ env "GITLAB_RUNNER_TOKEN" }}{{ end }}"
 
 ### Heroku
 export HEROKU_API_KEY="{{ if (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "HEROKU_API_KEY")) }}{{ includeTemplate "secrets/HEROKU_API_KEY" | decrypt | trim }}{{ else }}{{ env "HEROKU_API_KEY" }}{{ end }}"
diff --git a/software.yml b/software.yml
index 362b17cb..248cd15a 100644
--- a/software.yml
+++ b/software.yml
@@ -3531,6 +3531,8 @@ softwarePackages:
     pacman: gitlab-runner
     port: gitlab-runner
     scoop: gitlab-runner
+    _service: gitlab-runner
+    _type: cli
   gitleaks:
     _bin: gitleaks
     _desc: Extension to scan git repos (or files) for secrets using regex and entropy
@@ -8372,7 +8374,7 @@ softwarePackages:
     scoop: dua
     xbps: dua-cli
   soduto:
-    _github: 
+    _github:
     _name: Soduto
     _when:cask: '! test -d /Applications/Soduto.app'
     cask: soduto