{
  "manifest_version": "1",
  "slug": "gitlab-runner",
  "title": "GitLab Runner",
  "headline": "Run GitLab CI jobs on exe.dev, a fresh VM per job",
  "description": "A GitLab Runner that gives each CI/CD job its own exe.dev sandbox, copied from a warm base VM and deleted after. For GitLab.com and self-managed GitLab.",
  "category": "dev-tools",
  "tags": [
    "gitlab runner",
    "gitlab ci",
    "self-managed runners",
    "custom executor",
    "ephemeral runners",
    "ci",
    "continuous integration",
    "compute minutes",
    "gitlab hosted runners alternative",
    "sandbox per job"
  ],
  "url": "https://exe.dev/deploy/gitlab-runner",
  "markdown_url": "https://exe-staging.dev/deploy/gitlab-runner.md",
  "upstream": {
    "website": "https://docs.gitlab.com/runner/",
    "source": "https://gitlab.com/gitlab-org/gitlab-runner",
    "docs": "https://docs.gitlab.com/runner/executors/custom/",
    "license": "MIT (GitLab Runner)"
  },
  "example_vm_name": "my-runner",
  "time": "20 minutes",
  "stack": [
    {
      "name": "GitLab Runner",
      "detail": "the gitlab-runner service from GitLab's package repository, with the custom executor exe-executor",
      "data": "/etc/gitlab-runner/config.toml, /etc/gitlab-runner/exe.env"
    },
    {
      "name": "Base VM",
      "detail": "my-runner-base, a regular VM with gitlab-runner, your toolchains, and warm caches",
      "data": "~/.cache, ~/go, ~/.npm"
    },
    {
      "name": "Job sandboxes",
      "detail": "one cp --sandbox copy of the base per job, 2 vCPU / 4 GiB unless the job asks for more, deleted when the job ends"
    }
  ],
  "access": [
    {
      "url": "ssh my-runner.exe.xyz",
      "who": "private",
      "what": "the runner; it only makes outgoing connections, to GitLab and exe.dev"
    },
    {
      "url": "ssh my-runner-base.exe.xyz",
      "who": "private",
      "what": "the base VM, to install toolchains and warm caches"
    }
  ],
  "delivers": [
    "A base VM with gitlab-runner and git-lfs, ready to be copied",
    "A GitLab Runner registered with a glrt- token, whose custom executor copies the base for each job and deletes the copy afterwards",
    "A tag-scoped exe.dev SSH key on the runner VM only; job VMs hold no key",
    "Jobs with `tags: [exe]` that print `Running on my-runner-job-…, a copy of my-runner-base`"
  ],
  "deployable": false,
  "updated": "2026-11-04",
  "verified": "2026-11-04",
  "related": [
    "github-actions",
    "sandbox",
    "docker-host",
    "forgejo",
    "gitea",
    "tangled"
  ],
  "alternatives": [
    "GitLab-hosted runners",
    "GitLab Runner docker-autoscaler"
  ],
  "files": [
    "https://exe-staging.dev/deploy/gitlab-runner/base-setup.sh",
    "https://exe-staging.dev/deploy/gitlab-runner/exe-executor",
    "https://exe-staging.dev/deploy/gitlab-runner/runner-setup.sh"
  ]
}
