feat(creds): centralize credentials to ~/.creds/, add KNELCredsManager
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
This commit is contained in:
+17
-15
@@ -10,9 +10,11 @@ set -eu
|
|||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
cd "$SCRIPT_DIR"
|
cd "$SCRIPT_DIR"
|
||||||
|
|
||||||
# Ensure .env exists
|
ENV_FILE="${DISCOURSE_ENV_FILE:-/home/reachableceo/.creds/discourse.env}"
|
||||||
if [ ! -f .env ]; then
|
|
||||||
echo "FAIL: .env not found. Copy .env.example to .env and fill in real values."
|
# Ensure env file exists
|
||||||
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
|
echo "FAIL: env file not found: $ENV_FILE"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -36,9 +38,9 @@ echo ""
|
|||||||
echo "--- [0] Credential check (raw HTTP via containerized curl) ---"
|
echo "--- [0] Credential check (raw HTTP via containerized curl) ---"
|
||||||
|
|
||||||
# Load env vars from .env for the raw test
|
# Load env vars from .env for the raw test
|
||||||
DISCOURSE_URL=$(grep -E '^DISCOURSE_URL=' .env | cut -d= -f2-)
|
DISCOURSE_URL=$(grep -E '^DISCOURSE_URL=' "$ENV_FILE" | cut -d= -f2-)
|
||||||
DISCOURSE_API_KEY=$(grep -E '^DISCOURSE_API_KEY=' .env | cut -d= -f2-)
|
DISCOURSE_API_KEY=$(grep -E '^DISCOURSE_API_KEY=' "$ENV_FILE" | cut -d= -f2-)
|
||||||
DISCOURSE_API_USERNAME=$(grep -E '^DISCOURSE_API_USERNAME=' .env | cut -d= -f2-)
|
DISCOURSE_API_USERNAME=$(grep -E '^DISCOURSE_API_USERNAME=' "$ENV_FILE" | cut -d= -f2-)
|
||||||
|
|
||||||
HTTP_CODE=$(docker run --rm curlimages/curl:latest \
|
HTTP_CODE=$(docker run --rm curlimages/curl:latest \
|
||||||
-s -o /dev/null -w '%{http_code}' \
|
-s -o /dev/null -w '%{http_code}' \
|
||||||
@@ -67,7 +69,7 @@ echo ""
|
|||||||
# 1. whoami (live connection test)
|
# 1. whoami (live connection test)
|
||||||
# ---------------------------------------------------------------- #
|
# ---------------------------------------------------------------- #
|
||||||
echo "--- [1] whoami ---"
|
echo "--- [1] whoami ---"
|
||||||
OUT=$(docker run --rm --env-file .env "${IMAGE}" whoami 2>&1) || true
|
OUT=$(docker run --rm --env-file "$ENV_FILE" "${IMAGE}" whoami 2>&1) || true
|
||||||
if echo "$OUT" | grep -qE '^username:'; then
|
if echo "$OUT" | grep -qE '^username:'; then
|
||||||
ok "whoami returned user info"
|
ok "whoami returned user info"
|
||||||
echo " $OUT" | head -5
|
echo " $OUT" | head -5
|
||||||
@@ -81,7 +83,7 @@ echo ""
|
|||||||
# 2. categories (live read)
|
# 2. categories (live read)
|
||||||
# ---------------------------------------------------------------- #
|
# ---------------------------------------------------------------- #
|
||||||
echo "--- [2] categories ---"
|
echo "--- [2] categories ---"
|
||||||
OUT=$(docker run --rm --env-file .env "${IMAGE}" categories 2>&1) || true
|
OUT=$(docker run --rm --env-file "$ENV_FILE" "${IMAGE}" categories 2>&1) || true
|
||||||
if echo "$OUT" | grep -qE '^[0-9]+ category'; then
|
if echo "$OUT" | grep -qE '^[0-9]+ category'; then
|
||||||
ok "categories returned data"
|
ok "categories returned data"
|
||||||
echo " $OUT" | head -6
|
echo " $OUT" | head -6
|
||||||
@@ -98,7 +100,7 @@ echo ""
|
|||||||
# 3. topics / ls (live read)
|
# 3. topics / ls (live read)
|
||||||
# ---------------------------------------------------------------- #
|
# ---------------------------------------------------------------- #
|
||||||
echo "--- [3] topics (latest) ---"
|
echo "--- [3] topics (latest) ---"
|
||||||
OUT=$(docker run --rm --env-file .env "${IMAGE}" ls 2>&1) || true
|
OUT=$(docker run --rm --env-file "$ENV_FILE" "${IMAGE}" ls 2>&1) || true
|
||||||
if echo "$OUT" | grep -qE 'topic\(s\)'; then
|
if echo "$OUT" | grep -qE 'topic\(s\)'; then
|
||||||
ok "topics list returned data"
|
ok "topics list returned data"
|
||||||
echo " $OUT" | head -6
|
echo " $OUT" | head -6
|
||||||
@@ -115,7 +117,7 @@ echo ""
|
|||||||
# ---------------------------------------------------------------- #
|
# ---------------------------------------------------------------- #
|
||||||
if [ -n "${TOPIC_ID:-}" ]; then
|
if [ -n "${TOPIC_ID:-}" ]; then
|
||||||
echo "--- [4] show topic ${TOPIC_ID} ---"
|
echo "--- [4] show topic ${TOPIC_ID} ---"
|
||||||
OUT=$(docker run --rm --env-file .env "${IMAGE}" show "${TOPIC_ID}" 2>&1) || true
|
OUT=$(docker run --rm --env-file "$ENV_FILE" "${IMAGE}" show "${TOPIC_ID}" 2>&1) || true
|
||||||
if echo "$OUT" | grep -qE '^#'; then
|
if echo "$OUT" | grep -qE '^#'; then
|
||||||
ok "show topic ${TOPIC_ID} returned content"
|
ok "show topic ${TOPIC_ID} returned content"
|
||||||
echo " $OUT" | head -8
|
echo " $OUT" | head -8
|
||||||
@@ -132,7 +134,7 @@ echo ""
|
|||||||
# 5. search (live read)
|
# 5. search (live read)
|
||||||
# ---------------------------------------------------------------- #
|
# ---------------------------------------------------------------- #
|
||||||
echo "--- [5] search ---"
|
echo "--- [5] search ---"
|
||||||
OUT=$(docker run --rm --env-file .env "${IMAGE}" search "test" 2>&1) || true
|
OUT=$(docker run --rm --env-file "$ENV_FILE" "${IMAGE}" search "test" 2>&1) || true
|
||||||
if echo "$OUT" | grep -qE 'result\(s\)'; then
|
if echo "$OUT" | grep -qE 'result\(s\)'; then
|
||||||
ok "search returned results"
|
ok "search returned results"
|
||||||
echo " $OUT" | head -5
|
echo " $OUT" | head -5
|
||||||
@@ -147,7 +149,7 @@ echo ""
|
|||||||
# ---------------------------------------------------------------- #
|
# ---------------------------------------------------------------- #
|
||||||
echo "--- [6] create + reply + update + delete (write cycle) ---"
|
echo "--- [6] create + reply + update + delete (write cycle) ---"
|
||||||
|
|
||||||
CREATE_OUT=$(docker run --rm --env-file .env "${IMAGE}" create \
|
CREATE_OUT=$(docker run --rm --env-file "$ENV_FILE" "${IMAGE}" create \
|
||||||
${CAT_ID:+-c "$CAT_ID"} \
|
${CAT_ID:+-c "$CAT_ID"} \
|
||||||
-t "discourse-cli validation test $(date +%s)" \
|
-t "discourse-cli validation test $(date +%s)" \
|
||||||
-b "This is an automated validation test post. It will be cleaned up shortly after creation." \
|
-b "This is an automated validation test post. It will be cleaned up shortly after creation." \
|
||||||
@@ -159,7 +161,7 @@ if [ -n "${NEW_TOPIC_ID:-}" ]; then
|
|||||||
echo " $CREATE_OUT"
|
echo " $CREATE_OUT"
|
||||||
|
|
||||||
# reply
|
# reply
|
||||||
REPLY_OUT=$(docker run --rm --env-file .env "${IMAGE}" reply "${NEW_TOPIC_ID}" \
|
REPLY_OUT=$(docker run --rm --env-file "$ENV_FILE" "${IMAGE}" reply "${NEW_TOPIC_ID}" \
|
||||||
-b "Validation reply test." 2>&1) || true
|
-b "Validation reply test." 2>&1) || true
|
||||||
POST_ID=$(echo "$REPLY_OUT" | grep -oE 'id=[0-9]+' | grep -oE '[0-9]+')
|
POST_ID=$(echo "$REPLY_OUT" | grep -oE 'id=[0-9]+' | grep -oE '[0-9]+')
|
||||||
if echo "$REPLY_OUT" | grep -qE 'Posted reply'; then
|
if echo "$REPLY_OUT" | grep -qE 'Posted reply'; then
|
||||||
@@ -172,7 +174,7 @@ if [ -n "${NEW_TOPIC_ID:-}" ]; then
|
|||||||
|
|
||||||
# update
|
# update
|
||||||
if [ -n "${POST_ID:-}" ]; then
|
if [ -n "${POST_ID:-}" ]; then
|
||||||
UPD_OUT=$(docker run --rm --env-file .env "${IMAGE}" update "${POST_ID}" \
|
UPD_OUT=$(docker run --rm --env-file "$ENV_FILE" "${IMAGE}" update "${POST_ID}" \
|
||||||
-b "Updated validation reply test." 2>&1) || true
|
-b "Updated validation reply test." 2>&1) || true
|
||||||
if echo "$UPD_OUT" | grep -qE 'Updated post'; then
|
if echo "$UPD_OUT" | grep -qE 'Updated post'; then
|
||||||
ok "update post ${POST_ID} succeeded"
|
ok "update post ${POST_ID} succeeded"
|
||||||
@@ -182,7 +184,7 @@ if [ -n "${NEW_TOPIC_ID:-}" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# delete
|
# delete
|
||||||
DEL_OUT=$(docker run --rm --env-file .env "${IMAGE}" delete "${POST_ID}" 2>&1) || true
|
DEL_OUT=$(docker run --rm --env-file "$ENV_FILE" "${IMAGE}" delete "${POST_ID}" 2>&1) || true
|
||||||
if echo "$DEL_OUT" | grep -qE 'Deleted post'; then
|
if echo "$DEL_OUT" | grep -qE 'Deleted post'; then
|
||||||
ok "delete post ${POST_ID} succeeded"
|
ok "delete post ${POST_ID} succeeded"
|
||||||
else
|
else
|
||||||
|
|||||||
+6
-9
@@ -282,10 +282,8 @@ services:
|
|||||||
dockerfile: ../../dockerfiles/discourse-mcp/Dockerfile
|
dockerfile: ../../dockerfiles/discourse-mcp/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-discourse-mcp
|
container_name: kneldevstack-aimiddleware-discourse-mcp
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
env_file:
|
||||||
- DISCOURSE_URL=${DISCOURSE_URL}
|
- /home/reachableceo/.creds/discourse.env
|
||||||
- DISCOURSE_API_KEY=${DISCOURSE_API_KEY}
|
|
||||||
- DISCOURSE_API_USERNAME=${DISCOURSE_API_USERNAME}
|
|
||||||
profiles:
|
profiles:
|
||||||
- ops
|
- ops
|
||||||
|
|
||||||
@@ -398,10 +396,10 @@ services:
|
|||||||
dockerfile: ../../dockerfiles/mcp-redmine/Dockerfile
|
dockerfile: ../../dockerfiles/mcp-redmine/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-mcp-redmine
|
container_name: kneldevstack-aimiddleware-mcp-redmine
|
||||||
restart: "no"
|
restart: "no"
|
||||||
|
env_file:
|
||||||
|
- /home/reachableceo/.creds/redmine.env
|
||||||
environment:
|
environment:
|
||||||
- PYTHONUNBUFFERED=1
|
- PYTHONUNBUFFERED=1
|
||||||
- REDMINE_URL=${REDMINE_URL}
|
|
||||||
- REDMINE_API_KEY=${REDMINE_API_KEY}
|
|
||||||
profiles:
|
profiles:
|
||||||
- ops
|
- ops
|
||||||
|
|
||||||
@@ -609,11 +607,10 @@ services:
|
|||||||
dockerfile: ../../dockerfiles/beszel-mcp/Dockerfile
|
dockerfile: ../../dockerfiles/beszel-mcp/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-beszel-mcp
|
container_name: kneldevstack-aimiddleware-beszel-mcp
|
||||||
restart: "no"
|
restart: "no"
|
||||||
|
env_file:
|
||||||
|
- /home/reachableceo/.creds/beszel.env
|
||||||
environment:
|
environment:
|
||||||
- PYTHONUNBUFFERED=1
|
- PYTHONUNBUFFERED=1
|
||||||
- BESZEL_URL=${BESZEL_URL}
|
|
||||||
- BESZEL_USERNAME=${BESZEL_USERNAME}
|
|
||||||
- BESZEL_PASSWORD=${BESZEL_PASSWORD}
|
|
||||||
profiles:
|
profiles:
|
||||||
- ops
|
- ops
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,14 @@ if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' | grep -
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Load credentials from central store
|
||||||
|
CREDS_FILE="/home/reachableceo/.creds/beszel.env"
|
||||||
|
if [ -f "$CREDS_FILE" ]; then
|
||||||
|
set -a
|
||||||
|
. "$CREDS_FILE"
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
|
||||||
# Start MCP server with explicit name and environment
|
# Start MCP server with explicit name and environment
|
||||||
exec docker run -i --rm --name "${CONTAINER_NAME}" \
|
exec docker run -i --rm --name "${CONTAINER_NAME}" \
|
||||||
-e BESZEL_URL="${BESZEL_URL}" \
|
-e BESZEL_URL="${BESZEL_URL}" \
|
||||||
|
|||||||
@@ -14,6 +14,14 @@ if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/n
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Load credentials from central store
|
||||||
|
CREDS_FILE="/home/reachableceo/.creds/discourse.env"
|
||||||
|
if [ -f "$CREDS_FILE" ]; then
|
||||||
|
set -a
|
||||||
|
. "$CREDS_FILE"
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
|
||||||
# Start MCP server with explicit name and environment variables
|
# Start MCP server with explicit name and environment variables
|
||||||
exec docker run -i --rm --name "${CONTAINER_NAME}" \
|
exec docker run -i --rm --name "${CONTAINER_NAME}" \
|
||||||
-e "DISCOURSE_URL=${DISCOURSE_URL:-}" \
|
-e "DISCOURSE_URL=${DISCOURSE_URL:-}" \
|
||||||
|
|||||||
@@ -14,6 +14,14 @@ if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/n
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Load credentials from central store
|
||||||
|
CREDS_FILE="/home/reachableceo/.creds/redmine.env"
|
||||||
|
if [ -f "$CREDS_FILE" ]; then
|
||||||
|
set -a
|
||||||
|
. "$CREDS_FILE"
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
|
||||||
# Start MCP server with explicit name and environment variables
|
# Start MCP server with explicit name and environment variables
|
||||||
exec docker run -i --rm --name "${CONTAINER_NAME}" \
|
exec docker run -i --rm --name "${CONTAINER_NAME}" \
|
||||||
-e "REDMINE_URL=${REDMINE_URL:-}" \
|
-e "REDMINE_URL=${REDMINE_URL:-}" \
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
FROM node:22-slim
|
||||||
|
|
||||||
|
ARG BW_CLI_VERSION=2026.7.0
|
||||||
|
RUN npm install -g @bitwarden/cli@${BW_CLI_VERSION} && npm cache clean --force
|
||||||
|
|
||||||
|
ENTRYPOINT ["bw"]
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -t reachableceo-bw-cli:2026.7.0 .
|
||||||
|
```
|
||||||
|
|
||||||
|
### Wrapper
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Symlink the wrapper onto PATH
|
||||||
|
ln -sf ~/projects/KNEL-AIMiddleware/tooling-cli/KNELCredsManager/scripts/bw ~/.local/bin/bw
|
||||||
|
```
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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` |
|
||||||
Executable
+48
@@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# bw — Bitwarden CLI wrapper (Docker containerized, host stays clean).
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# bw login (interactive — prompts for email/master password/2FA)
|
||||||
|
# bw unlock (interactive — prints export BW_SESSION=... line)
|
||||||
|
# bw unlock --raw (prints only the session key, for scripting)
|
||||||
|
# bw list items
|
||||||
|
# bw get item <name-or-id>
|
||||||
|
# bw sync
|
||||||
|
# bw status
|
||||||
|
#
|
||||||
|
# Session management:
|
||||||
|
# After `bw unlock`, capture the session key:
|
||||||
|
# export BW_SESSION=$(bw unlock --raw)
|
||||||
|
# The wrapper passes BW_SESSION through automatically if already set.
|
||||||
|
#
|
||||||
|
# Data persistence:
|
||||||
|
# BW data.json lives at ~/.local/share/bw-cli/ mounted into the container,
|
||||||
|
# so login state persists across invocations.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
IMAGE="${BW_CLI_IMAGE:-reachableceo-bw-cli:2026.7.0}"
|
||||||
|
DATA_DIR="${HOME}/.local/share/bw-cli"
|
||||||
|
|
||||||
|
mkdir -p "$DATA_DIR"
|
||||||
|
|
||||||
|
# Detect TTY for interactive commands (login, unlock)
|
||||||
|
INTERACTIVE=""
|
||||||
|
if [ -t 0 ] && [ -t 1 ]; then
|
||||||
|
INTERACTIVE="-it"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Pass BW_SESSION through if set
|
||||||
|
SESSION_ARGS=()
|
||||||
|
if [ -n "${BW_SESSION:-}" ]; then
|
||||||
|
SESSION_ARGS+=( -e "BW_SESSION=${BW_SESSION}" )
|
||||||
|
fi
|
||||||
|
|
||||||
|
CONTAINER_NAME="reachableceo-bw-cli-$(date +%s)"
|
||||||
|
|
||||||
|
exec docker run --rm $INTERACTIVE \
|
||||||
|
--user "$(id -u):$(id -g)" \
|
||||||
|
--name "$CONTAINER_NAME" \
|
||||||
|
-e HOME=/home/bw \
|
||||||
|
-v "${DATA_DIR}:/home/bw/.config" \
|
||||||
|
"${SESSION_ARGS[@]}" \
|
||||||
|
"$IMAGE" "$@"
|
||||||
Reference in New Issue
Block a user