Repository environment and authentication
./enclavr host deploy --yes needs a configured secret-store connection before it can load or plan the current host. ./build-all.sh builds local binaries and images and does not require Enclavr namespace credentials. A build failure and a deployment authentication failure need separate diagnosis.
Choose the configuration for this host
| Host state | Required local values | Why they are required |
|---|---|---|
| Accepted OpenBao consumer | configr_openbao_config_file; optionally spell out configr_secret_store_provider=openbao |
OpenBao is the default. The absolute file path locates this host's accepted, scoped connection and transport trust. |
Local build with build-all.sh |
No namespace credentials | Compilation and image preparation do not load namespace runtime inputs. |
OpenBao is the default: omitting or leaving configr_secret_store_provider empty selects OpenBao, even if old 1Password credentials remain in the environment. The accepted connection path is still required; Enclavr does not discover or create credentials automatically. --yes confirms deployment; it supplies no credentials and bypasses no validation.
OpenBao is the only supported runtime provider. An explicit 1password selection is rejected before any external authentication. If an invocation asks for a service-account token, check for an older checkout or launcher target. Supply the accepted OpenBao connection instead of adding old credentials.
Runtime inputs belong in OpenBao
After authenticating the accepted connection, Go reads these four fields from secrets.<namespace>:
Field in secrets.<namespace> |
Purpose |
|---|---|
configr_src_ref |
Identifies the source repository used by repository/bootstrap operations. |
configr_op_hostlist_json_object_ref |
Must contain exactly op://<namespace>/assets.<namespace>/document; selects the authoritative inventory and feature policy. |
configr_users |
Declares managed users and their canonical personal-details references. |
configr_op_repo_read_key |
Supplies protected repository read access; the runtime contract requires it even when a particular action does not fetch the repository. |
Core item names are assets.<namespace>, secrets.<namespace>, and users.<namespace>. The assets document must satisfy the schema. Deployment resolves protected inputs needed by its selected actions, so referenced personal details and service documents must also be readable when used.
Those values are authoritative in OpenBao. Historical assignments in .env or the process environment cannot override them. Namespace repair edits secrets and personal details through the same OpenBao private editor used by private synchronization, retaining confirmation and conflict checks.
OpenBao: explicit selection and an accepted connection
For a host that has completed the attended consumer acceptance/cutover workflow, use:
configr_secret_store_provider=openbao
configr_openbao_config_file=/absolute/path/to/protected/openbao-connection.json
The connection file contains this host's scoped AppRole identity, expected namespace and cluster identity, HTTPS endpoints, pinned TLS trust, and permitted item set. It must already exist and satisfy the protected-file requirements. The path cannot be relative. Do not create a connection by hand or copy another host's credentials.
The runtime reads canonical namespace values from OpenBao, including references
spelled op://.... Those logical references identify OpenBao items. Retired
configr_op_service_account_name and configr_op_service_account_key assignments
are unsupported in the protected runtime environment; remove those obsolete
assignments instead of supplying an external-provider credential. Missing
connection files, rejected credentials, unavailable endpoints, or identity
mismatches fail closed without switching providers.
The provider line is optional because OpenBao is the default; it is included for clarity. Combining an OpenBao connection path with configr_secret_store_provider=1password is rejected. See Prepare a host and OpenBao in Enclavr for acceptance and recovery procedures.
File location, permissions, and environment precedence
- An explicit
--env-file PATHon commands supporting it selects that file. - Otherwise, exported
CONFIGR_ENV_FILEselects the file. - Otherwise, Enclavr reads
.envin the checkout selected by its launcher, not an arbitrary current directory. - For each supported key, a nonempty file value wins over the exported environment value. An absent or empty file value takes the exported value. An unreadable, malformed, or overly permissive selected file remains an error even if environment values are present.
Use mode 0600, readable by the account running Enclavr:
chmod 600 .env
./enclavr config validate
./enclavr host plan
Create or edit protected files in Vim. Keep secrets out of command arguments, shell history, logs, and Git. .env is parsed as assignments, not executed: simple single or double quotes and an optional export prefix are accepted; $VARIABLE, ~, and command substitutions are not expanded. Put comments on their own lines. Duplicate keys and unknown configr_* assignments are rejected. Enclavr reads the file itself; do not source .env.
Environment-only operation is supported when the required settings are exported to the Enclavr process through a protected mechanism and no conflicting file assignments exist. An unexported shell variable is insufficient. Changing an exported token will not override a stale nonempty token in .env. Do not use the internal CONFIGR_DOTENV_RESOLVED handoff marker as an override mechanism.
Each checkout has its own ignored .env; cloning or moving tracked files does not provision it. An installed enclavr wrapper can still point to an older checkout. Check command -v enclavr, inspect the wrapper or symlink target, and use ./enclavr from the intended checkout while diagnosing. Do not prefix the whole command with sudo: that can change the user and inherited environment; deployment adapters handle their own required escalation.
Separate a build failure from a runtime failure
./build-all.sh --go-only
./enclavr config validate
./enclavr host plan
The first command compiles without Docker or namespace authentication. A full build also needs a usable Docker daemon and Buildx. Its Unbound preparation calls enclavr internal dns render-unbound, which renders supplied UNBOUND_* inputs and Go defaults without loading .env or contacting a secret store.
Native cgo builds require a C compiler and development headers (build-essential on Ubuntu 26.04/Kali). Go dependencies and public image downloads require working DNS and network access. Public Docker builds normally use a temporary Docker configuration without registry credentials or credential helpers when those settings exist; exported MWC_DOCKER_USE_HOST_CREDENTIALS=true opts into the host's configuration. An external Docker credential-helper, Git/SSH integration, or shell wrapper failure is separate from Enclavr namespace authentication and is not fixed by adding more configr_* keys.
Preserve the first failing command, exit status, source, line, and caller stack from a build. Do not use bash -x around protected inputs. Share error output only after removing secrets.
| Failure | What to check |
|---|---|
Missing configr_openbao_config_file |
Supply the absolute path to this host's accepted OpenBao connection; OpenBao is the default. |
| A service-account token is requested | Check the checkout and launcher version; the OpenBao-only runtime does not request external-provider credentials. |
| Protected environment permissions are too broad | Protect the selected file with chmod 600; check its owner and readability. |
| Explicit legacy provider selection rejected | Configure the accepted OpenBao connection; no external sign-in is attempted. |
A secrets.<namespace> field or referenced item cannot be read |
Exact item/field name and the scoped OpenBao policy; keep canonical data in the namespace. |
| OpenBao connection is missing or rejected | The accepted host-specific connection and explicit provider selection; no 1Password fallback. |
| Go, compiler, Docker, or image-pull failure | The failing build component and its prerequisites; .env is not a build prerequisite. |
config validate and host plan do not apply host actions. They also do not prove that every protected input for a later action is readable. After they succeed and the plan is reviewed, follow Plan, deploy, and verify.
Tunnel schema and container startup errors
If OpenBao authentication succeeds but validation rejects udp_tcp_tunnelr.endpoints, compare the checkout with the installed tunnel version. Runtime version 2 uses endpoints; an older checkout expecting only target and rules lacks the matching schema, planner, and runtime. Restore the complete version-2 implementation and its generated schema documentation. Do not downgrade authoritative assets just to satisfy the older checkout. Uncommitted changes in a previous checkout do not travel with a Git clone.
A container exit status of 127 does not by itself identify a missing executable. Inspect Docker's recorded startup error. A file/directory mount mismatch involving /run/xtables.lock or /run/enclavr-tunnel.lock can occur after reboot: /run is volatile, and older short bind mounts can create directories at missing source paths.
The current adapter preserves existing regular lock files, repairs only empty directory placeholders, and installs a systemd tmpfiles declaration to recreate the files at boot before Docker starts. Nonempty directories, symlinks, and mounted directories are refused. The Compose lock mounts also disable automatic source-directory creation. See the official Docker bind-mount documentation and systemd-tmpfiles documentation.
From the current checkout on the configured ingress host, review and deploy only the tunnel:
./enclavr config validate
./enclavr host plan --only udp-tcp-tunnelr.deploy
./enclavr host deploy --only udp-tcp-tunnelr.deploy --yes
./enclavr host status --only udp-tcp-tunnelr.deploy
docker exec udp-tcp-tunnelr /usr/local/bin/udp-tcp-tunnelr --check-active
Verify the container is healthy, desired and deployed generations match, and backend reachability is reported for both configured families. Repeat the same deployment to check that the container identity and lock-file inodes remain unchanged. These checks do not replace a client-to-service test through the ingress host; a TCP backend probe confirms transport reachability only.
Local run logs
The checkout keeps diagnostics in logs_enclavr_local/, excluded from both Git and the general Docker build context. Files are private (0600), with protected category directories (0700). Each invocation gets a separate file so retries and concurrent runs preserve earlier evidence.
| Directory | Contents |
|---|---|
commands/ |
JSON lines recording the canonical CLI command label, PID, UTC start/end times, duration, exit status, and value-free failure metadata. Created before configuration validation, so missing connection failures are recorded. |
sessions/ |
The same lifecycle record for a TUI session launched with ./enclavr. |
scripts/ |
Messages written through the shared Bash logging helpers and failure diagnostics: command expression, status, source, line, and caller stack. |
deploy/ |
Host and fleet deployment diagnostics, with their path reported by the application. Older logs under .state/enclavr/deploy/ remain in place. |
CLI failures print the run-log path on stderr. Script failures print their script-log path. To find recent files, use ls -lt logs_enclavr_local/commands/ or ls -lt logs_enclavr_local/scripts/, then open the selected file in Vim.
Installed shell helpers receive the absolute checkout path through
ENCLAVR_REPO_ROOT in their managed service environment. The Unbound installer
sets it in the macOS resolver plist and Linux network-reconciliation environment.
The shared runtime writes to that checkout's logs_enclavr_local/scripts/;
it never derives a checkout from an installed /usr/local/libexec path.
Source-tree scripts can still identify the canonical src/scripts/lib layout.
Logging supports macOS's system Bash 3.2 and preserves the operation's exit status
if the destination is unavailable.
Run metadata does not record argument values, environment contents, protected stdin, terminal screens, or keystrokes. Arbitrary Go error text is also excluded because it can embed protected process output; the original terminal diagnostic remains available, and known value-free failures such as a missing OpenBao connection receive an explanatory record. Script logs record canonical log messages, not a blanket copy of subprocess stdout/stderr. Scripts with their own EXIT cleanup must call mwc_script_log_finish if they want a final status record; the error trap independently preserves failure diagnostics.
Treat deployment diagnostics and all logs as private and review them before sharing. A logging failure produces a warning while preserving the command's result. Logs are not automatically deleted; review and remove old local files when they are no longer needed. Git exclusion is not a substitute for protecting or reviewing their contents.