{"id":35181501,"url":"https://github.com/efrecon/gh-runner-krunvm","last_synced_at":"2026-01-21T05:05:28.854Z","repository":{"id":220858893,"uuid":"752036438","full_name":"efrecon/gh-runner-krunvm","owner":"efrecon","description":"Fully isolated microVM-based self-hosted GitHub runners","archived":false,"fork":false,"pushed_at":"2025-01-24T09:49:46.000Z","size":46293,"stargazers_count":12,"open_issues_count":2,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-24T10:29:35.610Z","etag":null,"topics":["github-runner","krunvm"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/efrecon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["efrecon"]}},"created_at":"2024-02-02T21:45:00.000Z","updated_at":"2025-01-24T09:49:50.000Z","dependencies_parsed_at":"2024-02-22T00:26:28.503Z","dependency_job_id":"5d707105-12a3-4c5b-8339-f72585447292","html_url":"https://github.com/efrecon/gh-runner-krunvm","commit_stats":null,"previous_names":["efrecon/gh-runner-krunvm"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/efrecon/gh-runner-krunvm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efrecon%2Fgh-runner-krunvm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efrecon%2Fgh-runner-krunvm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efrecon%2Fgh-runner-krunvm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efrecon%2Fgh-runner-krunvm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/efrecon","download_url":"https://codeload.github.com/efrecon/gh-runner-krunvm/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efrecon%2Fgh-runner-krunvm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28627388,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T04:47:28.174Z","status":"ssl_error","status_checked_at":"2026-01-21T04:47:22.943Z","response_time":86,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["github-runner","krunvm"],"created_at":"2025-12-29T02:00:50.882Z","updated_at":"2026-01-21T05:05:28.846Z","avatar_url":"https://github.com/efrecon.png","language":"Shell","funding_links":["https://github.com/sponsors/efrecon"],"categories":["Shell"],"sub_categories":[],"readme":"# krunvm-based GitHub Runner(s)\n\nThis project creates [self-hosted][self] (ephemeral) GitHub [runners] based on\n[libkrun]. [libkrun] creates [microVM]s, so the project enables fully isolated\n[runners] inside your infrastruture. MicroVMs boot fast, providing an experience\nclose to running containers. [libkrun] creates and starts VMs based on the\nmulti-platform OCI images created for this project -- [ubuntu] (default) or\n[fedora]. The project will create [microVM]s using either [krunvm] or\n[krun][crun] and [podman].\n\n![Demo](./demo/demo.gif)\n\n  [self]: https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners\n  [runners]: https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners\n  [libkrun]: https://github.com/containers/libkrun\n  [krunvm]: https://github.com/containers/krunvm\n  [microVM]: https://github.com/infracloudio/awesome-microvm\n  [ubuntu]: https://github.com/efrecon/gh-runner-krunvm/pkgs/container/runner-krunvm-ubuntu\n  [fedora]: https://github.com/efrecon/gh-runner-krunvm/pkgs/container/runner-krunvm-fedora\n  [crun]: https://github.com/containers/crun\n  [podman]: https://github.com/containers/podman\n\n## Example\n\nProvided you are at the root directory of this project, the following would\ncreate two runner loops (the `-n` option) that are bound to *this* repository\n(the `efrecon/gh-runner-krunvm` principal). Runners can also be registered at\nthe `organization` or `enterprise` scope using the `-s` option. In the example\nbelow, the value of the `-T` option should be an access [token](#github-token).\nIn each loop, as soon as one job has been picked up and executed, a new pristine\nrunner will be created and registered.\n\n```bash\n./orchestrator.sh -v -n 2 -- -T ghp_XXXX -p efrecon/gh-runner-krunvm\n```\n\nThe project tries to have good default options and behaviour. For example, nor\nthe value of the token, nor the value of the runner registration token will be\nvisible to the workflows using your runners. The default is to create far-less\ncapable runners than the GitHub [runners], i.e. 1G or memory and 2 vCPUs. Unless\notherwise specified, runners have random names and carry labels with the name of\nthe base repository, e.g. `ubuntu` and `krunvm`. The GitHub runner\nimplementation will automatically add other labels in addition to those.\n\nIn the example above, the double-dash `--` separates options given to the\nuser-facing [orchestrator] from options to the loop implementation [runner]\nscript. All options appearing after the `--` will be blindly passed to the\n[runner] loop and script. All scripts within the project accepts short options\nonly and can either be controlled through options or environment variables --\nbut CLI options have precedence. Running scripts with the `-h` option will\nprovide help and a list of those variables. Variables starting with\n`ORCHESTRATOR_` will affect the behaviour of the [orchestrator], while variables\nstarting with `RUNNER_` will affect the behaviour of each [runner] (loop).\n\n  [orchestrator]: ./orchestrator.sh\n  [runner]: ./runner.sh\n\n## Features\n\n+ Fully isolated GitHub [runners] on your [infrastructure][self], through\n  microVM.\n+ container-like experience: microVMs boot quickly.\n+ No special network configuration\n+ Ephemeral runners, i.e. will start from a pristine \"empty\" state at each run.\n+ Secrets isolation to avoid leaking to workflows.\n+ Run on amd64 and arm64 platforms, probably able to run on MacOS.\n+ Standard \"medium-sized\" base OS installations (node, python, dev tools, etc.)\n+ Run on top of any OCI image -- base \"OS\" separated from runner installation.\n+ Support for registration at the repository, organisation and enterprise level.\n+ Support for github.com, but also local installations of the forge.\n+ Ability to mount local directories to cache local runner-based requirements or\n  critical software tools.\n+ Good compatibility with the regular GitHub [runners]: same user ID, member of\n  the `docker` group, password-less `sudo`, etc.\n+ Supports both [krunvm] or the [krun][crun] runtime under [podman].\n+ In theory, the main [ubuntu] and [fedora] images should be able to be used in\n  more traditional container-based solutions -- perhaps [sysbox]? Reports and/or\n  changes are welcome.\n+ Relaying of the container daemon logs to provide for improved debugging of\n  complex workflows.\n\n  [sysbox]: https://github.com/nestybox/sysbox\n\n## Requirements\n\nThis project is coded in pure POSIX shell and has only been tested on Linux. The\nimages are automatically [built] both for amd64 and arm64. However, [krunvm]\nalso runs on MacOS. No \"esoteric\" options have been used when using the standard\nUNIX binary utilities. PRs are welcome to make the project work on MacOS, if it\ndoes not already.\n\nApart from the standard UNIX binary utilities, you will need the following\ninstalled on the host. Installation is easiest on Fedora (see original [issue]\nfor installation on older versions).\n\n+ `curl`\n+ `jq`\n+ A compatible runtime, i.e. either:\n  + `krun` and [`podman`][podman].\n  + `krunvm`, its [requirements] and `buildah`\n\nNote: When opting for `krunvm`, you do not need `podman`.\n\n  [built]: ./.github/workflows/ci.yml\n  [requirements]: https://github.com/containers/krunvm#installation\n  [issue]: https://github.com/efrecon/gh-runner-krunvm/issues/22\n\n## GitHub Token\n\nThe [runner] script requires a token to register the runners at the principal.\nThis project has been tested with classic [PAT], but should work with\nrepo-scoped tokens. When creating one, you should give your token the following\npermissions.\n\n+ repo\n+ workflow\n+ read:public_key\n+ read:repo_hook\n+ admin:org_hook\n+ notifications\n\n  [PAT]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens\n\n## Limitations\n\n+ Linux host installation easiest on Fedora\n+ Inside the runners: Docker not supported. Replaced by `podman` in [emulation]\n  mode.\n+ Inside the runners: No support for docker network, containers run in \"host\"\n  (but: inside the microVM) networking mode only. This is alleviated by a docker\n  [shim](./base/docker.sh)\n\n  [emulation]: https://docs.podman.io/en/latest/markdown/podman-system-service.1.html\n\n## Architecture and Design\n\nThe [orchestrator] creates as many loops of ephemeral runners as requested.\nThese loops are implemented as part of the [runner.sh][runner] script: the\nscript will create a microVM based on the default image (see below), memory and\nvCPU requirement. It will then start that microVM using `krunvm` or `podman` and\nthe VM will start an (ephemeral) GitHub [runner][self]. As soon as a job has\nbeen executed on that runner, the microVM will end and a new will be created.\n\nThe OCI image is built in two parts:\n\n+ The base images -- [fedora](./Dockerfile.base.fedora) and\n  [ubuntu](./Dockerfile.base.ubuntu) -- install a minimal set of binaries and\n  packages, both the ones necessary to execute the runner, but also a sane\n  minimal default for workflows. Regular GitHub [runners] have a wide number of\n  installed packages. The base images have much less.\n+ The [main](./Dockerfile) installs the runner binaries and scripts and creates\n  a directory structure that is used by the rest of the project.\n\nAs Docker-in-Docker does not work in krunvm microVMs, the base image installs\npodman and associated binaries. This should be transparent to the workflows as\npodman will be run in the background, in compatibility mode, and listening to\nthe Docker socket at its standard location. The Docker client (and compose and\nbuildx plugins) are however installed on the base image. This is to ensure that\nmost workflows should work without changes. The microVM also limits to running\ncontainers with the `--network host` option. This is made transparent through a\ndocker CLI [wrapper](./base/docker.sh) that will automatically add this option\nto all (relevant) commands.\n\nWhen the microVM starts, the [entrypoint.sh](./runner/entrypoint.sh) script will\nbe started. This script will pick its options using an `.env` file, shared from\nthe host. The file will be sourced and removed at once. This ensures that\nsecrets are not leaked to the workflows through the process table or a file.\nUpon start, the script will [request](./runner/token.sh) a runner token,\nconfigure the runner and then start the actions runner .NET implementation,\nunder the `runner` user. The `runner` user shares the same id as the one at\nGitHub and is also a member of the `docker` group. Similarily to GitHub runners,\nthe user is capable of `sudo` without a password.\n\nRunner tokens are written to the directory that is shared with the host. This is\nused during initial synchronisation, to avoid starting up several runners at the\nsame time from the main orchestrator loop. The tokens are automatically removed\nas soon as the runner is up, they are also protected so that the `runner` user\ncannot read their content.\n\n## History\n\nThis project was written to control my anxeity to face my daughter's newly\ndiscovered eating disorder and start helping her out of it. It started as a\nrewrite of [this] project after having failed to run those images inside the\nmicroVMs generated by [krunvm].\n\n  [this]: https://github.com/myoung34/docker-github-actions-runner\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fefrecon%2Fgh-runner-krunvm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fefrecon%2Fgh-runner-krunvm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fefrecon%2Fgh-runner-krunvm/lists"}