mirror of
https://github.com/curly60e/pyblock.git
synced 2026-08-13 12:33:15 +02:00
PyBLOCK's mode A (Bitcoin + Lightning) and mode B (Bitcoin only) call bitcoin-cli and lncli directly via subprocess. The Umbrel image did not ship those binaries, so the startup validation in PyBlock.py:1898-1909 detected the empty CLI paths and silently redirected to Lite Mode against public APIs — defeating the point of installing PyBLOCK on a node. Per nmfretz's review on getumbrel/umbrel-apps#5258, this takes the "bundle the binaries inside the PyBLOCK image" path (option 2): - dockerfile: download bitcoin-cli (Bitcoin Core 28.1) and lncli (LND v0.20.1-beta, matching what Umbrel ships) for both linux/amd64 and linux/arm64. Verifies the Bitcoin Core SHA256SUMS. Real binaries land at /usr/local/bin/{bitcoin-cli,lncli}.bin. - umbrel/{bitcoin-cli,lncli}-wrapper.sh: thin shell wrappers installed as /usr/local/bin/{bitcoin-cli,lncli} that exec the real binary with -rpcconnect/-rpcuser/-rpcpassword (or --rpcserver/--tlscertpath/ --macaroonpath for lncli) injected from the BITCOIN_RPC_* / LND_* env vars Umbrel provides via APP_BITCOIN_* / APP_LIGHTNING_*. They fail loud if those env vars are missing. - entrypoint.sh: default BITCOIN_CLI_PATH/LND_CLI_PATH to the wrapper locations when the relevant RPC host env vars are set and the wrapper is executable, so bclock.conf / blndconnect.conf get the right bitcoincli / ln paths automatically. - umbrel/: bump image tag and app version to v4.0.2 with release notes. Local smoke test on amd64: bitcoin-cli.bin --version -> Bitcoin Core RPC client version v28.1.0 lncli.bin --version -> lncli version 0.20.1-beta /usr/local/bin/bitcoin-cli (no env) -> fails with "BITCOIN_RPC_HOST must be set" /usr/local/bin/bitcoin-cli (env set) -> dispatches to the real binary Image grows ~70MB (mostly the Go-built lncli). Co-Authored-By: kulvex code <noreply@github.com>
112 lines
3.7 KiB
Bash
Executable file
112 lines
3.7 KiB
Bash
Executable file
#!/bin/bash
|
|
set -e
|
|
|
|
CONFIG_DIR="/app/pyblock/pybitblock/config"
|
|
mkdir -p "$CONFIG_DIR"
|
|
|
|
# Fail fast with a clear message if the config dir is not writable. This is
|
|
# almost always a UID mismatch between the host bind-mount owner and the
|
|
# container user (Umbrel forces `user: "1000:1000"`).
|
|
if ! touch "$CONFIG_DIR/.writetest" 2>/dev/null; then
|
|
echo "[PyBLOCK] FATAL: cannot write to $CONFIG_DIR" >&2
|
|
echo "[PyBLOCK] The bind-mounted host directory must be writable by UID $(id -u):$(id -g)." >&2
|
|
echo "[PyBLOCK] On Umbrel, ensure \${APP_DATA_DIR}/data/config is owned by 1000:1000." >&2
|
|
ls -ld "$CONFIG_DIR" >&2 || true
|
|
exit 1
|
|
fi
|
|
rm -f "$CONFIG_DIR/.writetest"
|
|
|
|
# Default to the bundled bitcoin-cli / lncli wrappers when the caller hasn't
|
|
# overridden them. The wrappers route every CLI invocation through RPC/gRPC
|
|
# against the Umbrel Bitcoin Core and LND containers, so PyBLOCK's mode A/B
|
|
# work without a real local node binary on disk.
|
|
if [ -n "$BITCOIN_RPC_HOST" ] && [ -x /usr/local/bin/bitcoin-cli ]; then
|
|
export BITCOIN_CLI_PATH="${BITCOIN_CLI_PATH:-/usr/local/bin/bitcoin-cli}"
|
|
fi
|
|
if [ -n "$LND_HOST" ] && [ -x /usr/local/bin/lncli ]; then
|
|
export LND_CLI_PATH="${LND_CLI_PATH:-/usr/local/bin/lncli}"
|
|
fi
|
|
|
|
# Auto-generate Bitcoin config from env vars if set
|
|
if [ -n "$BITCOIN_RPC_HOST" ] && [ -n "$BITCOIN_RPC_USER" ]; then
|
|
BITCOIN_RPC_PORT="${BITCOIN_RPC_PORT:-8332}"
|
|
cat > "$CONFIG_DIR/bclock.conf" <<BTCEOF
|
|
{
|
|
"ip_port": "http://${BITCOIN_RPC_HOST}:${BITCOIN_RPC_PORT}",
|
|
"rpcuser": "${BITCOIN_RPC_USER}",
|
|
"rpcpass": "${BITCOIN_RPC_PASS}",
|
|
"bitcoincli": "${BITCOIN_CLI_PATH:-}"
|
|
}
|
|
BTCEOF
|
|
echo "[PyBLOCK] Bitcoin RPC configured: ${BITCOIN_RPC_HOST}:${BITCOIN_RPC_PORT}"
|
|
fi
|
|
|
|
# Auto-generate LND config from env vars if set
|
|
if [ -n "$LND_HOST" ] || [ -n "$LND_TLS_CERT_PATH" ]; then
|
|
LND_GRPC_PORT="${LND_GRPC_PORT:-10009}"
|
|
# Only build ip_port if LND_HOST is set (matches Python _env_lnd_config)
|
|
if [ -n "$LND_HOST" ]; then
|
|
LND_IP_PORT="${LND_HOST}:${LND_GRPC_PORT}"
|
|
else
|
|
LND_IP_PORT=""
|
|
fi
|
|
cat > "$CONFIG_DIR/blndconnect.conf" <<LNDEOF
|
|
{
|
|
"ip_port": "${LND_IP_PORT}",
|
|
"tls": "${LND_TLS_CERT_PATH:-}",
|
|
"macaroon": "${LND_MACAROON_PATH:-}",
|
|
"ln": "${LND_CLI_PATH:-}"
|
|
}
|
|
LNDEOF
|
|
echo "[PyBLOCK] LND configured: ${LND_IP_PORT:-local paths only}"
|
|
fi
|
|
|
|
# Auto-set mode if specified (PYBLOCK_MODE always overwrites)
|
|
PYBLOCK_MODE="${PYBLOCK_MODE:-}"
|
|
if [ -n "$PYBLOCK_MODE" ]; then
|
|
echo "\"${PYBLOCK_MODE}\"" > "$CONFIG_DIR/intro.conf"
|
|
echo "[PyBLOCK] Mode set to: ${PYBLOCK_MODE}"
|
|
elif [ -n "$BITCOIN_RPC_HOST" ] && [ ! -f "$CONFIG_DIR/intro.conf" ]; then
|
|
# Auto-detect mode from available env vars
|
|
if [ -n "$LND_HOST" ] || [ -n "$LND_TLS_CERT_PATH" ]; then
|
|
echo '"A"' > "$CONFIG_DIR/intro.conf"
|
|
echo "[PyBLOCK] Auto-detected mode: A (Bitcoin + Lightning)"
|
|
else
|
|
echo '"B"' > "$CONFIG_DIR/intro.conf"
|
|
echo "[PyBLOCK] Auto-detected mode: B (Bitcoin Only)"
|
|
fi
|
|
fi
|
|
|
|
# Generate default settings if missing
|
|
if [ ! -f "$CONFIG_DIR/pyblocksettings.conf" ]; then
|
|
cat > "$CONFIG_DIR/pyblocksettings.conf" <<SEOF
|
|
{
|
|
"gradient": "",
|
|
"design": "block",
|
|
"colorA": "green",
|
|
"colorB": "yellow"
|
|
}
|
|
SEOF
|
|
fi
|
|
|
|
if [ ! -f "$CONFIG_DIR/pyblocksettingsClock.conf" ]; then
|
|
cat > "$CONFIG_DIR/pyblocksettingsClock.conf" <<SCEOF
|
|
{
|
|
"gradient": "",
|
|
"colorA": "green",
|
|
"colorB": "yellow"
|
|
}
|
|
SCEOF
|
|
fi
|
|
|
|
echo "[PyBLOCK] Starting..."
|
|
|
|
# Ensure UTF-8 for all terminal output (ttyd, AI responses, etc.)
|
|
export LANG="${LANG:-C.UTF-8}"
|
|
export LC_ALL="${LC_ALL:-C.UTF-8}"
|
|
export PYTHONIOENCODING=utf-8
|
|
|
|
# Launch PyBLOCK via ttyd
|
|
exec ttyd -W -p "${PYBLOCK_PORT:-6969}" \
|
|
${PYBLOCK_TTYD_AUTH:+-c "$PYBLOCK_TTYD_AUTH"} \
|
|
python3 /app/pyblock/pybitblock/PyBlock.py "$@"
|