WebAssembly
Sub-ms Cold Start
Deploy Fermyon Spin on a VPS
Serverless WebAssembly runtime with single-digit-ms cold starts, ~30 MB idle footprint, and OCI artifact deploys.
At a Glance
| Project | Fermyon Spin 3.x |
| License | Apache 2.0 |
| Recommended Plan | RamNode Cloud VPS 2 vCPU / 2-4 GB |
| OS | Ubuntu 22.04+ / Debian |
| Languages | Rust, TypeScript, Python, Go and more |
1
Install the Spin Runtime
Update + install
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl ca-certificates git build-essential
cd /tmp
curl -fsSL https://developer.fermyon.com/downloads/install.sh | bash
sudo install -m 0755 ./spin /usr/local/bin/spin
spin --version2
Dedicated Service User
Create system user + dirs
sudo useradd --system --create-home --home-dir /var/lib/spin --shell /usr/sbin/nologin spin
sudo mkdir -p /var/lib/spin/apps /var/log/spin
sudo chown -R spin:spin /var/lib/spin /var/log/spin3
Build a Sample Component
Rust toolchain + scaffold
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
source "$HOME/.cargo/env"
rustup target add wasm32-wasip1
cd ~
spin new -t http-rust hello-spin --accept-defaults
cd hello-spin
spin build
spin up --listen 127.0.0.1:3000 &
curl http://127.0.0.1:3000
kill %14
Package as an OCI Artifact
Push + pull
spin registry login ghcr.io -u YOUR_USERNAME
# paste a PAT with write:packages
spin registry push ghcr.io/your-username/hello-spin:0.1.0
# On the production host, as the spin user:
sudo -u spin spin registry pull ghcr.io/your-username/hello-spin:0.1.05
systemd Template Unit
/etc/systemd/system/spin@.service
[Unit]
Description=Spin application: %i
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=spin
Group=spin
WorkingDirectory=/var/lib/spin/apps/%i
ExecStart=/usr/local/bin/spin up --listen 127.0.0.1:%I --from /var/lib/spin/apps/%i/spin.toml
Restart=on-failure
RestartSec=5
StandardOutput=append:/var/log/spin/%i.log
StandardError=append:/var/log/spin/%i.err
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
ReadWritePaths=/var/lib/spin /var/log/spin
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
RestrictNamespaces=true
LockPersonality=true
MemoryDenyWriteExecute=false
[Install]
WantedBy=multi-user.targetMemoryDenyWriteExecute=false is required: the WebAssembly runtime needs JIT pages.
Enable
sudo systemctl daemon-reload
sudo systemctl enable --now spin@hello-spin.service
curl http://127.0.0.1:30006
Caddy + TLS
Install Caddy
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update && sudo apt install -y caddy/etc/caddy/Caddyfile
spin.example.com {
encode zstd gzip
reverse_proxy 127.0.0.1:3000 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
-Server
}
}7
Storage + Outbound Allowlist
spin.toml — declare allowed hosts
[component.my-app]
source = "target/wasm32-wasip1/release/my_app.wasm"
allowed_outbound_hosts = [
"https://api.example.com",
"redis://localhost:6379",
"postgres://db.internal:5432"
]runtime-config.toml — local KV + SQLite
[key_value_store.default]
type = "spin"
path = "/var/lib/spin/apps/hello-spin/data/kv.db"
[sqlite_database.default]
type = "spin"
path = "/var/lib/spin/apps/hello-spin/data/db.sqlite"8
Metrics + Backup
Prometheus scrape
scrape_configs:
- job_name: spin
static_configs:
- targets: ['127.0.0.1:3000']
labels:
app: hello-spinDaily backup
sudo tee /etc/cron.daily/spin-backup > /dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
DATE=$(date +%Y%m%d)
rsync -a --delete /var/lib/spin/ backup@backup.example.com:/srv/backups/spin-${DATE}/
EOF
sudo chmod +x /etc/cron.daily/spin-backup