Deployment guide

Excalidraw

Overview

Excalidraw is an open-source virtual whiteboard for sketching hand-drawn-style diagrams. It is local-first: your drawings live privately in your own browser, and there is no account, login or password to manage.

The SecureAnyCloud image, built from Excalidraw 0.18.1, self-hosts both halves of Excalidraw. You get a fully private deployment with no dependency on the public excalidraw.com. nginx serves the static web app on port 80. The official real-time collaboration room server runs alongside it on loopback, so the Share to Live collaboration feature connects to your own VM, not a public server.

What you get:

  • Excalidraw 0.18.1 static web app, built from the official source and served from /var/www/excalidraw
  • nginx on :80 serving the single-page app, with a Socket.IO reverse proxy to the local collaboration server
  • The official Excalidraw collaboration room server (excalidraw-room) on loopback 127.0.0.1:3002, never publicly exposed
  • excalidraw-room.service and nginx.service as systemd units, enabled and active on every boot
  • A first-boot service that writes an MOTD banner and a non-secret info note (Excalidraw has no credentials to rotate)
  • 24/7 SecureAnyCloud support

Prerequisites

Before you deploy, make sure you have:

  • An active Azure subscription
  • An SSH key pair
  • A VNet and subnet in the target region
  • NSG inbound rules that allow 22/tcp from your management network and 80/tcp for the whiteboard

Standard_B2ms (2 vCPU / 8 GiB RAM) is a good starting point. Excalidraw serves plain HTTP on port 80. For production, terminate TLS in front of it with your own domain.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Excalidraw by SecureAnyCloud, and select Create.

On Basics, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80). Then select Review + create and Create.

Step 2 - Deploy from the Azure CLI

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:excalidraw-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name excalidraw \
  --image sac1647283583153:excalidraw-ubuntu-24-04:default:latest \
  --size Standard_B2ms \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name excalidraw --port 80 --priority 1010

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

nginx serves the whiteboard, and the real-time collaboration server runs as excalidraw-room.service. Confirm both are active:

systemctl is-active excalidraw-room.service nginx.service

Both report active.

Step 5 - Verify the endpoints

Confirm that nginx serves the Excalidraw app on port 80. Also confirm that the Socket.IO collaboration endpoint is reachable through nginx, which proxies to the loopback room server:

echo "SPA index: $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/)"
echo "nginx /health: $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/health)"
echo "Socket.IO (nginx):$(curl -s -o /dev/null -w '%{http_code}' 'http://127.0.0.1/socket.io/?EIO=4&transport=polling')"

All three return 200. The Socket.IO request returns an Engine.IO handshake payload (it contains a sid session id). This proves the live-collaboration server is wired up behind nginx.

Step 6 - Confirm the collaboration server is private

The collaboration room server is bound to loopback 127.0.0.1:3002 and is never exposed directly. Only nginx on port 80 is public. A non-secret info note records the app URL:

ss -tlnp | grep 3002 cat /var/lib/sac/data/excalidraw-info.txt

Step 7 - Open the whiteboard

Browse to http://<vm-public-ip>/ in any modern browser. The Excalidraw canvas loads with the drawing toolbar across the top.

Because Excalidraw is local-first, there is no sign-in. Your drawings are saved privately in your browser.

Step 8 - Draw

Pick a tool from the toolbar (rectangle, ellipse, diamond, arrow, line, freedraw, text and more) and draw on the canvas.

Select a shape to show the style panel on the left. Use it to change stroke color, fill style, font family and size, opacity and layer order for the selected element.

Step 9 - Live collaboration

Click Share in the top-right and choose Live collaboration. Excalidraw starts a collaborative session and gives you a room link to share.

This VM's own room server serves the collaboration link, so your whiteboard data never leaves your host. Anyone you send the link to joins the same canvas in real time.

Maintenance

  • Data: Excalidraw is local-first, so drawings are stored in each visitor's browser. There is no server-side database to back up. Use the in-app Save to file and Open commands to export and import .excalidraw scenes.
  • Collaboration: the room server (excalidraw-room.service) holds an in-progress shared scene only while a session is active. Nothing is persisted to disk.
  • TLS: Excalidraw serves plain HTTP on port 80. For production, front it with TLS (for example certbot) and your own domain.
  • Restart: sudo systemctl restart excalidraw-room.service nginx.service to restart the services.
  • Security patches: unattended-upgrades remains enabled, so the OS keeps receiving security updates automatically.

Support

SecureAnyCloud provides 24/7 expert support for this image. Contact sales@secureanycloud.com.

Excalidraw is a trademark of Excalidraw, Inc. SecureAnyCloud is not affiliated with, endorsed by, or sponsored by Excalidraw, Inc. This image packages the open-source Excalidraw software (MIT License) for deployment on Microsoft Azure.

Deploy on Azure

Launch Excalidraw 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