Skip to content

Data Persistence ​

Everything created through the API survives a restart, a crash and a kill -9: resource groups, vaults, secrets (every version, soft-deleted ones included) and role assignments. Nothing is lost that the server acknowledged, because every change is on disk before the response is sent.

Where ​

whatwherecreated
journal, snapshotthe data directory (config state.dir)first boot, first write
state.key~/.armite/ (next to the CA key), 0600first boot
azurite/the data directory, Azurite's own filesfirst storage account

The data directory is ~/.local/share/armite on Linux, ~/Library/Application Support/armite on macOS, %LOCALAPPDATA%\armite on Windows — or $ARMITE_HOME/state when ARMITE_HOME is set, as in Docker (/data/state). The state files are encrypted (AES-256-GCM) with the key, so the data directory on its own cannot be read, and without state.key it cannot be opened. Deleting the data directory is the way to start over: the keys stay, clients stay trusted. Deleting the keys alone leaves data nobody can read — delete both instead.

To supply your own key instead of the generated one, set state.key in armite.yaml or ARMITE_STATE_KEY to a base64 32-byte value (openssl rand -base64 32). Then the state directory is unreadable to anyone who does not also have that value.

Blob contents are Azurite's and are not encrypted; account metadata and keys are Armite's and are.

How ​

Each change is one record: the new state of one resource, assignment or secret, or its deletion. Records are appended to the journal and synced to disk one at a time; the response goes out after the sync. On boot the snapshot is loaded, then the journal replayed over it.

When the journal grows past state.compact_after_mb (default 8), the current state is written to a new snapshot and the journal trimmed, in the background, without pausing requests. Set it to 0 to never compact.

A crash in the middle of a write leaves a torn record at the end of the journal. On the next boot it is dropped and logged; everything before it is intact. Anything else that fails to open - a changed byte, a different key - stops the boot with record cannot be opened: corrupted, or sealed with another key.

Starting over ​

Stop the server and delete the state directory; the key can stay. With compose: docker compose down -v removes both volumes.

To run without persistence, set state.dir: "": everything stays in memory and dies with the process, as before.

Seeds and the journal ​

role_assignments in the configuration are applied at every boot as "must exist": a seed that is already there - replayed from the journal, or granted by a client under its own name - is left alone. Removing a seed from the configuration does not revoke it; revoke it through the API (az role assignment delete) or start over.

Throughput ​

Every write costs one fsync, a few milliseconds on a local disk. That is a few hundred resource writes per second, far more than any client sends. Filesystems that are slow or unreliable at syncing make it worse: on WSL, keep the state directory on the Linux filesystem, not under /mnt/c.

Released under the Apache License 2.0. Azure, Entra and Key Vault are Microsoft trademarks; Armite is not affiliated with or endorsed by Microsoft.