Install
Ursula is currently installed from source. Pre-built release binaries are on the way. The build is plain Rust plus the standard C toolchain that Cargo expects — no embedded KV dependency.
Ursula ships two binaries you will use side by side:
ursula— the server daemon. Runs on every node in the cluster.ursulactl— the operator CLI. Lives on your control machine and talks to each node's HTTP surface. See ursulactl for the verbs it exposes.
Prerequisites
Required:
- the pinned Rust nightly toolchain from
rust-toolchain.tomland Cargo - a C compiler (for transitive native crates)
pkg-config
On macOS, install rustup so Cargo selects the pinned nightly from rust-toolchain.toml:
brew install rustup pkg-config
rustup-init -y
On Debian or Ubuntu:
sudo apt-get update
sudo apt-get install -y build-essential pkg-config curl
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Clone and build
git clone https://github.com/tonbo-io/ursula.git
cd ursula
cargo build --release -p ursula -p ursula-ctl
The resulting binaries land at target/release/ursula and target/release/ursulactl. Ship ursula to every node; keep ursulactl wherever you run operational tooling (laptop, CI runner, bastion host).
To work on the whole workspace:
cargo build --workspace
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
cargo build --workspace compiles every crate. For just the server use cargo build -p ursula; for just the CLI use cargo build -p ursula-ctl.
Verify
./target/release/ursula --help
./target/release/ursulactl --help
Both should print supported CLI flags. From the repository root, ./target/release/ursula --preset default still performs config-file discovery and will load ./ursula.toml when present. Use that command when you want the bundled ./ursula.toml with the default preset; for a true no-file smoke test, run from a directory with no Ursula config file or temporarily move/rename ./ursula.toml first.
./target/release/ursula --preset default &
For a single local node, ursulactl needs a one-node manifest to talk to:
cat > /tmp/local.json <<'JSON'
{"nodes": [{"id": 1, "http_url": "http://127.0.0.1:4437", "host": "127.0.0.1"}]}
JSON
./target/release/ursulactl status --config /tmp/local.json
Or, for a quick eyeball without writing a manifest, hit the HTTP surface directly:
curl -X PUT http://127.0.0.1:4437/demo
curl -X PUT http://127.0.0.1:4437/demo/hello
curl -X POST -H 'Content-Type: text/plain' --data 'hi' http://127.0.0.1:4437/demo/hello
curl 'http://127.0.0.1:4437/demo/hello?offset=-1'
Kill the background process when you're done.
Next
- Quick start — drive the HTTP API end-to-end
- Run locally — durability modes and flags
- Deploy a cluster — static gRPC Raft cluster
- ursulactl — the verbs you'll use once the cluster is up
- Configure S3 — shared cold storage