Deployment guide

Spin

Overview

Spin is an open source runtime for building and running WebAssembly serverless applications and microservices. It is a single, self-contained binary that loads a WebAssembly component and serves it over HTTP. You get the fast cold starts, strong sandboxing and small footprint of WebAssembly, with no language runtime to manage and no container to build for each service.

This SecureAnyCloud image runs Spin 4.0.2 on Ubuntu 24.04 on Azure, installed from the official prebuilt release binary and run under systemd as an unprivileged spin user. A small demo WebAssembly component ships in the image, so a new instance demonstrates end-to-end WebAssembly execution straight away.

Secure by default. The Spin runtime is bound to loopback only, so the nginx TLS reverse proxy is the sole network-reachable surface. The demo component runs inside the Spin sandbox with no ambient access to the host. Spin has no login, so no shared or default credential of any kind ships in the image.

What you get:

  • Spin 4.0.2 from the official prebuilt release binary, run by systemd as the unprivileged spin user (spin.service) and bound to 127.0.0.1:3000
  • nginx terminating HTTPS on port 443 and reverse proxying to the Spin runtime, with a permanent HTTP to HTTPS redirect on port 80 (nginx.service)
  • A demo WebAssembly HTTP component at /opt/spin-app/index.wasm that echoes your request path and reports a value it computes at request time, which shows that the Spin runtime executes the component rather than serving a static file (replace it with your own component)
  • The whole runtime in a single prebuilt binary, with no separate language runtime to install and no container image to build for each microservice
  • The Spin application bound to loopback only, so only the nginx TLS proxy is reachable from the network
  • A per-instance self-signed TLS certificate created by a one-shot service on the first boot of every VM and bound to that VM's address, ready for you to front with your own domain and a trusted certificate
  • The application manifest in one readable file, /opt/spin-app/spin.toml, that you can keep in version control

Prerequisites

You need an active Azure subscription, an SSH public key, a VNet with a subnet in the target region, and a subscription to the Spin listing on Azure Marketplace.

Configure the Network Security Group (NSG) to allow inbound TCP 22 from your management network. Also allow TCP 443 (HTTPS) and TCP 80 (HTTP redirect) from the clients that will reach your application.

Recommended VM size: Standard_B2s (2 vCPU, 4 GB RAM) is ample for a demo or a small application. Choose a larger size for production microservice workloads and higher request concurrency.

1

Deploy from the Azure Portal

  • Open the Spin offer on the Azure Marketplace and select Get It Now, then Create.
  • Choose your subscription, resource group and region.
  • Set the VM size (Standard_B2s or larger), your SSH public key and the admin username azureuser.
  • On the Networking tab, attach an NSG that allows inbound TCP 22 from your management network and TCP 443 and TCP 80 from your users.
  • Select Review + create. When the deployment completes, note the VM public IP address.
2

Deploy from the Azure CLI

az vm create \
  --resource-group my-rg \
  --name my-spin \
  --image <marketplace-image-urn> \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_rsa.pub \
  --public-ip-sku Standard
# open HTTPS (443), the HTTP redirect (80) and SSH (22)
az vm open-port --resource-group my-rg --name my-spin --port 443 --priority 1001
az vm open-port --resource-group my-rg --name my-spin --port 80 --priority 1002
3

First boot

On the first boot, the spin-firstboot.service one-shot unit generates a fresh self-signed TLS certificate bound to this VM's IP address. It then writes an informational note to /root/spin-info.txt and starts spin.service and nginx.service. This takes a few seconds. SSH in as azureuser:

ssh azureuser@<vm-public-ip>
4

Confirm the services are running

Confirm that spin.service and nginx.service are active and check the Spin version. Then confirm that the runtime is bound to loopback on port 3000 while nginx listens on port 443 (HTTPS) and port 80 (the redirect):

sudo systemctl is-active spin nginx /usr/local/bin/spin --version sudo ss -tln | grep -E '127.0.0.1:3000|:443 |:80 '

You should see active for both services and a version line reporting spin 4.0.2. The Spin runtime listens on 127.0.0.1:3000, and nginx listens on *:443 and *:80.

5

Verify WebAssembly execution over HTTPS

The Spin runtime executes the demo component at /opt/spin-app/index.wasm for every request. The component echoes the request path and reports a value it computes at request time (6 x 7). This shows that Spin is running the WebAssembly component rather than serving a static file.

Fetch the page over HTTPS. The -k flag accepts the per-instance self-signed certificate. The response echoes the path you request, which a static file server cannot do:

curl -ks https://127.0.0.1/hello-from-sac | sed -e 's|</tr>|\n|g' -e 's/<[^>]*>//g' | grep -iE 'produced by a WebAssembly|Request path|wasm-exec-check'
curl -ksI https://127.0.0.1/ | grep -i x-sac-spin

The response states that a WebAssembly component executed by the Spin runtime produced it and echoes the request path /hello-from-sac. It shows the WASM execution check (6 x 7) evaluating to 42 on the server, and it carries an x-sac-spin: executed-42 response header.

Now open https://<vm-public-ip>/ in a browser. Your browser warns about the self-signed certificate until you front the instance with a trusted certificate in Step 8. The demo landing page confirms the WebAssembly runtime and echoes your request path.

6

HTTP to HTTPS redirect and the loopback-bound runtime

Plain HTTP on port 80 permanently redirects (301) to HTTPS. Confirm the redirect, then confirm that Spin's port 3000 is bound to loopback only. The runtime itself is not reachable from the network; only the nginx TLS proxy is.

curl -ksI http://127.0.0.1/ | grep -iE 'HTTP/|location'
sudo ss -tln | grep ':3000 '

You should see HTTP/1.1 301 Moved Permanently with a Location: header that points at the HTTPS URL. The Spin runtime listens only on 127.0.0.1:3000.

7

Deploy your own WebAssembly component

The application directory is /opt/spin-app. Build a WebAssembly component (Spin supports Rust, JavaScript, TypeScript, Python, Go and more) and copy the compiled .wasm into the application directory. Point the Spin manifest at it, then restart the service:

# copy your compiled component into the application directory
sudo cp ./my-component.wasm /opt/spin-app/index.wasm
# (optional) edit /opt/spin-app/spin.toml to change the route or add components
# apply the change
sudo systemctl restart spin

The [[trigger.http]] and [component.*] sections of the manifest map an HTTP route to a component. You can host several components on one runtime and route between them by path.

8

Front your instance with a trusted certificate

The image ships with a per-instance self-signed certificate so it answers over HTTPS immediately. For production, point a domain's DNS A record at this instance and replace the certificate that nginx serves with a trusted one. You can get one from your own certificate authority or from an ACME client such as Certbot.

The nginx site is at /etc/nginx/sites-available/sac-spin. Update the ssl_certificate and ssl_certificate_key paths to your trusted certificate, then reload nginx:

sudo nano /etc/nginx/sites-available/sac-spin
sudo nginx -t && sudo systemctl reload nginx
9

Review the manifest and info note

The Spin application manifest is a single readable file, and the first-boot note records this instance's endpoint details:

sudo cat /opt/spin-app/spin.toml
sudo cat /root/spin-info.txt

The manifest maps the [[trigger.http]] route to the demo component with source = "index.wasm". The info note records the HTTPS and HTTP URLs for this instance. It also confirms that the Spin runtime is bound to loopback only behind nginx and that Spin has no login and no shared credential.

10

Security recommendations

  • Restrict the management port. Allow inbound TCP 22 only from your management network, never 0.0.0.0/0.
  • Serve users over HTTPS only. Expose TCP 443 to your users, and expose TCP 80 only so the redirect works. Switch to a trusted certificate for your own domain (Step 8) so browsers do not warn.
  • Keep the runtime on loopback. This image binds the Spin application to 127.0.0.1:3000, so only the nginx TLS proxy is reachable from the network. Leave it that way, and terminate TLS at nginx rather than exposing the runtime port.
  • Keep the OS patched. The image is patched at build time and ships with unattended-upgrades enabled, so security updates continue automatically. Reboot after kernel updates.
  • Run your components with least privilege. spin.service already runs as the unprivileged spin user with systemd sandboxing. WebAssembly components run inside the Spin sandbox with no ambient host access.
11

Support and Licensing

Spin is open source software distributed under the Apache License 2.0. This SecureAnyCloud image bundles Spin 4.0.2 on Ubuntu 24.04 LTS with nginx TLS termination, patched at build time and hardened. SecureAnyCloud provides the packaging, configuration, security hardening and support. It does not modify the upstream Spin license.

Deploy on Azure

Launch Spin on Ubuntu 24.04 from the SecureAnyCloud Azure Marketplace listing, then follow this guide to deploy your WebAssembly component.

Need Help?

SecureAnyCloud provides 24/7 technical support for this Spin image. Contact sales@secureanycloud.com for help with building WebAssembly components in Rust, JavaScript, Python and Go, the Spin manifest and HTTP routing, TLS and certificate options, and Spin version upgrades.

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.

Deploy on Azure

Launch Spin 4.0.2 on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure