Files
create-linux-swapfile/README.md
T
kevinveenbirkenbachandClaude Opus 5.5 91e1eff8a6 fix(btrfs): allocate the swapfile with fallocate instead of dd
On a btrfs root the swapfile was written with dd from /dev/zero, so a
swapfile the size of the RAM cost tens of GiB of writes and stalled
every other writer on the filesystem. A caller that bounds the run, such
as an async Ansible task, killed dd halfway, and the next run found the
wrong size and started over. btrfs accepts a preallocated NOCOW
swapfile and the swap directory already carries +C, so every filesystem
now allocates with fallocate.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-23 10:36:04 +02:00

139 lines
5.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SwapForge (swap-forge) 🔄
[![GitHub Sponsors](https://img.shields.io/badge/Sponsor-GitHub%20Sponsors-blue?logo=github)](https://github.com/sponsors/kevinveenbirkenbach) [![Patreon](https://img.shields.io/badge/Support-Patreon-orange?logo=patreon)](https://www.patreon.com/c/kevinveenbirkenbach) [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20me%20a%20Coffee-Funding-yellow?logo=buymeacoffee)](https://buymeacoffee.com/kevinveenbirkenbach) [![PayPal](https://img.shields.io/badge/Donate-PayPal-blue?logo=paypal)](https://s.veen.world/paypaldonate)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![GitHub stars](https://img.shields.io/github/stars/kevinveenbirkenbach/swap-forge.svg?style=social)](https://github.com/kevinveenbirkenbach/swap-forge/stargazers)
SwapForge is a small Python CLI for creating and managing Linux swapfiles. Whether you need to boost system performance or add swap space to your setup, SwapForge automates the process quickly and reliably — and it knows the difference between btrfs and everything else.
---
## 🧭 How it works
```mermaid
flowchart TD
A["swap-forge SIZE"] --> B["parse SIZE into MiB"]
B --> B2{"parsable?"}
B2 -- no --> X["Invalid size format - exit 1"]
B2 -- yes --> C["findmnt -no FSTYPE /"]
C --> D{"root filesystem is btrfs?"}
D -- yes --> E["target: /var/swap/swapfile"]
D -- no --> F["target: /swapfile"]
E --> G["read the size of the existing swapfile"]
F --> G
G --> H{"same size already?"}
H -- yes --> Y["Skipping - exit 0"]
H -- no --> I{"a swapfile is already there?"}
I -- yes --> J["swapoff, delete it, drop its fstab line"]
I -- no --> K
J --> K{"root filesystem is btrfs?"}
K -- yes --> L["chattr +C, turn compression off"]
K -- no --> M["allocate with fallocate"]
L --> M
M --> N["chmod 600"]
N --> O["mkswap"]
O --> P["swapon"]
P --> Q["append the entry to /etc/fstab"]
```
The fstab entry is written **after** activation succeeds, so a failed run never leaves a half-written fstab behind.
---
## 🛠 Features
- **Automated Swapfile Creation:** Easily create a swapfile with a specified size.
- **Btrfs Aware:** Disables copy-on-write and compression on the swap directory before allocating; every filesystem allocates with `fallocate`.
- **FSTAB Integration:** Automatically updates `/etc/fstab` to ensure the swapfile is mounted at boot.
- **Safety Checks:** Skips creation when a swapfile of the correct size already exists, and recreates it when the size differs.
- **Simple CLI Interface:** Run the command with a single argument.
---
## 📥 Installation
```bash
pip install swap-forge
```
pip is the single supported installation path.
The package installs **two** identical commands: `swap-forge` (primary) and `swafo` (kept for older documentation and scripts).
---
## 🔧 Requirements
- **Python 3.10+** 🐍
- **root privileges** — the tool writes `/etc/fstab` and activates swap
- Always required on `PATH`: `findmnt`, `swapoff`, `fallocate`, `chmod`, `mkswap`, `swapon`
- On a **btrfs** root additionally: `chattr`, `btrfs`
If a required command is missing, the tool exits with code `127` and a one‑line error instead of a traceback.
---
## 🚀 Usage
Run SwapForge by specifying the desired swapfile size. For example, to create a 2G swapfile:
```bash
sudo swap-forge 2G
```
Accepted sizes are whole numbers with an optional unit: `2048`, `2048M`, `2048MB`, `64G`, `64GB`. Without a unit the value is read as MiB.
The swapfile location follows the root filesystem:
| Root filesystem | Swapfile |
| --- | --- |
| `btrfs` | `/var/swap/swapfile` |
| anything else | `/swapfile` |
SwapForge compares the existing swapfile against the requested size, skips when they match, and otherwise removes the old one — including its `/etc/fstab` line — before creating the new one.
### Exit codes
| Code | Meaning |
| --- | --- |
| `0` | Swapfile is in place, either created or already correct. |
| `1` | Invalid size argument, or one of the swap commands failed. |
| `2` | Invalid command line arguments. |
| `127` | A required command is not installed. |
---
## 🧪 Development
```bash
make lint # ruff check + ruff format --check
make format # apply ruff format
make test # unit + integration tests
make test-unit
make test-integration
make test-e2e # install the package in a container and exercise the CLI
```
Tests run against the working tree — the `Makefile` puts `src/` on `PYTHONPATH`, so no install is needed. Every command execution is mocked and `fstab` handling is exercised against a temporary file, so the suite never touches real swap.
---
## 🧑‍💻 Author
Developed by **Kevin Veen-Birkenbach**
- 📧 [kevin@veen.world](mailto:kevin@veen.world)
- 🌐 [https://www.veen.world](https://www.veen.world)
---
## 📜 License
This project is licensed under the **MIT License**.
---
## 🤝 Contributions
Contributions are welcome! Feel free to fork the repository, submit pull requests, or open issues if you have suggestions or encounter any problems. Let's make Linux swap management easier together! 😊