- scripts/bitcoin-ln-node/setup.sh: one-shot installer for Bitcoin Core (pruned mainnet), LND, and LNbits on Apple Silicon Mac. Generates secrets, writes configs, installs launchd plists for auto-start. - scripts/bitcoin-ln-node/start.sh: start all services via launchctl; waits for RPC readiness and auto-unlocks LND wallet. - scripts/bitcoin-ln-node/stop.sh: graceful shutdown (lncli stop → bitcoin-cli stop). - scripts/bitcoin-ln-node/status.sh: full health check (Bitcoin sync %, LND channels/balance, LNbits HTTP, bore tunnel). Supports --json mode for machine consumption. - scripts/bitcoin-ln-node/expose.sh: opens bore tunnel from LNbits port 5000 to bore.pub for Replit access. - scripts/bitcoin-ln-node/get-lnbits-key.sh: fetches LNbits admin API key and prints Replit secret values. - artifacts/api-server/src/routes/node-diagnostics.ts: GET /api/admin/node-status (JSON) and /api/admin/node-status/html — Timmy self-diagnoses its LNbits/LND connectivity and reports issues.
98 lines
4.3 KiB
Bash
Executable File
98 lines
4.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# =============================================================================
|
|
# Timmy node — expose LNbits to Replit via bore tunnel
|
|
# Run this after LNbits is up. Keep this terminal open.
|
|
# =============================================================================
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
LNBITS_LOCAL="http://127.0.0.1:5000"
|
|
|
|
GREEN='\033[0;32m'; CYAN='\033[0;36m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; NC='\033[0m'
|
|
info() { echo -e "${CYAN}[expose]${NC} $*"; }
|
|
ok() { echo -e "${GREEN}[ok]${NC} $*"; }
|
|
warn() { echo -e "${YELLOW}[warn]${NC} $*"; }
|
|
die() { echo -e "${RED}[error]${NC} $*" >&2; exit 1; }
|
|
|
|
# ─── Ensure LNbits is up ──────────────────────────────────────────────────────
|
|
info "Checking LNbits is reachable locally…"
|
|
if ! curl -sf "$LNBITS_LOCAL/api/v1/health" &>/dev/null; then
|
|
warn "LNbits not responding at $LNBITS_LOCAL"
|
|
warn "Waiting up to 30s…"
|
|
for i in $(seq 1 6); do
|
|
sleep 5
|
|
curl -sf "$LNBITS_LOCAL/api/v1/health" &>/dev/null && break
|
|
[[ $i -eq 6 ]] && die "LNbits still not up. Run 'bash $SCRIPT_DIR/start.sh' first."
|
|
done
|
|
fi
|
|
ok "LNbits is running locally."
|
|
|
|
# ─── Ensure bore is installed ─────────────────────────────────────────────────
|
|
if ! command -v bore &>/dev/null; then
|
|
info "Installing bore (tunnel tool)…"
|
|
if command -v cargo &>/dev/null; then
|
|
cargo install bore-cli
|
|
elif command -v brew &>/dev/null; then
|
|
brew install bore-cli 2>/dev/null || {
|
|
warn "bore not in Homebrew — installing via cargo…"
|
|
brew install rust 2>/dev/null && cargo install bore-cli
|
|
}
|
|
else
|
|
die "Neither cargo nor brew found. Install bore manually: https://github.com/ekzhang/bore"
|
|
fi
|
|
fi
|
|
|
|
# Kill any existing bore tunnel on port 5000
|
|
if EXISTING=$(pgrep -f "bore local.*5000" 2>/dev/null); then
|
|
info "Killing existing bore tunnel (PID $EXISTING)…"
|
|
kill "$EXISTING" 2>/dev/null || true
|
|
sleep 1
|
|
fi
|
|
|
|
# ─── Start bore ──────────────────────────────────────────────────────────────
|
|
info "Opening bore tunnel: local:5000 → bore.pub…"
|
|
echo ""
|
|
|
|
# bore prints the public address on startup — capture it
|
|
BORE_OUT=$(mktemp)
|
|
bore local 5000 --to bore.pub 2>&1 &
|
|
BORE_PID=$!
|
|
|
|
sleep 3
|
|
|
|
# Extract the assigned port from bore output
|
|
if BORE_LINE=$(bore local 5000 --to bore.pub --help 2>&1 | head -1); then true; fi
|
|
# Check if bore is still running
|
|
if ! kill -0 $BORE_PID 2>/dev/null; then
|
|
die "bore exited immediately. Check your internet connection."
|
|
fi
|
|
|
|
# bore prints: "listening at bore.pub:PORT"
|
|
# We need to find what port was assigned
|
|
BORE_PORT=$(ps aux | grep "bore local 5000" | grep -v grep | grep -oE '\-\-port [0-9]+' | awk '{print $2}' || true)
|
|
if [[ -z "$BORE_PORT" ]]; then
|
|
# Fallback: tail the bore process log
|
|
sleep 2
|
|
BORE_PORT=$(bore local 5000 --to bore.pub 2>&1 & sleep 3; pkill -f "bore local" 2>/dev/null || true)
|
|
fi
|
|
|
|
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
echo -e "${GREEN} Bore tunnel is LIVE (PID: $BORE_PID)${NC}"
|
|
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
echo ""
|
|
echo " LNbits is now reachable from Replit."
|
|
echo ""
|
|
echo " Set these secrets in Replit:"
|
|
echo " ┌──────────────────────────────────────────────────┐"
|
|
echo " │ LNBITS_URL = http://bore.pub:<PORT> │"
|
|
echo " │ LNBITS_API_KEY = <your-lnbits-admin-key> │"
|
|
echo " └──────────────────────────────────────────────────┘"
|
|
echo ""
|
|
echo " Get your API key: bash $SCRIPT_DIR/get-lnbits-key.sh"
|
|
echo ""
|
|
echo " Keep this terminal open. Ctrl+C to stop the tunnel."
|
|
echo ""
|
|
|
|
# Wait for bore to exit
|
|
wait $BORE_PID
|