Skip to main content
Version: 1.0 (alpha)

Quickstart

A familiar starting example to get you up and running with wasmCloud.

Under Construction

🚧 This page is under active renovation for wasmCloud 1.0. Some details may not be aligned with v1.0 during the alpha period.

Before We Begin

info

Looking for an introduction? Check out What Is wasmCloud? or Concepts first.

info

If you have not installed wash, follow the installation guide first.

In this guide, we'll be taking a tour through the tooling in the wasmCloud ecosystem and a "Hello world" example. Once you're finished, you'll have a good understanding of how to use wash and wadm to build and deploy wasmCloud applications. All wasmCloud applications need a host to run on, so let's use wash to start one now.

Starting Host Infrastructure

To start a host, simply run wash up. The default settings should work well for this tutorial. The host can be killed at any time with CTRL+c.

This command bootstraps 3 independent processes to create the necessary local infrastructure for wasmCloud:

  • the wasmCloud host which manages the execution of components and providers
  • a NATS server to manage communications between application components
  • a wadm process which monitors the lattice and maintains the state of managed deployments

wash up infrastructure

By default, wash will run the host in interactive mode. If you'd rather run the host in the background, run wash up --detached (or wash up -d, for short).

Creating a Project

Now that our wasmCloud host infrastructure is running, let's generate a new component project. This is where our "Hello World" example begins. If you're running your host in the foreground, just switch to another terminal window to run these commands.

Pick your language of choice below to follow

caution

Component examples are experimental and likely to require recompilation with each new release of wasmCloud.

This command generates a new component project in the ./hello directory:

bash
wash new component hello --template-name hello-world-rust

This component is a simple Rust project with a few extra goodies included for wasmCloud. At a high level, the important pieces are:

  1. src/lib.rs: Where the business logic is implemented
  2. wasmcloud.toml: Component metadata and capability permissions
  3. wadm.yaml: A declarative manifest for running the full application
Rust dependencies

You don't need any Rust dependencies installed to run this example, but if you want to build it yourself you'll need to install the Rust toolchain and the wasm32-wasi target.

bash
rustup target add wasm32-wasi

Feel free to take a look at the code and the project structure. We'll take a look at each of these in depth later, so for now let's build and run the example.

Building the Application

info

If you prefer not to build anything yet, you can use wasmcloud.azurecr.io/hello:0.1.7 as the image inside of wadm.yaml instead to pull our prebuilt example component.

We can use the open source HTTP Server capability provider to serve our application, so the only thing you'll need to build is the component. Change directory into the generated hello directory and run wash build to build your component:

bash
cd hello # enter the new project directory (if you haven't already)
wash build
bash
Component built and signed and can be found at "/Users/wasmcloud/hello/build/http_hello_world_s.wasm"

Starting our Application

We'll use wash and wadm, the wasmCloud application deployment manager, to start this component, the httpserver capability, and link them together to configure them.

bash
cd hello # enter the new project directory (if you haven't already)
wash app deploy wadm.yaml

wash app deploy diagram

wadm will take care of taking this manifest and scheduling the resources on the host that you launched earlier. You should see output in the host logs when your component and capability start up, which should happen after just a few seconds. After you see that the HTTP server set up the listener in the host logs, or once the application is Deployed when you check wash app list, you can query it yourself:

bash
 wash app list

Name             Latest Version   Deployed Version   Deploy Status   Description
http-hello-world v0.0.1           v0.0.1                  Deployed   HTTP Hello World
bash
$ curl localhost:8080
Hello, World!

Congratulations, you just ran a WebAssembly application in wasmCloud!

How does it work?

hello app architecture

When you send your HTTP request to localhost:8080, that request is received by the HTTP Server capability provider. The HTTP Server capability provider then forwards that request to the component, which responds with the string "Hello, world!". This loose coupling of capability providers and components provides flexibility, security, and it lets our component code be purely business logic instead of compiling in vendor specific code. Let's take a look at your application code now:

go
package main

import (
	http "github.com/wasmcloud/wasmcloud/examples/golang/components/http-hello-world/gen"
)

// Helper type aliases to make code more readable
type HttpRequest = http.ExportsWasiHttp0_2_0_rc_2023_12_05_IncomingHandlerIncomingRequest
type HttpResponseWriter = http.ExportsWasiHttp0_2_0_rc_2023_12_05_IncomingHandlerResponseOutparam
type HttpOutgoingResponse = http.WasiHttp0_2_0_rc_2023_12_05_TypesOutgoingResponse
type HttpError = http.WasiHttp0_2_0_rc_2023_12_05_TypesErrorCode

type HttpServer struct{}

func init() {
	httpserver := HttpServer{}
	// Set the incoming handler struct to HttpServer
	http.SetExportsWasiHttp0_2_0_rc_2023_12_05_IncomingHandler(httpserver)
}

func (h HttpServer) Handle(request HttpRequest, responseWriter HttpResponseWriter) {
	// Construct HttpResponse to send back
	headers := http.NewFields()
	httpResponse := http.NewOutgoingResponse(headers)
	httpResponse.SetStatusCode(200)
	httpResponse.Body().Unwrap().Write().Unwrap().BlockingWriteAndFlush([]uint8("Hello from Go!\n")).Unwrap()

	// Send HTTP response
	okResponse := http.Ok[HttpOutgoingResponse, HttpError](httpResponse)
	http.StaticResponseOutparamSet(responseWriter, okResponse)
}

//go:generate wit-bindgen tiny-go wit --out-dir=gen --gofmt
func main() {}

This component has a single struct, HttpServer, that implements the Handle function. This function is called by the HTTP Server capability provider when it receives an incoming HTTP request. The Handle function constructs an HttpResponse and sends it back to the HTTP Server capability provider, which then sends it back to the client. There's no mention of ports, certificates, HTTP libraries, and if those things change this component will work all the same.

info

Capabilities are deny by default, the link inside of wadm.yaml explicitly allowed the "Hello World" component to receive an HTTP request. If you inspect the WIT output of your component with wash inspect --wit you'll see the only export is wasi:http/incoming-handler, and the only imports are standard capabilities. This means that this component cannot make network requests of its own, read arbitrary files, or even generate a random number, all are denied by the wasmCloud runtime.

When you ran wash app deploy wadm.yaml, wadm takes the application manifest and schedules the components on hosts according to the scale you specify. This example has a minimal manifest, let's take a look at it:

yaml
# Metadata
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: hello
  annotations:
    version: v0.0.1
    description: "wasmCloud Hello World Example"
spec:
  components:
    # Your application component, started from the wasmCloud example OCI artifact
    - name: hello
      type: component
      properties:
        image: wasmcloud.azurecr.io/hello:0.1.7
      traits:
        # One replica of this component will run
        - type: spreadscaler
          properties:
            replicas: 1
        # The link configuration tells the httpserver to listen on 8080
        - type: linkdef
          properties:
            target: httpserver
            values:
              address: 0.0.0.0:8080

    # The httpserver capability provider, started from the official wasmCloud OCI artifact
    - name: httpserver
      type: capability
      properties:
        image: wasmcloud.azurecr.io/httpserver:0.19.1
        contract: wasmcloud:httpserver

Scaling up 📈

WebAssembly can be easily scaled due to its small size, portability, and wasmtime's ability to efficiently instantiate multiple instances of a single WebAssembly component. We leverage these aspects to make it simple to scale your applications with wasmCloud. Components only use resources when they're actively processing requests, so you can specify the number of replicas you want to run and wasmCloud will automatically scale up and down to meet demand. Let's scale up our hello world application to 50 replicas by editing wadm.yaml:

yaml
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: hello
  annotations:
    # Make sure to bump the version so wadm knows to update the application
    version: v0.0.2
    description: 'wasmCloud Hello World Example'
spec:
  components:
    - name: hello
      type: actor
      properties:
        image: wasmcloud.azurecr.io/hello:0.1.7
      traits:
        - type: spreadscaler
          properties:
            # Update the scale to 50
            replicas: 50

Now your hello application is ready to deploy v0.0.2 with 50 replicas, meaning it can handle up to 50 concurrent incoming HTTP requests. Just run wash app deploy wadm.yaml again, wasmCloud will be configured to automatically scale your actor component based on incoming load. It's a little easier to visualize this in the wasmCloud dashboard, so let's take a look at that next.

Viewing the wasmCloud dashboard

To view the wasmCloud dashboard, you'll have to launch wash with the option --nats-websocket-port 4001. Go ahead and CTRL+c or wash down to stop your previous host, and then relaunch it with the new option:

bash
wash up --nats-websocket-port 4001
What will happen to my application?

Treat wasmCloud hosts as cattle, not pets. Stopping your host will stop all of the components running on it, and wadm will look for other available hosts to reschedule your application on. As soon as you launch your new host with the --nats-websocket-port option, your application will be rescheduled on it and work just as it did before.

Then, you can launch the wasmCloud dashboard using wash ui, which will launch the dashboard on http://localhost:3030. This is a great way to visualize what is running on your host, even multiple hosts that are connected to the same NATS server.

wasmCloud dashboard with hello world application

Log files

If you encounter any problems, the host log files may contain useful error messages, and it's good to know how to find them. The tabs below, organized by how you started the wasmCloud host, show you where to find logs:

By default, logs from wash up are automatically output to your terminal. If you ran the command with the --detached flag, logs can be found in ~/.wash/downloads/wasmcloud.log

Next steps

Congratulations! You've made it through the first guide to wasmCloud. You started your first application and got familiar with the fundamentals of wash and wadm. You should now feel comfortable exploring the ecosystem. We recommend proceeding onto the next guide, where you can build your own application and get into the developer loop.