Now with support for Iron, Cargo and Cargo.lock!

You can deploy an example Rust application to Heroku using this button:

Deploy

If you’d prefer to use the command line, you’ll need git and the Heroku toolbelt. Once these are installed, run:

git clone https://github.com/emk/heroku-rust-cargo-hello.git
cd heroku-rust-cargo-hello
heroku create --buildpack https://github.com/emk/heroku-buildpack-rust.git
git push heroku master

This will download the example application, create a new Heroku project, and deploy the code to Heroku. That’s it!

How it works

Our server is based on the Iron middleware library. We parse URL parameters and dispatch HTTP requests to the appropriate handler routine using Iron’s router module:

fn main() {
    let mut router = Router::new();
    router.get("/", hello);
    router.get("/:name", hello_name);
    Iron::new(router).listen(Ipv4Addr(0, 0, 0, 0), get_server_port());
}

The hello function returns an HTTP status code and the content to send to the user:

fn hello(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with(status::Ok, "Hello world!"))
}

The hello_name function is similar, but we look up the value of the :name parameter that we declared to the router, above.

fn hello_name(req: &mut Request) -> IronResult<Response> {
    let params = req.extensions.find::<Router,Params>().unwrap();
    let name = params.find("name").unwrap();
    Ok(Response::with(status::Ok, format!("Hello, {}!", name)))
}

The final piece needed to run on Heroku is a function to look up up our port number:

fn get_server_port() -> Port {
    getenv("PORT")
        .and_then(|s| from_str::<Port>(s.as_slice()))
        .unwrap_or(8080)
}

The full source code is available on GitHub. To learn more about Rust, see the excellent Rust guide.

Keep reading for notes on building the program locally and on configuring your own programs to run on Heroku.

Building the program locally

First, check to see if the example program builds against the latest version of Rust:

Build Status

If the build status is green: You should be able to install Rust, build the program, and run it as follows:

curl -s https://static.rust-lang.org/rustup.sh | sudo sh
cargo update
cargo build
PORT=5000 target/hello

Then visit 0.0.0.0:5000 and 0.0.0.0:5000/user in your browser.

(The rustup.sh script needs root access to your machine, so all the usual caveats apply. At least it’s served over SSL, and in any case, you were already going to be trusting the Rust developers enough to install their compiler. You can find other installation options on the Rust website.)

Once you verify that everything works with the latest Rust, you will probably also want to put your Rust binaries somewhere that Heroku can find them, and update your RustConfig. The easiest way to do this is using the update-bin.sh script:

./update-bin.sh my-s3-bucket-name

If the build status is red: You will either need to update the example program for the latest Rust, or you will need to download an older version of Rust and Cargo from the URLs list in the included RustConfig file and omit the rustup.sh and cargo update steps. The Rust language is still changing, but a Rust 1.0 release is planned for the end of 2014.

Configuring other projects for Heroku

First, set up your project with Cargo.toml and Cargo.lock as described in the Rust guide. You also need to create a Heroku project with the appropriate buildpack:

cd my-rust-project
heroku create --buildpack https://github.com/emk/heroku-buildpack-rust.git

Then, all you need to do is add a Procfile, which tells Heroku how to launch your project:

web: ./target/hello

…and a RustConfig file pointing at copies of the appropriate nightly tarballs:

URL="https://s3.amazonaws.com/rust-builds/2014-09-17/rust-nightly-x86_64-unknown-linux-gnu.tar.gz"
VERSION="2014-09-17"

CARGO_URL="https://s3.amazonaws.com/rust-builds/2014-09-17/cargo-nightly-x86_64-unknown-linux-gnu.tar.gz"
CARGO_VERSION="2014-09-17"

Make sure that your program listens on the port specified by the environment variable PORT, as demonstrated in the example program. Now you can commit these files and deploy to Heroku:

git push heroku master

A big thank you to Alex Crichton for helping debug various Cargo issues, and to the good folks at Heroku for their offers of help. And thanks to Chris Morgan and Huon Wilson for their help with the earliest versions of this code. If this breaks, please don’t hesitate to get in touch!