Skip to content
mstephenhollPublic

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Engraver

A fast, safe CLI tool for creating bootable USB drives, SD cards, and NVMe drives from ISO images.

Inspired by Balena Etcher, built for developers and automation.

New to Engraver? See the Quickstart Guide to get started in 5 minutes.

Features

  • Safety First - System drive protection prevents accidental overwrites
  • Fast - High-performance block writing with progress tracking
  • Reliable - Parallel write verification hashes data during write for fast integrity checks
  • Remote Sources - Write directly from HTTP/HTTPS URLs
  • Compression - Supports .gz, .xz, .zst, and .bz2 compressed images
  • Resumable - Resume interrupted writes with checkpoint support
  • USB Speed Detection - Warns if USB 3.0 device is connected at USB 2.0 speed
  • Cross-Platform - Linux, macOS, and Windows support
  • Developer-Friendly - Clean CLI, JSON output, scriptable

Installation

Quick Install (Linux/macOS)

curl -fsSL https://raw.githubusercontent.com/mstephenholl/engraver/main/install.sh | bash

This installs the binary, shell completions, and man pages.

Verify the script before running (recommended)
# Download and inspect
curl -fsSL https://raw.githubusercontent.com/mstephenholl/engraver/main/install.sh -o install.sh
less install.sh

# Verify checksum
echo "3d310d2094281e011d80db8d7dcf2922cbbb71c018ffdf365ab2966dd976adda  install.sh" | sha256sum -c

# Run after inspection
bash install.sh

From Source

cargo install --path crates/engraver-cli

Pre-built Binaries

Download from Releases.

Usage

# List available drives
engraver list

# Write an ISO to a USB drive
engraver write ubuntu.iso /dev/sdb

# Write directly from a URL
engraver write https://releases.ubuntu.com/24.04/ubuntu-24.04-desktop-amd64.iso /dev/sdb

# Write a compressed image (auto-detected)
engraver write ubuntu.iso.xz /dev/sdb

# Write with verification (hashes during write, then reads back to verify)
engraver write ubuntu.iso /dev/sdb --verify

# Skip confirmation prompt (for scripts)
engraver write ubuntu.iso /dev/sdb -y

# Silent mode (no output, implies -y)
engraver write ubuntu.iso /dev/sdb --silent

# Verify a device against an image
engraver verify ubuntu.iso /dev/sdb

# Calculate checksum (supports sha256, sha512, md5, crc32)
engraver checksum ubuntu.iso --algorithm sha256

# Enable checkpointing for resume support
engraver write ubuntu.iso /dev/sdb --checkpoint

# Resume an interrupted write
engraver write ubuntu.iso /dev/sdb --resume

# Auto-detect and verify checksum from .sha256/.sha512/.md5 files
engraver write ubuntu.iso /dev/sdb --auto-checksum

# Show partition layout before writing
engraver write ubuntu.iso /dev/sdb --show-partitions

# Benchmark drive write speed
engraver benchmark /dev/sdb

# Benchmark with custom settings
engraver benchmark /dev/sdb --size 1G --pattern random

# Test multiple block sizes to find optimal performance
engraver benchmark /dev/sdb --test-block-sizes "4K,64K,1M,4M,16M"

# Erase a drive (zero-fill)
engraver erase /dev/sdb

Resume Support

Engraver supports resuming interrupted writes. If a write is cancelled (Ctrl+C) or fails due to an error, a checkpoint is saved automatically when using --checkpoint or --resume.

# Start a write with checkpointing enabled
engraver write large-image.iso /dev/sdb --checkpoint

# If interrupted, resume from where it left off
engraver write large-image.iso /dev/sdb --resume

Resume limitations:

  • Local files: Always resumable (seekable)
  • HTTP/HTTPS sources: Resumable if the server supports Range headers
  • Compressed files (.gz, .xz, .zst, .bz2): Cannot be resumed

Checkpoints are stored in:

  • Linux/macOS: ~/.local/state/engraver/checkpoints/
  • Windows: %LOCALAPPDATA%\engraver\checkpoints\

Remote Sources

Engraver can write images directly from HTTP/HTTPS URLs without downloading first:

# Write from a URL
engraver write https://example.com/image.iso /dev/sdb

# Combine with verification
engraver write https://example.com/image.iso /dev/sdb --verify

# Resume support works with URLs (if server supports Range headers)
engraver write https://example.com/large-image.iso /dev/sdb --checkpoint

Cloud Storage

Write images directly from S3, Google Cloud Storage, or Azure Blob Storage:

# Write from Amazon S3
engraver write s3://my-bucket/images/firmware.img /dev/sdb

# Write from Google Cloud Storage
engraver write gs://my-bucket/images/ubuntu.iso /dev/sdb

# Write from Azure Blob Storage
engraver write az://my-container/images/debian.iso /dev/sdb

# Presigned URLs work as regular HTTPS URLs
engraver write "https://my-bucket.s3.amazonaws.com/image.iso?X-Amz-..." /dev/sdb

Cloud sources support resume via Range headers, just like HTTP/HTTPS. The cloud chunk size is configurable in the [network] section of the configuration file.

Note: Cloud storage support is an optional feature flag. Pre-built binaries include it by default. When building from source, enable it with cargo build --features cloud.

Compression Support

Compressed images are automatically detected and decompressed during write:

Format Extensions
Gzip .gz, .gzip
XZ .xz
Zstandard .zst, .zstd
Bzip2 .bz2, .bzip2
# Write compressed images (format auto-detected by extension)
engraver write ubuntu.iso.xz /dev/sdb
engraver write raspbian.img.gz /dev/sdb
engraver write archlinux.iso.zst /dev/sdb

Compressed images cannot be resumed if interrupted.

Erasing Drives

Securely wipe a drive by zero-filling the entire device:

# Erase a USB drive (with confirmation prompt)
engraver erase /dev/sdb

# Erase without confirmation (for scripting)
engraver erase /dev/sdb -y

# Erase with a larger block size for faster throughput
engraver erase /dev/sdb --block-size 16M

System drive protection applies to erase just as it does to write — Engraver refuses to erase drives containing system partitions.

Partition Inspection

Preview the partition layout of a source image before writing:

# Show MBR or GPT partition table
engraver write ubuntu.iso /dev/sdb --show-partitions

This displays partition type, sizes, and filesystem labels. Works with compressed sources by decompressing just the first 64 KB to read the partition table header.

Platform Notes

Engraver works on Linux, macOS, and Windows. Device paths differ by platform:

Platform Example Device Path List Command
Linux /dev/sdb engraver list
macOS /dev/disk2 engraver list
Windows \\.\PhysicalDrive1 engraver list
# macOS — write to an external drive
engraver write ubuntu.iso /dev/disk2 --verify

# Windows — write to a USB drive (run as Administrator)
engraver write ubuntu.iso \\.\PhysicalDrive1 --verify

On macOS, Engraver uses F_FULLFSYNC for guaranteed physical media flush and DKIOCGETBLOCKSIZE ioctl for accurate block size detection. On Linux, standard fsync and /sys/block are used.

Scripting & Automation

Engraver is designed to work well in scripts and CI/CD pipelines:

# JSON output for machine-readable drive listing
engraver list --json | jq -r '.[].path'

# Non-interactive write (skip confirmation)
engraver write ubuntu.iso /dev/sdb -y --verify

# Silent mode (no output except errors, implies -y)
engraver write ubuntu.iso /dev/sdb --silent --verify

# JSON benchmark results for performance tracking
engraver benchmark /dev/sdb --json --passes 3 -y

# Configuration as JSON
engraver config --json | jq '.write.block_size'

Exit Codes

Code Meaning
0 Success
1 Error (permission denied, device not found, verification failure, etc.)

Example: Scripted Write with Verification

#!/bin/bash
set -euo pipefail

IMAGE="ubuntu-24.04-desktop-amd64.iso"
DEVICE="/dev/sdb"

# Verify the image checksum before writing
engraver checksum "$IMAGE" --algorithm sha256

# Write with verification, skip prompt
engraver write "$IMAGE" "$DEVICE" -y --verify --auto-checksum

echo "Write complete and verified."

Shell Completions

Engraver can generate shell completions for tab-completion of commands and arguments.

# Bash
engraver completions bash > ~/.local/share/bash-completion/completions/engraver

# Zsh - place in a directory on your fpath
engraver completions zsh > ~/.zfunc/_engraver
# Then add to .zshrc if not already present:
#   fpath=(~/.zfunc $fpath)
#   autoload -Uz compinit && compinit

# Fish
engraver completions fish > ~/.config/fish/completions/engraver.fish

# PowerShell - add to your profile
engraver completions powershell >> $PROFILE

# Elvish
engraver completions elvish > ~/.elvish/lib/engraver.elv

Configuration

Engraver supports a configuration file for persistent settings. This allows you to set default values for frequently used options.

Configuration File Location

  • Linux/macOS: ~/.config/engraver/engraver_config.toml
  • Windows: %APPDATA%\engraver\engraver_config.toml

Managing Configuration

# View current settings
engraver config

# View settings as JSON
engraver config --json

# Show config file path
engraver config --path

# Create a new config file with defaults
engraver config --init

Example Configuration

[write]
block_size = "4M"
verify = true
checkpoint = false
retry_attempts = 3
retry_delay_ms = 100
read_buffer_size = "64K"

[checksum]
algorithm = "sha256"
auto_detect = false

[behavior]
skip_confirmation = false
quiet = false

[benchmark]
block_size = "4M"
test_size = "256M"
pattern = "zeros"
passes = 1
json = false

[network]
http_timeout_secs = 30
validation_timeout_secs = 10
cloud_chunk_size = "4M"

Configuration Options

Section Option Description Default
[write] block_size Default block size for writes "4M"
[write] verify Always verify writes false
[write] checkpoint Enable checkpointing by default false
[write] retry_attempts Number of retry attempts on transient errors 3
[write] retry_delay_ms Delay between retries in milliseconds 100
[write] read_buffer_size Buffer size for reading source data "64K"
[checksum] algorithm Default checksum algorithm "sha256"
[checksum] auto_detect Auto-detect checksum files false
[behavior] skip_confirmation Skip confirmation prompts false
[behavior] quiet Suppress non-error output false
[benchmark] block_size Default block size for benchmarks "4M"
[benchmark] test_size Default test data size "256M"
[benchmark] pattern Default data pattern (zeros, random, sequential) "zeros"
[benchmark] passes Default number of benchmark passes 1
[benchmark] json Output benchmark results in JSON format false
[network] http_timeout_secs HTTP request timeout 30
[network] validation_timeout_secs URL validation timeout 10
[network] cloud_chunk_size Chunk size for cloud storage downloads "4M"

Command-line flags always override configuration file settings.

Benchmarking

Test drive write speed before committing to a long write operation:

# Basic benchmark (256 MB test, 4 MB blocks)
engraver benchmark /dev/sdb

# Custom test size and pattern
engraver benchmark /dev/sdb --size 1G --pattern random

# Test multiple block sizes to find optimal performance
engraver benchmark /dev/sdb --test-block-sizes "4K,64K,1M,4M,16M"

# JSON output for scripting
engraver benchmark /dev/sdb --json

Benchmark Options

Option Description Default
--size Amount of data to write 256M
--block-size Block size for writes 4M
--pattern Data pattern: zeros, random, sequential zeros
--passes Number of benchmark passes 1
--test-block-sizes Test multiple block sizes (comma-separated) -

Note: --size and --test-block-sizes are mutually exclusive. All size values must be powers of 2, with block sizes limited to 64 MB maximum.

Warning: Benchmarking is a destructive operation that will overwrite data on the target device.

Safety

Engraver includes multiple safety mechanisms:

  1. System drive detection - Refuses to write to drives containing system partitions
  2. Removable-only by default - Only shows removable drives unless --all is specified
  3. Confirmation prompts - Requires explicit confirmation before writing
  4. Verification - Parallel write verification with --verify (hashes source during write, reads back to compare)

Development

Prerequisites

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Required Cargo Tools

These are used by pre-commit hooks and standard development workflows:

Tool Purpose Install
clippy Linter rustup component add clippy
rustfmt Code formatter rustup component add rustfmt

Pre-commit hooks are managed by cargo-husky and install automatically on cargo build or cargo test. They run cargo fmt --check, cargo clippy, and cargo test --lib.

Optional Cargo Tools

Tool Purpose Install
cargo-deny License compliance and dependency audit cargo install cargo-deny --locked
cargo-audit Security vulnerability scanning cargo install cargo-audit --locked
cargo-llvm-cov Code coverage cargo install cargo-llvm-cov --locked
cargo-fuzz Fuzz testing (requires nightly) cargo install cargo-fuzz --locked
cargo-sbom SBOM generation for releases cargo install cargo-sbom --locked

System Dependencies (optional)

Tool Purpose Install
musl-tools Static Linux binaries sudo apt-get install musl-tools
gcc-aarch64-linux-gnu ARM64 cross-compilation sudo apt-get install gcc-aarch64-linux-gnu
shellcheck Shell script linting sudo apt-get install shellcheck

Common Commands

# Run tests
cargo test

# Run clippy
cargo clippy -- -D warnings

# Check formatting
cargo fmt --check

# Build release
cargo build --release

# Run CLI
cargo r -- list

# Run benchmarks
cargo bench -p engraver-core

# Run fuzz targets (requires nightly)
cargo +nightly fuzz run fuzz_writer -p engraver-core

# Generate code coverage
cargo llvm-cov --html

# Audit dependencies
cargo deny check
cargo audit

License

MIT License - see LICENSE for details.

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages