feat(docker): add standalone mode and external orchestration support

- Add --standalone flag to use self-contained bitcoind/lnd
- Default to unified mode using shared regtest
- Track compose mode in state file for down/logs/reset
- Add _setup_after_start internal command for external orchestration
- Update help text with new options

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Patrick Mulligan 2026-02-15 16:03:13 -05:00
commit c3564beccf

View file

@ -8,7 +8,8 @@
# - Auto-configured ATM application # - Auto-configured ATM application
# #
# Usage: # Usage:
# ./dev.sh up # Start everything # ./dev.sh up # Start (uses shared regtest)
# ./dev.sh up --standalone # Start self-contained (own bitcoind/lnd)
# ./dev.sh up --fund # Start and auto-fund ATM with 100k sats # ./dev.sh up --fund # Start and auto-fund ATM with 100k sats
# ./dev.sh up --fund=50000 # Start and auto-fund with specific amount # ./dev.sh up --fund=50000 # Start and auto-fund with specific amount
# ./dev.sh up --machine # Start and launch ATM app # ./dev.sh up --machine # Start and launch ATM app
@ -38,6 +39,17 @@ PUBKEY_FILE="$STATE_DIR/lightning-pub-pubkey"
NPROFILE_FILE="$STATE_DIR/lightning-pub-nprofile" NPROFILE_FILE="$STATE_DIR/lightning-pub-nprofile"
APP_TOKEN_FILE="$STATE_DIR/atm-app-token" APP_TOKEN_FILE="$STATE_DIR/atm-app-token"
APP_ID_FILE="$STATE_DIR/atm-app-id" APP_ID_FILE="$STATE_DIR/atm-app-id"
MODE_FILE="$STATE_DIR/compose-mode" # "standalone" or "unified"
# Get current compose file based on last used mode
get_compose_file() {
local mode=$(cat "$MODE_FILE" 2>/dev/null || echo "unified")
if [[ "$mode" == "standalone" ]]; then
echo "docker-compose.dev.yml"
else
echo "docker-compose.regtest.yml"
fi
}
# Colors # Colors
GREEN='\033[0;32m' GREEN='\033[0;32m'
@ -363,6 +375,8 @@ cmd_up() {
local auto_fund=false local auto_fund=false
local fund_amount="$DEFAULT_FUNDING_SATS" local fund_amount="$DEFAULT_FUNDING_SATS"
local launch_machine=false local launch_machine=false
local standalone=false
local compose_file="docker-compose.regtest.yml"
# Parse arguments # Parse arguments
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
@ -370,6 +384,7 @@ cmd_up() {
--image) image="$2"; shift 2 ;; --image) image="$2"; shift 2 ;;
--worktree) worktree="$2"; shift 2 ;; --worktree) worktree="$2"; shift 2 ;;
--skip-regtest) skip_regtest=true; shift ;; --skip-regtest) skip_regtest=true; shift ;;
--standalone) standalone=true; shift ;;
--fund) auto_fund=true; shift ;; --fund) auto_fund=true; shift ;;
--fund=*) auto_fund=true; fund_amount="${1#*=}"; shift ;; --fund=*) auto_fund=true; fund_amount="${1#*=}"; shift ;;
--machine|--atm) launch_machine=true; shift ;; --machine|--atm) launch_machine=true; shift ;;
@ -377,19 +392,28 @@ cmd_up() {
esac esac
done done
# Determine compose file
if [[ "$standalone" == "true" ]]; then
compose_file="docker-compose.dev.yml"
skip_regtest=true # Standalone mode has its own bitcoind/lnd
log "Starting in STANDALONE mode (self-contained bitcoind/lnd)"
else
log "Starting in UNIFIED mode (shared regtest)"
fi
echo "" echo ""
log "Starting Lamassu development environment..." log "Starting Lamassu development environment..."
echo "" echo ""
# 1. Start regtest if needed # 1. Start shared regtest if needed (not in standalone mode)
if [[ "$skip_regtest" != "true" ]]; then if [[ "$standalone" != "true" ]] && [[ "$skip_regtest" != "true" ]]; then
start_regtest || exit 1 start_regtest || exit 1
else elif [[ "$standalone" != "true" ]] && ! is_regtest_running; then
if ! is_regtest_running; then error "Shared regtest not running."
error "Regtest not running. Remove --skip-regtest or start it manually." echo " Start with: regtest-start"
echo " Or use: ./dev.sh up --standalone"
exit 1 exit 1
fi fi
fi
# 2. Build from worktree if specified # 2. Build from worktree if specified
if [[ -n "$worktree" ]]; then if [[ -n "$worktree" ]]; then
@ -413,8 +437,15 @@ cmd_up() {
export LIGHTNING_PUB_IMAGE="$image" export LIGHTNING_PUB_IMAGE="$image"
export HOST_IP=$(get_local_ip) export HOST_IP=$(get_local_ip)
# Save mode for other commands
if [[ "$standalone" == "true" ]]; then
echo "standalone" > "$MODE_FILE"
else
echo "unified" > "$MODE_FILE"
fi
log "Starting lamassu services..." log "Starting lamassu services..."
docker compose -f "$SCRIPT_DIR/docker-compose.regtest.yml" up -d docker compose -f "$SCRIPT_DIR/$compose_file" up -d
# 5. Wait for Lightning.Pub # 5. Wait for Lightning.Pub
if ! wait_for_lightning_pub; then if ! wait_for_lightning_pub; then
@ -450,8 +481,9 @@ cmd_up() {
} }
cmd_down() { cmd_down() {
local compose_file=$(get_compose_file)
log "Stopping lamassu services..." log "Stopping lamassu services..."
docker compose -f "$SCRIPT_DIR/docker-compose.regtest.yml" down 2>/dev/null || true docker compose -f "$SCRIPT_DIR/$compose_file" down 2>/dev/null || true
if [[ "$1" == "--all" ]]; then if [[ "$1" == "--all" ]]; then
stop_regtest stop_regtest
@ -469,8 +501,9 @@ cmd_reset() {
exit 0 exit 0
fi fi
local compose_file=$(get_compose_file)
log "Stopping services..." log "Stopping services..."
docker compose -f "$SCRIPT_DIR/docker-compose.regtest.yml" down -v 2>/dev/null || true docker compose -f "$SCRIPT_DIR/$compose_file" down -v 2>/dev/null || true
log "Removing state files..." log "Removing state files..."
rm -rf "$STATE_DIR" rm -rf "$STATE_DIR"
@ -480,7 +513,8 @@ cmd_reset() {
} }
cmd_logs() { cmd_logs() {
docker compose -f "$SCRIPT_DIR/docker-compose.regtest.yml" logs -f "$@" local compose_file=$(get_compose_file)
docker compose -f "$SCRIPT_DIR/$compose_file" logs -f "$@"
} }
cmd_status() { cmd_status() {
@ -672,6 +706,16 @@ case "${1:-help}" in
shift shift
cmd_logs "$@" cmd_logs "$@"
;; ;;
# Internal command for external orchestration (called by regtest-start --with-lamassu)
_setup_after_start)
if ! is_lightning_pub_ready; then
wait_for_lightning_pub || exit 1
fi
local pubkey=$(extract_lightning_pub_info)
update_atm_env "$pubkey"
setup_atm_app || true
echo "ATM setup complete"
;;
status|info) status|info)
cmd_status cmd_status
;; ;;
@ -709,15 +753,17 @@ case "${1:-help}" in
echo " ./dev.sh logs miner" echo " ./dev.sh logs miner"
echo "" echo ""
echo "Options for 'up':" echo "Options for 'up':"
echo " --standalone Use self-contained mode (own bitcoind/lnd)"
echo " --worktree <path> Build Lightning.Pub from git worktree" echo " --worktree <path> Build Lightning.Pub from git worktree"
echo " --image <name> Use specific Docker image" echo " --image <name> Use specific Docker image"
echo " --skip-regtest Don't auto-start regtest" echo " --skip-regtest Don't auto-start shared regtest"
echo " --fund Auto-fund ATM with 100k sats after startup" echo " --fund Auto-fund ATM with 100k sats after startup"
echo " --fund=<sats> Auto-fund ATM with specific amount" echo " --fund=<sats> Auto-fund ATM with specific amount"
echo " --machine Launch ATM app after startup" echo " --machine Launch ATM app after startup"
echo "" echo ""
echo "Examples:" echo "Examples:"
echo " $0 up # Start with default image" echo " $0 up # Start (uses shared regtest)"
echo " $0 up --standalone # Start self-contained"
echo " $0 up --fund # Start and fund ATM" echo " $0 up --fund # Start and fund ATM"
echo " $0 up --fund --machine # Start, fund, and launch ATM" echo " $0 up --fund --machine # Start, fund, and launch ATM"
echo " $0 up --fund=50000 # Start and fund with 50k sats" echo " $0 up --fund=50000 # Start and fund with 50k sats"