# Deploy a Rust web app to a VPS with cargo, no Docker Deploy a Rust web app from a Cargo workspace to your own VPS: ox installs stable Rust, runs cargo build --release --locked, and starts the binary. To deploy a Rust web app to a VPS with ox, add the repo as a project and deploy it, with no Dockerfile and no ox.toml. ox reads `crates/api/Cargo.toml` and `Cargo.lock`, runs `cargo build --release --locked`, then starts `target/release/api` under systemd behind Caddy with HTTPS. Run `ox check` in your repo to see the same plan before the first deploy. **Plan verified, real-server test pending.** The plan below is what `ox check` prints for a minimal Rust repo in ox's tests. A deploy on a real server is not recorded yet. ox reads `crates/api/Cargo.toml` and `Cargo.lock`, builds the plan on the card, and starts `target/release/api` on your server. ## What ox detects in a Rust repo This is the plan `ox check` prints for a minimal a Rust web app in a Cargo workspace, with no ox.toml. Each row says where its value came from: a file in the repo, or ox's default. | Field | Value | Source | | --- | --- | --- | | `app.start` | `target/release/api` | `detected:crates/api/Cargo.toml` | | `build.commands[0]` | `cargo build --release --locked` | `detected:Cargo.lock` | | `tools.rust` | `stable` | `default` | ## The ox.toml for Rust None is needed: the plan above comes from the repo alone. Write one to serve your own domain or to change what ox detected. This one passes `ox check` against the same repo: `[app]` keeps the detected start command and build. ox.toml, optional: ```toml domains = ["api.example.com"] [app] ``` ## Check and deploy Rust Add the repo as a project, then check and ship it from a terminal: Check, deploy and read the logs: ```sh ox check # in the repo: the plan above, offline ox new --server # add the repo as a project ox deploy --wait # stream the deploy, exit with its result ox logs --follow # the app's own logs ``` ## Variables to set for Rust None before the first deploy: `ox check` asks for no variable. Add your own on the dashboard's Variables tab or with `ox vars set KEY`. ox provides these to the app itself: `PORT`, `HOST`, `OX_ENV`, `OX_PROJECT`, `OX_RELEASE`, `OX_DATA_DIR`, `PUBLIC_URL` and `PUBLIC_HOST`. ## If the Rust deploy fails - `several binaries in the Cargo workspace (api, worker); set [app] start = "target/release/" to the one to run`: Set `[app] start` to the binary to run; run another one as a worker. [More](https://deploywithox.com/docs/config#workers). - `killed by the out-of-memory killer (the build needs more memory than the project or host allows)`: The build ran out of memory. Raise the project's memory, add swap, or use a bigger server. [More](https://deploywithox.com/docs/troubleshooting#out-of-memory). - `TCP connect to 127.0.0.1:8001 did not answer within 120s: dial tcp 127.0.0.1:8001: connect: connection refused`: The app started but never answered on the port ox gave it. Listen on `127.0.0.1` at `$PORT`; the lines above the message are the app's own output. [More](https://deploywithox.com/docs/troubleshooting#health-check-failed). Your visitors never see a failed deploy: the previous release keeps serving until the new one passes its health check. ## Next steps - [The `[tools]` keys](https://deploywithox.com/docs/config#tools): pin a runtime version. - [The `[app]` keys](https://deploywithox.com/docs/config#app): start, health check, memory and the rest. - [Add a custom domain](https://deploywithox.com/docs/operate/domains) with one A record; Caddy gets the HTTPS certificate. - [Read the logs](https://deploywithox.com/docs/operate/logs) live, search them, or download them. - [Set variables and secrets](https://deploywithox.com/docs/operate/variables) on the dashboard or with `ox vars`. ## Rust FAQ ### Do I need a Dockerfile or an ox.toml to deploy a Rust web app to a VPS? No. ox does not use Docker, and `ox check` on a Rust repo with no ox.toml prints `Ready to deploy.` Write an ox.toml only to change what ox detected. ### What does ox install on the server for Rust? Only what the plan names: `rust stable` (ox's default). Your app's own dependencies are installed by the build into the release folder, not system-wide. ### Which binary does ox run in a workspace? The one binary in the workspace's members, here `target/release/api`. With several, `ox check` asks you to set `[app] start` to one. ## Related guides - [**React with Vite**Deploy a React app built with Vite to your own VPS with no Dockerfile: ox runs the build from your lockfile and Caddy serves dist over HTTPS, no ox.toml.](https://deploywithox.com/docs/guides/react-vite) - [**Create React App**Deploy a Create React App project to your own VPS: ox runs react-scripts build and Caddy serves the build folder over HTTPS. No Docker, no ox.toml.](https://deploywithox.com/docs/guides/create-react-app) Every stack ox deploys, and the ones it does not yet, is on the [Stacks page](https://deploywithox.com/docs/guides). Last updated 2026-10-09. The page as HTML: https://deploywithox.com/docs/guides/rust