Skip to content

Release Notes

Sipke Schoorstra edited this page Aug 12, 2026 · 2 revisions

Release Notes

Newest first. Only changes that affect how you run or configure the images are listed here — image contents track the Elsa version in the tag.


2026-08 — Runtime writes moved off /app

⚠️ Breaking: the default SQLite path changed

Was Data Source=elsa.db — relative, so it resolved inside /app
Now Data Source=/data/elsa.db

You are affected if you relied on the default connection string and mounted a volume at /app to keep the database. That volume is no longer where the database is written, and after upgrading the image will start with an empty database — your existing one is still on the old volume, untouched.

You are not affected if you set an absolute SQLite path yourself, or use PostgreSQL, SQL Server, MySQL, Oracle or MongoDB.

To migrate, either move the mount and copy the file across:

# with the container stopped, copy elsa.db from the old volume to the new one
docker run --rm -v old-app-volume:/from -v elsa-data:/to alpine \
  sh -c 'cp /from/elsa.db /to/elsa.db'
docker run ... -v elsa-data:/data valenceruntimeimages.azurecr.io/runtime-server:<tag>

…or keep your existing layout by pinning the old path explicitly:

{
  "ConnectionStrings": { "Elsa": "Data Source=/app/elsa.db" },
  "CShells": { "Shells": { "Default": { "Features": {
    "SqliteWorkflowPersistence": { "ConnectionString": "Data Source=/app/elsa.db" },
    "SqliteIdentityPersistence": { "ConnectionString": "Data Source=/app/elsa.db" },
    "QuartzSqlite":              { "ConnectionString": "Data Source=/app/elsa.db" }
  } } } }
}

New writable paths

Everything the application writes now has a declared home outside /app — see Production Checklist for how to mount each one, including the Data Protection key ring caveat on /var/lib/valence-runtime.

Path Holds
/data The default SQLite database
/var/lib/valence-runtime Extracted packages, Nuplane store state and lock file, and HOME
/tmp NuGet scratch space

Kubernetes users: the images run as UID 1654, so a pod securityContext with fsGroup: 1654 is now required — see the manifest in Running the Images.

Automatic package reconciliation is now off by default

Nuplane:Setup:AutomaticReconciliation ships as false. Previously a background cycle polled the feeds every minute; every cycle after the first left package reconciliation in a degraded state, and it did so silently — /health and /alive stayed healthy throughout.

If you relied on packages being picked up without a restart, re-enable it explicitly, and note that Nuplane:Reconciliation:EnableAutomaticReconciliation is not the key to use — it is ignored while the Setup key is set.

Re-enabling is safe in these images. Earlier ones had a defect where every reconciliation cycle after startup left package reconciliation permanently degraded, silently — /health and /alive kept returning 200 throughout. That is fixed.

Startup is more forgiving

A package that cannot be resolved at startup no longer takes the whole host down; the last known good package set is used instead. This is what previously turned a mistaken version pin into a container that would not boot at all.

Offline and air-gapped startup

A mounted package directory containing the full transitive closure of your packages now lets a container start with no network access at all. See Extending with Nuplane. The mount may be :ro and needs no particular ownership.

readOnlyRootFilesystem is now supported

With /data (SQLite only), /var/lib/valence-runtime and a tmpfs at /tmp mounted writable, the root filesystem can be read-only. Verified on the server and combined images with a read-only root, --network none and a :ro package mount: full package set loaded, no filesystem violations, serving normally.

Clone this wiki locally