Deployment guide

SpiffArena

Overview

SpiffArena is the web application built around the SpiffWorkflow engine, and it turns a diagram into a running system. Analysts and subject matter experts draw a business process in the browser using standard BPMN notation. They express the decisions inside it as DMN decision tables and save it into a version-controlled process model repository.

The same diagram is what actually executes. SpiffArena starts process instances from it, drives them through their tasks, gathers input through generated forms, evaluates the decision tables, runs script steps and records the full history of every instance. The SecureAnyCloud image installs SpiffArena from the pinned upstream release as a single self-contained appliance, with nothing to assemble.

What you get:

  • SpiffArena, installed from the pinned upstream tag v3.0.0 (LGPL-2.1), together with the SpiffWorkflow engine (LGPL-3.0) that upstream pins from source. Exact upstream URLs and refs for both are recorded on the VM at /opt/spiffarena/SOURCE.txt
  • The workflow engine and API, the BPMN and DMN editor, the administrator interface, the background scheduler and a bundled database, all on one VM
  • The React interface built at image build time and served as static files by nginx on port 80. The API runs under gunicorn with uvicorn workers bound to 127.0.0.1 only
  • A bundled single-file SQLite database in WAL mode, so there is no external database to run
  • The background scheduler as its own service, so process instances advance with no message broker
  • A git-backed process model repository at /var/lib/spiffarena/process-models, seeded with a runnable Hello World example that you can open in the editor and execute immediately
  • No usable default login. SpiffArena's development sign-in publishes a set of demo accounts (admin/admin, nelson/nelson, malala/malala, oskar/oskar and more). This image deletes those files entirely and ships with no credential at all. The first boot of each VM generates a unique administrator username and password, OpenID signing key, client secret, session key and encryption key
  • spiffarena-selftest.sh, shipped as a tool, so you can prove at any time that the workflow engine executes and that no publicly known credential works
  • A base patched at build time, with unattended security upgrades enabled
  • 24/7 SecureAnyCloud support

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region.

Standard_B2s (2 vCPU / 4 GiB RAM) is the recommended size. It runs the API, the scheduler, nginx and the database comfortably. Choose a larger size if you expect many concurrent modellers or long-running processes with large data payloads.

In the NSG, allow inbound 22/tcp from your management network and 80/tcp for the web interface. Nothing else needs to be open, because the API process is bound to loopback and is not reachable from the network.

The appliance serves plain HTTP on port 80 on the VM's own IP address, so you can evaluate it immediately. Add a real hostname and a TLS certificate before you put business processes or their data on it. See "Set your own domain and TLS".

Step 1 - Deploy from the Azure Marketplace

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

On Basics, pick your subscription, resource group, region and size (Standard_B2s). Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80). Then choose Review + create, followed by 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:spiff-arena-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name spiff-arena \
  --image sac1647283583153:spiff-arena-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

Then open the web port on the VM's NSG:

az vm open-port --resource-group <your-rg> --name spiff-arena --port 80 --priority 900

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

On first boot, the image generates this VM's administrator credential and every application secret. It also points the application at the VM's own address, lays the database down from a pristine template, and starts the stack. Confirm that all three services are active:

systemctl is-active nginx spiffarena spiffarena-scheduler

Expected output:

active active active

spiffarena is the API and workflow engine, spiffarena-scheduler is the background processor that advances waiting process instances, and nginx serves the web interface and proxies the API.

First boot takes roughly thirty seconds. If a service is still starting, wait and run the command again.

Step 5 - Check the health endpoint

The API exposes an unauthenticated readiness endpoint that queries the database, so a 200 response means more than "a port answered":

curl -s http://localhost/v1.0/status

Expected output:

{"ok":true,"can_access_frontend":true}

There is also a plain liveness endpoint for load balancer probes:

curl -s http://localhost/healthz

Expected output:

ok

Step 6 - Retrieve the per-VM administrator credentials

The first boot generated every secret on this VM, and none of them exists anywhere else. Read them with:

sudo cat /root/spiffarena-credentials.txt

Expected output. Your username, password and URL will differ, because they are unique to your VM:

# SpiffArena on Ubuntu 24.04 LTS by sac
# Generated on first boot 2026-08-07T09:22:41Z. Unique to this VM. SPIFFARENA_URL=http://<vm-public-ip> SPIFFARENA_ADMIN_USERNAME=spiffadmin-613eb2 SPIFFARENA_ADMIN_PASSWORD=<set-at-first-boot> SPIFFARENA_OPENID_CLIENT_SECRET=<set-at-first-boot>

The administrator username is randomly generated, as well as the password. This is deliberate, and Step 7 explains why.

Step 7 - Confirm SpiffArena's published demo logins do not work

SpiffArena's development sign-in ships a set of accounts whose passwords are published in the project's own configuration. They are admin/admin, nelson/nelson, malala/malala, oskar/oskar, and several more in the local development profile. This image deletes those files from the installed package outright, so none of them exists.

Prove it:

for u in admin nelson malala oskar jason kevin dan jon; do
R=$(curl -s -o /dev/null -w '%{redirect_url}' -X POST \
  http://127.0.0.1:7000/openid/form_submit \
  --data-urlencode "Uname=$u" --data-urlencode "Pass=$u" \
  --data-urlencode 'redirect_uri=http://127.0.0.1/v1.0/login_return') case "$R" in *code=*) printf '%-16s -> ACCEPTED\n' "$u/$u" ;; *) printf '%-16s -> rejected\n' "$u/$u" ;; esac done

Expected output, with every login rejected:

admin/admin -> rejected nelson/nelson -> rejected malala/malala -> rejected oskar/oskar -> rejected jason/jason -> rejected kevin/kevin -> rejected dan/dan -> rejected jon/jon -> rejected

This image has a second, more important hardening. SpiffArena's own authors describe its built-in sign-in as "definitely not a production ready system". Its back-channel token endpoint issues a signed administrator token without ever checking the password. Only the API itself calls that endpoint, over loopback, so this image blocks it at nginx and it is unreachable from the network:

curl -s -o /dev/null -w 'POST /openid/token -> HTTP %{http_code}\n' -X POST http://localhost/openid/token
curl -s -o /dev/null -w 'POST /openid/refresh -> HTTP %{http_code}\n' -X POST http://localhost/openid/refresh

Expected output:

POST /openid/token -> HTTP 403 POST /openid/refresh -> HTTP 403

With no account whose name or password is published anywhere, and no reachable endpoint that skips the password check, there is nothing on this VM that an attacker can guess. The sign-in page itself verifies the password and works normally.

Step 8 - Sign in to the web interface

Open http://<vm-public-ip>/ in a browser. The site redirects you to the sign-in form. Enter the username and password from Step 6.

After you sign in, you land on the home screen. The navigation shows Processes, Process Instances, Data Stores, Messages and Configuration. Choose Processes to see the process model repository, which ships with the SecureAnyCloud Examples group.

Step 9 - Open the example model in the BPMN editor

Expand SecureAnyCloud Examples, choose the Hello World model, open the Files tab and select hello-world.bpmn.

The bundled BPMN editor opens with the full modelling palette on the left and a properties panel on the right. The example has three nodes: a start event, a script task named Set greeting that assigns two process variables, and an end event.

Drag new elements from the palette, connect them and edit their properties. Then press Save. The model is written back to the git repository on the VM, so every change to a business process is versioned.

Step 10 - Run a process instance

Return to the Hello World model page and press Start. SpiffArena creates a process instance, runs it, and takes you to the instance view.

The instance page shows the status, who started it, when it started and finished, and the git revision of the model that was executed. The Diagram tab renders the same BPMN diagram with every completed element shaded, so you can see exactly which path the instance took.

The Milestones, Events, Messages and Tasks tabs hold the rest of the audit trail, including the data each task produced.

Step 11 - Run the shipped self test

The image ships a self test that exercises the whole appliance end to end. It checks the health endpoint, the rejection of every published demo login, your own credential, the blocked token endpoint and the loopback binding. It also creates and executes a real process instance and checks the value its script task computed:

sudo /usr/local/sbin/spiffarena-selftest.sh

Expected output:

process instance 6 ran to completion as 'spiffadmin-613eb2' OK

Any final line other than OK is a failure, and the reason is printed above it. Run the self test after any configuration change.

Step 12 - Add your own process models

Process models live in a git repository on the VM. You can create them entirely from the web interface. Choose Processes, then Add Process Group, and add a model and a BPMN file inside it. Alternatively, work directly on disk:

sudo ls -R /var/lib/spiffarena/process-models

Expected output:

/var/lib/spiffarena/process-models: sac-demo /var/lib/spiffarena/process-models/sac-demo: hello-world process_group.json /var/lib/spiffarena/process-models/sac-demo/hello-world: hello-world.bpmn process_model.json

Each group directory holds a process_group.json, and each model directory a process_model.json naming its primary BPMN file and process id. The directory is a git working tree, so you can inspect the history of every model:

sudo -u spiffarena git -C /var/lib/spiffarena/process-models log --oneline

Expected output:

8276a04 sac: seed example process models

To pull a library of models in from your own repository, add it as a remote and merge, or clone it into a subdirectory. The application picks up whatever is on disk.

Step 13 - Back up

Your data lives in two places: the database and the process model repository.

sudo install -d -m 0700 /var/backups/spiffarena
sudo sqlite3 /var/lib/spiffarena/db.sqlite3 ".backup '/var/backups/spiffarena/db-$(date +%F).sqlite3'"
sudo tar -czf /var/backups/spiffarena/process-models-$(date +%F).tar.gz -C /var/lib/spiffarena process-models
sudo ls -lh /var/backups/spiffarena

.backup takes a consistent snapshot while the application is running, so no downtime is needed.

Copy both files off the VM. Azure Blob Storage or any object store is fine. For a byte-for-byte restore, keep /etc/spiffarena/spiffarena.env with them, because it holds this VM's encryption key.

Step 14 - Change the administrator password, or add users

The accounts for the built-in sign-in are defined in one file:

sudo cat /etc/spiffarena/permissions.yml

Edit the password: value under your administrator to change it, or add another user and put their email address into a group. Then restart the API to pick up the change:

sudo systemctl restart spiffarena.service

The groups: and permissions: blocks control who can do what. The rule uri: /* with actions: [all] grants full administration, and finer-grained rules can be scoped to individual process groups and models. Upstream documents the full permission URL syntax.

For anything beyond a small team, point SpiffArena at a real identity provider instead. It speaks standard OpenID Connect. Set SPIFFWORKFLOW_BACKEND_AUTH_CONFIGS__0__uri, __client_id and __client_secret in /etc/spiffarena/spiffarena.env to your Entra ID, Keycloak or Okta tenant, and restart. Pointing that URI anywhere other than this VM's own /openid also removes the built-in sign-in from the application entirely.

Set your own domain and TLS

The image serves plain HTTP, so it works as soon as it boots. Before you put real business processes on it, give it a hostname and a certificate.

Point a DNS A record at the VM's public IP, then run:

sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d spiff.example.com --redirect --agree-tos -m you@example.com

Certbot edits the nginx site in place and installs a renewal timer. Then tell the application its new address, because the sign-in redirect and the browser bundle both use it:

sudo sed -i \
  -e 's|^SPIFFWORKFLOW_BACKEND_URL=.*|SPIFFWORKFLOW_BACKEND_URL=https://spiff.example.com|' \
  -e 's|^SPIFFWORKFLOW_BACKEND_URL_FOR_FRONTEND=.*|SPIFFWORKFLOW_BACKEND_URL_FOR_FRONTEND=https://spiff.example.com|' \
  -e 's|^SPIFFWORKFLOW_BACKEND_CORS_ALLOW_ORIGINS=.*|SPIFFWORKFLOW_BACKEND_CORS_ALLOW_ORIGINS=https://spiff.example.com|' \
  -e 's|^SPIFFWORKFLOW_BACKEND_AUTH_CONFIGS__0__uri=.*|SPIFFWORKFLOW_BACKEND_AUTH_CONFIGS__0__uri=https://spiff.example.com/openid|' \
  /etc/spiffarena/spiffarena.env
sudo sed -i "s|BACKEND_BASE_URL = '[^']*'|BACKEND_BASE_URL = 'https://spiff.example.com/v1.0'|" \
  /opt/spiffarena/frontend/index.html
sudo systemctl restart spiffarena.service spiffarena-scheduler.service

Finally, tighten the NSG so that port 80 only serves the certbot challenge and redirect, and restrict port 22 to your management network.

Maintenance and production notes

Patching. Unattended security upgrades are enabled, so the OS keeps itself current. The application is pinned to upstream tag v3.0.0. To move to a newer release, take a backup first, then follow upstream's release notes.

Sizing. On Standard_B2s, the whole appliance idles at well under 1 GiB of RAM, which leaves comfortable headroom. Scale up if you run many concurrent process instances or models that carry large data payloads. The image ships no swap, because Azure manages swap on the ephemeral resource disk.

Where things live. Application at /opt/spiffarena, configuration at /etc/spiffarena, database and process models at /var/lib/spiffarena, logs via journalctl -u spiffarena.

Scaling beyond one VM. This image is upstream's own minimal deployment, hardened. If you outgrow it, upstream's next steps are an external MySQL or PostgreSQL database and a Redis or RabbitMQ broker for Celery. Configure both in /etc/spiffarena/spiffarena.env. Point SPIFFWORKFLOW_BACKEND_DATABASE_URI at the external database, and set SPIFFWORKFLOW_BACKEND_CELERY_ENABLED=true with a broker URL. The appliance is a starting point, not a dead end.

Support. Every SecureAnyCloud image comes with 24/7 support. Contact us through secureanycloud.com.

Deploy on Azure

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