If you’ve ever hit that dreaded No space left on device error mid-build in your GitHub Actions workflow, you’re not alone. GitHub Actions is a powerhouse for CI/CD, but the hosted runners it uses come with finite resources—especially disk space. As your projects grow (think massive Docker builds, hefty node_modules, or sprawling test suites), that space can evaporate faster than a bad pull request.
In this post, we’ll unpack the disk space landscape for GitHub-hosted runners, including the rising star of arm64 options. We’ll break down what’s hogging your storage, and arm you with a battle-tested script to reclaim precious GBs right in your workflow YAML. By the end, you’ll be optimizing like a pro, keeping your pipelines humming without upgrading to larger runners or self-hosting (though we’ll touch on when those make sense).
Let’s roll up our sleeves and dive in.
Table of Contents
- Understanding Disk Space on GitHub-Hosted Runners
- What’s Eating Your Disk? A Breakdown of Runner Filesystem Usage
- Reclaiming Space: A GitHub Actions Cleanup Script
Understanding Disk Space on GitHub-Hosted Runners
GitHub’s hosted runners are virtual machines spun up on demand, pre-loaded with a treasure trove of tools (Node.js, Python, Java, Docker—you name it). But they’re not infinite. According to the official GitHub-hosted runners reference, Linux runners (the go-to for most workflows via ubuntu-latest) ship with 14 GB of SSD disk space. This is the usable ephemeral storage allocated for your job—enough for small-to-medium builds, but tight for anything involving large artifacts or layered Docker images.
In practice, the underlying filesystem is much beefier, clocking in at around 72 GB total. Fresh runners start with about 22 GB free for x64 and 45 GB free for arm64, but that shrinks as your workflow downloads dependencies, caches layers, or installs SDKs. Windows and macOS runners have similar constraints, but we’ll focus on Linux since it’s the most common.
Spotlight on arm64 Runners: Efficiency Meets Constraints
If you’re building for modern ARM-based environments—like AWS Graviton, Apple Silicon, or edge devices—GitHub’s arm64 runners are a game-changer. Launched in public preview in early 2025 and now generally available, these runners (labeled ubuntu-24.04-arm or ubuntu-22.04-arm for Linux) deliver native arm64 execution, slashing build times (e.g., from 30+ minutes to ~4 minutes) and cutting costs by 37% compared to equivalent x64 runners by avoiding emulation overhead. They’re free for public repos and available on Team/Enterprise plans for private repos, with the same documented 14 GB usable disk space as their x64 counterparts—ensuring parity in storage limits but with sustainability perks like 30-40% lower power use.
All GitHub-provided actions are compatible, though you’ll want ARM-native dependencies to avoid cross-compilation hiccups.
Pro tip: Use
runs-on: ubuntu-latest-arm64(alias for the latest stable) to future-proof.
Why the discrepancy in docs? GitHub emphasizes guaranteed usable space for jobs, while the full VM has overhead for the OS, pre-installed tools, and runner internals. If you’re seeing warnings like You are running out of disk space. Free space left: 54 MB, it’s time to audit and act—regardless of architecture.
Quick Tip: Monitor Your Space
Add this to any workflow for a snapshot:
- name: Check Disk Usage
run: |
df -h /
du -sh /* 2>/dev/null | sort -hr | head -10
uname -m # Bonus: Confirms x64 vs. aarch64
This’ll reveal the top space hogs at a glance, plus architecture for ARM verification.
x64 runner disk usage:
Run df -h /
df -h /
du -sh /* 2>/dev/null | sort -hr | head -10
uname -m # Bonus: Confirms x64 vs. aarch64
shell: /usr/bin/bash -e {0}
Filesystem Size Used Avail Use% Mounted on
/dev/root 72G 50G 22G 70% /
38G /usr
8.5G /opt
4.1G /mnt
1.6G /home
690M /etc
492M /var
62M /boot
1.2M /run
784K /imagegeneration
84K /dev
x86_64
arm64 runner disk usage:
Run df -h /
df -h /
du -sh /* 2>/dev/null | sort -hr | head -10
uname -m # Bonus: Confirms x64 vs. aarch64
shell: /usr/bin/bash -e {0}
Filesystem Size Used Avail Use% Mounted on
/dev/root 72G 27G 46G 38% /
19G /usr
3.1G /swapfile
2.2G /opt
1.7G /home
605M /etc
546M /var
61M /boot
1.1M /run
772K /imagegeneration
100K /dev
aarch64
What’s Eating Your Disk? A Breakdown of Runner Filesystem Usage
GitHub runners boot from a standardized image (check the actions/runner-images repo for x64; arm64 uses actions/partner-runner-images), so the filesystem is predictable. The workspace for your repo lives under /home/runner/work/<repo>, but the real culprits are system-wide installs and caches.
To get granular, I simulated a fresh ubuntu-latest (x64) and ubuntu-latest-arm64 runner and ran du -h -d1 / | sort -hr. Here’s a typical breakdown (your mileage may vary slightly based on the image version; arm64 tends to be leaner due to native binaries):
| Directory/Path | Typical Size (x64) | Typical Size (arm64) | What’s Inside? |
|---|---|---|---|
/usr/lib/jvm | N/A | 1.5 GB | Java JDK |
/usr/local/.ghcup | 6.4 GB | N/A | Haskell compiler installer |
/usr/local/lib/android | 9.5 GB | N/A | Android SDK/NDK |
/usr/local/share/powershell | N/A | 1.3 GB | Powershell SDKs |
/usr/share/dotnet | 3.4 GB | 3.6 GB | .NET runtimes and SDKs |
/usr/share/swift | 3.2 GB | 3.2 GB | Swift runtime and SDKs |
/opt/hostedtoolcache | 6 GB | N/A | Pre-cached tools (Node, Python, Go, Ruby, .NET SDKs, etc.) |
| Potential space savings | 28.5 GB | 9.6 GB |
Reclaiming Space: A GitHub Actions Cleanup Script
The beauty of GitHub Actions? You can script cleanups within your workflow. No need for self-hosted runners (yet)—just add a step early on to prune the fat. This works identically on x64 and arm64 Linux runners, as the paths and commands are OS-agnostic. You can use custom actions like jlumbroso/free-disk-space but even removing targeted directories yourself is easy and can quickly give you 5-10 GB of free space.
The GHA workflow YAML script
GitHub Action step to clean runner
- name: Clean Up Disk Space
if: runner.os == 'Linux'
run: |
# Space usage before cleanup
df -h /
# Remove unused tool caches (comment any required ones with #)
sudo rm -rf /usr/lib/jvm
sudo rm -rf /usr/local/.ghcup
sudo rm -rf /usr/local/lib/android
sudo rm -rf /usr/local/share/powershell
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/share/swift
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
# Verify gains
df -h /
Results
x64 runner (53 GB usable space)
Run # Space usage before cleanup
# Space usage before cleanup
df -h /
# Remove unused tool caches (comment any required ones with #)
sudo rm -rf /usr/lib/jvm
sudo rm -rf /usr/local/.ghcup
sudo rm -rf /usr/local/lib/android
sudo rm -rf /usr/local/share/powershell
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/share/swift
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
# Verify gains
df -h /
shell: /usr/bin/bash -e {0}
Filesystem Size Used Avail Use% Mounted on
/dev/root 72G 50G 22G 70% /
Filesystem Size Used Avail Use% Mounted on
/dev/root 72G 20G 53G 27% /
arm64 runner (55 GB usable space)
Run # Space usage before cleanup
# Space usage before cleanup
df -h /
# Remove unused tool caches (comment any required ones with #)
sudo rm -rf /usr/lib/jvm
sudo rm -rf /usr/local/.ghcup
sudo rm -rf /usr/local/lib/android
sudo rm -rf /usr/local/share/powershell
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/share/swift
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
# Verify gains
df -h /
shell: /usr/bin/bash -e {0}
Filesystem Size Used Avail Use% Mounted on
/dev/root 72G 27G 46G 38% /
Filesystem Size Used Avail Use% Mounted on
/dev/root 72G 18G 55G 25% /
Happy cleaning! 🧹
