Rewire all MCP wrappers, docker-compose services, and validate scripts to source credentials from ~/.creds/ instead of scattered per-service .env files. This removes credential duplication and prepares for the HashiCorp Vault migration. Add KNELCredsManager under tooling-cli with: - Containerized Bitwarden CLI (pinned image, host stays clean) - scripts/bw wrapper with session management and data persistence - README documenting credential layout, consumer wiring, and roadmap Also fixes latent bug in MCP wrappers that were silently getting empty creds from ambient shell env — they now explicitly source ~/.creds/. Tracked in Redmine #407. Discourse: https://community.turnsys.com/t/308 💘 Generated with Crush Assisted-by: Crush
KNELCredsManager
Centralized credential management for KNEL infrastructure. Stores service
credentials on disk in ~/.creds/ and provides a containerized Bitwarden CLI
for future migration to a password manager.
Credential store layout
All credentials live in ~/.creds/ as flat .env files, one per service:
~/.creds/
├── beszel.env # Beszel monitoring (hub URL set, auth TBD — see #406)
├── discourse.env # Discourse forum API keys + admin key
├── phpipam.env # phpIPAM app_id + app_code
├── redmine.env # Redmine REST API key
├── technitium.env # Technitium DNS API key + admin password
└── uptime-kuma.env # Uptime Kuma push/API key
Permissions: directory 700, files 600 (owner read/write only).
Consumers
All credential consumers source from ~/.creds/:
| Service | Wrapper / consumer | Mechanism |
|---|---|---|
| Redmine | ~/daytoday/redmine/bin/redmine |
--env-file ~/.creds/redmine.env |
| Redmine MCP | mcp-redmine-wrapper.sh |
set -a; . ~/.creds/redmine.env; set +a |
| Discourse | ~/daytoday/discourse/bin/discourse |
--env-file ~/.creds/discourse.env |
| Discourse MCP | mcp-discourse-wrapper.sh |
set -a; . ~/.creds/discourse.env; set +a |
| Beszel MCP | mcp-beszel-wrapper.sh |
set -a; . ~/.creds/beszel.env; set +a |
| Uptime Kuma | (no active consumer yet) | Direct env reference |
| Technitium | (no active consumer yet) | Direct env reference |
| phpIPAM | (no active consumer yet) | Direct env reference |
Bitwarden CLI
The Bitwarden CLI runs in a pinned Docker container — no host installation required. Built from this directory's Dockerfile.
Build
docker build -t reachableceo-bw-cli:2026.7.0 .
Wrapper
# Symlink the wrapper onto PATH
ln -sf ~/projects/KNEL-AIMiddleware/tooling-cli/KNELCredsManager/scripts/bw ~/.local/bin/bw
Usage
bw login # interactive first-time login
export BW_SESSION=$(bw unlock --raw) # unlock and capture session
bw sync # sync vault
bw list items # list all vault items
bw get item <name> # get a specific item
bw status # check auth/session status
Session state persists in ~/.local/share/bw-cli/ across container runs.
MCP integration (machine-to-machine)
For agent automation without interactive login, the KNEL-AIMiddleware fleet
includes mcp-bitwarden-wrapper.sh which uses BITWARDEN_CLIENT_ID /
BITWARDEN_CLIENT_SECRET / BITWARDEN_PASSWORD env vars (machine account
auth). That is a separate integration from this CLI wrapper.
Build arguments
| Arg | Default | Description |
|---|---|---|
BW_CLI_VERSION |
2026.7.0 |
Pinned @bitwarden/cli npm version |
Environment variables
| Variable | Default | Description |
|---|---|---|
BW_CLI_IMAGE |
reachableceo-bw-cli:2026.7.0 |
Override image tag |
BW_SESSION |
(unset) | Session key from bw unlock |