Move the namespace writer
Move namespace-writing responsibility by preparing the destination, transferring the approved writer custody, changing the authoritative designation from the current writer, and verifying the new writer before retiring the old copy. Coordinate the handover as one attended operation.
This guide covers an existing, reachable writer and an already enrolled target in the same namespace and initialized OpenBao cluster. It does not move OpenBao leadership, Raft data, DNS authority, DNS publication or certificate storage. Those roles have separate owners and acceptance procedures.
The required isolated OpenBao management endpoint and its private DNS must follow
the writer. namespace web starts the implemented temporary endpoint on the
current writer and refuses missing private-network or DNS prerequisites. The
custody/designation edit alone does not provision those prerequisites. Complete
the separate isolation, routing and old-endpoint retirement checks before
reporting a successful management-endpoint handover.
Understand the handover boundary
Enclavr currently has no dedicated atomic writer-transfer command. The supported designation change is an explicit edit to the complete assets document by the currently designated writer. The CLI editor verifies the current machine's hostname, selects an accepted writer connection, checks item-update capability, validates the edited document, asks for confirmation, and verifies the write.
That edit does not transport credentials, rebind a host-bound connection, update an AppRole's server restrictions, revoke existing tokens, move issuance checkpoints or provide automatic rollback. Ordinary access-management forms protect the current writer's identity and custody fields; changing scoped permissions there is not a writer-transfer workflow.
| State | Required outcome |
|---|---|
namespace_writer_host |
Exactly one declared host, matching the new writer's actual hostname. |
Existing writer entry in openbao_roles.roles |
Accurate owner, target host and literal protected connection path; the approved identity and scope remain intact. |
| Writer connection | Accepted for the same namespace and cluster, usable from the destination, with the required existing update scope. |
| Each host's normal runtime connection | Its own accepted consumer connection remains the runtime source. |
| Private OpenBao management endpoint | Declare the new writer's isolated placement, publish/adopt its private DNS and start it with namespace web; verify the old endpoint stops. |
| Old writer custody | Retained under operator control until acceptance, then retired from operational use. |
The hostname check is an Enclavr application boundary. Changing it does not invalidate an OpenBao credential or token held elsewhere.
1. Discover and record the current state
On an accepted member, from its repository root, run:
./enclavr namespace status
Record the current writer, its declared role and scope, the exact custody path, the destination's exact inventory hostname, and the existing cluster identity. Use role declarations rather than searching for credential files. A denied lookup does not establish that a role or connection is missing.
Record the intended destination account and the accepted writer connection's exact destination path. The initial provisioning convention is:
${XDG_STATE_HOME:-$HOME/.local/state}/enclavr-openbao-writer/connection.json
An existing accepted connection may use another protected path. Normal writes
use the role registry's literal connection_file; they do not derive a path
from the caller's home or try the provisioning convention as a fallback. In the
assets role registry, connection_file must be a clean absolute path, without
shell variables or ~. Keep only non-secret names, paths, approvals and
verification results in the handover record.
If namespace_writer_host is not yet established, establish the first writer
on the host already holding the accepted connection before planning a transfer.
If the current writer is unavailable, use an explicitly planned recovery
procedure; the destination cannot appoint itself through ordinary priv edit.
2. Prepare the destination and recovery path
- Confirm the target is declared exactly once and already has a working checkout,
its own accepted runtime connection, and connectivity to the pinned OpenBao
endpoints. Run
hostnameand./enclavr namespace statusthere. Successful status proves discovery/read access, not writer capability. - Confirm the existing writer identity is authorized for the new custody owner
and consumer host. A guide or a host move is not approval for additional
resources. Any new/replacement AppRole, ACL, credential or expanded scope
requires explicit prior approval recorded in the repository's
docs/openbao-change-approvals.md. - Inspect existing connection and issuance bindings privately. If the connection or its checkpoint is bound to the old host, or server CIDR restrictions exclude the destination, stop for an approved administrator migration and acceptance. Editing assets does not resolve those constraints. Do not remove a hostname binding or rewrite a checkpoint to make a copied credential pass.
- Verify the staged writer's live update capabilities for every required existing item using approved OpenBao capability inspection. The core assets, secrets and users grants must remain available. A status report or an operation's plan-only output is not evidence of these capabilities. Enclavr has no dedicated pre-cutover target writer-acceptance command.
- Resolve pending writes and retained access-change checkpoints before moving ownership. Quiesce namespace editing and close stale editor sessions on both hosts. Keep the old accepted connection protected and available until the destination is verified.
- Establish a usable recovery path before changing the designation. Enclavr's
attended administrator workflow is writer-only and discovers an existing local
enclavr-openbaocontainer through a local Docker socket. If that workflow is needed after the move, the target must already meet those prerequisites. A working namespace writer connection alone does not provide administrator recovery, role issuance or access-management authority. Do not relocate a Raft volume or initialize a cluster as part of this handover.
See Prepare and enroll a host and OpenBao operations for those separate prerequisites.
Private management endpoint prerequisite
The required https://openbao.<namespace>/ui/ endpoint belongs on the declared
writer, using a dedicated private virtual interface/address, network namespace,
container workload and network. Its private port 443 uses the existing OpenBao
TLS identity and CA. It must remain separate from public ingress: no
caddy-mask-proxy route, shared listener or public application network, AWS
Global Accelerator forwarding, wildcard host binding, Let's Encrypt certificate
or Tailscale Service. Ordinary tailnet routing to the isolated endpoint is allowed.
Prepare and verify the destination's declared hosts[].openbao_web network,
private route and isolation before the designation cutover. The start command
does not create networks, routes or access grants. Do not replace missing
prerequisites with a public proxy route.
Plan the corresponding private DNS update and old-endpoint retirement while
preserving existing scoped consumer/API access. See
OpenBao browser access
for the supported startup workflow; certificate export alone does not provide
this endpoint or its relocation.
3. Stage the approved writer custody
Use an authenticated, host-key-verified transfer to the exact destination
account, or reuse an already accepted destination copy when its identity and
contents match the approved handover. Keep the directory 0700 and the
connection a regular 0600 file under parents not writable by other accounts.
Check for conflicting files and symlinks before installation; never overwrite a
different connection. An identical staged file is a successful no-op.
This is a controlled handover of the approved writer identity, not a source for
other hosts' consumer credentials. Preserve the existing namespace, cluster ID,
CA, endpoint set, RoleID/SecretID and approved item scope. Keep credentials out of
argv, Git, Docker build contexts, logs and transcripts. Do not change either
host's runtime .env to select the writer connection.
Inventory writer-owned enrollment/issuance checkpoints and automation separately. The designation change does not relocate them. Transfer only custody explicitly included in the approved operation, preserving checkpoints and their bindings. DNS publisher/observer connections remain at their declared owners unless a separate move has been approved. Recovery shares and CA signing keys remain operator-owned and are not bundled with a routine writer connection transfer.
4. Change the designation from the current writer
On the current writer, use the attended CLI editor:
./enclavr priv edit --namespace '<namespace>' --component assets
Replace <namespace> with the selected namespace. This command opens the
protected component in Vim; it is a CLI workflow. In one complete assets edit:
- Set
namespace_writer_hostto the destination's exact declared hostname. - Update the existing writer role's
owner_host,identity.hostnameandconnection_fileto the verified destination custody. These declarations must describe already accepted identity state; they do not reissue or rebind a credential. Preserve the role's identity name, enabled/write state, core grants and every other approved permission. - Preserve unrelated hosts, services, roles and DNS-publication declarations.
Review the complete validated change and confirm publication. Do not edit a partial host projection or create a second writer-role entry. Saving Vim alone does not publish; the CLI requires its subsequent confirmation and checks for concurrent version/fingerprint changes. Inspect read-back before continuing and keep complete repository assets mirrors aligned with the accepted document.
After this write, the destination is the designated writer. The old host's normal namespace-write workflows must refuse further edits, even while its protected connection still exists. Do not rely on a previously opened editor as a way around that boundary.
5. Verify the new writer
On the new writer, run:
./enclavr namespace status
./enclavr priv edit --namespace '<namespace>' --component assets
Confirm status shows the new owner, target and custody path consistently. The editor must open through the existing accepted writer and its capability checks. Exit without changes first; this should make no namespace write. It proves the edit preflight, not a completed update.
Complete a planned, meaningful write to an existing item and verify read-back. Use a pre-agreed existing-item metadata correction, such as completing the writer's custody description. If already correct with verified write evidence, preserve the no-op rather than introduce a dummy edit solely to test permissions. Repeat the unchanged operation and confirm no extra item version.
The assets change does not invalidate an unchanged Caddy publication. If the Caddyfile itself changed, use the new writer's TUI preparation and publication forms described in Caddy publication troubleshooting, then deploy and verify affected serving hosts. Keep DNS publishing with its existing owner; verify any affected consumer through its normal workflow. A writer move alone does not require restarting OpenBao or every host service.
After publishing and adopting the current DNS placement, run the CLI command
./enclavr namespace web --yes to start the endpoint on the new writer. Repeated
starts retain the original four-hour deadline. The old supervisor detects changed
writer ownership or a lost lease and stops; verify this on the old host.
Verify that private DNS resolves to the new writer's isolated endpoint, that an authorized private client
can reach it with the existing OpenBao TLS identity, and that public ingress
cannot receive or forward those requests. Verify existing scoped API consumers
still work. Record failed endpoint checks as incomplete acceptance; a successful
namespace write or Caddy publication does not prove these network checks.
On the old writer, run ./enclavr namespace status and confirm that it sees
the new designation. A fresh attempted priv edit --component assets must be
refused as a non-writer before opening an editor or performing a namespace write.
6. Retire old operational custody
After successful read-back, publication and affected-consumer acceptance, remove the old operational writer connection and any transfer staging copies. Retain only approved operator backups outside routine runtime discovery. End old writer and administrator sessions and revoke their session tokens through their normal logout procedure. Preserve the old host's own consumer connection and enrollment.
Retire the old private management endpoint and its obsolete private DNS placement after the new endpoint passes acceptance. Keep the independent DNS authority, publisher and existing scoped API access intact. Endpoint retirement must not be inferred from deleting the writer connection file.
If the same AppRole/SecretID was moved, do not delete that AppRole, its policy or the shared SecretID as old-host cleanup: the new writer still uses them. Retiring a local file is not server-side revocation. Suspected credential exposure needs an explicitly approved rotation with renewed acceptance.
Record the completed owner/custody change, successful write and read-back, unchanged repeat, old-host refusal, publication/consumer verification, and retirement of old operational copies. Repeating an already completed handover should only verify this state, without creating credentials or writing another assets version.
Interrupted handover and rollback
| Failure point | Recovery action |
|---|---|
| Before the designation is published | Keep the existing writer authoritative. Resolve staging/access conflicts or remove only this attempt's destination staging files. |
| Required private endpoint is unavailable or not isolated | Keep the current ownership while the declared endpoint prerequisites and routing are completed; do not route management traffic through public ingress. |
| Assets publication reports a conflict | Read current authoritative state and prepare a fresh reviewed edit on the current writer. Do not force old version numbers. |
| Publication response is uncertain | Read namespace status and authoritative assets before retrying. Establish which host is now designated; do not assume failure means no write occurred. |
| New writer works, but the move must be reversed | Verify old custody is still usable, then use the new writer to restore the old designation and matching role metadata. Verify the restored writer before retiring the abandoned destination copy. Unchanged Caddy publications remain valid. |
| Designation changed but the new writer cannot authenticate/write | Keep both hosts' protected evidence and stop ordinary mutation attempts. The old host is now refused too. Use the prearranged, authorized administrator/recovery path against the same cluster to restore consistent ownership; retaining the old file alone is not rollback. |
| Caddy reports stale source versions after handover | Update the checkout and relaunch Enclavr; this retired check belongs to an older build. Current code accepts unchanged published Caddyfiles across asset edits and writer moves. |
Never create a replacement namespace, reset cluster identity, change the seal/CA, disable writer checks or broaden a consumer's permissions to force completion. Resolve the specific failed prerequisite and retry from observed state.
For the underlying edit behavior, see Edit private data safely.