├── .github ├── FUNDING.yml └── workflows │ ├── debug.yaml │ └── test.yaml ├── LICENSE ├── README.md └── action.yml /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: flexiondotorg -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Martin Wimpress 4 | Copyright (c) 2024 Lucas Eduardo 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/debug.yaml: -------------------------------------------------------------------------------- 1 | name: Debug 🐛 2 | on: 3 | workflow_dispatch: 4 | 5 | concurrency: 6 | group: ${{ github.workflow }} 7 | cancel-in-progress: true 8 | 9 | jobs: 10 | test-ubuntu: 11 | name: Debug ${{ matrix.os }} 12 | runs-on: ${{ matrix.os }} 13 | strategy: 14 | matrix: 15 | os: [ubuntu-22.04, ubuntu-24.04] 16 | fail-fast: false 17 | permissions: 18 | contents: read 19 | id-token: write 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@v4 23 | with: 24 | path: ./.github/actions/this 25 | - name: Purge 26 | uses: ./.github/actions/this 27 | with: 28 | hatchet-protocol: rampage 29 | witness-carnage: true 30 | mnt-safe-haven: 10240 31 | root-safe-haven: 10240 32 | - name: Debug 33 | run: | 34 | sudo du -csh /opt/* | grep -v "Z 0" 35 | sudo du -csh /usr/bin/* | grep -v "Z 0" 36 | sudo du -csh /usr/lib/* | grep -v "Z 0" 37 | sudo du -csh /usr/share/* | grep -v "Z 0" 38 | sudo du -csh /var/lib/* | grep -v "Z 0" 39 | dpkg-query -W -f='${Installed-Size;8}\t${Status;1}\t${Package}\n' | grep -v "\sd\s" | sort -n | cut -f1,3- -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: Test 🧪 2 | on: 3 | workflow_dispatch: 4 | 5 | concurrency: 6 | group: ${{ github.workflow }} 7 | cancel-in-progress: true 8 | 9 | jobs: 10 | determinate-nix-action: 11 | name: determinate-nix-action (${{ matrix.hatchet-protocol }}) on ${{ matrix.os }} 12 | runs-on: ${{ matrix.os }} 13 | strategy: 14 | matrix: 15 | os: [ubuntu-22.04, ubuntu-24.04] 16 | hatchet-protocol: [holster, carve, cleave, rampage] 17 | fail-fast: false 18 | permissions: 19 | contents: read 20 | id-token: write 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@v4 24 | with: 25 | path: ./.github/actions/this 26 | - name: Purge 27 | uses: ./.github/actions/this 28 | with: 29 | hatchet-protocol: ${{ matrix.hatchet-protocol }} 30 | witness-carnage: true 31 | - uses: DeterminateSystems/determinate-nix-action@main 32 | - name: Nix 33 | run: | 34 | nix --version 35 | echo "Hello Nix" | nix run "https://flakehub.com/f/NixOS/nixpkgs/*#neo-cowsay" 36 | # Build a package to ensure the Nix store is functional 37 | nix build "https://flakehub.com/f/NixOS/nixpkgs/*#hello" 38 | nix-quick-install: 39 | name: nix-quick-action (${{ matrix.hatchet-protocol }}) on ${{ matrix.os }} 40 | runs-on: ${{ matrix.os }} 41 | strategy: 42 | matrix: 43 | os: [ubuntu-22.04, ubuntu-24.04] 44 | hatchet-protocol: [holster, carve, cleave, rampage] 45 | fail-fast: false 46 | permissions: 47 | contents: read 48 | id-token: write 49 | steps: 50 | - name: Checkout 51 | uses: actions/checkout@v4 52 | with: 53 | path: ./.github/actions/this 54 | - name: Purge 55 | uses: ./.github/actions/this 56 | with: 57 | hatchet-protocol: ${{ matrix.hatchet-protocol }} 58 | witness-carnage: true 59 | nix-permission-edict: true 60 | - uses: nixbuild/nix-quick-install-action@v30 61 | - name: Nix 62 | run: | 63 | nix --version 64 | echo "Hello Nix" | nix run "nixpkgs#neo-cowsay" 65 | # Build a package to ensure the Nix store is functional 66 | nix build "nixpkgs#hello" 67 | cachix-nix-action: 68 | name: cachix-nix-action (${{ matrix.hatchet-protocol }}) on ${{ matrix.os }} 69 | runs-on: ${{ matrix.os }} 70 | strategy: 71 | matrix: 72 | os: [ubuntu-22.04, ubuntu-24.04] 73 | hatchet-protocol: [holster, carve, cleave, rampage] 74 | fail-fast: false 75 | permissions: 76 | contents: read 77 | id-token: write 78 | steps: 79 | - name: Checkout 80 | uses: actions/checkout@v4 81 | with: 82 | path: ./.github/actions/this 83 | - name: Purge 84 | uses: ./.github/actions/this 85 | with: 86 | hatchet-protocol: ${{ matrix.hatchet-protocol }} 87 | witness-carnage: true 88 | nix-permission-edict: true 89 | - uses: cachix/install-nix-action@v31 90 | - name: Nix 91 | run: | 92 | nix --version 93 | echo "Hello Nix" | nix run "nixpkgs#neo-cowsay" 94 | # Build a package to ensure the Nix store is functional 95 | nix build "nixpkgs#hello" -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 🌐 Language 5 |
6 |
7 | English 8 | | 简体中文 9 | | 繁體中文 10 | | 日本語 11 | | 한국어 12 | | हिन्दी 13 | | ไทย 14 | | Français 15 | | Deutsch 16 | | Español 17 | | Italiano 18 | | Русский 19 | | Português 20 | | Nederlands 21 | | Polski 22 | | العربية 23 | | فارسی 24 | | Türkçe 25 | | Tiếng Việt 26 | | Bahasa Indonesia 27 |
28 |
29 |
30 |
31 | 32 | # Nothing but Nix 33 | 34 | **Transform your GitHub Actions runner into a [Nix](https://zero-to-nix.com/concepts/nix/) ❄️ powerhouse by ruthlessly slashing pre-installed bloat.** 35 | 36 | GitHub Actions runners come with meager disk space for Nix - a mere ~20GB. 37 | *Nothing but Nix* **brutally purges** unnecessary software, giving you **65GB to 130GB** for your Nix store! 💪 38 | 39 | ## Usage 🔧 40 | 41 | Add this action **before** installing Nix in your workflow: 42 | 43 | ```yaml 44 | jobs: 45 | build: 46 | runs-on: ubuntu-latest 47 | permissions: 48 | contents: read 49 | id-token: write 50 | steps: 51 | - uses: actions/checkout@v4 52 | - uses: wimpysworld/nothing-but-nix@main 53 | - name: Install Nix 54 | uses: DeterminateSystems/nix-installer-action@main 55 | - name: Run Nix 56 | run: | 57 | nix --version 58 | # Your Nix-powered steps here... 59 | ``` 60 | 61 | ### Requirements ️✔️ 62 | 63 | - Only supports official **Ubuntu** GitHub Actions runners 64 | - Must run **before** Nix is installed 65 | 66 | ## The Problem: Making Room for Nix to Thrive 🌱 67 | 68 | Standard GitHub Actions runners are stuffed with *"bloatware"* you'll never use in a Nix workflow: 69 | 70 | - 🌍 Web browsers. Lots of them. Gotta have 'em all! 71 | - 🐳 Docker images consuming gigabytes of precious disk space 72 | - 💻 Unnecessary language runtimes (.NET, Ruby, PHP, Java...) 73 | - 📦 Package managers gathering digital dust 74 | - 📚 Documentation no one will ever read 75 | 76 | This bloat leaves only ~20GB for your Nix store - barely enough for serious Nix builds! 😞 77 | 78 | ## The Solution: Nothing but Nix ️❄️ 79 | 80 | **Nothing but Nix** takes a scorched-earth approach to GitHub Actions runners and mercilessly reclaims disk space using a two-phase attack: 81 | 82 | 1. **Initial Slash:** Instantly creates a large `/nix` volume (~65GB) by claiming free space from `/mnt` 83 | 2. **Background Rampage:** While your workflow continues, we ruthlessly eliminate unnecessary software to expand your `/nix` volume up to ~130GB 84 | - Web browsers? Nope ⛔ 85 | - Docker images? Gone 🗑️ 86 | - Language runtimes? Obliterated 💥 87 | - Package managers? Annihilated 💣 88 | - Documentation? Vaporized ️👻 89 | 90 | The file system purge is powered by `rmz` (from the [Fast Unix Commands (FUC)](https://github.com/SUPERCILEX/fuc) project) - a high-performance alternative to `rm` that makes space reclamation blazing fast! ⚡ 91 | - Outperforms standard `rm` by an order of magnitude 92 | - Parallel-processes deletions for maximum efficiency 93 | - **Reclaims disk space in seconds rather than minutes!** ️⏱️ 94 | 95 | The end result? A GitHub Actions runner with **65GB to 130GB** of Nix-ready space! 😁 96 | 97 | ### Dynamic Volume Growth 98 | 99 | Unlike other solutions, **Nothing but Nix** grows your `/nix` volume dynamically: 100 | 101 | 1. **Initial Volume Creation (1-10 seconds):** (*depending on Hatchet Protocol*) 102 | - Creates a loop device from free space on `/mnt` 103 | - Sets up a BTRFS filesystem in RAID0 configuration 104 | - Mounts with compression and performance tuning 105 | - Provides a 65GB `/nix` immediately, even before the purge begins 106 | 107 | 2. **Background Expansion (30-180 seconds):** (*depending on Hatchet Protocol*) 108 | - Executes purging operations 109 | - Monitors for newly freed space as bloat is eliminated 110 | - Dynamically adds an expansion disk to the `/nix` volume 111 | - Rebalances the filesystem to incorporate new space 112 | 113 | The `/nix` volume automatically **grows during workflow execution** 🎩🪄 114 | 115 | ### Choose Your Weapon: The Hatchet Protocol 🪓 116 | 117 | Control the level of annihilation 💥 with the `hatchet-protocol` input: 118 | 119 | ```yaml 120 | - uses: wimpysworld/nothing-but-nix@main 121 | with: 122 | hatchet-protocol: 'cleave' # Options: holster, carve, cleave (default), rampage 123 | ``` 124 | 125 | #### Protocol Comparison ⚖️ 126 | 127 | | Protocol | `/nix` | Description | Purge apt | Purge docker | Purge snap | Purged file systems | 128 | |----------|--------|--------------------------------------------------|------------|--------------|------------|-------------------------| 129 | | Holster | ~65GB | Keep the hatchet sheathed, use space from `/mnt` | No | No | No | None | 130 | | Carve | ~85GB | Craft and combine free space from `/` and `/mnt` | No | No | No | None | 131 | | Cleave | ~115GB | Make powerful, decisive cuts to large packages | Minimal | Yes | Yes | `/opt` and `/usr/local` | 132 | | Rampage | ~130GB | Relentless, brutal elimination of all bloat | Aggressive | Yes | Yes | Muahahaha! 🔥🌎 | 133 | 134 | Choose wisely: 135 | - **Holster** when you need the runner's tools to remain fully functional 136 | - **Carve** to preserve functional runner tooling but claim all free space for Nix 137 | - **Cleave** (*default*) for a good balance of space and functionality 138 | - **Rampage** when you need maximum Nix space and don't care what breaks `#nix-is-life` 139 | 140 | ### Witness The Carnage 🩸 141 | 142 | By default, the purging process executes silently in the background while your workflow continues. But if you want to watch the slaughter in real-time: 143 | 144 | ```yaml 145 | - uses: wimpysworld/nothing-but-nix@main 146 | with: 147 | ️hatchet-protocol: 'cleave' 148 | witness-carnage: true # Default: false 149 | ``` 150 | 151 | ### Customize Safe Havens 🛡️ 152 | 153 | Control how much space to spare from the Nix store land grab with custom safe haven sizes: 154 | 155 | ```yaml 156 | - uses: wimpysworld/nothing-but-nix@main 157 | with: 158 | ️hatchet-protocol: 'cleave' 159 | root-safe-haven: '3072' # Reserve 3GB on the / filesystem 160 | mnt-safe-haven: '2048' # Reserve 2GB on the /mnt filesystem 161 | ``` 162 | 163 | These safe havens define how much space (in MB) will be mercifully spared during space reclamation: 164 | - Default `root-safe-haven` is 2048MB (2GB) 165 | - Default `mnt-safe-haven` is 1024MB (1GB) 166 | 167 | Increase these values if you need more breathing room on your filesystems, or decrease them to show no mercy! 😈 168 | 169 | ### Grant User Ownership of /nix (Nix Permission Edict) 🧑‍⚖️ 170 | 171 | Some Nix installers or configurations expect the `/nix` directory to be writable by the current user. By default, `/nix` is owned by root. If you need user ownership (e.g., for certain Nix installer scripts that don't use `sudo` for all operations within `/nix`), you can enable the `nix-permission-edict`: 172 | 173 | ```yaml 174 | - uses: wimpysworld/nothing-but-nix@main 175 | with: 176 | nix-permission-edict: true # Default: false 177 | ``` 178 | 179 | When `nix-permission-edict` is set to `true`, the action will run `sudo chown -R "$(id --user)":"$(id --group)" /nix` after mounting `/nix`. 180 | 181 | Now go and build something amazing with all that glorious Nix store space! ❄️ -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'Nothing but Nix' 2 | description: 'Removes all the cruft 🪓 from a GitHub Actions runner to make the most space possible for Nix ️❄️' 3 | branding: 4 | icon: 'trash-2' 5 | color: 'red' 6 | inputs: 7 | hatchet-protocol: 8 | description: 'Level of file purging (Holster: none, Cleave: standard, Rampage: aggressive)' 9 | required: false 10 | default: 'cleave' 11 | witness-carnage: 12 | description: 'Display purge progress in real-time instead of running in background' 13 | required: false 14 | default: 'false' 15 | root-safe-haven: 16 | description: 'Space in MB to mercifully spare on the / filesystem (default: 2048)' 17 | required: false 18 | default: '2048' 19 | mnt-safe-haven: 20 | description: 'Space in MB to mercifully spare on the /mnt filesystem (default: 1024)' 21 | required: false 22 | default: '1024' 23 | nix-permission-edict: 24 | description: 'Grant user ownership of /nix directory (default: false). Useful for Nix installers that require user-writable /nix.' 25 | required: false 26 | default: 'false' 27 | runs: 28 | using: composite 29 | steps: 30 | - name: The Checks 31 | id: environment-check 32 | shell: bash 33 | run: | 34 | if [[ "${{ runner.os }}" == "Linux" ]]; then 35 | if [ "$(lsb_release -is)" != "Ubuntu" ]; then 36 | echo "is_supported=false" >> $GITHUB_OUTPUT 37 | echo "This action only works on Ubuntu runners" 38 | exit 1 39 | else 40 | echo "is_supported=true" >> $GITHUB_OUTPUT 41 | fi 42 | fi 43 | 44 | if [ -z "$GITHUB_ACTIONS" ]; then 45 | echo "is_supported=false" >> $GITHUB_OUTPUT 46 | echo "This action only works on GitHub Actions runner" 47 | exit 1 48 | fi 49 | 50 | if [ -d /nix ]; then 51 | echo "is_supported=false" >> $GITHUB_OUTPUT 52 | echo "This action must be run before Nix is installed" 53 | exit 1 54 | else 55 | echo "is_supported=true" >> $GITHUB_OUTPUT 56 | fi 57 | - name: The Hatchet Protocol 58 | id: set-hatchet-protocol 59 | if: steps.environment-check.outputs.is_supported == 'true' 60 | shell: bash 61 | run: | 62 | input_protocol="${{ inputs.hatchet-protocol }}" 63 | # Convert to lowercase for case-insensitive comparison 64 | input_protocol="$(tr '[:upper:]' '[:lower:]' <<< "$input_protocol")" 65 | 66 | case "$input_protocol" in 67 | "holster") 68 | echo "🪓 Hatchet Protocol: Holster - Keep the hatchet sheathed, use space from /mnt (Level 0)" 69 | protocol_level=0;; 70 | "carve") 71 | echo "🪓 Hatchet Protocol: Carve - Craft and combine free space from / and /mnt (Level 1)" 72 | protocol_level=1;; 73 | "cleave") 74 | echo "🪓 Hatchet Protocol: Cleave - Make powerful, decisive cuts to large packages (Level 2)" 75 | protocol_level=2;; 76 | "rampage") 77 | echo "🪓 Hatchet Protocol: Rampage - Relentless, brutal elimination of all bloat (Level 3)" 78 | protocol_level=3;; 79 | *) 80 | echo "🪓 Hatchet Protocol: Cleave - Make powerful, decisive cuts to large packages (Level 2)" 81 | protocol_level=2;; 82 | esac 83 | 84 | echo "level=${protocol_level}" >> $GITHUB_OUTPUT 85 | - name: The Setup 86 | if: steps.environment-check.outputs.is_supported == 'true' && steps.set-hatchet-protocol.outputs.level > 1 87 | shell: bash 88 | run: | 89 | ARCH=$(uname -m) 90 | if [[ "$ARCH" == "x86_64" ]]; then 91 | URL_ARCH="x86_64" 92 | elif [[ "$ARCH" == "aarch64" || "$ARCH" == "arm64" ]]; then 93 | URL_ARCH="aarch64" 94 | else 95 | echo "Unsupported architecture: $ARCH" 96 | exit 1 97 | fi 98 | 99 | OS=$(uname -s) 100 | if [[ "$OS" == "Linux" ]]; then 101 | URL_OS="unknown-linux-gnu" 102 | elif [[ "$OS" == "Darwin" ]]; then 103 | URL_OS="apple-darwin" 104 | else 105 | echo "Unsupported OS: $OS" 106 | exit 1 107 | fi 108 | 109 | DOWNLOAD_URL="https://github.com/SUPERCILEX/fuc/releases/download/3.0.1/${URL_ARCH}-${URL_OS}-rmz" 110 | curl -L -o rmz "$DOWNLOAD_URL" 111 | chmod +x rmz 112 | sudo mv rmz /usr/bin/rmz 113 | rmz --version 114 | - name: The Volume 115 | if: steps.environment-check.outputs.is_supported == 'true' 116 | shell: bash 117 | run: | 118 | free_space=$(df -m --output=avail /mnt | tail -n 1 | tr -d ' ') 119 | echo "Initial free space of /mnt: ${free_space}MB" 120 | loop_dev=$(sudo losetup --find) 121 | loop_num=${loop_dev##*/loop} 122 | 123 | if sudo fallocate -l $((free_space - ${{ inputs.mnt-safe-haven }}))M "/mnt/disk${loop_num}.img"; then 124 | sudo losetup ${loop_dev} "/mnt/disk${loop_num}.img" 125 | fi 126 | 127 | # Create filesystem 128 | sudo mkfs.btrfs -L nix -d raid0 -m raid0 --nodiscard "${loop_dev}" 129 | sudo btrfs device scan 130 | sudo btrfs filesystem show 131 | 132 | # Mount filesystem 133 | sudo mkdir -p /nix 134 | sudo mount LABEL=nix /nix -o noatime,nobarrier,nodiscard,compress=zstd:1,space_cache=v2,commit=120 135 | sudo df -h 136 | 137 | if [[ "${{ inputs.nix-permission-edict }}" == "true" ]]; then 138 | echo "Applying Nix Permission Edict: Granting user ownership of /nix" 139 | sudo chown -R "$(id --user)":"$(id --group)" /nix 140 | fi 141 | 142 | # Create a tmp directory within /mnt for Nix builds and set TMPDIR 143 | TMPNIX="$(sudo mktemp --directory --tmpdir=/mnt)" 144 | sudo chmod 1777 "${TMPNIX}" 145 | echo "TMPDIR=${TMPNIX}" >> $GITHUB_ENV 146 | echo "TMPDIR set to ${TMPNIX} to use space on the /mnt volume for builds." 147 | 148 | # Create a directory to store expansion state 149 | mkdir -p "${HOME}/.expansion" 150 | echo "Initial volume created" | tee "${HOME}/.expansion/holster_done" 151 | - name: The Local 152 | if: steps.environment-check.outputs.is_supported == 'true' && steps.set-hatchet-protocol.outputs.level >= 2 153 | shell: bash 154 | run: | 155 | # Nix is often installed in /usr/local, so we need to ensure that it is purged early 156 | sudo rmz -f /usr/local 157 | sudo mkdir -p /usr/local/{bin,doc,include,lib,man,sbin,share,src} || true 158 | - name: The Purge 159 | if: steps.environment-check.outputs.is_supported == 'true' 160 | shell: bash 161 | run: | 162 | cat > /tmp/expand_nix_volume.sh << 'EOF' 163 | #!/usr/bin/env bash 164 | set -e 165 | 166 | protocol_level="${{ steps.set-hatchet-protocol.outputs.level }}" 167 | expansion_dir="${HOME}/.expansion" 168 | root_safe_haven="${{ inputs.root-safe-haven }}" 169 | 170 | function add_expansion_disk() { 171 | # Check for additional free space after purging 172 | free_space=$(df -m --output=avail / | tail -n 1 | tr -d ' ') 173 | echo "Free space of / after purge: ${free_space}MB" 174 | 175 | # Create additional disk if suitable free space exists 176 | if [ $free_space -gt $((root_safe_haven + 2048)) ]; then 177 | # Calculate the size of the expansion disk, reserving the safe haven 178 | disk_size=$((free_space - root_safe_haven)) 179 | echo "Creating expansion disk of ${disk_size}MB in /" 180 | # Create expansion disk image 181 | loop_dev=$(sudo losetup --find) 182 | loop_num=${loop_dev##*/loop} 183 | if sudo fallocate -l ${disk_size}M "/disk${loop_num}.img"; then 184 | sudo losetup ${loop_dev} "/disk${loop_num}.img" 185 | 186 | # Add the new device to the pool 187 | sudo btrfs device add --nodiscard ${loop_dev} /nix 188 | echo "Added expansion disk "/disk${loop_num}.img" (${loop_dev}, ${disk_size}MB) to /nix pool" > $expansion_dir/expansion_done 189 | 190 | # Balance the filesystem to use the new space 191 | sudo btrfs balance start -dusage=50 /nix 192 | sudo btrfs filesystem show 193 | fi 194 | fi 195 | } 196 | 197 | # If carve is selected, claim space from / now 198 | if [[ "$protocol_level" -eq 1 ]]; then 199 | echo "Disk space has been carved out" > $expansion_dir/carve_done 200 | add_expansion_disk 201 | fi 202 | 203 | # Cleanse docker 204 | if [[ "$protocol_level" -ge 2 ]]; then 205 | for CRUFT in $(docker image ls --format '{{.ID}}'); do 206 | docker rmi --force "${CRUFT}" || true 207 | done 208 | docker system prune --all --force 209 | sudo apt-get -y remove --purge '^docker.*' 210 | sudo rmz -f /usr/bin/docker* /var/lib/docker 211 | echo "Cleanse docker complete" > $expansion_dir/docker_done 212 | fi 213 | 214 | # Cleanse snap 215 | if [[ "$protocol_level" -ge 2 ]]; then 216 | sudo apt-get -y remove --purge snapd 217 | sudo rmz -f \ 218 | /snap \ 219 | /usr/lib/snapd \ 220 | /var/snap \ 221 | /var/lib/snapd \ 222 | "${HOME}/snap" 223 | echo "Cleanse snap complete" > $expansion_dir/snap_done 224 | fi 225 | 226 | # Cleanse apt 227 | if [[ "$protocol_level" -ge 2 ]]; then 228 | sudo tee /etc/dpkg/dpkg.cfg.d/01_nocruft > /dev/null << 'APTCFG' 229 | path-exclude /usr/share/doc/* 230 | path-exclude /usr/share/fonts/* 231 | path-exclude /usr/share/icons/* 232 | path-exclude /usr/share/info/* 233 | path-exclude /usr/share/man/* 234 | APTCFG 235 | 236 | if [[ "$protocol_level" -ge 3 ]]; then 237 | sudo apt-get -y remove --purge \ 238 | '^apache2.*' \ 239 | '^aspnetcore-.*' \ 240 | azure-cli \ 241 | buildah \ 242 | '^byobu.*' \ 243 | '^clang-.*' \ 244 | containerd.io \ 245 | containernetworking-plugins \ 246 | '^dotnet-.*' \ 247 | firefox \ 248 | '^fonts-.*' \ 249 | fwupd \ 250 | '^gfortran-.*' \ 251 | '^google-.*' \ 252 | '^gradle.*' \ 253 | '^java.*' \ 254 | '^kotlin.*' \ 255 | kubectl \ 256 | '^libclang-.*' \ 257 | libgl1-mesa-dri \ 258 | '^libgirepository-.*' \ 259 | '^libgtk-.*' \ 260 | '^libllvm-.*' \ 261 | '^libx265-.*' \ 262 | '^llvm-.*' \ 263 | man-db \ 264 | '^mecab.*' \ 265 | mediainfo \ 266 | '^mercurial.*' \ 267 | microsoft-edge-stable \ 268 | '^mongodb-.*' \ 269 | '^mono-.*' \ 270 | '^mssql-.*' \ 271 | '^mysql-.*' \ 272 | '^nginx-.*' \ 273 | '^php.*' \ 274 | '^podman.*' \ 275 | '^powershell.*' \ 276 | '^postgres.*' \ 277 | python-babel-localedata \ 278 | '^python3-babel.*' \ 279 | '^python3-boto.*' \ 280 | '^ruby.*' \ 281 | '^r-base.*' \ 282 | skopeo \ 283 | tcl \ 284 | tk \ 285 | '^tex-.*' \ 286 | '^vim.*' 287 | fi 288 | 289 | sudo apt-get -y autoremove --purge 290 | sudo apt-get -y clean 291 | echo "Cleanse apt complete" > $expansion_dir/apt_done 292 | fi 293 | 294 | # Cleave 295 | if [[ "$protocol_level" -ge 2 ]]; then 296 | sudo rmz -f \ 297 | "${HOME}/.rustup" \ 298 | "${HOME}/.cargo" \ 299 | "${HOME}/.dotnet" \ 300 | /opt/containerd \ 301 | /opt/hostedtoolcache \ 302 | /opt/microsoft \ 303 | /opt/az \ 304 | /opt/pipx* \ 305 | /opt/google \ 306 | /opt/mssql-tools 307 | echo "Cleave complete" > $expansion_dir/cleave_done 308 | fi 309 | 310 | # Rampage 311 | if [[ "$protocol_level" -ge 3 ]]; then 312 | sudo rmz -f \ 313 | /usr/bin/kotlin* \ 314 | /usr/lib/heroku \ 315 | /usr/share/apache-* \ 316 | /usr/share/az_* \ 317 | /usr/share/doc/* \ 318 | /usr/share/fonts/* \ 319 | /usr/share/gradle-* \ 320 | /usr/share/icons/* \ 321 | /usr/share/info/* \ 322 | /usr/share/kotlinc \ 323 | /usr/share/java \ 324 | /usr/share/man/* \ 325 | /usr/share/miniconda \ 326 | /usr/share/sbt \ 327 | /usr/share/swift \ 328 | /usr/share/tcltk \ 329 | /usr/share/texinfo \ 330 | /var/lib/containerd \ 331 | /var/lib/gems \ 332 | /var/lib/mysql \ 333 | /var/lib/ubuntu-advantage 334 | echo "Rampage complete" > $expansion_dir/rampage_done 335 | fi 336 | 337 | # Claim the space from / for purging 338 | if [[ "$protocol_level" -ge 2 ]]; then 339 | echo "The Purge Is Complete!" > $expansion_dir/purge_done 340 | add_expansion_disk 341 | fi 342 | 343 | echo "Everything completed" > $expansion_dir/all_done 344 | EOF 345 | 346 | # Make script executable 347 | chmod +x /tmp/expand_nix_volume.sh 348 | # Execute based on witness-carnage setting 349 | if [ "${{ inputs.witness-carnage }}" == "true" ]; then 350 | echo "😮 Displaying the carnage in real-time. This will block until completion." 351 | /tmp/expand_nix_volume.sh | tee ${HOME}/.expansion/expansion.log 352 | else 353 | /tmp/expand_nix_volume.sh > ${HOME}/.expansion/expansion.log 2>&1 & 354 | echo "📈 Background space expansion started. /nix will grow as space becomes available." 355 | fi 356 | - name: The Post 357 | if: ${{ runner.os }} == 'Linux' 358 | uses: srz-zumix/post-run-action@v2 359 | with: 360 | shell: bash -e {0} 361 | post-run: | 362 | ls -ltr ${HOME}/.expansion/*_done || true 363 | all_disks=() 364 | 365 | # Check for disks in /mnt directory 366 | mnt_disks=(/mnt/disk*.img) 367 | if [[ -e "${mnt_disks[0]}" ]]; then 368 | all_disks+=("${mnt_disks[@]}") 369 | fi 370 | 371 | # Check for disks in / directory 372 | root_disks=(/disk*.img) 373 | if [[ -e "${root_disks[0]}" ]]; then 374 | all_disks+=("${root_disks[@]}") 375 | fi 376 | 377 | echo "Found ${#all_disks[@]} disk image(s):" 378 | for disk in "${all_disks[@]}"; do 379 | echo "- $disk ($(du -h "$disk" | cut -f1))" 380 | done 381 | echo "Space used by TMPDIR:" 382 | sudo du -csh "$TMPDIR" || true 383 | echo "Space used by disk images:" 384 | sudo df -h 385 | echo "Check which device(s) btrfs is using:" 386 | sudo btrfs filesystem show /nix 387 | echo "See actual allocation per device:" 388 | sudo btrfs device stats /nix 389 | 390 | --------------------------------------------------------------------------------