wasmCloud on Ubuntu 24.04 on Azure User Guide
Overview
wasmCloud is a Cloud Native Computing Foundation (CNCF) platform for running WebAssembly components in a distributed application mesh called a lattice. A wasmCloud host runs your components and connects them to capability providers — HTTP servers, key-value stores, message brokers and more — over a NATS message bus. The wasmCloud Application Deployment Manager (wadm) reconciles the applications you declare against the hosts that are running, so you describe the desired state and the platform keeps it running. Because components are portable, sandboxed WebAssembly, the same artifact runs anywhere a host runs.
The cloudimg image installs a complete single-node wasmCloud environment on one machine, from the pinned upstream releases (each verified by SHA-256): NATS 2.14.5 (the lattice bus, with JetStream), the wasmCloud host 1.9.2, wadm 0.21.1, and wash 0.43.0 (the wasmCloud Shell). All four run as hardened systemd services under a dedicated wasmcloud user. A sample hello-world HTTP WebAssembly component and the httpserver capability provider are deployed automatically by wadm on boot, so the platform is running and serving HTTP the moment the VM is up.
NATS ships no authentication of its own, so it is bound to the loopback interface only and is never reachable off the VM; the host, wadm and wash all reach it over 127.0.0.1. nginx terminates TLS on port 443 and fronts the washboard web UI, the demo endpoint and the NATS websocket the browser washboard connects over, guarding the whole surface with HTTP Basic Auth. At first boot, wasmcloud-firstboot.service generates this VM's own Basic Auth password and TLS certificate and writes them to /root/wasmcloud-credentials.txt (mode 0600, root only). There is no shared or default login in the image.
What is included:
- wasmCloud host 1.9.2 (
/opt/wasmcloud/bin/wasmcloud, Apache-2.0),wasmcloud.service - NATS 2.14.5 with JetStream (
nats.service), bound to127.0.0.1only - wadm 0.21.1 (
wadm.service) reconciling declared applications - wash 0.43.0 (
/opt/wasmcloud/bin/wash), the CLI + the washboard web UI (wash-ui.service) - A sample hello-world HTTP component + httpserver provider, deployed on boot by
wasmcloud-app-deploy.service - The washboard web UI and demo endpoint fronted by nginx TLS on 443 with per-VM HTTP Basic Auth
wasmcloud-firstboot.serviceminting the per-VM Basic Auth password + TLS certificate- Ubuntu 24.04 LTS base, latest security patches applied at build time
- 24/7 cloudimg support, 24h response SLA
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet + subnet. Recommended VM size: Standard_B2s for evaluation and demonstration; scale up for heavier workloads. You will reach the washboard over HTTPS (port 443). No inbound port for NATS is needed or opened — the lattice bus is private to the VM.
Deploy the image
Create a VM from the offer with an NSG that allows inbound 22 (SSH) and 443 (HTTPS). Port 80 redirects to 443. Everything else — the NATS client bus (4222), the NATS websocket (4223), the washboard (3030) and the demo httpserver (8080) — binds 127.0.0.1 and is never exposed off the VM.
Once the VM is running, connect over SSH as azureuser:
ssh azureuser@<public-ip>
First-boot posture
Every service is enabled and comes up on boot. The wasmCloud/NATS surfaces bind loopback only; nginx is the single public front door. Confirm the posture:
systemctl is-active nats wasmcloud wadm wash-ui nginx
/opt/wasmcloud/bin/wasmcloud --version
ss -tlnH | awk '{print $4}' | grep -E ':(443|4222|4223|3030|8080)$' | sort
swapon --show | wc -l
Expected output — the four platform services and nginx are active, NATS and the washboard bind loopback only, and no swap ships on the OS disk:
active
active
active
active
active
wasmcloud 1.9.2
0.0.0.0:443
127.0.0.1:3030
127.0.0.1:4222
127.0.0.1:4223
127.0.0.1:8080
0

Retrieve your per-VM credentials
The washboard and the demo endpoint are served over TLS behind HTTP Basic Auth. The password is generated uniquely on this VM at first boot and written to a root-only file:
sudo cat /root/wasmcloud-credentials.txt
Expected output (the password is unique to your VM):
# wasmCloud on Ubuntu 24.04 — Per-VM Credentials
# Washboard web UI (HTTPS via nginx): https://<public-ip>/
# Demo hello-world HTTP component: https://<public-ip>/demo/?name=cloudimg
# Sign in (HTTP Basic Auth): cloudimg / <password below>
#
# NATS lattice bus is bound to 127.0.0.1 only and is NOT reachable off-host.
#
WASMCLOUD_USER=cloudimg
WASMCLOUD_PASSWORD=************************
WASMCLOUD_URL=https://<public-ip>/
WASMCLOUD_DEMO_URL=https://<public-ip>/demo/?name=cloudimg

The nginx front door enforces this credential. A request with no credentials, or a guessed one, is rejected; the per-VM credential is accepted:
PASS=$(sudo grep '^WASMCLOUD_PASSWORD=' /root/wasmcloud-credentials.txt | cut -d= -f2-)
curl -sk -o /dev/null -w 'healthz %{http_code}\n' https://127.0.0.1/healthz
curl -sk -o /dev/null -w 'no auth %{http_code}\n' https://127.0.0.1/
curl -sk -o /dev/null -w 'guess %{http_code}\n' -u admin:admin https://127.0.0.1/
curl -sk -o /dev/null -w 'per-VM cred %{http_code}\n' -u "cloudimg:$PASS" https://127.0.0.1/
Expected output — the static health probe answers, unauthenticated and guessed requests are challenged (401), and the per-VM credential is accepted (200):
healthz 200
no auth 401
guess 401
per-VM cred 200
The sample application is already running
wadm deployed the bundled hello-world application on boot. The HTTP component answers immediately, both locally and through the TLS front door:
PASS=$(sudo grep '^WASMCLOUD_PASSWORD=' /root/wasmcloud-credentials.txt | cut -d= -f2-)
curl -s http://127.0.0.1:8080/
curl -sk -u "cloudimg:$PASS" https://127.0.0.1/demo/
Expected output:
Hello from Rust!
Hello from Rust!

Inspect the lattice from the command line
wash talks to the local lattice with no configuration — it defaults to the loopback NATS and the default lattice. List the running host, the deployed components and providers, and the applications wadm is managing:
wash get hosts
wash get inventory
wash app list
Expected output — one host is running the hello-world component and the httpserver provider, and wadm reports the application Deployed:
Host ID Friendly name Uptime (seconds)
NAVVAEXCCUF4UBWHKY3DLMXWWKPIVCRGSUJUO6W2W55G6AOZKF2R74HA cold-dream-6979 147
Component ID Name Max count
hello_world-http_component http-hello-world 1
Provider ID Name
hello_world-httpserver http-server-provider
Name Deployed Version Status
hello-world v0.0.1 Deployed

The washboard web UI
Browse to https://<public-ip>/ and sign in with the Basic Auth user cloudimg and the per-VM password from /root/wasmcloud-credentials.txt. The certificate is self-signed and generated per VM, so your browser will warn on first visit — accept it, or install a CA-signed certificate as described below. The washboard connects to the lattice through the nginx TLS proxy and shows the live state: the connected host, the deployed component and provider, and the link that wires them together.

Expand the host to see its labels and the components and providers it is running.

The Components and Providers tables list the deployed hello-world component and the httpserver provider with its health showing Running.

The Links table shows the wasi:http/incoming-handler link that connects the httpserver provider to the hello-world component — the wiring that turns an inbound HTTP request into a component invocation.

Deploy your own components
The bundled application manifest lives at /opt/wasmcloud/apps/hello-world.wadm.yaml. wadm applications are declared as OAM manifests: you list the components and capability providers you want and the links between them, and wadm keeps the lattice reconciled to that declaration. Inspect and manage the running application with wash:
wash app get hello-world
cat /opt/wasmcloud/apps/hello-world.wadm.yaml
To deploy your own WebAssembly component, publish it to an OCI registry (or reference a local .wasm file), write a manifest that references it, and run wash app deploy <your-manifest>.yaml. The wasmCloud documentation covers building components in Rust, Go, TypeScript and other languages, the full catalogue of capability providers, and scaling a component across multiple hosts by raising its spreadscaler instance count.
Add a custom domain and a CA-signed certificate
The image ships a per-VM self-signed certificate so HTTPS works out of the box. For production, point a DNS name at the VM and install a CA-signed certificate. Replace the certificate and key that nginx serves:
sudo cp <your-domain>.crt /etc/nginx/ssl/wasmcloud.crt
sudo cp <your-domain>.key /etc/nginx/ssl/wasmcloud.key
sudo systemctl reload nginx
You can also change the washboard Basic Auth password at any time:
sudo htpasswd -bB /etc/nginx/.wasmcloud.htpasswd cloudimg '<new-password>'
sudo systemctl reload nginx
Security model
- NATS is private to the VM. The lattice bus binds
127.0.0.1only (client 4222 and websocket 4223) and is never reachable off the machine. The host, wadm and wash reach it over loopback; the browser washboard reaches it through the authenticated nginx TLS proxy. - No default credential ships. No NATS auth account exists and no nginx password file is baked into the image. nginx refuses to start until first boot has minted this VM's Basic Auth password and TLS certificate, so no shared or guessable login is ever present.
- Single public surface. Only SSH (22), the HTTP→HTTPS redirect (80) and the TLS front door (443) are exposed. The washboard (3030), the demo httpserver (8080) and the NATS ports all bind loopback and sit behind nginx.
- Fully patched base. Ubuntu 24.04 LTS is patched at build time with unattended security updates enabled on your running VM.
Support
cloudimg provides 24/7 technical support for this wasmCloud image by email (support@cloudimg.co.uk) and live chat, covering deployment, retrieving and rotating the first-boot password, adding a custom domain and CA-signed certificate, deploying your own WebAssembly components and capability providers, scaling the lattice, upgrades and patch management, and troubleshooting. Critical issues receive a one-hour average response time.
wasmCloud is a trademark of its respective holder. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.