feat: Phase 1 — per-installation credential generation, eliminate hardcoded passwords
Generate unique random passwords at first boot for Bitcoin RPC, all database services (mempool, btcpay, immich, penpot, mysql-root), and Fedimint gateway. Credentials stored in /var/lib/archipelago/secrets/ with 600 permissions. Scripts: first-boot-containers.sh, deploy-to-target.sh, deploy-bitcoin-knots.sh, container-doctor.sh all read from secrets files instead of hardcoded values. Rust backend: new bitcoin_rpc module reads password from secrets file, env var, or dev fallback. All .basic_auth() calls and container config strings now use the shared credential reader instead of hardcoded "archipelago123". Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
f273816405
commit
809a976960
+73
-21
@@ -734,6 +734,58 @@ MANIFEST_EOF
|
||||
|
||||
# Bitcoin Knots: required for Mempool, ElectrumX, BTCPay, Fedimint
|
||||
TARGET_IP="$(echo "$TARGET_HOST" | cut -d@ -f2)"
|
||||
|
||||
# Read per-installation Bitcoin RPC credentials from server secrets
|
||||
progress "Reading Bitcoin RPC credentials"
|
||||
BITCOIN_RPC_PASS=$(ssh $SSH_OPTS "$TARGET_HOST" '
|
||||
SECRETS_DIR="/var/lib/archipelago/secrets"
|
||||
sudo mkdir -p "$SECRETS_DIR" && sudo chmod 700 "$SECRETS_DIR"
|
||||
if [ ! -f "$SECRETS_DIR/bitcoin-rpc-password" ]; then
|
||||
openssl rand -base64 24 | sudo tee "$SECRETS_DIR/bitcoin-rpc-password" > /dev/null
|
||||
sudo chmod 600 "$SECRETS_DIR/bitcoin-rpc-password"
|
||||
fi
|
||||
sudo cat "$SECRETS_DIR/bitcoin-rpc-password"
|
||||
' 2>/dev/null)
|
||||
BITCOIN_RPC_USER="archipelago"
|
||||
if [ -z "$BITCOIN_RPC_PASS" ]; then
|
||||
echo " WARNING: Could not read Bitcoin RPC password from server, aborting container fixes"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Read per-installation database passwords from server secrets
|
||||
DB_PASSWORDS=$(ssh $SSH_OPTS "$TARGET_HOST" '
|
||||
SECRETS_DIR="/var/lib/archipelago/secrets"
|
||||
for svc in mempool btcpay immich penpot mysql-root; do
|
||||
if [ ! -f "$SECRETS_DIR/${svc}-db-password" ]; then
|
||||
openssl rand -base64 24 | sudo tee "$SECRETS_DIR/${svc}-db-password" > /dev/null
|
||||
sudo chmod 600 "$SECRETS_DIR/${svc}-db-password"
|
||||
fi
|
||||
done
|
||||
echo "MEMPOOL_DB_PASS=$(sudo cat "$SECRETS_DIR/mempool-db-password")"
|
||||
echo "BTCPAY_DB_PASS=$(sudo cat "$SECRETS_DIR/btcpay-db-password")"
|
||||
echo "IMMICH_DB_PASS=$(sudo cat "$SECRETS_DIR/immich-db-password")"
|
||||
echo "PENPOT_DB_PASS=$(sudo cat "$SECRETS_DIR/penpot-db-password")"
|
||||
echo "MYSQL_ROOT_PASS=$(sudo cat "$SECRETS_DIR/mysql-root-db-password")"
|
||||
# Fedimint gateway password and hash
|
||||
if [ ! -f "$SECRETS_DIR/fedimint-gateway-password" ]; then
|
||||
FEDI_PASS=$(openssl rand -base64 16)
|
||||
echo "$FEDI_PASS" | sudo tee "$SECRETS_DIR/fedimint-gateway-password" > /dev/null
|
||||
sudo chmod 600 "$SECRETS_DIR/fedimint-gateway-password"
|
||||
if command -v htpasswd >/dev/null 2>&1; then
|
||||
htpasswd -bnBC 10 "" "$FEDI_PASS" | tr -d ":\n" | sudo tee "$SECRETS_DIR/fedimint-gateway-hash" > /dev/null
|
||||
sudo chmod 600 "$SECRETS_DIR/fedimint-gateway-hash"
|
||||
fi
|
||||
fi
|
||||
if [ -f "$SECRETS_DIR/fedimint-gateway-hash" ]; then
|
||||
echo "FEDI_HASH=$(sudo cat "$SECRETS_DIR/fedimint-gateway-hash")"
|
||||
fi
|
||||
' 2>/dev/null)
|
||||
eval "$DB_PASSWORDS"
|
||||
# Fallback if hash not available
|
||||
if [ -z "$FEDI_HASH" ]; then
|
||||
FEDI_HASH='$2y$10$t9YjjxkiktrlYvjajB/zgOMDnSNVg4HqrbDqh47u7Jf42whNdxNqC'
|
||||
fi
|
||||
|
||||
progress "Ensuring Bitcoin Knots"
|
||||
ssh $SSH_OPTS "$TARGET_HOST" "
|
||||
DOCKER=podman
|
||||
@@ -759,7 +811,7 @@ MANIFEST_EOF
|
||||
docker.io/bitcoinknots/bitcoin:latest \
|
||||
-server=1 \$BTC_EXTRA_ARGS \
|
||||
-rpcallowip=0.0.0.0/0 -rpcbind=0.0.0.0:8332 \
|
||||
-rpcuser=archipelago -rpcpassword=archipelago123 \
|
||||
-rpcuser=$BITCOIN_RPC_USER -rpcpassword=$BITCOIN_RPC_PASS \
|
||||
-dbcache=\$BTC_DBCACHE
|
||||
echo ' Bitcoin Knots started (sync may take hours)'
|
||||
else
|
||||
@@ -788,8 +840,8 @@ MANIFEST_EOF
|
||||
-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 \
|
||||
-e MYSQL_PASSWORD=$MEMPOOL_DB_PASS \
|
||||
-e MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASS \
|
||||
docker.io/mariadb:10.11
|
||||
sleep 3
|
||||
fi
|
||||
@@ -814,7 +866,7 @@ MANIFEST_EOF
|
||||
sudo \$DOCKER run -d --name electrumx --restart unless-stopped \$NET_OPT \
|
||||
-p 50001:50001 \
|
||||
-v /var/lib/archipelago/electrumx:/data \
|
||||
-e DAEMON_URL=http://archipelago:archipelago123@bitcoin-knots:8332/ \
|
||||
-e DAEMON_URL=http://$BITCOIN_RPC_USER:$BITCOIN_RPC_PASS@bitcoin-knots:8332/ \
|
||||
-e COIN=Bitcoin \
|
||||
-e DB_DIRECTORY=/data \
|
||||
-e SERVICES=tcp://:50001,rpc://0.0.0.0:8000 \
|
||||
@@ -840,12 +892,12 @@ MANIFEST_EOF
|
||||
-e CORE_RPC_HOST=\$TARGET_IP \
|
||||
-e CORE_RPC_PORT=8332 \
|
||||
-e CORE_RPC_USERNAME=archipelago \
|
||||
-e CORE_RPC_PASSWORD=archipelago123 \
|
||||
-e CORE_RPC_PASSWORD=$BITCOIN_RPC_PASS \
|
||||
-e DATABASE_ENABLED=true \
|
||||
-e DATABASE_HOST=\$MYSQL_CNT \
|
||||
-e DATABASE_DATABASE=mempool \
|
||||
-e DATABASE_USERNAME=mempool \
|
||||
-e DATABASE_PASSWORD=mempoolpass \
|
||||
-e DATABASE_PASSWORD=$MEMPOOL_DB_PASS \
|
||||
docker.io/mempool/backend:v2.5.0
|
||||
fi
|
||||
# Recreate mempool frontend - handle both 'mempool' and 'mempool-web' (frontend was on wrong port 8999)
|
||||
@@ -884,13 +936,13 @@ MANIFEST_EOF
|
||||
-v /var/lib/archipelago/postgres-btcpay:/var/lib/postgresql/data \
|
||||
-e POSTGRES_DB=btcpay \
|
||||
-e POSTGRES_USER=btcpay \
|
||||
-e POSTGRES_PASSWORD=btcpaypass \
|
||||
-e POSTGRES_PASSWORD=$BTCPAY_DB_PASS \
|
||||
docker.io/postgres:15-alpine
|
||||
sleep 3
|
||||
fi
|
||||
# Create NBXplorer database in PostgreSQL (NBXplorer needs its own DB)
|
||||
sudo \$DOCKER exec archy-btcpay-db psql -U postgres -tc \"SELECT 1 FROM pg_database WHERE datname='nbxplorer'\" 2>/dev/null | grep -q 1 || \
|
||||
sudo \$DOCKER exec -e PGPASSWORD=btcpaypass archy-btcpay-db psql -U postgres -c \"CREATE DATABASE nbxplorer;\" 2>/dev/null || true
|
||||
sudo \$DOCKER exec -e PGPASSWORD=$BTCPAY_DB_PASS archy-btcpay-db psql -U postgres -c \"CREATE DATABASE nbxplorer;\" 2>/dev/null || true
|
||||
# Create NBXplorer (required by BTCPay - indexes blocks for payment tracking)
|
||||
if ! sudo \$DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -q archy-nbxplorer; then
|
||||
if sudo \$DOCKER ps -a --format '{{.Names}}' 2>/dev/null | grep -q archy-nbxplorer; then
|
||||
@@ -907,8 +959,8 @@ MANIFEST_EOF
|
||||
-e NBXPLORER_BIND=0.0.0.0:32838 \
|
||||
-e NBXPLORER_BTCRPCURL=http://bitcoin-knots:8332 \
|
||||
-e NBXPLORER_BTCRPCUSER=archipelago \
|
||||
-e NBXPLORER_BTCRPCPASSWORD=archipelago123 \
|
||||
-e NBXPLORER_POSTGRES='User ID=btcpay;Password=btcpaypass;Host=archy-btcpay-db;Port=5432;Database=nbxplorer;Include Error Detail=true' \
|
||||
-e NBXPLORER_BTCRPCPASSWORD=$BITCOIN_RPC_PASS \
|
||||
-e NBXPLORER_POSTGRES='User ID=btcpay;Password=$BTCPAY_DB_PASS;Host=archy-btcpay-db;Port=5432;Database=nbxplorer;Include Error Detail=true' \
|
||||
docker.io/nicolasdorier/nbxplorer:2.6.0
|
||||
sleep 5
|
||||
fi
|
||||
@@ -936,8 +988,8 @@ MANIFEST_EOF
|
||||
-e BTCPAY_BTCEXPLORERURL=http://archy-nbxplorer:32838 \
|
||||
-e BTCPAY_BTCRPCURL=http://bitcoin-knots: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' \
|
||||
-e BTCPAY_BTCRPCPASSWORD=$BITCOIN_RPC_PASS \
|
||||
-e BTCPAY_POSTGRES='User ID=btcpay;Password=$BTCPAY_DB_PASS;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
|
||||
@@ -961,7 +1013,7 @@ MANIFEST_EOF
|
||||
if ! sudo \$DOCKER ps -a --format '{{.Names}}' 2>/dev/null | grep -q immich_postgres; then
|
||||
sudo \$DOCKER run -d --name immich_postgres --restart unless-stopped --network immich-net \
|
||||
-v /var/lib/archipelago/immich-db:/var/lib/postgresql/data \
|
||||
-e POSTGRES_PASSWORD=immichpass -e POSTGRES_USER=postgres -e POSTGRES_DB=immich \
|
||||
-e POSTGRES_PASSWORD=$IMMICH_DB_PASS -e POSTGRES_USER=postgres -e POSTGRES_DB=immich \
|
||||
ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0 2>/dev/null || true
|
||||
sleep 5
|
||||
fi
|
||||
@@ -973,7 +1025,7 @@ MANIFEST_EOF
|
||||
if ! sudo \$DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -q immich_server; then
|
||||
sudo \$DOCKER run -d --name immich_server --restart unless-stopped --network immich-net \
|
||||
-p 2283:2283 -v /var/lib/archipelago/immich:/usr/src/app/upload \
|
||||
-e DB_HOSTNAME=immich_postgres -e DB_USERNAME=postgres -e DB_PASSWORD=immichpass \
|
||||
-e DB_HOSTNAME=immich_postgres -e DB_USERNAME=postgres -e DB_PASSWORD=$IMMICH_DB_PASS \
|
||||
-e DB_DATABASE_NAME=immich -e REDIS_HOSTNAME=immich_redis \
|
||||
-e UPLOAD_LOCATION=/usr/src/app/upload \
|
||||
ghcr.io/immich-app/immich-server:release 2>/dev/null || true
|
||||
@@ -1098,7 +1150,7 @@ print("torrc generated with %d services" % (len(lines) // 3))
|
||||
-v /var/lib/archipelago/fedimint:/data \
|
||||
-e FM_DATA_DIR=/data \
|
||||
-e FM_BITCOIND_USERNAME=archipelago \
|
||||
-e FM_BITCOIND_PASSWORD=archipelago123 \
|
||||
-e FM_BITCOIND_PASSWORD=$BITCOIN_RPC_PASS \
|
||||
-e FM_BITCOIN_NETWORK=bitcoin \
|
||||
-e FM_BIND_P2P=0.0.0.0:8173 \
|
||||
-e FM_BIND_API=0.0.0.0:8174 \
|
||||
@@ -1117,7 +1169,7 @@ print("torrc generated with %d services" % (len(lines) // 3))
|
||||
sudo mkdir -p /var/lib/archipelago/fedimint-gateway
|
||||
LND_CERT=/var/lib/archipelago/lnd/tls.cert
|
||||
LND_MACAROON=/var/lib/archipelago/lnd/data/chain/bitcoin/mainnet/admin.macaroon
|
||||
GW_COMMON=\"-p 8176:8176 -v /var/lib/archipelago/fedimint-gateway:/data docker.io/fedimint/gatewayd:v0.10.0 gatewayd --data-dir /data --listen 0.0.0.0:8176 --bcrypt-password-hash '\$2y\$10\$t9YjjxkiktrlYvjajB/zgOMDnSNVg4HqrbDqh47u7Jf42whNdxNqC' --network bitcoin --bitcoind-url http://$TARGET_IP:8332 --bitcoind-username archipelago --bitcoind-password archipelago123\"
|
||||
GW_COMMON=\"-p 8176:8176 -v /var/lib/archipelago/fedimint-gateway:/data docker.io/fedimint/gatewayd:v0.10.0 gatewayd --data-dir /data --listen 0.0.0.0:8176 --bcrypt-password-hash '$FEDI_HASH' --network bitcoin --bitcoind-url http://$TARGET_IP:8332 --bitcoind-username $BITCOIN_RPC_USER --bitcoind-password $BITCOIN_RPC_PASS\"
|
||||
if sudo \$DOCKER ps --format '{{.Names}}' | grep -q '^lnd\$' && sudo test -f \$LND_CERT && sudo test -f \$LND_MACAROON; then
|
||||
echo ' LND detected — using lnd mode'
|
||||
sudo \$DOCKER run -d --name fedimint-gateway --restart unless-stopped \
|
||||
@@ -1129,9 +1181,9 @@ print("torrc generated with %d services" % (len(lines) // 3))
|
||||
-v /var/lib/archipelago/lnd/data/chain/bitcoin/mainnet/admin.macaroon:/lnd/admin.macaroon:ro \
|
||||
docker.io/fedimint/gatewayd:v0.10.0 \
|
||||
gatewayd --data-dir /data --listen 0.0.0.0:8176 \
|
||||
--bcrypt-password-hash '\$2y\$10\$t9YjjxkiktrlYvjajB/zgOMDnSNVg4HqrbDqh47u7Jf42whNdxNqC' \
|
||||
--bcrypt-password-hash '$FEDI_HASH' \
|
||||
--network bitcoin --bitcoind-url http://$TARGET_IP:8332 \
|
||||
--bitcoind-username archipelago --bitcoind-password archipelago123 \
|
||||
--bitcoind-username $BITCOIN_RPC_USER --bitcoind-password $BITCOIN_RPC_PASS \
|
||||
lnd --lnd-rpc-host $TARGET_IP:10009 --lnd-tls-cert /lnd/tls.cert --lnd-macaroon /lnd/admin.macaroon
|
||||
else
|
||||
echo ' No LND found — using ldk (built-in Lightning)'
|
||||
@@ -1142,9 +1194,9 @@ print("torrc generated with %d services" % (len(lines) // 3))
|
||||
-v /var/lib/archipelago/fedimint-gateway:/data \
|
||||
docker.io/fedimint/gatewayd:v0.10.0 \
|
||||
gatewayd --data-dir /data --listen 0.0.0.0:8176 \
|
||||
--bcrypt-password-hash '\$2y\$10\$t9YjjxkiktrlYvjajB/zgOMDnSNVg4HqrbDqh47u7Jf42whNdxNqC' \
|
||||
--bcrypt-password-hash '$FEDI_HASH' \
|
||||
--network bitcoin --bitcoind-url http://$TARGET_IP:8332 \
|
||||
--bitcoind-username archipelago --bitcoind-password archipelago123 \
|
||||
--bitcoind-username $BITCOIN_RPC_USER --bitcoind-password $BITCOIN_RPC_PASS \
|
||||
ldk --ldk-lightning-port 9737 --ldk-alias archipelago-gateway
|
||||
fi
|
||||
" 2>&1 | sed 's/^/ /') || echo " (Fedimint fix timed out or skipped - run manually if needed)"
|
||||
@@ -1179,7 +1231,7 @@ bitcoin.node=bitcoind
|
||||
[Bitcoind]
|
||||
bitcoind.rpchost=bitcoin-knots:8332
|
||||
bitcoind.rpcuser=archipelago
|
||||
bitcoind.rpcpass=archipelago123
|
||||
bitcoind.rpcpass=$BITCOIN_RPC_PASS
|
||||
bitcoind.rpcpolling=true
|
||||
bitcoind.estimatemode=ECONOMICAL
|
||||
|
||||
|
||||
Reference in New Issue
Block a user