open-horizon / open-horizon/devops
mgmt-hub: OpenBao auth plugin is staged in /tmp, so systemd-tmpfiles deletes it and the bao container fails to start (exit 127)
Nobody has claimed this yet.
- Dominant language
- Shell
- Stars
- 12
- Forks
- 46
- PR merge metrics
- No merged PRs in 30d
Description
Summary
The all-in-one management hub stages the OpenBao auth plugin binary under /tmp and bind-mounts it into the bao container directly from there:
-
mgmt-hub/deploy-mgmt-hub.sh:290—TMP_DIR=/tmp/horizon-all-in-1 -
mgmt-hub/deploy-mgmt-hub.sh:770-771— plugin tarball extracted to$TMP_DIR/openbao/plugins -
mgmt-hub/docker-compose.yml:244:- /tmp/horizon-all-in-1/openbao/plugins/openbao-plugin-auth-openhorizon:/openbao/plugins/openbao-plugin-auth-openhorizon:ro
/tmp is not durable storage. On a stock Ubuntu host, /usr/lib/tmpfiles.d/tmp.conf contains:
D /tmp 1777 root root 30d
which means systemd-tmpfiles both wipes /tmp at every boot and deletes files older than 30 days during the daily systemd-tmpfiles-clean.timer run. The plugin binary is written once at install time and never touched again, so it reliably ages out after 30 days.
Why it fails silently, then breaks all at once
The running bao container holds the bind mount by inode, so it keeps working normally after the host file is deleted. Nothing is logged and nothing appears wrong — until the next time the container is recreated (Docker daemon upgrade/restart, host reboot, docker-compose up). At that point the mount source no longer exists.
Docker then auto-creates the missing bind source as a directory, while the container-side target is a file, producing a confusing error that does not mention the real problem:
failed to create task for container: failed to create shim task: OCI runtime create failed:
runc create failed: unable to start container process: error during container init:
error mounting "/tmp/horizon-all-in-1/openbao/plugins/openbao-plugin-auth-openhorizon" to rootfs at
"/openbao/plugins/openbao-plugin-auth-openhorizon": ... not a directory:
Are you trying to mount a directory onto a file (or vice-versa)?
The container exits 127. Note that although the service is declared restart: always, this is a create-time failure, so RestartCount stays at 0 and Docker never retries — the hub simply comes up permanently without OpenBao.
In our case the hub was installed 2026-05-23 and ran fine for two months. systemd-tmpfiles-clean.service last ran 2026-07-22, and a Docker daemon restart the following day left bao dead with the error above.
Steps to reproduce
-
Install the all-in-one management hub on a stock Ubuntu host:
curl -sSL https://raw.githubusercontent.com/open-horizon/devops/master/mgmt-hub/deploy-mgmt-hub.sh -o deploy-mgmt-hub.sh chmod +x deploy-mgmt-hub.sh && ./deploy-mgmt-hub.sh -
Confirm the plugin is staged in
/tmpand the container is healthy:ls -l /tmp/horizon-all-in-1/openbao/plugins/openbao-plugin-auth-openhorizon docker ps --filter name=bao -
Simulate the tmpfiles cleanup that occurs after 30 days (or a reboot):
sudo rm -rf /tmp/horizon-all-in-1The
baocontainer is still running and healthy at this point — this is the silent window. -
Restart the container the way a Docker upgrade or reboot would:
docker restart bao docker ps -a --filter name=bao # Exited (127) docker inspect bao --format '{{.State.Error}}'
To observe it without waiting 30 days, you can instead confirm the aging rule directly with grep '^[dD] /tmp' /usr/lib/tmpfiles.d/tmp.conf and check systemctl status systemd-tmpfiles-clean.timer.
Suggested improvements
In rough order of preference:
-
Stage the plugin somewhere persistent. Anywhere outside
/tmpfixes the root cause — e.g. aopenbao/plugins/directory next to the generateddocker-compose.ymlin the install directory, or/var/lib/horizon/openbao/plugins. This is a one-line change toTMP_DIRusage for this specific artifact plus the compose mount. -
Or hold the plugin in a named Docker volume (e.g.
bao-plugins-vol), populated at install time and mounted at/openbao/plugins. This puts the plugin under the same lifecycle management asbao-volandbao-logs-vol, which are already named volumes, and keeps it consistent with how the rest of OpenBao's state is handled. -
Mount the plugin directory rather than the individual file. Bind-mounting a single file is what turns a missing source into the misleading "directory onto a file" error. Mounting
.../openbao/plugins→/openbao/pluginsfails more clearly and also allows the plugin to be replaced/upgraded without editing the compose file. -
Add a preflight check. Have
deploy-mgmt-hub.shverify the plugin binary exists before bringing upbaoand re-stage it if not — ideally comparing against the SHA256 already registered in the OpenBao plugin catalog, since a mismatch there is its own failure mode. -
If
/tmpmust be retained, ship atmpfiles.ddrop-in that exempts the path from cleanup and restores it at boot.
Workaround
For anyone hitting this now: re-download the plugin matching the version in OPENBAO_PLUGIN_AUTH_OPENHORIZON_VERSION (checksums are published on the plugin's release page), place it somewhere persistent, and restore it. The registered SHA256 in the catalog must match the binary, so the same release version must be used. The container then starts, and OpenBao needs unsealing again with the key from the install summary.
We additionally added an /etc/tmpfiles.d/ drop-in so the file is re-copied into /tmp at boot and exempted from age-based cleaning, which survives reboots without modifying the upstream compose file:
d /tmp/horizon-all-in-1/openbao/plugins 0755 root root -
C /tmp/horizon-all-in-1/openbao/plugins/openbao-plugin-auth-openhorizon 0755 root root - /path/to/persistent/openbao-plugin-auth-openhorizon
x /tmp/horizon-all-in-1
Environment
| Deployment | deploy-mgmt-hub.sh all-in-one, defaults |
| OpenBao | 2.0.3 (quay.io/openbao/openbao-ubi:2.0) |
| Plugin | openbao-plugin-auth-openhorizon v1.0.1 |
| Host | Ubuntu 24.04 (kernel 6.8), Docker 29.6.2 |
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with mgmt-hub/deploy-mgmt-hub.sh around lines 290 and 770-771, then inspect the plugin bind mount in mgmt-hub/docker-compose.yml around line 244. Reproduce the failure by removing /tmp/horizon-all-in-1 and recreating the bao container. Done means the plugin survives tmpfiles cleanup and bao starts successfully after recreation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, docker-compose, shell
- Domain
- devops, infrastructure
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 66/100