Skip to main content
Version: 1.x

Quickstart

Before we begin

Learn the fundamentals

Looking for an introduction to the basic concepts of WebAssembly components and wasmCloud? Check out What is wasmCloud? or Platform Overview first.

In this guide, we'll take a tour through the wasmCloud ecosystem with a "Hello world" example. Once you're finished, you'll have a good understanding of how to use wasmCloud Shell (wash) to build and deploy wasmCloud applications.

Start the wasmCloud host

Install wasmCloud Shell (wash)

If you haven't installed wash yet, follow the installation guide first.

All wasmCloud applications need a host to run on, so let's use wash to start one now. You can start a wasmCloud host on your local machine with wash up or run a host in a Docker container.

To start a host, simply run:

shell
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 three 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).

Create 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

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 build information
  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.

Build the application

info

If you prefer not to build anything yet, you can use ghcr.io/wasmcloud/components/http-hello-world-rust:0.1.0 as the image inside of wadm.yaml instead to pull our prebuilt example component.

We can use the open source httpserver 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"

Start our application

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

Then, we can deploy our application:

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 provider 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 httpserver provider. The httpserver provider then forwards that request to the component, which responds with the string "Hello, world!". This loose coupling of providers and components provides flexibility and security, and it lets our component code focus purely on business logic rather than including and compiling 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_IncomingHandlerIncomingRequest
type HttpResponseWriter = http.ExportsWasiHttp0_2_0_IncomingHandlerResponseOutparam
type HttpOutgoingResponse = http.WasiHttp0_2_0_TypesOutgoingResponse
type HttpError = http.WasiHttp0_2_0_TypesErrorCode

type HttpServer struct{}

func init() {
	httpserver := HttpServer{}
	// Set the incoming handler struct to HttpServer
	http.SetExportsWasiHttp0_2_0_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)
	body := httpResponse.Body().Unwrap()
	bodyWrite := body.Write().Unwrap()
	bodyWrite.BlockingWriteAndFlush([]uint8("Hello from Go!\n")).Unwrap()

	// Send HTTP response
	okResponse := http.Ok[HttpOutgoingResponse, HttpError](httpResponse)
	bodyWrite.Drop()
	http.StaticOutgoingBodyFinish(body, http.None[http.WasiHttp0_2_0_TypesTrailers]())
	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 httpserver provider when it receives an incoming HTTP request. The Handle function constructs an HttpResponse and sends it back to the httpserver 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 build/http_hello_world.wasm 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 received the application manifest and scheduled the components on hosts as specified in your application. 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-world
  annotations:
    description: 'HTTP hello world demo'
spec:
  components:
    - name: http-component
      type: component
      properties:
        # Your manifest deploys from a local .wasm file, but you can also use OCR registries like below
        image: ghcr.io/wasmcloud/components/http-hello-world-rust:0.1.0
      traits:
        # One replica of this component will run
        - type: spreadscaler
          properties:
            replicas: 1
    # The httpserver capability provider, started from the official wasmCloud OCI artifact
    - name: httpserver
      type: capability
      properties:
        image: ghcr.io/wasmcloud/http-server:0.22.0
      traits:
        # Link the HTTP server and set it to listen on the local machine's port 8080
        - type: link
          properties:
            target: http-component
            namespace: wasi
            package: http
            interfaces: [incoming-handler]
            source_config:
              - name: default-http
                properties:
                  ADDRESS: 127.0.0.1:8080

View the wasmCloud dashboard

To view the wasmCloud dashboard, you can start it using the wash.

bash
wash ui

If you would like to change the port that the websocket is enabled on, you can pass the --nats-websocket-port option to wash up. Note that you will need to stop NATS if it is already running or the new config will not apply. You can do this with wash down --all to stop everything.

bash
wash up --nats-websocket-port 4444 # defaults to 4223
What will happen to my application?

Treat wasmCloud hosts as commodity. 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.