{"id":13487154,"url":"https://github.com/vbem/multi-runners","last_synced_at":"2025-04-04T13:08:19.609Z","repository":{"id":197582125,"uuid":"697119408","full_name":"vbem/multi-runners","owner":"vbem","description":"Multi self-hosted runners on single host!","archived":false,"fork":false,"pushed_at":"2025-02-11T05:31:49.000Z","size":115,"stargazers_count":194,"open_issues_count":0,"forks_count":15,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-28T12:08:10.704Z","etag":null,"topics":["actions-runner","proxy"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vbem.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-27T05:12:46.000Z","updated_at":"2025-03-28T11:16:17.000Z","dependencies_parsed_at":"2023-10-12T18:11:41.983Z","dependency_job_id":"f7281121-dec9-46b0-8723-12d40632cc28","html_url":"https://github.com/vbem/multi-runners","commit_stats":null,"previous_names":["vbem/rctl","vbem/multi-runners"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbem%2Fmulti-runners","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbem%2Fmulti-runners/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbem%2Fmulti-runners/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbem%2Fmulti-runners/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vbem","download_url":"https://codeload.github.com/vbem/multi-runners/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247182367,"owners_count":20897380,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["actions-runner","proxy"],"created_at":"2024-07-31T18:00:56.003Z","updated_at":"2025-04-04T13:08:19.590Z","avatar_url":"https://github.com/vbem.png","language":"Shell","funding_links":[],"categories":["Shell","The matrix (might be better readable on [GitHub pages](https://jonico.github.io/awesome-runners/))"],"sub_categories":["A word about self-hosted action runner images / virtual environments and how to test locally"],"readme":"# multi-runners\n\n[![awesome-runners](https://img.shields.io/badge/listed%20on-awesome--runners-blue.svg)](https://github.com/jonico/awesome-runners)\n[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/vbem/multi-runners?label=Release\u0026logo=github)](https://github.com/vbem/multi-runners/releases)\n[![Linter](https://github.com/vbem/multi-runners/actions/workflows/linter.yml/badge.svg)](https://github.com/vbem/multi-runners/actions/workflows/linter.yml)\n![GitHub closed issues](https://img.shields.io/github/issues-closed/vbem/multi-runners?logo=github)\n\n🌈🌈🌈 **Multi self-hosted GitHub action runners on single host!** 🌈🌈🌈\n\n## Introduction\n\nThis application is designed for controlling multi [self-hosted GitHub Action runners](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners) on single host, when [Actions Runner Controller (ARC)](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners-with-actions-runner-controller/quickstart-for-actions-runner-controller) is not feasible in your engineering environment. This application has following advantages:\n\n- Single Linux host required.\n- Single Bash script.\n- Lightweight wrapper of [GitHub official self-hosted runner](https://github.com/actions/runner).\n- Both *github.com* and *GitHub Enterprise* are support.\n- Either *organization* or *repository* or *GitHub Cloud Enterprise* level runners are supported.\n\n## Usage\n\n```plain\nmr.bash - https://github.com/vbem/multi-runners\n\nEnvironment variables:\n  MR_GITHUB_BASEURL=https://github.com\n  MR_GITHUB_API_BASEURL=https://api.github.com\n  MR_RELEASE_URL=\u003clatest on github.com/actions/runner/releases\u003e\n  MR_USER_BASE=\u003cdefault in /etc/default/useradd\u003e\n  MR_GITHUB_PAT=***\n\nSub-commands:\n  add       Add one self-hosted runner on this host\n            e.g. ./mr.bash add --org ORG --repo REPO --labels cloud:ali,region:cn-shanghai\n            e.g. ./mr.bash add --org ORG --count 3\n  del       Delete one self-hosted runner on this host\n            e.g. ./mr.bash del --user runner-1\n            e.g. ./mr.bash del --org ORG --count 3\n  list      List all runners on this host\n            e.g. ./mr.bash list\n  download  Download GitHub Actions Runner release tar to /tmp/\n            Detect latest on github.com/actions/runner/releases if MR_RELEASE_URL empty\n            e.g. ./mr.bash download\n  pat2token Get runner registration token from GitHub PAT (MR_GITHUB_PAT)\n            e.g. ./mr.bash pat2token --org SOME_OWNER --repo SOME_REPO\n\nOptions:\n  --enterprise  GitHub Cloud Enterprise name, optional\n  --org         GitHub organization name\n  --repo        GitHub repository name, registration on organization-level if empty\n  --user        Linux local username of runner\n  --labels      Extra labels for the runner\n  --group       Runner group for the runner\n  --token       Runner registration token, takes precedence over MR_GITHUB_PAT\n  --dotenv      The lines to set in runner's '.env' files\n  --count       The number to add or del, optional, defaults to 1 for add and all for del\n  --opts        Extra options for 'config.sh', optional, such as '--no-default-labels'\n  -h --help     Show this help.\n```\n\n### Download this application\n\nThis application requires to be run under a Linux user with **non-password sudo permission** (e.g., `%runners ALL=(ALL) NOPASSWD:ALL`). It's also fine to run this application by `root`:\n\n```bash\ngit clone https://github.com/vbem/multi-runners.git\ncd multi-runners\n./mr.bash --help\n```\n\n### Setup PAT\n\nThis application requires a [GitHub personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) with smallest permissions and shortest expiration time. Only `add`/`del`/`pat2token` sub-commands need this PAT. You can remove it on *GitHub* after multi-runners' setup.\n\nPAT types | Repository level runners | Organization level runners\n--- | --- | ---\n*Fine-grained PAT* (recommended) | Referring to [repository API](https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#create-a-registration-token-for-a-repository), the `administration:write` permission is required. | Referring to [organization policy](https://docs.github.com/en/organizations/managing-programmatic-access-to-your-organization/setting-a-personal-access-token-policy-for-your-organization) \u0026 [organization API](https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#create-a-registration-token-for-an-organization), the `organization_self_hosted_runners:write` permission is required.\n*Classic PAT* | Referring to [repository API](https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#create-a-registration-token-for-a-repository), need the `repo` scope | Refer to [organization API](https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#create-a-registration-token-for-an-organization), need the `admin:org` scope; if the repository is private, `repo` scope is also required.\n\nDuring runtime, you can set your *PAT* in environment variable `MR_GITHUB_PAT`. **To simplify subsequent execution, you can define any environment variable in `.env` file**. For example,\n\n```bash\n# .env file under the directory of this application\nMR_GITHUB_PAT='github_pat_***********'\nALL_PROXY=socks5h://localhost\n```\n\nYou can run following command to check whether or not your PAT can generate [GitHub Actions runners' registration-token](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/autoscaling-with-self-hosted-runners#authentication-requirements):\n\n```bash\n./mr.bash pat2token --org \u003cORG-NAME\u003e --repo \u003cREPO-NAME\u003e\n```\n\n### Download the latest version of GitHub Actions package\n\nIf environment variable `MR_RELEASE_URL` is empty, this application will download the [latest version of GitHub Actions runners tar package](https://github.com/actions/runner/releases) to local directory `/tmp/` during runtime.\n\n```bash\n./mr.bash download\n```\n\nIf your Linux host is internet bandwidth limited, you can also manually upload it from laptop to `/tmp/\u003ctar.gz file name\u003e`, and set the `MR_RELEASE_URL` env in `.env` file, e.g. `/tmp/actions-runner-linux-x64-2.345.6.tar.gz`.\n\n### GitHub Enterprise Server editions\n\n*GitHub Enterprise Server* editions usually have different server and API URL prefixes comparing with *github.com*, you can set them in environment variables `MR_GITHUB_BASEURL` and `MR_GITHUB_API_BASEURL`.\n\n### GitHub Enterprise Cloud level registration\n\nFor *GitHub Enterprise Cloud* level registration, you can specify the `--enterprise` option to set the *GitHub Enterprise Cloud* name.\n\n### Setup multi-runners on single host\n\nTo setup multi-runners, you can simplify run following command multi times:\n\n```bash\n# 1 runner for repository `\u003cORG-NAME-1\u003e/\u003cREPO-NAME-1\u003e`\n./mr.bash add --org \u003cORG-NAME-1\u003e --repo \u003cREPO-NAME-1\u003e\n\n# 2 runners for repository `\u003cORG-NAME-1\u003e/\u003cREPO-NAME-2\u003e`\n./mr.bash add --org \u003cORG-NAME-1\u003e --repo \u003cREPO-NAME-2\u003e --count 2\n\n# 3 runners for organization `\u003cORG-NAME-2\u003e`\n./mr.bash add --org \u003cORG-NAME-2\u003e --count 3\n```\n\nThis application will create one Linux local user for one runner via `useradd` command. The *Base Directory* of these users is read from `HOME` setting in your `/etc/default/useradd` file by default (typically `/home`). You can also set it in environment variable `MR_USER_BASE` to override system-wide default.\n\n### List all runners on current host\n\nThis application also integrated status check of runners.\n\n```bash\n./mr.bash list\n```\n\nWhich outputs,\n\n```bash\nrunner-0 537M running https://github.com/\u003cORG-NAME-1\u003e/\u003cREPO-NAME-1\u003e\nrunner-1 537M running https://github.com/\u003cORG-NAME-1\u003e/\u003cREPO-NAME-2\u003e\nrunner-2 537M running https://github.com/\u003cORG-NAME-1\u003e/\u003cREPO-NAME-2\u003e\nrunner-3 537M running https://github.com/\u003cORG-NAME-2\u003e\nrunner-4 537M running https://github.com/\u003cORG-NAME-2\u003e\nrunner-5 537M running https://github.com/\u003cORG-NAME-2\u003e\n```\n\n### Delete an existing runner\n\n```bash\n# delete an existing runner by its local Linux username.\n./mr.bash del --user \u003crunner-?\u003e\n\n# delete all runners for specific repository\n./mr.bash del --org \u003cORG-NAME-1\u003e --repo \u003cREPO-NAME-2\u003e\n\n# delete multi runners by `--count` options.\n./mr.bash del --org \u003cORG-NAME-2\u003e --count 2\n```\n\n### Specify runner in workflow file\n\nIn [`jobs.\u003cjob_id\u003e.runs-on`](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on), target runners can be based on the labels as follows via [GitHub context](https://docs.github.com/en/actions/learn-github-actions/contexts#github-context):\n\n```yaml\n# For organization level self-hosted runners\nruns-on: [self-hosted, '${{ github.repository_owner }}']\n\n# For repository level self-hosted runners\nruns-on: [self-hosted, '${{ github.repository }}']\n```\n\n### Set environment variables into runners process\n\nAs described in GitHub official document, there's an approach to [inject environment variables into runners process](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/using-a-proxy-server-with-self-hosted-runners#using-a-env-file-to-set-the-proxy-configuration) via the `.env` file before configuring or starting the self-hosted runners. This can be achieved via the `--dotenv` option, for example:\n\n```bash\n./mr.bash add --org \u003cORG\u003e --repo \u003cREPO\u003e --dotenv 'TZ=Asia/Shanghai' --dotenv 'PATH=\\$PATH:/mybin' --dotenv 'all_proxy=socks5h://localhost:1080'\n```\n\nThen the following lines will be added to `.env` file located in self-hosted runner's directory before its configuring and starting:\n\n```plain\nTZ=Asia/Shanghai\nPATH=$PATH:/mybin\nall_proxy=socks5h://localhost:1080\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvbem%2Fmulti-runners","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvbem%2Fmulti-runners","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvbem%2Fmulti-runners/lists"}