Configure storage
Available now
A node keeps designs, facilities, packages and saved matches in object storage. A fresh node starts on local storage — files on the machine it runs on — which works, and is where the installer leaves you.
You can point it somewhere else at any time, from the running node. There is no redeploy and no configuration file to edit.
This is an operator task: /settings/storage needs an admin key.
What you are looking at
The panel shows two things that are easy to confuse, and separates them on purpose:
- The configuration — the provider and bucket the node is set to use.
- What answered — what it is actually connected to, and how many designs and facilities are in there.
When storage misbehaves, the gap between those two is usually the answer.
It also shows which credentials are set, by name only. The node cannot show you a credential value: it does not keep one it could read back. Credentials here are write-only — you can replace one, never read it.
Switching, in the panel
Pick a provider, give it a bucket or container, and fill in whatever credentials it needs.
The node checks the new backend before committing to anything: it connects, writes a probe object, reads it back, and confirms the directory structure — then, and only then, switches. If any of that fails you are told which part failed, and the node carries on serving from where it was. A wrong credential costs you an error message, not your node.
The panel leaves your existing data where it is. It switches which backend the node reads and writes; nothing is copied and nothing is deleted. The old data stays on the old backend — invisible to the node, still there.
That is usually what you want. If you need the data to come with you, or the old backend emptied, use the command line.
Switching from the command line
ohm storage config set works from a shell on the node, but it is a separate
process from the running node. It saves the new configuration, and the running node
does not pick it up until it is restarted — until then it keeps serving from the
old storage. The panel does not have this limit: a switch made there takes effect
straight away.
So after a command-line switch, restart the node's API, then check /settings/storage
shows the new backend as what answered.
Checking whether a restart is pending
reads a local file the node's API writes while it is running — a heartbeat, not an HTTP call, because the command line has no way to log in to the node as itself. It reports whether the node is running, what backend it is actually serving (not just configured for), and whether that agrees with what was just saved. When it does not agree, a restart is pending: the node keeps answering from the backend it booted with until you restart it.
A second switch or migrate is refused while one is already pending. Restart first — switching twice without restarting in between would mean the first switch is silently lost the moment the node finally does restart, since only the most recently saved configuration survives to be applied.
The panel shows the same thing, without needing the command line: a banner on
/settings/storage when a restart is pending, naming both the backend the
node is still running on and the one it will switch to once restarted. The
inline panel switch itself is unaffected — it still applies at once and never
leaves anything pending.
Moving or erasing data
Moving data is available from the command line only. It is not in the panel: it copies potentially a great deal of data, and does not belong behind a button you can press by accident.
Migrate — bring the data with you
ohm storage config set --provider azure_blob --bucket production \
--mode migrate \
--credential account_name=myaccount --credential account_key=secret
Copies everything to the new backend, verifies it, and only then switches. The node keeps serving from the old storage for the whole copy, so a migration that fails partway — or that you give up on — leaves a working node on the storage you started with. Every object is read back from the destination and compared before the switch happens: a copy that says it verified, did.
Migrate is a command-line operation
--mode migrate works from the CLI. Requested over the API it is refused with a
400 that points at the CLI, and changes nothing: the background job it used to
start could never find the storage it was meant to copy from.
A change to the old storage during the copy refuses the switch
Verifying the copy proves it matches what was read — not that the old storage held still while reading it. So it is checked again after the copy finishes, and if anything was added, changed or deleted in between, the switch is refused and nothing is touched:
❌ The source changed while the copy was running (1 changed) and a copy
that verified against a moving source is not trustworthy. Nothing
was switched.
That is the migration doing its job. Re-run once nothing is writing to the old storage and it will go through.
Restart right after, and stop writers first if it must be complete
The running node keeps writing to the old storage until you restart it. A write during the copy is caught by the check above; one after the copy finishes but before you restart is not — a successful migrate prints the exact cutoff. Restart straight after migrating; if the move has to be complete with nothing missed, stop whatever writes to the node first.
Works between any two providers. Local to Azure, S3 to Google Cloud, whichever pair.
It does not erase the source. If you want the old backend emptied, migrate first, restart the node, confirm the new one is serving, then wipe separately.
Erasing the old storage
There is no single command that switches and erases: that was retired, because run from the command line it deleted the old storage while the running node was still serving from it. Erasing is its own step now, taken after you are sure the node no longer needs the old storage:
- Switch or migrate (in the panel, or from the command line followed by a restart).
- Confirm
/settings/storageshows the new backend as what answered, and that your designs and facilities are there. - Wipe the old backend — same echo guard as a switch (name the bucket you are
erasing, exactly), and
--dry-runreports what would go without deleting anything.
It refuses on its own if you get ahead of yourself: wiping the backend a running node is still live on, the saved configuration, the environment default with nothing saved, or anything while a restart is pending, all come back as an explained refusal rather than a deletion.
Reading the current configuration
For whether a restart is pending specifically, ohm storage status is more
direct — see above.
Background jobs
A node deployed with Docker Compose or on Azure also runs a worker for background jobs such as importing a design from a URL. Those jobs do not read or write your object storage, so switching storage does not affect them and there is nothing to change on the worker.
Where the configuration lives
In an encrypted file beside the node's data, not in the object store it configures — credentials for a new provider written into the old one would be orphaned the moment the switch took effect.
If you installed with the installer, that file is already on a mounted volume, so your configuration survives upgrading the container.
Credentials are encrypted with the node's own encryption secret. A node that was never given one refuses to store them at all, rather than pretending that encrypting with a published default key protects anything.