{"id":52598,"date":"2025-09-11T16:37:36","date_gmt":"2025-09-11T16:37:36","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=52598"},"modified":"2025-09-11T16:37:36","modified_gmt":"2025-09-11T16:37:36","slug":"github-self-hosted-runners-faq","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/github-self-hosted-runners-faq\/","title":{"rendered":"GitHub Self-Hosted Runners \u2013 FAQ"},"content":{"rendered":"\n<p>Here\u2019s a <strong>GitHub Self-Hosted Runners FAQ<\/strong> you can use as a quick reference or to share with your team:<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">GitHub Self-Hosted Runners \u2013 FAQ<\/h1>\n\n\n\n<h3 class=\"wp-block-heading\">1. What is a self-hosted runner?<\/h3>\n\n\n\n<p>A self-hosted runner is a machine you set up and maintain that runs GitHub Actions workflows. Unlike GitHub-hosted runners (ephemeral, managed by GitHub), self-hosted runners give you <strong>full control<\/strong> over hardware, OS, network, and installed tools.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why use a self-hosted runner?<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Custom environments<\/strong> \u2013 install specific tools, SDKs, or dependencies.<\/li>\n\n\n\n<li><strong>Private networking<\/strong> \u2013 access to internal systems (databases, APIs).<\/li>\n\n\n\n<li><strong>Cost optimization<\/strong> \u2013 avoid GitHub\u2019s per-minute billing on hosted runners.<\/li>\n\n\n\n<li><strong>Performance<\/strong> \u2013 use faster hardware, GPUs, or larger memory machines.<\/li>\n\n\n\n<li><strong>Compliance\/security<\/strong> \u2013 keep builds and data within your controlled environment.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">3. Where can I install self-hosted runners?<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>On-prem servers<\/li>\n\n\n\n<li>VMs (AWS, Azure, GCP, etc.)<\/li>\n\n\n\n<li>Kubernetes clusters (via Actions Runner Controller \u2013 ARC)<\/li>\n\n\n\n<li>Even edge devices (Raspberry Pi, ARM systems, etc.)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">4. How do I register a self-hosted runner?<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Go to your GitHub <strong>repository \/ org \/ enterprise<\/strong> \u2192 <em>Settings<\/em> \u2192 <em>Actions<\/em> \u2192 <em>Runners<\/em>.<\/li>\n\n\n\n<li>Click <strong>New self-hosted runner<\/strong>, select OS\/arch, and copy the registration token + command.<\/li>\n\n\n\n<li>Run the commands on your machine: <code>.\/config.sh --url https:\/\/github.com\/&lt;org>\/&lt;repo> --token &lt;TOKEN> .\/run.sh<\/code><\/li>\n\n\n\n<li>(Optional) Install as a <strong>service<\/strong> for automatic startup.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">5. Are self-hosted runners shared across repos?<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Repository-level<\/strong> \u2013 runner only available for that repo.<\/li>\n\n\n\n<li><strong>Organization-level<\/strong> \u2013 available to all repos in the org.<\/li>\n\n\n\n<li><strong>Enterprise-level<\/strong> \u2013 available to all orgs in an enterprise account.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">6. Do self-hosted runners scale automatically?<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>By default, <strong>no<\/strong> \u2013 each runner is static.<\/li>\n\n\n\n<li>For scaling, use:\n<ul class=\"wp-block-list\">\n<li><strong>Actions Runner Controller (ARC)<\/strong> on Kubernetes.<\/li>\n\n\n\n<li>Cloud autoscaling scripts (start\/stop VMs).<\/li>\n\n\n\n<li>Third-party solutions (Terraform modules, GitHub Actions Runner Scale Sets).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">7. How do I secure self-hosted runners?<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Run in <strong>ephemeral mode<\/strong> (one job per runner, auto-cleanup).<\/li>\n\n\n\n<li>Use <strong>network isolation<\/strong> (VPC, firewall rules).<\/li>\n\n\n\n<li>Regularly <strong>patch OS and dependencies<\/strong>.<\/li>\n\n\n\n<li>Restrict access via <strong>labels<\/strong> (only trusted workflows can target runners).<\/li>\n\n\n\n<li>Store secrets in <strong>GitHub Secrets or HashiCorp Vault<\/strong>, not on the runner itself.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">8. What OS and architectures are supported?<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Linux (x64, ARM64, ARM32)<\/li>\n\n\n\n<li>Windows (x64)<\/li>\n\n\n\n<li>macOS (x64, ARM64\/Apple Silicon)<\/li>\n\n\n\n<li>Experimental: custom builds for other archs<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">9. Can I use Docker with self-hosted runners?<\/h3>\n\n\n\n<p>Yes. Options:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Run jobs <strong>inside Docker containers<\/strong> on the runner.<\/li>\n\n\n\n<li>Run the <strong>runner itself inside a container<\/strong>.<\/li>\n\n\n\n<li>Use <strong>Kubernetes + ARC<\/strong> for containerized scaling.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">10. How does billing work?<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>No runner usage fees<\/strong> from GitHub.<\/li>\n\n\n\n<li>You pay only for the infrastructure where the runner runs (your VM, on-prem server, etc.).<\/li>\n\n\n\n<li>Still subject to <strong>GitHub Actions limits<\/strong> (e.g., job concurrency per plan).<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">11. What happens if a runner goes offline?<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>GitHub marks it as <strong>offline<\/strong>.<\/li>\n\n\n\n<li>Jobs targeting that runner will stay <strong>queued<\/strong> until it comes back, or until another matching runner picks them up.<\/li>\n\n\n\n<li>Use monitoring (Prometheus, Datadog, GitHub webhooks) for health checks.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">12. Best practices?<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use <strong>ephemeral runners<\/strong> for untrusted repos.<\/li>\n\n\n\n<li>Tag runners with <strong>labels<\/strong> (<code>linux<\/code>, <code>gpu<\/code>, <code>arm<\/code>, <code>prod<\/code>).<\/li>\n\n\n\n<li>Automate runner lifecycle with <strong>IaC (Terraform, Ansible)<\/strong>.<\/li>\n\n\n\n<li>Keep <strong>secrets &amp; credentials external<\/strong>.<\/li>\n\n\n\n<li>Monitor and auto-replace unhealthy runners.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>When you ask, <strong>\u201cWhat are the status of GitHub self-hosted runner\u201d<\/strong>, you\u2019re likely curious about what runner statuses exist and how to check or interpret them.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Runner Status Types<\/h2>\n\n\n\n<p>GitHub supports three main statuses for self-hosted runners:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Idle<\/strong> \u2013 Runner is connected to GitHub and is ready to take on jobs.<\/li>\n\n\n\n<li><strong>Active<\/strong> \u2013 Runner is currently executing a job.<\/li>\n\n\n\n<li><strong>Offline<\/strong> \u2013 Runner is not connected (e.g. machine down, runner application stopped, or communication issue) (<a href=\"https:\/\/docs.github.com\/en\/actions\/how-tos\/manage-runners\/self-hosted-runners\/monitor-and-troubleshoot?utm_source=chatgpt.com\" target=\"_blank\" rel=\"noopener\">GitHub Docs<\/a>).<\/li>\n<\/ul>\n\n\n\n<p>These statuses are visible in the GitHub UI under <strong>Settings \u2192 Actions \u2192 Runners<\/strong>, whether at the repository, organization, or enterprise level (<a href=\"https:\/\/docs.github.com\/en\/actions\/how-tos\/manage-runners\/self-hosted-runners\/monitor-and-troubleshoot?utm_source=chatgpt.com\" target=\"_blank\" rel=\"noopener\">GitHub Docs<\/a>).<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">How to Check Status via GitHub REST API<\/h2>\n\n\n\n<p>You can also retrieve runner status programmatically using GitHub\u2019s REST API:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>For a repository<\/strong> \u2013<br><code>GET \/repos\/{owner}\/{repo}\/actions\/runners<\/code><br>The response includes each runner\u2019s <code>status<\/code> (e.g., <code>online<\/code>, <code>offline<\/code>) along with details like <code>id<\/code>, <code>name<\/code>, <code>os<\/code>, and whether it&#8217;s <code>busy<\/code> (<a href=\"https:\/\/docs.github.com\/en\/rest\/actions\/self-hosted-runners?utm_source=chatgpt.com\" target=\"_blank\" rel=\"noopener\">GitHub Docs<\/a>, <a href=\"https:\/\/www.getorchestra.io\/guides\/github-actions-api-list-self-hosted-runners-for-a-repository?utm_source=chatgpt.com\" target=\"_blank\" rel=\"noopener\">Orchestra<\/a>).<\/li>\n\n\n\n<li><strong>For an organization<\/strong> \u2013<br><code>GET \/orgs\/{org}\/actions\/runners<\/code><br>Returns similar details across all runners in the organization (<a href=\"https:\/\/docs.github.com\/en\/rest\/actions\/self-hosted-runners?utm_source=chatgpt.com\" target=\"_blank\" rel=\"noopener\">GitHub Docs<\/a>, <a href=\"https:\/\/www.getorchestra.io\/guides\/github-actions-api-list-self-hosted-runners-for-an-organization?utm_source=chatgpt.com\" target=\"_blank\" rel=\"noopener\">Orchestra<\/a>).<\/li>\n<\/ul>\n\n\n\n<p>The REST API status field may use slightly different terminology (e.g. <code>online<\/code> or <code>offline<\/code>) but maps directly to the UI&#8217;s <code>Idle<\/code>, <code>Active<\/code>, or <code>Offline<\/code> states.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Health &amp; Connectivity Checks<\/h2>\n\n\n\n<p>To further troubleshoot or check connectivity:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Run the runner\u2019s config script with <code>--check<\/code>, supplying <code>--url<\/code> and <code>--pat<\/code>, to validate network access to GitHub and see <code>PASS<\/code>\/<code>FAIL<\/code> outputs (<a href=\"https:\/\/docs.github.com\/en\/actions\/how-tos\/manage-runners\/self-hosted-runners\/monitor-and-troubleshoot?utm_source=chatgpt.com\" target=\"_blank\" rel=\"noopener\">GitHub Docs<\/a>).<\/li>\n\n\n\n<li>On the runner machine:\n<ul class=\"wp-block-list\">\n<li><strong>Linux\/systemd<\/strong>: <code>sudo journalctl -u actions.runner.&lt;org>-&lt;repo>.&lt;runnerName>.service -f<\/code><\/li>\n\n\n\n<li>**macOS\/**launchd or <strong>Windows<\/strong>\/PowerShell: use system service tools to check the service state or logs (<a href=\"https:\/\/docs.github.com\/en\/actions\/how-tos\/manage-runners\/self-hosted-runners\/monitor-and-troubleshoot?utm_source=chatgpt.com\" target=\"_blank\" rel=\"noopener\">GitHub Docs<\/a>).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Summary Table<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th><strong>Status Source<\/strong><\/th><th><strong>Status Value<\/strong><\/th><th><strong>Meaning<\/strong><\/th><\/tr><\/thead><tbody><tr><td>GitHub UI<\/td><td>Idle<\/td><td>Runner connected and ready<\/td><\/tr><tr><td>GitHub UI<\/td><td>Active<\/td><td>Runner currently executing a job<\/td><\/tr><tr><td>GitHub UI<\/td><td>Offline<\/td><td>Runner disconnected or unreachable<\/td><\/tr><tr><td>REST API (<code>status<\/code>)<\/td><td>online\/offline<\/td><td>Corresponds to Idle or Offline<\/td><\/tr><tr><td>Runner service tools\/logs<\/td><td>\u2013<\/td><td>Indicate if the runner service is running or encountering errors<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here\u2019s a GitHub Self-Hosted Runners FAQ you can use as a quick reference or to share with your team: GitHub Self-Hosted Runners \u2013 FAQ 1. What is a self-hosted runner?&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[2],"tags":[],"class_list":["post-52598","post","type-post","status-publish","format-standard","hentry","category-uncategorised"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/52598","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=52598"}],"version-history":[{"count":1,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/52598\/revisions"}],"predecessor-version":[{"id":52672,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/52598\/revisions\/52672"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=52598"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=52598"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=52598"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}