feat: container-based Bitwarden CLI, no host Node.js
Adds the dockerized bw deployment in production use on the TSGCOO orchestration host since 2026-08-13: pinned debian-slim image carrying the pre-compiled bw binary, an in-container auth lifecycle entrypoint (config, API-key login, unlock, sync), a transparent host wrapper, and a one-command installer. ADR-002 records the decision and supersedes ADR-001 for BW CLI purposes: hosts keep zero language runtimes. Known caveat documented: the upstream "native" binary is a Node.js SEA, so Node is embedded in the image though absent from all hosts. Shellcheck clean (zero warnings incl. info-level).
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
# ADR-002: Container-Based Bitwarden CLI (No Host Node.js)
|
||||
|
||||
## Status
|
||||
|
||||
Accepted (supersedes ADR-001 for BW CLI purposes)
|
||||
|
||||
## Context
|
||||
|
||||
ADR-001 selected a hybrid Node.js version-management strategy because the
|
||||
Bitwarden CLI (`bw`) is distributed via npm and therefore requires a Node.js
|
||||
runtime on every consuming host. For TSYS hosts operating under CMMC L3 /
|
||||
ITAR / STIG alignment, any host-side language runtime is an attack surface
|
||||
and a compliance finding. The KNEL/TSYS baseline ("Docker for everything")
|
||||
also forbids host language toolchains.
|
||||
|
||||
Bitwarden additionally publishes the CLI as a pre-compiled single binary.
|
||||
Distributing that binary inside a minimal pinned container gives every host
|
||||
transparent `bw` access with zero host-side runtimes.
|
||||
|
||||
## Decision
|
||||
|
||||
**Run the official pre-compiled bw binary inside a pinned Docker container,
|
||||
exposed to users as a transparent `bw` wrapper at `~/.local/bin/bw`.**
|
||||
|
||||
Components (all in this repo):
|
||||
|
||||
| File | Role |
|
||||
|---|---|
|
||||
| `docker/bw-native/Dockerfile` | `debian:12-slim` + ca-certificates + bw binary, pinned `2026.7.0` |
|
||||
| `bin/bw-entrypoint.sh` | In-container auth lifecycle: config server, API-key login, unlock, sync, exec |
|
||||
| `bin/bw-cli.sh` | Host wrapper: docker run with volume-persisted session, tsys- container prefix |
|
||||
| `bin/bw-install.sh` | One-command installer for the wrapper + image |
|
||||
|
||||
Credentials live only in `~/.config/bw/env` (single-quoted values, mode 600)
|
||||
per the org-wide "no secrets on disk except BW access info" rule. The
|
||||
Vaultwarden API key is used for login (no TOTP interaction needed); the
|
||||
master password unlocks the vault; `bw sync` runs after every login so
|
||||
multi-client vault state stays coherent.
|
||||
|
||||
## Known Caveat
|
||||
|
||||
The Bitwarden "native" Linux binary is actually a Node.js SEA (Single
|
||||
Executable Application): it embeds a Node.js runtime and can print Node
|
||||
errors on crash. Node.js is **absent from every host**, which satisfies the
|
||||
host-hygiene goal, but the "zero Node.js anywhere" stretch goal is not met.
|
||||
Alternatives (Rust vaultwarden clients such as `rbw`) were considered and
|
||||
rejected for now due to Vaultwarden API compatibility gaps. Revisit if a
|
||||
mature Rust client emerges; the wrapper isolates users from this swap.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- Zero language runtimes on hosts (CMMC/ITAR/STIG-friendly host hygiene)
|
||||
- Identical bw behavior across all TSYS hosts; version pinned in one Dockerfile
|
||||
- Session persistence via named Docker volume; no state divergence when
|
||||
wrapper is used consistently
|
||||
- Vendoring into shell frameworks is one installer invocation
|
||||
|
||||
### Negative
|
||||
|
||||
- Requires Docker on every consuming host (accepted: it is an org baseline)
|
||||
- SEA caveat above (Node embedded inside the container image)
|
||||
|
||||
## Verification
|
||||
|
||||
Deployed and verified on the TSGCOO orchestration host against
|
||||
`https://pwvault.turnsys.com` (account `coo@turnsys.com`): status, list,
|
||||
generate, get password/totp/item, create/edit items. Shellcheck clean at
|
||||
zero warnings including info-level. In production use since 2026-08-13.
|
||||
|
||||
---
|
||||
|
||||
**Decision Date:** 2026-08-14
|
||||
**Decision Makers:** VP TechOps (proposed), TSGCOO (implemented)
|
||||
**Related:** ADR-001 (superseded for BW CLI purposes; MISE guidance remains
|
||||
valid for projects that genuinely require host Node.js)
|
||||
Reference in New Issue
Block a user