A comprehensive set of tools for restoring Btrfs snapshots created with btrbk, available in Python and Rust with different user interfaces.
This project provides tools to easily restore Btrfs subvolume snapshots created by the btrbk tool. The tools allow you to:
- Automatic detection of all snapshot types present
- Dynamic interface that adapts to the number of groups found
- View available snapshots for all subvolumes
- Select and restore specific snapshots
- Automatically manage backup of existing subvolumes
- Persistent configuration shared between versions
- Intelligent cleanup of old snapshots
- System reboot with visual indicators
- Optionally reboot the system after restoration
- Root cause: the purge kept only the most recent snapshot per type, deleting the one the backup target still needed as parent. btrbk does not protect parent snapshots itself (
btrbk.conf(5)), so the next run had no common parent and fell back to a full send — on a ~900 GiB subvolume, over an hour of transfer - Fix: the target is queried over ssh (
btrfs subvolume list -u -R) and each local snapshot'sUUIDis matched against the target'sreceived_uuid. The newest snapshot present on both survives, together with everything newer - Fails safe: if the target is unreachable, or shares no snapshot with the local pool, nothing is deleted and the UI says so — a broken chain is never made worse
- UI feedback: the status bar announces the target check before the ssh call blocks the interface
- Unit tests (Rust) cover the parsing of
btrbk.conf, ofreceived_uuidlists and ofbtrfs subvolume show— including the trap whereParent UUID:is matched instead ofUUID:
.ruff.tomladded: the project had no ruff configuration, so the effective rule set was whatever the installed ruff defaulted to. The "zero linter warnings" claim of v2.6 quietly expired as ruff was upgraded — 51 warnings had accumulated by v2.7- Explicit rule selection (correctness, modernisation, bugbear, bandit, pylint) with every waiver documented inline:
subprocess.runwithoutcheck=is deliberate where return codes drive the rollback logic, broadexcept Exceptionkeeps a fullscreen curses app from dying, naive datetimes match btrbk's own local-time snapshot names - 166 findings fixed: modern type annotations (
dict/listovertyping),sys.exit()over thesitebuiltinexit(),.values()iteration,contextlib.suppress, unused unpacked variables ruff checkandcargo clippyboth pass clean, and now stay that way across tool upgrades
- Verified rollback: every rollback command (
mv/btrfs delete) return code is checked. Three distinct outcomes are reported: success, failed (rollback succeeded, previous state restored) and rollback failed (inconsistent state →.BROKENkept and a CRITICAL message points to it for manual recovery) - Source pre-check: the source snapshot existence is verified before touching the current subvolume
- Subvolume guard:
btrfs subvolume showis run before the destructivemv, preventing a plain directory from being moved by mistake - CLI brought to parity:
btrbk_tui.pynow performs the same verify + rollback as the TUI versions, reads the shared config, requires root and runssyncbefore reboot
- Rust UTF-8 safety: all string truncation is char-aware (
truncate_str), eliminating panics on multibyte characters in snapshot names or btrbk output - Snapshot cache: the snapshots directory is no longer re-read on every frame; the cache is invalidated only on refresh/restore/purge/clean/create. The
Rkey now actually refreshes - Cleaner output: the snapshot-creation output area is fully redrawn (no scroll glitches), and dead/unreachable code was removed
- Zero linter warnings:
cargo clippy(Rust) andruff check(Python) both pass clean
- No longer limited to 3 fixed types (@, @home, @games)
- Automatically scans the snapshots directory
- Detects any prefix (@, @home, @games, @custom, @backup, @work, etc.)
- Automatically adapts to any user's btrbk configuration
- Fixed timestamp parsing - Now supports both
YYYYMMDDTHHMMSSandYYYYMMDD_HHMMSSformats - Fixed .BROKEN conflicts - Unique timestamps prevent restore failures
- Fixed hardcoded restore logic - Now fully dynamic for all subvolume types
- Fixed purge function - Dynamic detection instead of hardcoded types
- Simplified log display - Removed problematic side borders
- Dynamic columns: Number of columns adapts to groups found
- Automatic width: Columns resize automatically
- Smart sorting: @ always first, then alphabetical order
- Snapshot count: Shows number of snapshots per group
Basic User: @ | @home
Gaming User: @ | @home | @games
Pro User: @ | @home | @games | @work | @backup
Server User: @ | @home | @var | @opt | @srv | @data
- Separator lines at full screen width
- Perfect visual consistency between header and footer
- Optimized colors for better readability
Basic User: @ | @home
Gaming User: @ | @home | @games
Pro User: @ | @home | @games | @work | @backup
Server User: @ | @home | @var | @opt | @srv | @data
- Separator lines at full screen width
- Perfect visual consistency between header and footer
- Optimized colors for better readability
btrbk_tui.py- Simple CLI version with text menubtrbk_tui_pro.py- Professional TUI interface with persistent configuration and dynamic columns
btrbk_tui_rust/- High-performance TUI version written in Rust with ncurses (identical to Python Pro version)
# Basic CLI version
python3
# Professional TUI version
python3 (with curses module included)# Rust installation (edition 2024)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Build the project
cd btrbk_tui_rust
cargo build --releaseThe tool assumes by default:
- Btrfs Pool:
/mnt/btr_pool - Snapshots directory:
/mnt/btr_pool/btrbk_snapshots
Shared Configuration: The TUI Pro (Python) and Rust versions share the same JSON configuration file at ~/.config/btrbk_tui/config.json, ensuring a completely consistent user experience.
sudo ./btrbk_tui.pysudo ./btrbk_tui_pro.pycd btrbk_tui_rust
sudo ./target/release/btrbk_tui- Numbered list of all snapshots organized by type
- Number-based selection with simple interface
- Complete dynamic support for any configuration (@, @home, @games, @custom, @backup, etc.)
- Simple interface for occasional use
- Automatic management of .BROKEN backups
- Automatic detection of all snapshot types present
- Dynamic interface: Columns that automatically adapt to groups found
- Persistent configuration: Automatic saving to
~/.config/btrbk_tui/config.json - Advanced navigation: Arrow keys for fluid navigation
- Complete settings screen:
Skey for advanced configuration - Configurable settings: Directories, auto-cleanup, confirmations, timestamps
- Status messages: Real-time operation feedback
- Themes and colors: Professional interface with highlighting
- Auto-save: Every change is automatically saved
- Snapshot creation: Dedicated interface for
btrbk run --progress - Smart purge: Automatic cleanup of old snapshots
- Reboot system: Visual indicators and dedicated shortcuts
- Optimized performance: Native Rust implementation
- Identical interface: Layout and functionality identical to Python Pro version
- Shared configuration: Uses exactly the same JSON file as Python version
- Complete settings screen: Same editing functionality as Python version
- Efficient memory management: Ideal for resource-limited systems
- Total compatibility: Zero functional differences with Python Pro version
- Optimized compilation: Rust edition 2024, zero errors and warnings
- Snapshot creation: Multi-threaded interface for real-time output
- Purge and reboot: All advanced features implemented
The tool automatically handles snapshots with this nomenclature:
@.YYYYMMDD_HHMMSS- Root subvolume snapshot@home.YYYYMMDD_HHMMSS- Home subvolume snapshot@games.YYYYMMDD_HHMMSS- Games subvolume snapshot@custom.YYYYMMDD_HHMMSS- Custom subvolume snapshots@backup.YYYYMMDD_HHMMSS- Backup snapshots@work.YYYYMMDD_HHMMSS- Work snapshots- And any other prefix that starts with
@followed by a dot
The tool automatically adapts to any user's btrbk configuration!
- ↑↓: Vertical navigation through snapshots
- ←→: Dynamic column switching (adaptive to number of groups)
- ENTER: Snapshot selection and restoration
- S: Access settings screen
- R: Refresh snapshot list
- I: Create new snapshots (btrbk run --progress)
- P: Purge old snapshots (keeps what the backup target still needs)
- H: System reboot (when needed)
- Q: Exit application
- ↑↓: Navigate between options
- ENTER: Edit value (for strings)
- SPACE: Toggle value (for booleans)
- S: Manual save (optional, auto-save active)
- ESC: Return to main screen
- Executes:
btrbk run --progresswith dedicated interface - Real-time output: Professional progress visualization
- Dedicated window: Fullscreen with borders and title
- Cancellation: ESC to interrupt operation at any time
- Auto-scroll: Automatic scrolling for long output
- Complete feedback: Colored success/error messages
- Stderr handling: Perfectly aligned output without overlaps
- Analyzes all snapshots by type (@, @home, @games)
- Chain-aware: queries the backup target and keeps the newest snapshot the target also holds, plus everything newer. That snapshot is the parent for the next incremental send — deleting it forces a full send on the next run
- Deletes only the snapshots older than that parent
- Refuses to purge when the target is unreachable, or when no snapshot is shared with it: without that information there is no safe way to tell what can go
- Confirmation before operation for safety
- Detailed feedback on how many snapshots were deleted
- Error handling: Continues operation even if individual deletions fail
- Space optimization: Frees disk space without ever breaking the incremental chain
Why this matters: btrbk does not protect snapshots that are still needed as parents for incremental backups (see
btrbk.conf(5)). A purge that keeps only the most recent snapshot per type will silently break the chain whenever the target is behind — for example after a backup run was interrupted. The next run then has no common parent and falls back to a full send, which on a large subvolume means hours of transfer.
- R Key: Always available for snapshot list refresh
- H Key: Appears in footer after restore for quick reboot
- Persistent warning: Status bar shows "⚠ REBOOT REQUIRED" after each restore
- Dedicated keys: R for refresh, H for reboot, I for snapshot, P for purge - no confusion
- Visual indicators: Dynamic footer that changes based on context
btrbk-tui.desktop launches the Rust TUI through pkexec, so the desktop's
polkit agent asks for the password instead of the tool failing on a missing
root. It expects the binary at /usr/local/bin/btrbk_tui; adjust Exec= if you
installed it elsewhere.
install -Dm644 btrbk-tui.desktop ~/.local/share/applications/btrbk-tui.desktop
update-desktop-database ~/.local/share/applications- Mandatory confirmations: Confirmation dialogs for all critical operations
- Automatic backup: Existing subvolumes are renamed to .BROKEN before restoration
- Source pre-check & subvolume guard: the source snapshot must exist and the current subvolume must be a valid btrfs subvolume before any destructive operation
- Verified rollback: on failure the original subvolume is restored and the rollback outcome is checked; if the rollback itself fails, the
.BROKENbackup is kept and a CRITICAL message indicates manual recovery is needed - Error handling: Robust operations with fallback and clear error messages
- Optional auto-cleanup: Configurable automatic cleanup of .BROKEN files
- Operating System: Linux with Btrfs filesystem
- Dependencies: btrfs-progs, btrbk
- Desktop: Tested on KDE Plasma, compatible with other DEs
- Supported subvolumes: Any configuration starting with @ (dynamic)
- Architectures: x86_64, ARM64 (Rust), all architectures supported by Python
Both TUI versions (Python Pro and Rust) share the configuration saved at:
~/.config/btrbk_tui/config.json
- btr_pool_dir: Btrfs pool directory (default:
/mnt/btr_pool) - snapshots_dir: Snapshots directory (default:
/mnt/btr_pool/btrbk_snapshots) - auto_cleanup: Auto-cleanup of .BROKEN files (default:
false) - confirm_actions: Action confirmation (default:
true) - show_timestamps: Display formatted timestamps (default:
true) - theme: Interface theme (default:
"default")
{
"btr_pool_dir": "/mnt/btr_pool",
"snapshots_dir": "/mnt/btr_pool/btrbk_snapshots",
"auto_cleanup": false,
"confirm_actions": true,
"show_timestamps": true,
"theme": "default"
}- Automatic loading: At startup of any TUI version
- Automatic saving: On every change in TUI versions
- Synchronization: Changes in one version apply immediately to the other
- Fallback: If file is corrupted or missing, default values are used
- ✅ Occasional or sporadic use
- ✅ Automated scripts
- ✅ Resource-limited environments
- ✅ When only basic functionality is needed
- ✅ Frequent and interactive use
- ✅ Advanced configuration and customization
- ✅ When Python is preferred for modifications
- ✅ Development and debugging
- ✅ Complete snapshot management
- ✅ Dynamic interface that adapts to any configuration
- ✅ Maximum performance and speed
- ✅ Systems with limited or absent Python
- ✅ Production environments
- ✅ When memory efficiency is needed
- ✅ All Pro version features
- ✅ Dynamic interface identical to Python version
- Single configuration file for both TUI versions
- Automatically synchronized changes
- Consistent user experience
- Same interface and controls
- Same configuration options
- Same behavior and workflow
- Same advanced features (purge, reboot, settings)
- Switch from Python to Rust without losing configurations
- Choose language based on specific needs
- Simplified maintenance with shared configuration
- Python: Ease of modification and debugging
- Rust: Execution speed and memory efficiency
- Both: Same user experience
btrbk_tui/
├── README.md # Complete documentation
├── btrbk_tui.py # Simple CLI version
├── btrbk_tui_pro.py # Python professional TUI version
├── btrbk_tui_rust/ # Rust professional TUI version
│ ├── Cargo.toml # Rust configuration (edition 2024)
│ ├── src/main.rs # Rust source code
│ └── target/release/ # Compiled binary
├── btrbk-tui.desktop # Desktop file for DE integration
└── .git/ # Git repository
- Python 3: CLI and TUI Pro versions
- Rust 2024: High-performance TUI version
- JSON: Shared configuration
- Python:
curses,json,pathlib,subprocess,osmodules - Rust:
ncurses,serde,serde_json,chrono,dirs,libc
- Python:
ruff—ruff check btrbk_tui.py btrbk_tui_pro.py - Rust:
cargo clippy— both pass with zero warnings
- Tested on Arch Linux with KDE Plasma 6
- Compatible with other Linux desktop environments
- Full support for Btrfs filesystem
- Startup:
sudo ./btrbk_tui_pro.pyor Rust version - Navigation: Use arrows to explore available snapshots
- Configuration: Press
Sto modify settings if needed - Snapshot creation: Use
Ito create new snapshots with btrbk - Selection: Choose snapshot to restore with
ENTER - Confirmation: Confirm the restoration operation
- Reboot: Choose whether to reboot immediately or continue
- Cleanup: Use
Pto delete old snapshots when needed - Quick reboot: Use
Hto reboot when indicated
Open source project - see source code for implementation details.
Contributions welcome! The project demonstrates implementing the same functionality in different languages (Python/Rust) with interfaces optimized for different use cases, while maintaining full configuration compatibility and identical user experience.
- Modular and well-structured architecture
- Shared configuration between different languages
- Professional and intuitive user interfaces
- Robust error handling
- Performance optimized for each language
- Complete and up-to-date documentation
- Advanced snapshot management features
- Integrated security system
# Clone the repository
git clone https://github.com/rylos/btrbk_tui.git
cd btrbk_tui
# Make scripts executable
chmod +x btrbk_tui.py btrbk_tui_pro.py
# For Rust version
cd btrbk_tui_rust
cargo build --release
cd ..
# Run (requires root privileges)
sudo ./btrbk_tui_pro.py# Verify btrfs tools
which btrfs btrbk
# Verify Python
python3 --version
# Verify Rust (for Rust version)
rustc --versionThe dynamic interface automatically adapts to your btrbk configuration:
2 Groups (Basic):
@ (3) | @HOME (2)
4 Groups (Advanced):
@ (3) | @HOME (2) | @GAMES (4) | @WORK (1)
6+ Groups (Server):
@ (3) | @HOME (2) | @VAR (1) | @OPT (2) | @SRV (1) | @DATA (3)
- Issues: Report bugs or request features via GitHub Issues
- Documentation: Complete documentation in this README
- Community: Contributions and feedback welcome
Made with ❤️ for the Btrfs and btrbk community