| Crates.io | rustpatcher |
| lib.rs | rustpatcher |
| version | 0.2.2 |
| created_at | 2025-03-05 21:50:32.541891+00 |
| updated_at | 2025-10-26 09:53:37.117679+00 |
| description | distributed patching system for single binary applications |
| homepage | https://rustonbsd.github.io/ |
| repository | https://github.com/rustonbsd/rustpatcher |
| max_upload_size | |
| id | 1579865 |
| size | 179,174 |
Secure fully decentralized software updates.
| Platform | Architecture | Supported |
|---|---|---|
| Linux | x86_64 | Yes |
| Linux | ARM64 | Yes |
| macOS | x86_64 | Yes |
| macOS | ARM64 | Yes |
| Windows | - | Not yet |
Note: windows support will follow, windows build err: libc is not available in nix pkg
# Cargo.toml
[dependencies]
rustpatcher = "0.2"
rustpatcher-macros = "0.2"
tokio = { version = "1", features = ["rt-multi-thread","macros"] }
#[tokio::main]
#[rustpatcher::public_key("axegnqus3miex47g1kxf1j7j8spczbc57go7jgpeixq8nxjfz7gy")]
async fn main() -> anyhow::Result<()> {
// Only in --release builds, not intended for debug builds
rustpatcher::spawn(rustpatcher::UpdaterMode::At(13, 40)).await?;
println!("my version is {:?}", rustpatcher::Version::current()?);
// your app code after this
tokio::select! {
_ = tokio::signal::ctrl_c() => {
println!("Exiting on Ctrl-C");
}
}
Ok(())
}
cargo install rustpatcher
rustpatcher gen ./owner_key
Output includes:
# build your binary
cargo build --release
# sign the compiled binary in-place
rustpatcher sign target/release/<your-bin> --key-file=./owner_key
Run the newly signed binary on at least one node until a couple of peers have updated themselfs.
The running process periodically publishes the latest PatchInfo to the DHT.
Clients discover new PatchInfo, fetch the patch from peers, verify, and self-replace.
git clone https://github.com/rustonbsd/rustpatcher
cd rustpatcher
cargo build --release --example simple
cargo run --bin rustpatcher sign target/release/examples/simple --key-file ./owner_key_example
# Run signed app:
./target/release/examples/simple
# if you increase the version in /crates/rustpatcher/Cargo.toml
# and build+sign+start another node, then the first
# node will update via the second node.
sequenceDiagram
participant Owner as Owner Node (new version)
participant DTT as DHT Topic Tracker
participant Peer as Peer Node (old)
Owner->>DTT: Publish PatchInfo(version, size, hash, sig)
Peer->>DTT: Query latest PatchInfo (minute slots)
DTT-->>Peer: Return newest records
Peer->>Owner: Iroh connect (ALPN /rustpatcher/<owner>/v0)
Peer->>Owner: Auth = sha512(pubkey || unix_minute)
Owner-->>Peer: OK + Patch (postcard)
Peer->>Peer: Verify(hash, size, ed25519(pubkey))
Peer->>Peer: Atomic replace + optional execv restart
At runtime, the library:
DO NOT COMMIT YOUR PRIVATE KEY!
# add this to your .gitignore
owner_key*
Notes:
use rustpatcher::UpdaterMode;
#[tokio::main]
#[rustpatcher::public_key("axegnqus3miex47g1kxf1j7j8spczbc57go7jgpeixq8nxjfz7gy")]
async fn main() -> anyhow::Result<()> {
rustpatcher::spawn(UpdaterMode::At(02, 30)).await?;
// app code...
Ok(())
}
build:
cargo build --release
rustpatcher sign target/release/<your-bin> --key-file ./owner_key
publish:
target/release/<your-bin>