Files
KNELSecretsManager/bin/bw-install.sh
T
VP TechOpsandvptechops 01b0eed9fc 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).
2026-08-14 09:51:43 -05:00

126 lines
4.1 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# bw-install.sh — Install the container-based Bitwarden CLI wrapper.
#
# Downloads the native Rust bw binary, builds the Docker image, and installs
# the host-side wrapper plus container entrypoint to the user's local paths.
# No Node.js is involved at any layer.
#
# Usage:
# bw-install.sh Download, build, and install everything
# bw-install.sh --check Verify installation status without changes
#
# Prerequisites:
# - docker on PATH
# - BW env file at ~/.config/bw/env (see prereq-check.sh in TSYSGroupAIOS)
#
# After install, ~/.local/bin/bw provides transparent CLI access. Add
# ~/.local/bin to PATH if not already (most distros do this via ~/.profile).
set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$HERE/.." && pwd)"
BW_VERSION="2026.7.0"
BW_IMAGE="reachableceo-bw-native:${BW_VERSION}"
BW_BINARY_URL="https://github.com/bitwarden/clients/releases/download/cli-v${BW_VERSION}/bw-linux-${BW_VERSION}.zip"
INSTALL_BIN="${HOME}/.local/bin"
INSTALL_LIB="${HOME}/.local/share/bw"
BUILD_DIR=""
# --- Helpers ---
log_info() { printf '\033[0;34m\033[0m %s\n' "$*"; }
log_ok() { printf '\033[0;32m✓\033[0m %s\n' "$*"; }
log_warn() { printf '\033[1;33m⚠\033[0m %s\n' "$*" >&2; }
log_error() { printf '\033[0;31m✗\033[0m %s\n' "$*" >&2; }
log_step() { printf '\n\033[1m== %s ==\033[0m\n' "$*"; }
die() { log_error "$*"; exit 1; }
# --- Cleanup on exit ---
cleanup() {
[ -n "$BUILD_DIR" ] && rm -rf "$BUILD_DIR"
}
trap cleanup EXIT
# --- Check mode ---
if [ "${1:-}" = "--check" ]; then
log_step "BW CLI installation check"
if command -v docker >/dev/null 2>&1; then
log_ok "docker on PATH"
else
log_error "docker not on PATH"
fi
if docker image inspect "$BW_IMAGE" >/dev/null 2>&1; then
log_ok "Docker image ${BW_IMAGE} exists"
else
log_error "Docker image ${BW_IMAGE} missing"
fi
if [ -x "${INSTALL_BIN}/bw" ]; then
log_ok "Host wrapper at ${INSTALL_BIN}/bw"
else
log_error "Host wrapper at ${INSTALL_BIN}/bw missing"
fi
if [ -f "${INSTALL_LIB}/entrypoint.sh" ]; then
log_ok "Entrypoint at ${INSTALL_LIB}/entrypoint.sh"
else
log_error "Entrypoint at ${INSTALL_LIB}/entrypoint.sh missing"
fi
exit 0
fi
# --- Prerequisites ---
command -v docker >/dev/null 2>&1 || die "docker not found on PATH"
log_step "Installing container-based Bitwarden CLI (native Rust, no Node.js)"
# --- Step 1: Download and extract the native binary ---
BUILD_DIR=$(mktemp -d)
log_info "Downloading bw ${BW_VERSION} native binary..."
docker run --rm -v "${BUILD_DIR}:/build" alpine:3.20 \
sh -c "apk add --no-cache unzip >/dev/null 2>&1 && \
wget -q -O /build/bw.zip '${BW_BINARY_URL}' && \
unzip -o /build/bw.zip -d /build/ && \
rm /build/bw.zip && \
chmod +x /build/bw"
[ -f "${BUILD_DIR}/bw" ] || die "download failed: bw binary not found"
log_ok "Downloaded native binary"
# --- Step 2: Build the Docker image ---
log_info "Building Docker image ${BW_IMAGE}..."
DOCKERFILE_DIR="${REPO_ROOT}/docker/bw-native"
if [ ! -f "${DOCKERFILE_DIR}/Dockerfile" ]; then
die "Dockerfile not found: ${DOCKERFILE_DIR}/Dockerfile"
fi
cp "${BUILD_DIR}/bw" "${DOCKERFILE_DIR}/bw"
docker build -t "$BW_IMAGE" "$DOCKERFILE_DIR"
rm -f "${DOCKERFILE_DIR}/bw"
log_ok "Built image ${BW_IMAGE}"
# --- Step 3: Install host-side wrapper and entrypoint ---
mkdir -p "$INSTALL_BIN" "$INSTALL_LIB"
cp "${HERE}/bw-cli.sh" "${INSTALL_BIN}/bw"
chmod 755 "${INSTALL_BIN}/bw"
log_ok "Installed wrapper to ${INSTALL_BIN}/bw"
cp "${HERE}/bw-entrypoint.sh" "${INSTALL_LIB}/entrypoint.sh"
chmod 755 "${INSTALL_LIB}/entrypoint.sh"
log_ok "Installed entrypoint to ${INSTALL_LIB}/entrypoint.sh"
# --- Step 4: Verify ---
log_info "Verifying installation..."
if "${INSTALL_BIN}/bw" --version >/dev/null 2>&1; then
log_ok "bw CLI is operational"
else
log_warn "bw wrapper installed but verification call failed"
log_warn "check ~/.config/bw/env credentials and try: bw status"
fi
log_step "Installation complete"
log_info "Usage: bw status | bw list items | bw get password \"Item Name\""