Update Fedimint configuration and enhance onboarding process
- Upgraded Fedimint version to v0.10.0 in docker-compose.yml and manifest.yml, adding support for the built-in Guardian UI. - Modified .gitignore to exclude deploy-config.sh script. - Enhanced onboarding process in AuthManager to persist onboarding state and validate password strength during user setup. - Updated API to handle onboarding completion and password change requests, ensuring a smoother user experience. - Improved configuration management to support Nostr discovery and Tor proxy settings, enhancing node identity features.
This commit is contained in:
7
scripts/deploy-config.example
Normal file
7
scripts/deploy-config.example
Normal file
@@ -0,0 +1,7 @@
|
||||
# Deploy config (copy to deploy-config.sh and set your password)
|
||||
# deploy-config.sh is gitignored so the password is not committed.
|
||||
#
|
||||
# cp scripts/deploy-config.example scripts/deploy-config.sh
|
||||
# Edit deploy-config.sh and set ARCHIPELAGO_PASSWORD
|
||||
#
|
||||
export ARCHIPELAGO_PASSWORD='your_password_here'
|
||||
@@ -5,7 +5,8 @@
|
||||
# Usage:
|
||||
# ./scripts/deploy-to-target.sh # Sync and rebuild
|
||||
# ./scripts/deploy-to-target.sh --quick # Sync only, no rebuild
|
||||
# ./scripts/deploy-to-target.sh --live # Deploy to live system
|
||||
# ./scripts/deploy-to-target.sh --live # Deploy to live system (default: 192.168.1.228)
|
||||
# ./scripts/deploy-to-target.sh --both # Deploy to 228, then copy to 198
|
||||
#
|
||||
|
||||
set -e
|
||||
@@ -13,12 +14,16 @@ set -e
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
|
||||
# Load deploy config (password etc.) - deploy-config.sh is gitignored
|
||||
[ -f "$SCRIPT_DIR/deploy-config.sh" ] && . "$SCRIPT_DIR/deploy-config.sh"
|
||||
|
||||
# Configuration
|
||||
TARGET_HOST="${ARCHIPELAGO_TARGET:-archipelago@192.168.1.228}"
|
||||
TARGET_DIR="/home/archipelago/archy"
|
||||
# Password for non-interactive SSH/rsync (dev server only). See .cursor/rules/Development-Workflow.md
|
||||
# Password for non-interactive SSH/rsync. Set in deploy-config.sh or ARCHIPELAGO_PASSWORD env.
|
||||
ARCHIPELAGO_PASSWORD="${ARCHIPELAGO_PASSWORD:-archipelago}"
|
||||
SSH_OPTS="-o StrictHostKeyChecking=no"
|
||||
# Force password auth when using sshpass (avoids "Permission denied" from SSH key mismatch)
|
||||
SSH_OPTS="-o StrictHostKeyChecking=no -o PreferredAuthentications=password -o PubkeyAuthentication=no"
|
||||
|
||||
echo "╔════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ Deploying to Archipelago Target ║"
|
||||
@@ -30,13 +35,40 @@ echo ""
|
||||
# Parse arguments
|
||||
QUICK=false
|
||||
LIVE=false
|
||||
BOTH=false
|
||||
for arg in "$@"; do
|
||||
case $arg in
|
||||
--quick) QUICK=true ;;
|
||||
--live) LIVE=true ;;
|
||||
--both) BOTH=true ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# When --both: deploy to 228 first, then copy to 198
|
||||
if [ "$BOTH" = true ]; then
|
||||
echo "Deploying to both servers (228, then 198)..."
|
||||
"$0" --live
|
||||
echo ""
|
||||
echo "📤 Copying to 192.168.1.198 (no rsync/cargo on that node)..."
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" scp $SSH_OPTS archipelago@192.168.1.228:$TARGET_DIR/core/target/release/archipelago /tmp/archipelago-both 2>/dev/null || true
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" scp $SSH_OPTS /tmp/archipelago-both archipelago@192.168.1.198:/tmp/archipelago-new
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS archipelago@192.168.1.228 "cd $TARGET_DIR && tar cf - web/dist/neode-ui 2>/dev/null" | sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS archipelago@192.168.1.198 "mkdir -p /tmp/web-deploy && cd /tmp/web-deploy && tar xf -"
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS archipelago@192.168.1.198 '
|
||||
sudo systemctl stop archipelago
|
||||
sudo cp /tmp/archipelago-new /usr/local/bin/archipelago
|
||||
sudo chmod +x /usr/local/bin/archipelago
|
||||
rm -f /tmp/archipelago-new
|
||||
sudo rm -rf /opt/archipelago/web-ui/*
|
||||
sudo cp -r /tmp/web-deploy/web/dist/neode-ui/* /opt/archipelago/web-ui/ 2>/dev/null || true
|
||||
sudo chown -R 1000:1000 /opt/archipelago/web-ui
|
||||
sudo systemctl start archipelago
|
||||
sudo systemctl restart nginx
|
||||
echo " ✅ 192.168.1.198 deployed"
|
||||
'
|
||||
rm -f /tmp/archipelago-both
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Sync code
|
||||
echo "📦 Syncing code..."
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" rsync -avz --delete \
|
||||
@@ -88,17 +120,310 @@ if [ "$LIVE" = true ]; then
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS "$TARGET_HOST" "sudo cp -r $TARGET_DIR/web/dist/neode-ui/* /opt/archipelago/web-ui/"
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS "$TARGET_HOST" "sudo chown -R 1000:1000 /opt/archipelago/web-ui"
|
||||
|
||||
# Add /archipelago/ to nginx if missing (for peer messaging over Tor)
|
||||
if [ -f "$SCRIPT_DIR/nginx-archipelago-patch.conf" ]; then
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" scp $SSH_OPTS "$SCRIPT_DIR/nginx-archipelago-patch.conf" "$TARGET_HOST:/tmp/archipelago-nginx-patch.conf" 2>/dev/null || true
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS "$TARGET_HOST" '
|
||||
CFG=/etc/nginx/sites-available/archipelago
|
||||
if [ -f "$CFG" ] && [ -f /tmp/archipelago-nginx-patch.conf ] && ! grep -q "location /archipelago/" "$CFG"; then
|
||||
echo " Adding /archipelago/ to nginx..."
|
||||
sudo sed -i "/# Proxy API requests to backend/r /tmp/archipelago-nginx-patch.conf" "$CFG"
|
||||
fi
|
||||
rm -f /tmp/archipelago-nginx-patch.conf
|
||||
' 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Restart services
|
||||
echo " Restarting services..."
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS "$TARGET_HOST" "sudo systemctl start archipelago && sudo systemctl restart nginx"
|
||||
|
||||
# Rebuild and restart LND UI container (serves the static app at port 8081; otherwise changes to docker/lnd-ui/ are not visible)
|
||||
# Rebuild and recreate LND UI container (port 8081 so Launch from UI and http://host:8081 both work)
|
||||
echo " Rebuilding LND UI..."
|
||||
if sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS "$TARGET_HOST" "cd $TARGET_DIR/docker/lnd-ui && (command -v podman >/dev/null 2>&1 && sudo podman build -t lnd-ui:latest . || sudo docker build -t lnd-ui:latest .)" 2>&1 | tail -8 | sed 's/^/ /'; then
|
||||
echo " Restarting LND UI container..."
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS "$TARGET_HOST" 'for c in $(sudo podman ps -a --format "{{.Names}}" 2>/dev/null | grep -i lnd-ui) $(sudo docker ps -a --format "{{.Names}}" 2>/dev/null | grep -i lnd-ui); do [ -n "$c" ] && (sudo podman restart "$c" 2>/dev/null || sudo docker restart "$c" 2>/dev/null) && break; done' || true
|
||||
if sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS "$TARGET_HOST" "cd $TARGET_DIR/docker/lnd-ui && (command -v podman >/dev/null 2>&1 && sudo podman build --no-cache -t lnd-ui:latest . || sudo docker build --no-cache -t lnd-ui:latest .)" 2>&1 | tail -12 | sed 's/^/ /'; then
|
||||
echo " Recreating LND UI container (port 8081)..."
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS "$TARGET_HOST" '
|
||||
DOCKER=podman
|
||||
command -v podman >/dev/null 2>&1 || DOCKER=docker
|
||||
for c in $(sudo $DOCKER ps -a --format "{{.Names}}" 2>/dev/null | grep -i lnd-ui); do
|
||||
[ -n "$c" ] && sudo $DOCKER stop "$c" 2>/dev/null; sudo $DOCKER rm -f "$c" 2>/dev/null
|
||||
done
|
||||
sudo $DOCKER run -d --name archy-lnd-ui -p 8081:80 --restart unless-stopped lnd-ui:latest
|
||||
' 2>&1 | sed 's/^/ /' || true
|
||||
fi
|
||||
|
||||
|
||||
# Rebuild and recreate Electrs UI container (port 50002)
|
||||
echo " Rebuilding Electrs UI..."
|
||||
if sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS "$TARGET_HOST" "cd $TARGET_DIR/docker/electrs-ui && (command -v podman >/dev/null 2>&1 && sudo podman build --no-cache -t electrs-ui:latest . || sudo docker build --no-cache -t electrs-ui:latest .)" 2>&1 | tail -12 | sed 's/^/ /'; then
|
||||
echo " Recreating Electrs UI container (port 50002, host network)..."
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS "$TARGET_HOST" '
|
||||
DOCKER=podman
|
||||
command -v podman >/dev/null 2>&1 || DOCKER=docker
|
||||
for c in $(sudo $DOCKER ps -a --format "{{.Names}}" 2>/dev/null | grep -i electrs-ui); do
|
||||
[ -n "$c" ] && sudo $DOCKER stop "$c" 2>/dev/null; sudo $DOCKER rm -f "$c" 2>/dev/null
|
||||
done
|
||||
sudo $DOCKER run -d --name archy-electrs-ui --network host --restart unless-stopped electrs-ui:latest
|
||||
' 2>&1 | sed 's/^/ /' || true
|
||||
fi
|
||||
|
||||
# Bitcoin Knots: required for Mempool, Electrs, BTCPay, Fedimint
|
||||
TARGET_IP="$(echo "$TARGET_HOST" | cut -d@ -f2)"
|
||||
echo " Ensuring Bitcoin Knots (required for Electrs/Mempool)..."
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS "$TARGET_HOST" "
|
||||
DOCKER=podman
|
||||
command -v podman >/dev/null 2>&1 || DOCKER=docker
|
||||
sudo \$DOCKER network create archy-net 2>/dev/null || true
|
||||
NET_OPT='--network archy-net'
|
||||
if ! sudo \$DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -qE 'bitcoin-knots|archy-bitcoin-knots'; then
|
||||
echo ' Creating Bitcoin Knots (mainnet, archipelago RPC)...'
|
||||
sudo mkdir -p /var/lib/archipelago/bitcoin
|
||||
sudo \$DOCKER run -d --name bitcoin-knots --restart unless-stopped \$NET_OPT \
|
||||
-p 8332:8332 -p 8333:8333 \
|
||||
-v /var/lib/archipelago/bitcoin:/home/bitcoin/.bitcoin \
|
||||
docker.io/bitcoinknots/bitcoin:latest \
|
||||
-server=1 -txindex=1 \
|
||||
-rpcallowip=0.0.0.0/0 -rpcbind=0.0.0.0:8332 \
|
||||
-rpcuser=archipelago -rpcpassword=archipelago123 \
|
||||
-dbcache=4096
|
||||
echo ' Bitcoin Knots started (sync may take hours)'
|
||||
else
|
||||
sudo \$DOCKER network connect archy-net bitcoin-knots 2>/dev/null || true
|
||||
fi
|
||||
" 2>&1 | sed 's/^/ /' || true
|
||||
|
||||
# Fix Mempool: clean duplicates, ensure full stack - mysql, backend (8999), frontend (4080)
|
||||
echo " Fixing Mempool stack (host=$TARGET_IP)..."
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS "$TARGET_HOST" "
|
||||
DOCKER=podman
|
||||
command -v podman >/dev/null 2>&1 || DOCKER=docker
|
||||
TARGET_IP='$TARGET_IP'
|
||||
NET_OPT='--network archy-net'
|
||||
# Clean any duplicate/old mempool containers (user may have two versions)
|
||||
for c in mempool mempool-api mempool-electrs mempool-web archy-mempool-api archy-mempool-web; do
|
||||
sudo \$DOCKER stop \$c 2>/dev/null
|
||||
sudo \$DOCKER rm -f \$c 2>/dev/null
|
||||
done
|
||||
# Create mysql-mempool if missing
|
||||
if ! sudo \$DOCKER ps -a --format '{{.Names}}' 2>/dev/null | grep -qE 'mysql-mempool|archy-mempool-db'; then
|
||||
echo ' Creating mysql-mempool...'
|
||||
sudo mkdir -p /var/lib/archipelago/mysql-mempool
|
||||
sudo \$DOCKER run -d --name archy-mempool-db --restart unless-stopped \$NET_OPT \
|
||||
-v /var/lib/archipelago/mysql-mempool:/var/lib/mysql \
|
||||
-e MYSQL_DATABASE=mempool \
|
||||
-e MYSQL_USER=mempool \
|
||||
-e MYSQL_PASSWORD=mempoolpass \
|
||||
-e MYSQL_ROOT_PASSWORD=rootpass \
|
||||
docker.io/mariadb:10.11
|
||||
sleep 3
|
||||
fi
|
||||
MYSQL_CNT=\$(sudo \$DOCKER ps -a --format '{{.Names}}' 2>/dev/null | grep -E 'mysql-mempool|archy-mempool-db' | head -1)
|
||||
MYSQL_CNT=\${MYSQL_CNT:-archy-mempool-db}
|
||||
# Ensure DB is on archy-net so mempool-api can resolve it
|
||||
sudo \$DOCKER network connect archy-net \$MYSQL_CNT 2>/dev/null || true
|
||||
# Create mempool-electrs (indexer - connects to Bitcoin, exposes Electrum protocol on 50001)
|
||||
for c in \$(sudo \$DOCKER ps -a --format '{{.Names}}' 2>/dev/null | grep mempool-electrs); do
|
||||
echo ' Recreating mempool-electrs...'
|
||||
sudo \$DOCKER stop \"\$c\" 2>/dev/null
|
||||
sudo \$DOCKER rm -f \"\$c\" 2>/dev/null
|
||||
done
|
||||
if ! sudo \$DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -q mempool-electrs; then
|
||||
echo ' Creating mempool-electrs (indexer - may take hours to sync)...'
|
||||
sudo mkdir -p /var/lib/archipelago/mempool-electrs
|
||||
# Use host IP to reach Bitcoin (TARGET_IP:8332) - more reliable than container DNS (bitcoin-knots)
|
||||
sudo \$DOCKER run -d --name mempool-electrs --restart unless-stopped \
|
||||
-p 50001:50001 \
|
||||
-v /var/lib/archipelago/mempool-electrs:/data \
|
||||
docker.io/mempool/electrs:latest \
|
||||
--daemon-rpc-addr \$TARGET_IP:8332 \
|
||||
--cookie archipelago:archipelago123 \
|
||||
--jsonrpc-import \
|
||||
--electrum-rpc-addr 0.0.0.0:50001 \
|
||||
--db-dir /data \
|
||||
--lightmode
|
||||
fi
|
||||
# Create/recreate mempool-api (backend on 8999) - required for mempool to work
|
||||
for c in \$(sudo \$DOCKER ps -a --format '{{.Names}}' 2>/dev/null | grep -E 'mempool-api|archy-mempool-api'); do
|
||||
echo ' Recreating mempool-api (backend)...'
|
||||
sudo \$DOCKER stop \"\$c\" 2>/dev/null
|
||||
sudo \$DOCKER rm -f \"\$c\" 2>/dev/null
|
||||
done
|
||||
if ! sudo \$DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -q mempool-api; then
|
||||
echo ' Creating mempool-api (backend)...'
|
||||
sudo mkdir -p /var/lib/archipelago/mempool
|
||||
sudo \$DOCKER run -d --name mempool-api --restart unless-stopped \$NET_OPT \
|
||||
-p 8999:8999 \
|
||||
-v /var/lib/archipelago/mempool:/data \
|
||||
-e MEMPOOL_BACKEND=electrum \
|
||||
-e ELECTRUM_HOST=mempool-electrs \
|
||||
-e ELECTRUM_PORT=50001 \
|
||||
-e ELECTRUM_TLS_ENABLED=false \
|
||||
-e CORE_RPC_HOST=\$TARGET_IP \
|
||||
-e CORE_RPC_PORT=8332 \
|
||||
-e CORE_RPC_USERNAME=archipelago \
|
||||
-e CORE_RPC_PASSWORD=archipelago123 \
|
||||
-e DATABASE_ENABLED=true \
|
||||
-e DATABASE_HOST=\$MYSQL_CNT \
|
||||
-e DATABASE_DATABASE=mempool \
|
||||
-e DATABASE_USERNAME=mempool \
|
||||
-e DATABASE_PASSWORD=mempoolpass \
|
||||
docker.io/mempool/backend:v2.5.0
|
||||
fi
|
||||
# Recreate mempool frontend - handle both 'mempool' and 'mempool-web' (frontend was on wrong port 8999)
|
||||
for c in \$(sudo \$DOCKER ps -a --format '{{.Names}}' 2>/dev/null | grep -E '^mempool\$|mempool-web|archy-mempool-web'); do
|
||||
echo ' Recreating mempool frontend on 4080...'
|
||||
sudo \$DOCKER stop \"\$c\" 2>/dev/null
|
||||
sudo \$DOCKER rm -f \"\$c\" 2>/dev/null
|
||||
break
|
||||
done
|
||||
if ! sudo \$DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -q archy-mempool-web; then
|
||||
echo ' Creating mempool frontend on 4080...'
|
||||
sudo \$DOCKER run -d --name archy-mempool-web --restart unless-stopped \$NET_OPT \
|
||||
-p 4080:8080 \
|
||||
-e FRONTEND_HTTP_PORT=8080 \
|
||||
-e BACKEND_MAINNET_HTTP_HOST=mempool-api \
|
||||
docker.io/mempool/frontend:v2.5.0
|
||||
fi
|
||||
" 2>&1 | sed 's/^/ /' || true
|
||||
|
||||
# Fix BTCPay Server: requires PostgreSQL; create archy-btcpay-db, recreate btcpay-server with BTCPAY_POSTGRES
|
||||
echo " Fixing BTCPay Server stack..."
|
||||
TARGET_IP="$(echo "$TARGET_HOST" | cut -d@ -f2)"
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS "$TARGET_HOST" "
|
||||
DOCKER=podman
|
||||
command -v podman >/dev/null 2>&1 || DOCKER=docker
|
||||
TARGET_IP='$TARGET_IP'
|
||||
sudo \$DOCKER network create archy-net 2>/dev/null || true
|
||||
NET_OPT='--network archy-net'
|
||||
# Create PostgreSQL for BTCPay if missing
|
||||
if ! sudo \$DOCKER ps -a --format '{{.Names}}' 2>/dev/null | grep -qE 'archy-btcpay-db|postgres-btcpay'; then
|
||||
echo ' Creating archy-btcpay-db (PostgreSQL)...'
|
||||
sudo mkdir -p /var/lib/archipelago/postgres-btcpay
|
||||
sudo \$DOCKER run -d --name archy-btcpay-db --restart unless-stopped \$NET_OPT \
|
||||
-v /var/lib/archipelago/postgres-btcpay:/var/lib/postgresql/data \
|
||||
-e POSTGRES_DB=btcpay \
|
||||
-e POSTGRES_USER=btcpay \
|
||||
-e POSTGRES_PASSWORD=btcpaypass \
|
||||
docker.io/postgres:15-alpine
|
||||
sleep 3
|
||||
fi
|
||||
# Recreate btcpay-server with PostgreSQL and Bitcoin RPC
|
||||
for c in \$(sudo \$DOCKER ps -a --format '{{.Names}}' 2>/dev/null | grep -E 'btcpay-server|archy-btcpay'); do
|
||||
echo ' Recreating btcpay-server with PostgreSQL...'
|
||||
sudo \$DOCKER stop \"\$c\" 2>/dev/null
|
||||
sudo \$DOCKER rm -f \"\$c\" 2>/dev/null
|
||||
break
|
||||
done
|
||||
if ! sudo \$DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -q btcpay-server; then
|
||||
echo ' Creating btcpay-server on 23000...'
|
||||
sudo mkdir -p /var/lib/archipelago/btcpay
|
||||
sudo \$DOCKER run -d --name btcpay-server --restart unless-stopped \$NET_OPT \
|
||||
-p 23000:49392 \
|
||||
-v /var/lib/archipelago/btcpay:/datadir \
|
||||
-e ASPNETCORE_URLS=http://0.0.0.0:49392 \
|
||||
-e BTCPAY_PROTOCOL=http \
|
||||
-e BTCPAY_HOST=\$TARGET_IP:23000 \
|
||||
-e BTCPAY_CHAINS=btc \
|
||||
-e BTCPAY_BTCRPCURL=http://\$TARGET_IP:8332 \
|
||||
-e BTCPAY_BTCRPCUSER=archipelago \
|
||||
-e BTCPAY_BTCRPCPASSWORD=archipelago123 \
|
||||
-e BTCPAY_POSTGRES='User ID=btcpay;Password=btcpaypass;Host=archy-btcpay-db;Port=5432;Database=btcpay;Include Error Detail=true' \
|
||||
docker.io/btcpayserver/btcpayserver:1.13.5
|
||||
fi
|
||||
" 2>&1 | sed 's/^/ /' || true
|
||||
|
||||
# Tor: global hidden services - each service gets its own .onion address
|
||||
echo " Setting up Tor (hidden services for each app)..."
|
||||
TARGET_IP="$(echo "$TARGET_HOST" | cut -d@ -f2)"
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS "$TARGET_HOST" "
|
||||
DOCKER=podman
|
||||
command -v podman >/dev/null 2>&1 || DOCKER=docker
|
||||
TARGET_IP='$TARGET_IP'
|
||||
sudo mkdir -p /var/lib/archipelago/tor
|
||||
# Deploy torrc from repo (or create if missing)
|
||||
if [ -f $TARGET_DIR/scripts/tor/torrc.template ]; then
|
||||
sudo cp $TARGET_DIR/scripts/tor/torrc.template /var/lib/archipelago/tor/torrc
|
||||
fi
|
||||
if [ ! -f /var/lib/archipelago/tor/torrc ]; then
|
||||
echo 'SocksPort 9050' | sudo tee /var/lib/archipelago/tor/torrc
|
||||
echo 'ControlPort 0' | sudo tee -a /var/lib/archipelago/tor/torrc
|
||||
echo 'DataDirectory /var/lib/archipelago/tor' | sudo tee -a /var/lib/archipelago/tor/torrc
|
||||
echo 'HiddenServiceDir /var/lib/archipelago/tor/hidden_service_archipelago/' | sudo tee -a /var/lib/archipelago/tor/torrc
|
||||
echo 'HiddenServicePort 80 127.0.0.1:80' | sudo tee -a /var/lib/archipelago/tor/torrc
|
||||
echo 'HiddenServiceDir /var/lib/archipelago/tor/hidden_service_lnd/' | sudo tee -a /var/lib/archipelago/tor/torrc
|
||||
echo 'HiddenServicePort 80 127.0.0.1:8081' | sudo tee -a /var/lib/archipelago/tor/torrc
|
||||
echo 'HiddenServiceDir /var/lib/archipelago/tor/hidden_service_btcpay/' | sudo tee -a /var/lib/archipelago/tor/torrc
|
||||
echo 'HiddenServicePort 80 127.0.0.1:23000' | sudo tee -a /var/lib/archipelago/tor/torrc
|
||||
echo 'HiddenServiceDir /var/lib/archipelago/tor/hidden_service_mempool/' | sudo tee -a /var/lib/archipelago/tor/torrc
|
||||
echo 'HiddenServicePort 80 127.0.0.1:4080' | sudo tee -a /var/lib/archipelago/tor/torrc
|
||||
echo 'HiddenServiceDir /var/lib/archipelago/tor/hidden_service_fedimint/' | sudo tee -a /var/lib/archipelago/tor/torrc
|
||||
echo 'HiddenServicePort 80 127.0.0.1:8175' | sudo tee -a /var/lib/archipelago/tor/torrc
|
||||
fi
|
||||
for c in \$(sudo \$DOCKER ps -a --format '{{.Names}}' 2>/dev/null | grep -E 'archy-tor|^tor\$'); do
|
||||
sudo \$DOCKER stop \"\$c\" 2>/dev/null
|
||||
sudo \$DOCKER rm -f \"\$c\" 2>/dev/null
|
||||
done
|
||||
if ! sudo \$DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -q archy-tor; then
|
||||
echo ' Creating Tor container (host network for hidden services)...'
|
||||
if sudo \$DOCKER run -d --name archy-tor --restart unless-stopped --network host \
|
||||
-v /var/lib/archipelago/tor:/var/lib/archipelago/tor \
|
||||
--entrypoint tor \
|
||||
docker.io/andrius/alpine-tor:latest \
|
||||
-f /var/lib/archipelago/tor/torrc 2>/dev/null; then
|
||||
echo ' Tor container started (andrius/alpine-tor)'
|
||||
else
|
||||
echo ' Tor container image failed, trying system tor...'
|
||||
sudo apt-get update -qq && sudo apt-get install -y -qq tor 2>/dev/null || true
|
||||
if command -v tor >/dev/null 2>&1; then
|
||||
sudo cp /var/lib/archipelago/tor/torrc /etc/tor/torrc 2>/dev/null || true
|
||||
sudo chown -R debian-tor:debian-tor /var/lib/archipelago/tor 2>/dev/null || true
|
||||
sudo systemctl enable tor 2>/dev/null
|
||||
sudo systemctl restart tor 2>/dev/null
|
||||
echo ' Using system Tor daemon'
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
" 2>&1 | sed 's/^/ /' || true
|
||||
|
||||
# Tor diagnostic: check if hostname files exist (may take 30-60s after Tor starts)
|
||||
echo " Checking Tor hostname files..."
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS "$TARGET_HOST" "
|
||||
for svc in archipelago btcpay mempool lnd fedimint; do
|
||||
f=/var/lib/archipelago/tor/hidden_service_\${svc}/hostname
|
||||
if [ -f \"\$f\" ]; then
|
||||
echo \" ✓ \$svc: \$(cat \$f)\"
|
||||
else
|
||||
echo \" ✗ \$svc: hostname not yet generated (Tor may need 30-60s)\"
|
||||
fi
|
||||
done
|
||||
" 2>&1 | sed 's/^/ /' || true
|
||||
|
||||
# Recreate Fedimint with FM_API_URL for Guardian UI (fixes "Api URL must be configured")
|
||||
echo " Fixing Fedimint API URL..."
|
||||
TARGET_IP="$(echo "$TARGET_HOST" | cut -d@ -f2)"
|
||||
sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS "$TARGET_HOST" "
|
||||
DOCKER=podman
|
||||
command -v podman >/dev/null 2>&1 || DOCKER=docker
|
||||
for c in \$(sudo \$DOCKER ps -a --format '{{.Names}}' 2>/dev/null | grep -E '^fedimint\$'); do
|
||||
echo ' Recreating fedimint with FM_API_URL...'
|
||||
sudo \$DOCKER stop \"\$c\" 2>/dev/null
|
||||
sudo \$DOCKER rm -f \"\$c\" 2>/dev/null
|
||||
sudo \$DOCKER run -d --name fedimint --restart unless-stopped \
|
||||
-p 8173:8173 -p 8174:8174 -p 8175:8175 \
|
||||
-v /var/lib/archipelago/fedimint:/data \
|
||||
-e FM_DATA_DIR=/data \
|
||||
-e FM_BITCOIND_USERNAME=archipelago \
|
||||
-e FM_BITCOIND_PASSWORD=archipelago123 \
|
||||
-e FM_BITCOIN_NETWORK=bitcoin \
|
||||
-e FM_BIND_P2P=0.0.0.0:8173 \
|
||||
-e FM_BIND_API=0.0.0.0:8174 \
|
||||
-e FM_BIND_UI=0.0.0.0:8175 \
|
||||
-e FM_P2P_URL=fedimint://$TARGET_IP:8173 \
|
||||
-e FM_API_URL=ws://$TARGET_IP:8174 \
|
||||
-e FM_BITCOIND_URL=http://$TARGET_IP:8332 \
|
||||
docker.io/fedimint/fedimintd:v0.10.0
|
||||
break
|
||||
done
|
||||
" 2>&1 | sed 's/^/ /' || true
|
||||
|
||||
echo ""
|
||||
echo "✅ Deployed to live system!"
|
||||
echo " Backend: $(sshpass -p "$ARCHIPELAGO_PASSWORD" ssh $SSH_OPTS "$TARGET_HOST" 'sudo systemctl is-active archipelago')"
|
||||
|
||||
6
scripts/nginx-archipelago-patch.conf
Normal file
6
scripts/nginx-archipelago-patch.conf
Normal file
@@ -0,0 +1,6 @@
|
||||
location /archipelago/ {
|
||||
proxy_pass http://127.0.0.1:5678;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
}
|
||||
20
scripts/tor/README.md
Normal file
20
scripts/tor/README.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Archipelago Tor Integration
|
||||
|
||||
Each service gets its own .onion address. Tor runs in a container with host networking so it can reach host-mapped ports.
|
||||
|
||||
## Service → Onion mapping
|
||||
|
||||
| Service | LAN Port | Tor Hidden Service Dir |
|
||||
|-----------|----------|-------------------------------|
|
||||
| Archipelago | 80 | hidden_service_archipelago |
|
||||
| LND UI | 8081 | hidden_service_lnd |
|
||||
| BTCPay | 23000 | hidden_service_btcpay |
|
||||
| Mempool | 4080 | hidden_service_mempool |
|
||||
| Fedimint | 8175 | hidden_service_fedimint |
|
||||
|
||||
## Hostname files
|
||||
|
||||
After Tor starts, each service's .onion address is written to:
|
||||
`/var/lib/archipelago/tor/hidden_service_<name>/hostname`
|
||||
|
||||
The backend reads these to expose Tor addresses in the package API.
|
||||
29
scripts/tor/torrc.template
Normal file
29
scripts/tor/torrc.template
Normal file
@@ -0,0 +1,29 @@
|
||||
# Archipelago Tor Hidden Services
|
||||
# Each service gets its own .onion address
|
||||
# Tor runs with --network host so 127.0.0.1 refers to host ports
|
||||
# DataDirectory: use /var/lib/archipelago/tor so backend can read hostnames
|
||||
# SocksPort 9050: required for outbound .onion requests (peer messaging)
|
||||
|
||||
SocksPort 9050
|
||||
ControlPort 0
|
||||
DataDirectory /var/lib/archipelago/tor
|
||||
|
||||
# Archipelago main web UI (nginx port 80)
|
||||
HiddenServiceDir /var/lib/archipelago/tor/hidden_service_archipelago/
|
||||
HiddenServicePort 80 127.0.0.1:80
|
||||
|
||||
# LND UI
|
||||
HiddenServiceDir /var/lib/archipelago/tor/hidden_service_lnd/
|
||||
HiddenServicePort 80 127.0.0.1:8081
|
||||
|
||||
# BTCPay Server
|
||||
HiddenServiceDir /var/lib/archipelago/tor/hidden_service_btcpay/
|
||||
HiddenServicePort 80 127.0.0.1:23000
|
||||
|
||||
# Mempool (frontend)
|
||||
HiddenServiceDir /var/lib/archipelago/tor/hidden_service_mempool/
|
||||
HiddenServicePort 80 127.0.0.1:4080
|
||||
|
||||
# Fedimint Guardian UI
|
||||
HiddenServiceDir /var/lib/archipelago/tor/hidden_service_fedimint/
|
||||
HiddenServicePort 80 127.0.0.1:8175
|
||||
Reference in New Issue
Block a user