A buildpack for Rust applications on Heroku, with full support for Rustup, cargo and build caching.

Overview

Heroku buildpack for Rust

Build Status

This is a Heroku buildpack for Rust with support for cargo and rustup. Features include:

  • Caching of builds between deployments.
  • Automatic updates to the latest stable Rust by default.
  • Optional pinning of Rust to a specific version.
  • Support for export so that other buildpacks can access the Rust toolchain.
  • Support for compiling Rust-based extensions for projects written in other languages.

Example projects

Here are several example projects:

Using this buildpack

To deploy an application to Heroku, we recommend installing the Heroku CLI.

If you're creating a new Heroku application, cd to the directory containing your code, and run:

heroku create --buildpack emk/rust

This will only work if your application has a Cargo.toml and uses git. If you want to set a particular name for application, see heroku create --help first.

To use this as the buildpack for an existing application, run:

heroku buildpacks:set emk/rust

You will also need to create a Procfile pointing to the release version of your application, and commit it to git:

web: ./target/release/hello

...where hello is the name of your binary.

To deploy your application, run:

git push heroku master

Running Diesel migrations during the release phase

This will install the diesel CLI at build time and make it available in your dyno. Migrations will run whenever a new version of your app is released. Add the following line to your RustConfig

RUST_INSTALL_DIESEL=1

and this one to your Procfile

release: ./target/release/diesel migration run

Specifying which version of Rust to use

By default, your application will be built using the latest stable Rust. Normally, this is pretty safe: New stable Rust releases have excellent backwards compatibility.

But you may wish to use nightly Rust or to lock your Rust version to a known-good configuration for more reproducible builds. To specify a specific version of the toolchain, use a rust-toolchain file in the format rustup uses.

Note: if you previously specified a VERSION variable in RustConfig, that will continue to work, and will override a rust-toolchain file.

Combining with other buildpacks

If you have a project which combines both Rust and another programming language, you can insert this buildpack before your existing one as follows:

heroku buildpacks:add --index 1 emk/rust

If you have a valid Cargo.toml in your project, this is all you need to do. The Rust buildpack will run first, and your existing buildpack will run second.

But if you only need Rust to build a particular Ruby gem, and you have no top-level Cargo.toml file, you'll need to let the buildpack know to skip the build stage. You can do this by adding the following line to RustConfig:

RUST_SKIP_BUILD=1

Customizing build flags

If you want to change the cargo build command, you can set the RUST_CARGO_BUILD_FLAGS variable inside the RustConfig file.

RUST_CARGO_BUILD_FLAGS="--release -p some_package --bin some_exe --bin some_bin_2"

The default value of RUST_CARGO_BUILD_FLAGS is --release. If the variable is not set in RustConfig, the default value will be used to build the project.

Using the edge version of the buildpack

The emk/rust buildpack from the Heroku Registry contains the latest stable version of the buildpack. If you'd like to use the latest buildpack code from this Github repository, you can set your buildpack to the Github URL:

heroku buildpacks:set https://github.com/emk/heroku-buildpack-rust

Development notes

If you need to tweak this buildpack, the following information may help.

Testing with Docker

To test changes to the buildpack using the included docker-compose-test.yml, run:

./test_buildpack

Then make sure there are no Rust-related *.so files getting linked:

ldd heroku-rust-cargo-hello/target/release/hello

This uses the Docker image heroku/cedar, which allows us to test in an official Cedar-like environment.

We also run this test automatically on Travis CI.

Comments
  • Export Rust build environment for use by other buildpacks

    Export Rust build environment for use by other buildpacks

    See #9. The theory here is that we might have a Ruby application that uses a gem implemented in Rust, and in order to compile the gem, the Ruby buildpack needs access to the Rust compiler.

    To support this, we need to create an export file in our buildpack directory containing all the environment variables needed to run cargo and rustc.

    Note that this still has some limitations: You almost certainly need to have a valid Cargo.toml in your project for the buildpack to detect and build before you can run the other buildpack that needs Rust.

    • CC @binarycleric Feel free to take a look at this and let me know what you think.
    • CC @schneems @elifoster Please let me know if this works for your use cases.

    To try this, I think you can run heroku buildpacks:set https://github.com/emk/heroku-buildpack-rust#multirust_export and redeploy. But please set it back when you're done, because I'll delete the branch when I merge it.

    opened by emk 20
  • Ruby/Rust ld cannot find lruby

    Ruby/Rust ld cannot find lruby

    I've built a Ruby/Rust hello application, but it does not want to deploy to Heroku. @schneems

    remote:        Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
    remote:        
    remote:        current directory: /tmp/build_b49520d155f32d44a5ec710ef7b84985/vendor/bundle/ruby/2.3.0/gems/string-utility-2.7.3/ex
    remote:        /tmp/build_b49520d155f32d44a5ec710ef7b84985/vendor/ruby-2.3.0/bin/ruby -r ./siteconf20160926-228-cc92i.rb extconf.rb
    remote:        cargo 0.12.0-nightly (6b98d1f 2016-07-04)
    remote:        rustc 1.11.0 (9b21dcd6a 2016-08-15)
    remote:        
    remote:        current directory: /tmp/build_b49520d155f32d44a5ec710ef7b84985/vendor/bundle/ruby/2.3.0/gems/string-utility-2.7.3/ex
    remote:        make "DESTDIR=" clean
    remote:        rm -rf target
    remote:        
    remote:        current directory: /tmp/build_b49520d155f32d44a5ec710ef7b84985/vendor/bundle/ruby/2.3.0/gems/string-utility-2.7.3/ex
    remote:        make "DESTDIR="
    remote:        cargo build --release
    remote:        Updating registry `https://github.com/rust-lang/crates.io-index`
    remote:        Downloading ruru v0.7.8
    remote:        Downloading ruby-sys v0.2.13
    remote:        Downloading libc v0.2.16
    remote:        Compiling ruby-sys v0.2.13
    remote:        Compiling libc v0.2.16
    remote:        Compiling ruru v0.7.8
    remote:        Compiling string-utility-rb-native v1.0.0 (file:///tmp/build_b49520d155f32d44a5ec710ef7b84985/vendor/bundle/ruby/2.3.0/gems/string-utility-2.7.3/ext)
    remote:        src/lib.rs:4:12: 4:21 warning: unused import, #[warn(unused_imports)] on by default
    remote:        src/lib.rs:4 use ruru::{AnyObject, Class, RString, VM};
    remote:        ^~~~~~~~~
    remote:        src/lib.rs:4:39: 4:41 warning: unused import, #[warn(unused_imports)] on by default
    remote:        src/lib.rs:4 use ruru::{AnyObject, Class, RString, VM};
    remote:        ^~
    remote:        src/lib.rs:5:19: 5:23 warning: unused import, #[warn(unused_imports)] on by default
    remote:        src/lib.rs:5 use ruru::types::{Argc, Value};
    remote:        ^~~~
    remote:        src/lib.rs:5:25: 5:30 warning: unused import, #[warn(unused_imports)] on by default
    remote:        src/lib.rs:5 use ruru::types::{Argc, Value};
    remote:        ^~~~~
    remote:        src/lib.rs:6:5: 6:25 warning: unused import, #[warn(unused_imports)] on by default
    remote:        src/lib.rs:6 use ruru::traits::Object;
    remote:        ^~~~~~~~~~~~~~~~~~~~
    remote:        error: linking with `cc` failed: exit code: 1
    remote:        note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/app/tmp/cache/multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/tmp/build_b49520d155f32d44a5ec710ef7b84985/vendor/bundle/ruby/2.3.0/gems/string-utility-2.7.3/ext/target/release/stringutility.0.o" "-o" "/tmp/build_b49520d155f32d44a5ec710ef7b84985/vendor/bundle/ruby/2.3.0/gems/string-utility-2.7.3/ext/target/release/libstringutility.so" "/tmp/build_b49520d155f32d44a5ec710ef7b84985/vendor/bundle/ruby/2.3.0/gems/string-utility-2.7.3/ext/target/release/stringutility.metadata.o" "-Wl,-O1" "-nodefaultlibs" "-L" "/tmp/build_b49520d155f32d44a5ec710ef7b84985/vendor/bundle/ruby/2.3.0/gems/string-utility-2.7.3/ext/target/release" "-L" "/tmp/build_b49520d155f32d44a5ec710ef7b84985/vendor/bundle/ruby/2.3.0/gems/string-utility-2.7.3/ext/target/release/deps" "-L" "/app/vendor/ruby-2.3.1/lib" "-L" "/app/tmp/cache/multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "-Wl,-Bdynamic" "-Wl,--whole-archive" "/tmp/rustc.q8eAleDtOvmp/libruru-35c12ee1cec9de02.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.q8eAleDtOvmp/libruby_sys-a3c0096998cfe6fb.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.q8eAleDtOvmp/liblibc-1417726cb94dbc83.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.q8eAleDtOvmp/libstd-39b92f95.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.q8eAleDtOvmp/libpanic_unwind-39b92f95.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.q8eAleDtOvmp/libunwind-39b92f95.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.q8eAleDtOvmp/librand-39b92f95.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.q8eAleDtOvmp/libcollections-39b92f95.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.q8eAleDtOvmp/librustc_unicode-39b92f95.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.q8eAleDtOvmp/liballoc-39b92f95.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.q8eAleDtOvmp/liballoc_system-39b92f95.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.q8eAleDtOvmp/liblibc-39b92f95.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.q8eAleDtOvmp/libcore-39b92f95.rlib" "-Wl,--no-whole-archive" "-l" "ruby" "-l" "util" "-l" "dl" "-l" "pthread" "-l" "gcc_s" "-l" "pthread" "-l" "c" "-l" "m" "-l" "rt" "-l" "util" "-shared" "-l" "compiler-rt"
    remote:        note: /usr/bin/ld: cannot find -lruby
    remote:        collect2: error: ld returned 1 exit status
    remote:        
    remote:        error: aborting due to previous error
    remote:        error: Could not compile `string-utility-rb-native`.
    remote:        
    remote:        To learn more, run the command again with --verbose.
    remote:        make: *** [all] Error 101
    remote:        
    remote:        make failed, exit code 2
    remote:        
    remote:        Gem files will remain installed in /tmp/build_b49520d155f32d44a5ec710ef7b84985/vendor/bundle/ruby/2.3.0/gems/string-utility-2.7.3 for inspection.
    remote:        Results logged to /tmp/build_b49520d155f32d44a5ec710ef7b84985/vendor/bundle/ruby/2.3.0/extensions/x86_64-linux/2.3.0-static/string-utility-2.7.3/gem_make.out
    remote:        An error occurred while installing string-utility (2.7.3), and Bundler cannot
    remote:        continue.
    remote:        Make sure that `gem install string-utility -v '2.7.3'` succeeds before bundling.
    
    opened by elifoster 17
  • Updated buildpack to use rustup.sh

    Updated buildpack to use rustup.sh

    Previously this buildpack was trying to download and install rust manually which caused many stdlibs to be missing. Rust provides a script to automate a bunch of the install processes and switching to this greatly simplified the buildpack.

    I tried it on a test app using iron and everything seemed to work correctly (https://github.com/binarycleric/resume-api). Forgive any bad code in that repo, I'm still learning Rust.

    opened by binarycleric 16
  • Not able to build nightly

    Not able to build nightly

    When I specify the buildpack to use nightly, I get this on heroku:

    -----> Rust app detected
    -----> Downloading rustup
    -----> Using rustup to install Rust channel nightly
    info: downloading installer
    error: invalid toolchain name: 'nightly
     !     Push rejected, failed to compile Rust app.
     !     Push failed
    
    opened by marvin-bitterlich 12
  • Avoid copying non-executable files into BUILD_DIR

    Avoid copying non-executable files into BUILD_DIR

    This does not rely upon any Rust toolchain support, but rather upon the good old find program. Thus, it copies all executables in $CARGO_TARGET_DIR/release, rather than any specifically-named executable file.

    In short, this is a somewhat hacky method for circumnavigating #17.

    opened by mmirate 12
  • Remove build artifacts after the build process?

    Remove build artifacts after the build process?

    Heroku has a limit of 300 MB for the slug size (ie. the output of the build process).

    Unfortunately I've run into an annoying problem this morning, which is that running cargo build --release creates a target directory that weights 310 MB, though the actual binary itself is only 41 MB.

    Heroku's docs suggest that you use a .slugignore file (similar to a .gitignore). However the files that match .slugignore are removed before the build process, so it's useless in my situation.

    I don't know if you have a solution to suggest for me and people who run in the same situation as me? Removing the /target/release/deps in the buildpack would be nice, but as I'm not familiar with heroku's caching process I don't know if it's a good idea to do so.

    opened by tomaka 9
  • Use rust-toolchain instead of RustConfig

    Use rust-toolchain instead of RustConfig

    Something pretty similar to this is currently powering rusty-dash.com after I moved it over to Heroku last night/this morning. I think it should be backwards compatible with RustConfig's VERSION setup as well.

    Fixes https://github.com/emk/heroku-buildpack-rust/issues/11

    opened by anp 7
  • Ruby application with Rust dependencies

    Ruby application with Rust dependencies

    I've got a gem, string-utility, which is written in Rust using ruru for a few of its methods. I am trying to use this buildpack to install Rust and Cargo (without running cargo build, I can just fork the project and remove that tiny amount of code since it's a pretty uncommon desire at this point I'd imagine). However, it seems, even if the Rust buildpack runs successfully, Bundler is unable to find cargo or rustc to compile string-utility's Rust code. There was a similar question #6, except that question was regarding a project that was written with Node and Rust, not Node with Rust dependencies. In other words, it actually wanted to compile Rust code, then run Node separately. I've been trying to figure this out through experimentation and talking with Heroku support, and I've been unsuccessful for about 3 weeks. The majority of my projects depend on this library, and chances are, once I figure this out, many of my other libraries are going to be rewritten partially in Rust.

    I'm not really sure how to briefly ask what I'm trying to ask here. I suppose:

    • Is using this buildpack the correct way to get Rust/Cargo installed on a Heroku project?
    • If so, how can I get it to install such that Bundler can actually find it, or is that a bug in the buildpack?

    My buildpack order: 1. emk/heroku-buildpack-rust, 2. heroku/ruby

    opened by elifoster 7
  • Allow SSH into private GH repo

    Allow SSH into private GH repo

    This line is one copied from a PR I found 2 years ago that never was merged. It is really awesome as it allows this buildpack to talk with a private GH repo in conjunction with this buildpack: https://github.com/heroku/heroku-buildpack-ssh-key.git

    opened by hwsimmons17 6
  • Build is failing, need help to figure this out

    Build is failing, need help to figure this out

    Build log on Heroku is :

    -----> Rust app detected
    -----> Downloading rustup
    -----> Using rustup to install Rust channel beta
    info: downloading installer
    error: invalid toolchain name: 'beta
     !     Push rejected, failed to compile Rust app.
     !     Push failed
    

    So, why is it 'beta instead of beta?

    RustConfig : VERSION="beta"

    If you need more info, I can give it! Thanks for the help!

    opened by king-numsgil 6
  • Fix missing rust libs problems, improve caching and refactor compile steps

    Fix missing rust libs problems, improve caching and refactor compile steps

    • I had a problem when running compiled app on heroku: it wasn't able to find libnative library which is a part of rustc libs directory. After inspecting a slug I understood, that it has no build cache when dyno is running. Resolved issue by copying these libs inside of build directory and sourcing proper LD_LIBRARY_PATH.
    • It was a pain to wait for dependencies to be re-downloaded through git and rebuilt from scratch at each deploy. So I put build artifacts (target and $cargo_home) to cache, and on next builds reusing it, so Cargo can decide what to download and what to rebuild on any updates in Cargo.lock file. Turns out that .git folders in cache survive between build perfectly.
    • Since bin/compile is too bloated, I have refactored it to different bin/steps/* and call them from bin/compile.
    opened by waterlink 6
  • Cope with CARGO_HOME existing, but not rustup

    Cope with CARGO_HOME existing, but not rustup

    Was upgrading an app that used https://github.com/Hoverbear/heroku-buildpack-rust before and got the error

    -----> Checking for new releases of Rust stable channel        
    /tmp/buildpacks/custom/bin/compile: line 107: rustup: command not found  
    

    This fixes the rustup detection

    opened by palfrey 0
  • Change

    Change "find" command to find example binaries

    When building with cargo build --example whatever, cargo places the resulting binary into target/release/examples/whatever. The find command's argument, maxdepth is set at 1, which excluded the examples directory. Changing this to 2 lets find look into the example directory.

    opened by mateocabanal 0
  • Make (certain) environment variables available at build time

    Make (certain) environment variables available at build time

    Thought adding a general prefix to identify the variables wanted was simplest. Response to issue #25.

    User sets Config Var for their Heroku application using the BUILDVAR_ prefix. These variables get exported similar to the DATABASE_URL for Diesel functionality.

    $ heroku config:set BUILDVAR_KEY=mysecret
    

    First time doing a contribution so please excuse but note any technical misses.

    opened by jrc-dev3 0
  • Add support for Trunk

    Add support for Trunk

    Hi, buildpack newbie here, so please apologise if I'm mistaken.

    I believe a Rust buildpack should support Trunk, the application bundler recommended for Yew - a rather popular WASM framework.

    Thanks!

    opened by holubond 0
  • Support for `WEB_CONCURRENCY`

    Support for `WEB_CONCURRENCY`

    This buildpack doesn't set the WEB_CONCURRENCY environment variable. For example, the official Python buildpack sets it. I'm guessing that this is set by Heroku themselves, and the buildpacks just expose it. Here's a link that mentions the use of WEB_CONCURRENCY for Python.

    Could you look into this, and add support if it's feasible and makes sense for Rust servers?

    opened by rharish101 0
Owner
Eric Kidd
Eric Kidd
Habitat is open source software that creates platform-independent build artifacts and provides built-in deployment and management capabilities.

Habitat is open source software that creates platform-independent build artifacts and provides built-in deployment and management capabilities. The go

Habitat 2.4k Dec 27, 2022
Valheim Docker powered by Odin. The Valheim dedicated gameserver manager which is designed with resiliency in mind by providing automatic updates, world backup support, and a user friendly cli interface.

Valheim Docker If you are looking for a guide on how to get started click here Mod Support! It is supported to launch the server with BepInEx but!!!!!

Michael 657 Dec 30, 2022
⚪️ `wasm-pack build` executed in remote deployment

rsw-node wasm-pack build executed in remote deployment, use with vite-plugin-rsw. Pre-installed rust nodejs wasm-pack: npm install -g wasm-pack vite-p

Len C... 10 Jul 6, 2022
Docker images for compiling static Rust binaries using musl-libc and musl-gcc, with static versions of useful C libraries. Supports openssl and diesel crates.

rust-musl-builder: Docker container for easily building static Rust binaries Source on GitHub Changelog UPDATED: Major updates in this release which m

Eric Kidd 1.3k Jan 1, 2023
oci-image and oci-runtime spec in rust.

oci-lib Oci-Spec for your container runtime or container registry. Oci-lib is a rust port for original oci spec written in go. Following crate contain

flouthoc 12 Mar 10, 2022
Rust Kubernetes client and controller runtime

kube-rs Rust client for Kubernetes in the style of a more generic client-go, a runtime abstraction inspired by controller-runtime, and a derive macro

kube-rs 1.8k Jan 8, 2023
An infrastructure-as-code and deployment tool for Roblox.

Rocat ?? An infrastructure-as-code and deployment tool for Roblox. ⚠ Please note that this is an early release and the API is unstable. Releases follo

Blake Mealey 45 Dec 29, 2022
An infrastructure-as-code and deployment tool for Roblox.

Mantle ?? An infrastructure-as-code and deployment tool for Roblox. ⚠ Please note that this is an early release and the API is unstable. Releases foll

Blake Mealey 44 Dec 22, 2022
Desktop launcher to install and use Holochain apps locally

Holochain Launcher A cross-platform executable that launches a local Holochain conductor, and installs and opens apps. Feedback is immensely welcome i

Holochain 58 Dec 30, 2022
Tool to monitor the statistics and the energy consumption of docker containers

Docker Activity Docker activity is a tool to monitor the statistics of your containers and output their energy consumption. Warning It's still in earl

Jérémie Drouet 39 Dec 6, 2022
Qovery Engine is an open-source abstraction layer library that turns easy apps deployment on AWS, GCP, Azure, and other Cloud providers in just a few minutes.

Qovery Engine is an open-source abstraction layer library that turns easy apps deployment on AWS, GCP, Azure, and other Cloud providers in just a few minutes.

Qovery 1.9k Jan 4, 2023
Runc - CLI tool for spawning and running containers according to the OCI specification

runc Introduction runc is a CLI tool for spawning and running containers on Linux according to the OCI specification. Releases You can find official r

Open Container Initiative 9.9k Jan 5, 2023
Containerize your development and continuous integration environments. 🥂

Toast ?? Toast is a tool for doing work in containers. You define tasks in a YAML file called a toastfile, and Toast runs them in a containerized envi

Stephan Boyer 1.4k Dec 27, 2022
Inspect and dump OCI images.

reinlinsen ?? rl is a tool to inspect and dump OCI images or single image layers. Installation From source If you have cargo installed you can just ru

Tobias Brumhard 5 May 11, 2023
docker-rust — the official Rust Docker image

About this Repo This is the Git repo of the Docker official image for rust. See the Docker Hub page for the full readme on how to use this Docker imag

The Rust Programming Language 321 Dec 11, 2022
Very small rust docker image

mini-docker-rust Very small rust docker image. This is an example project on how to build very small docker images for a rust project. The resulting i

null 155 Jan 1, 2023
Docker images for compiling static Rust binaries using musl-cross

rust-musl-cross Docker images for compiling static Rust binaries using musl-cross-make, inspired by rust-musl-builder Prebuilt images Currently we hav

messense 365 Dec 30, 2022
A wasm template for Rust to publish to gh-pages without npm-deploy

Wasm template for Rust hosting without npm-deploy on github pages using Travis script It automatically hosts you wasm projects on gh-pages using a tra

Siddharth Naithani 102 Dec 24, 2022
App Engine Rust boilerplate

Rust App Engine This projects is a minimal boilerplate ro run Rust web application inside Google App Engine. To deploy it use Google Cloud Shell: ```s

Denis Kolodin 48 Apr 26, 2022