# How Do I Set Up a Rust Dev Environment in a Cloud Sandbox?

> A new sandbox already has Rust 1.99.1 through rustup, so clone and run cargo build --release. On 2026-10-27 a clean release build of ripgrep 15.1.0 took a median 36.4 s on small, 19.5 s on default and 12.6 s on large, about $0.0002 each. Save the target directory in a named snapshot to skip rebuilds.

Source: https://sandboxer.com/guides/rust-dev-environment-in-a-cloud-sandbox. Updated 2026-10-27.

**Short answer:** A new sandbox already has Rust 1.99.1 through rustup, so clone and run cargo build --release. On 2026-10-27 a clean release build of ripgrep 15.1.0 took a median 36.4 s on small, 19.5 s on default and 12.6 s on large, about $0.0002 each. Save the target directory in a named snapshot to skip rebuilds.

We ran every command on this page on prod on 2026-10-27 between 11:06 and 11:17 UTC, in eu-central. The project is [BurntSushi/ripgrep](https://github.com/BurntSushi/ripgrep) at tag `15.1.0` (commit `af60c2d`): a real Cargo workspace with a `Cargo.lock`.

## Results

| Step | `small` (2 vCPU) | `default` (4 vCPU) | `large` (8 vCPU) |
| - | - | - | - |
| `cargo build --release`, empty registry and `target/` (3 runs) | 31.5, **36.4**, 38.3 s | 20.4, **19.5**, 19.3 s | 13.1, 11.9, **12.6** s |
| `cargo build --release`, warm registry, `cargo clean` first (3 runs) | 37.2, **38.2**, 38.4 s | 19.4, **18.8**, 18.0 s | 11.2, **11.3**, 11.4 s |
| Rebuild after `touch crates/core/main.rs` | 10.3 s | 6.1 s | 4.1 s |
| `cargo test`, first run (builds the debug profile, 443 tests) | 24.5 s | 12.2 s | 9.8 s |
| `cargo test`, second run | 2.7 s | 1.2 s | 0.9 s |
| From the named snapshot: `cargo build --release` / `cargo test` | (source) | **0.1 s** / 1.2 s | **0.1 s** / 0.9 s |
| `sbx new --from` the snapshot to ready | | 3.2 s | 3.2 s |

Medians are in bold. Every build used `-j` equal to the vCPU count, which is also Cargo's default. One fresh sandbox per size, run one after another. Other sandboxes on the shared account were running at the same time, and `lscpu` on the `small` sandbox showed an AMD Ryzen 9 7950X3D host. Your sandbox can land on a different machine, so treat these as one dated sample, not a guarantee.

What the numbers say:

- **The compile is the cost, not the download.** An empty registry was no slower than a warm one: the medians differ by less than run-to-run noise. ripgrep's crates are only 37 MB. On `small` the first cold run was even the shortest of all six.
- **More vCPUs help, but not linearly.** `default` was 1.9 times faster than `small`, and `large` 2.9 times. Parts of a Rust build, such as the final crate and the link step, can't be spread across cores. For per-core numbers see [CPU performance by sandbox size](/guides/cpu-performance-by-sandbox-size).
- **A snapshot with `target/` skips the build.** Cargo decides what to rebuild from file timestamps, and the snapshot keeps them. A sandbox started from it found nothing to rebuild, even on a bigger size.

## Price per build

Prices from our [pricing](/pricing), billed per second: `small` $0.018/hour, `default` $0.036/hour, `large` $0.072/hour. For the median clean release build:

| Size | Arithmetic | Cost per build | Per 1,000 builds |
| - | - | - | - |
| `small` | 36.4 s × $0.018 / 3600 | $0.000182 | $0.18 |
| `default` | 19.5 s × $0.036 / 3600 | $0.000195 | $0.20 |
| `large` | 12.6 s × $0.072 / 3600 | $0.000252 | $0.25 |

This counts build time only. Your sandbox also bills while you clone, test and copy files out. `large` costs about 38% more per build than `small` and finishes in about a third of the time. Pick it when someone is waiting on the result.

## 1. See what the sandbox already has

```bash
sbx new --name rust-dev --type small
sbx exec sb_pxma7ivcrc bash -lc "rustc -V; cargo -V; rustup toolchain list; du -sh ~/.rustup"
```

```text
rustc 1.99.1 (58cf8f9c3 2026-10-13)
cargo 1.99.1 (5f94df478 2026-08-27)
stable-x86_64-unknown-linux-gnu (active, default)
600M	/home/user/.rustup
```

The image also has `gcc` 13.3, which Cargo uses as the linker, plus `clippy`, `rustfmt` and `rust-analyzer`. Use `bash -lc` so the login `PATH` includes `~/.cargo/bin`. These are the versions on 2026-10-27; the image changes over time. The full list is in [What's pre-installed in a sandbox](/guides/whats-preinstalled-in-a-sandbox).

## 2. Pin a toolchain

To add a dated nightly:

```bash
sbx exec sb_pxma7ivcrc --timeout 300 bash -lc "rustup toolchain install nightly-2026-10-25 --profile minimal; rustup run nightly-2026-10-25 rustc -V"
```

```text
info: downloading self-update (new version: 1.29.2)
…
rustc 1.101.0-nightly (12433c307 2026-10-24)
```

That took 7.5 s, including a rustup self-update to 1.29.2.

To pin the project, add a `rust-toolchain.toml` file. One catch: the preinstalled toolchain is registered as `stable`, so pinning the same version by number downloads a second copy.

```bash
cd ~/ripgrep
printf '[toolchain]\nchannel = "1.99.1"\nprofile = "minimal"\n' > rust-toolchain.toml
rustc -V
rustup toolchain list
```

```text
info: you may opt out with `RUSTUP_AUTO_INSTALL=0` or `rustup set auto-install disable`
rustc 1.99.1 (58cf8f9c3 2026-10-13)
stable-x86_64-unknown-linux-gnu (default)
nightly-2026-10-25-x86_64-unknown-linux-gnu
1.99.1-x86_64-unknown-linux-gnu (active)
```

The first `rustc -V` took 7.4 s while rustup installed `1.99.1`. With both extra toolchains, `~/.rustup` grew from 600 MB to 1.8 GB. That matters on `small`, so pin `stable` if the preinstalled version is good enough. You can also install your pinned version once and save it in a snapshot (step 5).

## 3. Build and test a real workspace

```bash
sbx exec sb_pxma7ivcrc --timeout 120 bash -lc "git clone -q https://github.com/BurntSushi/ripgrep && cd ripgrep && git checkout -q 15.1.0 && git log -1 --format='%h %cs %s'"
```

```text
af60c2d 2025-10-22 15.1.0
```

A full build and test run can take longer than the 30-second default timeout of `sbx exec`. Run it in the background with `--detach` and poll. We timed each step with this script, copied into the sandbox with `sbx scp bench.sh sb_pxma7ivcrc:/home/user/`:

```bash
#!/bin/bash
# bench.sh JOBS RUNS
. ~/.cargo/env; cd ~/ripgrep; J=$1; R=${2:-1}
t() { local s=$(date +%s.%N); "$@" >/tmp/last.log 2>&1; local rc=$?; local e=$(date +%s.%N)
      printf '%s rc=%d %.1f s\n' "$LABEL" $rc $(awk "BEGIN{print $e-$s}"); tail -1 /tmp/last.log; }
for i in $(seq 1 $R); do rm -rf ~/.cargo/registry ~/.cargo/git target
  LABEL="cold build $i" t cargo build --release --locked -j $J; done
for i in $(seq 1 $R); do cargo clean -q
  LABEL="warm registry build $i" t cargo build --release --locked -j $J; done
LABEL="no-op build" t cargo build --release --locked -j $J
touch crates/core/main.rs
LABEL="touch main.rs build" t cargo build --release --locked -j $J
LABEL="cargo test first" t cargo test --locked -j $J
LABEL="cargo test again" t cargo test --locked -j $J
du -sh target ~/.cargo/registry ~/.rustup
```

```bash
sbx exec sb_pxma7ivcrc --detach "bash ~/bench.sh 2 3 > ~/bench-small.log 2>&1"
sbx exec sb_pxma7ivcrc "cat ~/bench-small.log"
```

```text
cold build 1 rc=0 31.5 s
    Finished `release` profile [optimized + debuginfo] target(s) in 31.47s
cold build 2 rc=0 36.4 s
…
touch main.rs build rc=0 10.3 s
cargo test first rc=0 24.5 s
cargo test again rc=0 2.7 s
676M	target
37M	/home/user/.cargo/registry
1.8G	/home/user/.rustup
```

All 443 tests passed. `--locked` makes Cargo fail rather than change `Cargo.lock`. ripgrep's `[profile.release]` sets `debug = 1`, so the release binary carries debug info.

### Disk used by `target/`

| Path | Size |
| - | - |
| `target/release` (release build) | 171 MB |
| `target/debug` (from `cargo test`) | 505 MB |
| `~/.cargo/registry` (downloaded crates) | 37 MB |
| `~/.rustup` (stable, plus 1.99.1 and a nightly) | 1.8 GB |

For ripgrep, `cargo test` adds three times as much disk as the release build. On a bigger workspace, `target/` is usually what fills a `small` disk first. `cargo clean` reclaims it.

## 4. Copy the binary out with `sbx scp`

```bash
sbx scp sb_pxma7ivcrc:/home/user/ripgrep/target/release/rg ./rg
./rg --version
```

```text
ripgrep 15.1.0 (rev af60c2de9d)
```

The 30.4 MB binary took 21 s to copy, and its SHA-256 matched the copy in the sandbox. Stripping the debug info first made it 5.3 MB and the copy took 6.4 s:

```bash
sbx exec sb_pxma7ivcrc bash -lc "cd ~/ripgrep && strip -o rg-stripped target/release/rg && ls -l rg-stripped"
sbx scp sb_pxma7ivcrc:/home/user/ripgrep/rg-stripped ./rg-stripped
```

```text
-rwxr-xr-x 1 user user 5281704 Oct 27 11:11 rg-stripped
```

The binary links against glibc from Ubuntu 24.04. It ran on our Linux x86-64 machine, but it won't run on macOS or on an older glibc. Build for those targets separately.

## 5. Save it as a named snapshot

```bash
sbx snapshot sb_pxma7ivcrc rust-rg
```

```text
{"ok":true,"type":"snapshot.named.info","snapshot":{…,"name":"rust-rg",…,"status":"ready","type":"small",…}}
```

The save took 2.1 s. It holds the toolchains, `~/.cargo/registry`, the clone and the 676 MB `target/`. We started bigger sandboxes from it:

```bash
sbx new --name rust-dev-2 --type default --from rust-rg
sbx exec sb_kr2r5rjeif --timeout 300 "bash ~/snap.sh 4"
```

```text
rustc 1.99.1 (58cf8f9c3 2026-10-13)
as saved: release build rc=0 0.1 s
    Finished `release` profile [optimized + debuginfo] target(s) in 0.07s
as saved: cargo test rc=0 1.2 s
passed 443 failed 0
```

`snap.sh` runs the same timed `cargo build --release` and `cargo test` as `bench.sh`. Cargo rebuilt nothing on the new 4-vCPU sandbox. The same was true on `large`. Going up in size from a snapshot works, but moving to a smaller size isn't supported yet, so build the snapshot on the smallest size you plan to use. To rebuild the snapshot when `Cargo.lock` changes, name it after the lockfile's hash as in [Cache dependencies in a named snapshot](/guides/cache-dependencies-in-a-named-snapshot).

We didn't test sccache or other shared compiler caches. Within one project, a snapshot with `target/` already skips the work they would save.

## FAQ

### Is Rust already installed in a Sandboxer sandbox?

Yes. On 2026-10-27 the image had rustc and cargo 1.99.1 as rustup's `stable` toolchain, plus clippy, rustfmt and rust-analyzer. Run `rustc -V` in your own sandbox, because the image is updated over time.

### Which sandbox size is the best value for Rust builds?

In our test `small` was cheapest per clean build ($0.000182) and `large` took the least time (12.6 s), at $0.000252 per build. Pick by whether someone is waiting. For repeat builds of the same project, a snapshot with `target/` saves more than any size.

### Should I set cargo -j to the number of vCPUs?

Cargo already defaults to the number of CPUs it sees, and `nproc` shows the size's vCPUs (2, 4 or 8 here). We passed `-j` explicitly only to keep the runs comparable.

### Does target/ survive sbx stop and sbx resume?

Yes. `target/`, `~/.cargo` and `~/.rustup` live under `/home/user` on the sandbox disk. Stop keeps the disk, and a named snapshot or fork copies it. Our snapshot test shows Cargo still treats the saved build as fresh.

### How do I get a long build's output if exec times out?

Start it with `sbx exec <id> --detach "…"`, which returns a process id. Then read its log with `sbx exec <id> --status <pid>` or follow it with `--attach <pid>`. Redirecting to a log file, as we did, also works.

## Related

- [Set up a Python dev environment in a cloud sandbox](/guides/python-dev-environment-in-a-cloud-sandbox)
- [CPU performance by sandbox size](/guides/cpu-performance-by-sandbox-size)
- [Cache dependencies in a named snapshot](/guides/cache-dependencies-in-a-named-snapshot)
- [Set up a Go dev environment in a cloud sandbox](/guides/go-dev-environment-in-a-cloud-sandbox)
