Taking Spin for a spin

Let’s get Spin and take it from nothing to a “hello world” application!

Install Spin

Download the spin binary along with a starter set of templates and plugins using the install.sh script hosted on this site:

$ curl -fsSL https://developer.fermyon.com/downloads/install.sh | bash

Then move the spin binary somewhere in your path, so you can run it from anywhere. For example:

$ sudo mv ./spin /usr/local/bin/spin

See more options for installing Spin.

Install the Prerequisites

Install a Template

If you used the installer script above, the templates are already installed, and you can skip this section!

The quickest and most convenient way to start a new application is to install and use a Spin template for your preferred language.

$ spin templates install --git https://github.com/fermyon/spin --update
Copying remote template source
Installing template redis-rust...
Installing template http-rust...
... other templates omitted ...
+------------------------------------------------------------------------+
| Name                Description                                        |
+========================================================================+
| ... other templates omitted ...                                        |
| http-rust           HTTP request handler using Rust                    |
| redis-rust          Redis message handler using Rust                   |
| ... other templates omitted ...                                        |
+------------------------------------------------------------------------+

Note: The Rust templates are in a repo that contains several other languages; they will all be installed together.

Install the Tools

Some languages require additional tool support for Wasm:

You’ll need the wasm32-wasi target for Rust:

$ rustup target add wasm32-wasi

Learn more in the language guide.

Create Your First Application

sample
Cloud GitHub
sample
Cloud GitHub
template
Cloud GitHub

Now you are ready to create your first Spin application:

Use the spin new command and the http-rust template to scaffold a new Spin application:

$ spin new
Pick a template to start your application with:
  http-c (HTTP request handler using C and the Zig toolchain)
  http-csharp (HTTP request handler using C# (EXPERIMENTAL))
  http-go (HTTP request handler using (Tiny)Go)
  http-grain (HTTP request handler using Grain)
> http-rust (HTTP request handler using Rust)
  http-swift (HTTP request handler using SwiftWasm)
  http-zig (HTTP request handler using Zig)
  redis-go (Redis message handler using (Tiny)Go)
  redis-rust (Redis message handler using Rust)

Enter a name for your new application: hello_rust
Project description: My first Rust Spin application
HTTP path: /...

This command created a directory with the necessary files needed to build and run a Rust Spin application. Change to that directory, and look at the files. It looks very much like a normal Rust library project:

$ cd hello_rust
$ tree
.
├── .gitignore
├── Cargo.toml
├── spin.toml
└── src
    └── lib.rs

The additional spin.toml file is the manifest file, which tells Spin what events should trigger what components. In this case our trigger is HTTP, for a Web application, and we have only one component, at the route /.... This is a wildcard that matches any route:

spin_manifest_version = 2

[application]
name = "hello_rust"
version = "0.1.0"
authors = ["Your Name <your-name@example.com>"]
description = "My first Rust Spin application"

[[trigger.http]]
route = "/..."
component = "hello-rust"

[component.hello-rust]
source = "target/wasm32-wasi/release/hello_rust.wasm"
allowed_outbound_hosts = []
[component.hello-rust.build]
command = "cargo build --target wasm32-wasi --release"
watch = ["src/**/*.rs", "Cargo.toml"]

This represents a simple Spin HTTP application (triggered by an HTTP request). It has:

  • A single HTTP trigger, for the /... route, associated with the hello-rust component. /... is a wildcard, meaning it will match any route. When the application gets an HTTP request that matches this route - that is, any HTTP request at all! - Spin will run the hello-rust component.
  • A single component called hello-rust, whose implementation is in the associated hello_rust.wasm WebAssembly component. When, in response to the HTTP trigger, Spin runs this component, it will execute the HTTP handler in hello_rust.wasm. (We’re about to see the source code for that.)

Learn more about the manifest here.

Now let’s have a look at the code. Below is the complete source code for a Spin HTTP component written in Rust — a regular Rust function that takes an HTTP request as a parameter and returns an HTTP response, and it is annotated with the http_component macro which identifies it as the entry point for HTTP requests:

use spin_sdk::http::{IntoResponse, Request, Response};
use spin_sdk::http_component;

/// A simple Spin HTTP component.
#[http_component]
fn handle_hello_rust(req: Request) -> anyhow::Result<impl IntoResponse> {
    println!("Handling request to {:?}", req.header("spin-full-url"));
    Ok(Response::builder()
        .status(200)
        .header("content-type", "text/plain")
        .body("Hello, Fermyon")
        .build())
}

Build Your Application

The Spin template creates starter source code. Now you need to turn that into a Wasm module. The template puts build instructions for each component into the manifest. Use the spin build command to run them:

$ spin build
Executing the build command for component hello-rust: cargo build --target wasm32-wasi --release
    Updating crates.io index
    Updating git repository `https://github.com/fermyon/spin`
    Updating git repository `https://github.com/bytecodealliance/wit-bindgen`
   Compiling anyhow v1.0.69
   Compiling version_check v0.9.4
   # ...
   Compiling spin-sdk v0.10.0 
   Compiling hello-rust v0.1.0 (/home/ivan/testing/start/hello_rust)
    Finished release [optimized] target(s) in 11.94s
Finished building all Spin components

If the build fails, check:

  • Are you in the hello_rust directory?
  • Did you successfully install the wasm32-wasi target?
  • Is your version of Rust up to date (cargo --version)? The Spin SDK needs Rust 1.64 or above.

If you would like to know what build command Spin runs for a component, you can find it in the manifest, in the component.(id).build section:

[component.hello-rust.build]
command = "cargo build --target wasm32-wasi --release"

You can always run this command manually; spin build is a shortcut to save you having to remember it.

spin build can be used to build all components defined in the Spin manifest file at the same time, and also has a flag that starts the application after finishing the compilation, spin build --up.

For more details, see the page about building Spin applications.

Run Your Application

Now that you have created the application and built the component, you can spin up the application (pun intended):

$ spin up
Serving http://127.0.0.1:3000
Available Routes:
  hello-typescript: http://127.0.0.1:3000 (wildcard)

If you would like to see what Spin is doing under the hood, set the RUST_LOG environment variable for detailed logs, before running spin up:

$ export RUST_LOG=spin=trace

The variable is RUST_LOG no matter what language your application is written in, because this is setting the log level for Spin itself.

Spin instantiates all components from the application manifest, and creates the router configuration for the HTTP trigger according to the routes in the manifest. The component can now be invoked by making requests to http://localhost:3000/ (or any path under that, since it’s a wildcard):

$ curl -i localhost:3000
HTTP/1.1 200 OK
content-type: text/plain
content-length: 14
date = "2023-11-04T00:00:01Z"

Hello, Fermyon

The curl output may vary based on which language SDK you use.

Congratulations! You just created, built and ran your first Spin application!

Deploy Your Application to Fermyon Cloud

spin up runs your application locally. Now it’s time to put it on the Web via Fermyon Cloud.

Fermyon Cloud’s Starter tier is free, and doesn’t require you to enter any kind of payment instrument. You only need a GitHub account.

Log in to Fermyon Cloud

Before deploying your application to Fermyon Cloud, you have to log in, using the spin login command. This generates a code to authorize your current device against the Fermyon Cloud, and prints a link that will take you to where you enter the code. (You will need to be logged into your GitHub account; if you’re not, it will prompt you to log in.) Follow the instructions in the prompt to complete the authorization process.

spin login prints a confirmation message when authorization completes:

$ spin login

Copy your one-time code:

XXXXXXXX

...and open the authorization page in your browser:

https://cloud.fermyon.com/device-authorization

Waiting for device authorization...
Device authorized!

Deploy the Application

Now let’s deploy the application:

$ spin deploy

The deployment process prints progress information as your application uploads and is rolled out to the cloud:

Uploading hello_typescript version 0.1.0+XXXXXXXX to Fermyon Cloud...
Deploying...
Waiting for application to become ready... ready
Available Routes:
  hello-typescript: https://hello-typescript-XXXXXXXX.fermyon.app (wildcard)

You can Ctrl+Click on the link in the terminal to visit the web application you just deployed.

In the example output above, hello_typescript is a placeholder for your application name - you’ll see whatever you entered as the application name when you ran spin new earlier. The XXXXXXXX fragment is randomly generated to make a unique URL.

Congratulations again - you’ve now deployed your first Spin application to Fermyon Cloud!

Next Steps