Skip to content

High-performance, ephemeral, and horizontally scalable self-hosted GitHub Actions runners powered by Modal. Pay only for the seconds you run.

License

Notifications You must be signed in to change notification settings

manascb1344/modal-github-runner

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Modal GitHub Runner

Modal GitHub Actions License: MIT

A high-performance, ephemeral self-hosted GitHub Actions runner powered by Modal. Achieve zero idle costs and instant horizontal scaling with Just-In-Time (JIT) security.

🚀 Key Features

  • ⚡ Ephemeral: Every job runs in a fresh, hardware-isolated Modal Sandbox, ensuring a clean state and preventing side effects between runs.
  • 💰 Zero Idle Cost: No long-running servers or "warm" instances. You only pay for the exact seconds your runner is executing jobs.
  • 🛡️ JIT Security: Utilizes GitHub's Just-In-Time runner registration. Runners are created on-demand and automatically cleaned up by GitHub after a single use.
  • 📈 Horizontal Scaling: Modal's serverless infrastructure allows you to scale to hundreds of concurrent runners instantly. Each job gets its own dedicated resources without queueing delays.

🏗️ Architecture

The runner follows a reactive, event-driven flow:

sequenceDiagram
    participant GH as GitHub Actions
    participant WE as Modal Web Endpoint
    participant GA as GitHub API
    participant MS as Modal Sandbox
    
    GH->>WE: 1. workflow_job (queued) Webhook
    Note over WE: Verify Signature (HMAC-SHA256)
    WE->>GA: 2. Request JIT Config (generate-jitconfig)
    GA-->>WE: 3. Return JIT Config String
    WE->>MS: 4. modal.Sandbox.create(image, JIT_CONFIG)
    Note over MS: 5. Execute run.sh (as root in /tmp)
    MS->>GH: 6. Connect & Execute Job
    GH-->>MS: 7. Job Finished
    MS->>MS: 8. Exit & Terminate Sandbox
Loading
  1. Workflow Queued: A GitHub Action workflow is triggered and a job enters the queued state.
  2. Webhook Trigger: GitHub sends a workflow_job webhook to the Modal web endpoint.
  3. JIT Handshake: The Modal app validates the request and calls the GitHub API to generate a JIT (Just-In-Time) runner configuration.
  4. Sandbox Spawning: A Modal Sandbox is provisioned immediately with the pre-configured runner image.
  5. Execution & Cleanup: The runner connects to GitHub, executes the specific job, and the Sandbox is terminated immediately upon completion.

🏁 Quick Start

Setting up your own Modal runner takes only a few minutes.

Refer to the DEPLOY.md for step-by-step instructions on:

  • Setting up Modal secrets.
  • Deploying the webhook endpoint.
  • Configuring GitHub repository webhooks.

🛠️ Technical Details

  • Modal Sandbox: Built on top of Modal's serverless runtime, providing sub-second startup times and robust isolation using micro-VM technology.
  • JIT Configuration: Instead of persistent runner tokens, this project uses the generate-jitconfig endpoint. This ensures that even if a runner environment were compromised, the credentials are valid for only one specific job.
  • Custom Images: The runner environment is defined directly within app.py, allowing you to easily add dependencies (e.g., specific versions of Python, Node.js, or system libraries) that are pre-baked into the runner image.
  • Root Execution: Sandboxes run with RUNNER_ALLOW_RUNASROOT=1 in ephemeral /tmp directories, ensuring compatibility with all GitHub Actions features without permission hurdles.

📄 License

This project is licensed under the MIT License.


👤 Author

Manas C. Bavaskar

About

High-performance, ephemeral, and horizontally scalable self-hosted GitHub Actions runners powered by Modal. Pay only for the seconds you run.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages