fix(01-11): remove every shipped Fedimint gateway credential (FED-07)
Six code paths configured the Lightning gateway with a bcrypt hash committed to this repository — and one deploy path with a plaintext password literal — whenever the per-install secret was missing. Anyone holding a copy of the repo held the admin credential for every gateway that ever took a fallback. container::secrets now owns the credential end to end: ensure_gateway_credential (idempotent, delegates to ensure_one's bcrypt arm) and gateway_bcrypt_hash, which returns Err when the secret is missing/empty and when the stored value is on the KNOWN_DEFAULT_GATEWAY_HASHES denylist — so this codebase cannot hand back the compromised value even to a node already carrying it. get_app_config was widened to Result so a credential-less install cannot reach podman run at all; configure_fedimint_lnd takes the resolved hash instead of re-reading with its own fallback. The four shell paths stop generating credentials entirely (dropping the htpasswd host dependency) and skip container creation with a printed reason rather than substituting anything. Naming converges on the manifest's fedimint-gateway-hash/.pw, with legacy fedimint-gateway-password values copied forward rather than regenerated so no node loses a working unique credential. Plan 01-16 owns rotation of installs already carrying the default. Verified: cargo build clean; cargo test -p archipelago 999 passed (2 boot_reconciler timing tests failed under concurrent load, green in isolation, untouched by this diff); bash -n clean on all five scripts; the compromised literal now appears exactly once in the tree, as the denylist. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
5faf1a3c5f
commit
4265254700
@@ -101,6 +101,10 @@ reset_spec() {
|
||||
SPEC_SECURITY="no-new-privileges:true" SPEC_RESTART="unless-stopped"
|
||||
SPEC_HEALTH_CMD="" SPEC_ENV="" SPEC_CUSTOM_ARGS="" SPEC_READONLY="false"
|
||||
SPEC_TMPFS="" SPEC_TIER="3" SPEC_DATA_DIR="" SPEC_DATA_UID="100000:100000"
|
||||
# Set by a loader (e.g. fedimint-gateway) to signal "spec is valid but this
|
||||
# container must not be created/recreated right now" — e.g. a required
|
||||
# per-install secret hasn't been generated yet. Empty means no skip.
|
||||
SPEC_SKIP_REASON=""
|
||||
# SPEC_OPTIONAL defaults true: reconcile-containers.sh only REPAIRS existing
|
||||
# containers — it never creates missing ones. Baseline (filebrowser) is
|
||||
# bootstrapped by first-boot-containers.sh; all other apps come from the
|
||||
@@ -323,6 +327,16 @@ load_spec_fedimint-gateway() {
|
||||
SPEC_DATA_DIR="/var/lib/archipelago/fedimint-gateway"
|
||||
SPEC_DEPENDS="bitcoin-knots fedimint"
|
||||
SPEC_OPTIONAL="true"
|
||||
# FED-07: no shipped fallback credential. If the per-install bcrypt hash
|
||||
# (fedimint-gateway-hash, generated by container::secrets::ensure_gateway_credential
|
||||
# via the daemon, first-boot, or reconcile secret-generation step) doesn't
|
||||
# exist yet, do not build an entrypoint with an empty --bcrypt-password-hash
|
||||
# — skip creating/recreating this container and let the caller retry once
|
||||
# the credential exists.
|
||||
if [ -z "$FEDI_HASH" ]; then
|
||||
SPEC_SKIP_REASON="fedimint-gateway credential not generated yet (no shipped default; will retry once a per-install credential exists)"
|
||||
return
|
||||
fi
|
||||
# Custom entrypoint depends on whether LND is available
|
||||
local LND_CERT=/var/lib/archipelago/lnd/tls.cert
|
||||
local LND_MAC=/var/lib/archipelago/lnd/data/chain/bitcoin/mainnet/admin.macaroon
|
||||
|
||||
+55
-40
@@ -493,15 +493,17 @@ deploy_node() {
|
||||
sudo chmod 600 "$SECRETS_DIR/${svc}-db-password"
|
||||
fi
|
||||
done
|
||||
# Fedimint gateway
|
||||
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
|
||||
# FED-07: no shipped fallback, ever. The canonical per-install gateway
|
||||
# credential (fedimint-gateway-hash / .pw) is generated by the daemon
|
||||
# via container::secrets::ensure_gateway_credential — this deploy script
|
||||
# no longer generates it (removes the htpasswd host dependency too).
|
||||
# Legacy migration only: carry an existing fedimint-gateway-password
|
||||
# value forward to the canonical fedimint-gateway-hash.pw name if that
|
||||
# name does not exist yet; never regenerate a working credential, and
|
||||
# never delete the legacy file (plan 01-16 owns retirement).
|
||||
if [ -f "$SECRETS_DIR/fedimint-gateway-password" ] && [ ! -f "$SECRETS_DIR/fedimint-gateway-hash.pw" ]; then
|
||||
sudo cp "$SECRETS_DIR/fedimint-gateway-password" "$SECRETS_DIR/fedimint-gateway-hash.pw"
|
||||
sudo chmod 600 "$SECRETS_DIR/fedimint-gateway-hash.pw"
|
||||
fi
|
||||
' 2>/dev/null
|
||||
# Read each password individually (avoids eval on SSH output)
|
||||
@@ -509,7 +511,12 @@ deploy_node() {
|
||||
BTCPAY_DB_PASS=$(ssh $SSH_OPTS "$TARGET" 'sudo cat /var/lib/archipelago/secrets/btcpay-db-password 2>/dev/null' 2>/dev/null)
|
||||
MYSQL_ROOT_PASS=$(ssh $SSH_OPTS "$TARGET" 'sudo cat /var/lib/archipelago/secrets/mysql-root-db-password 2>/dev/null' 2>/dev/null)
|
||||
FEDI_HASH=$(ssh $SSH_OPTS "$TARGET" 'sudo cat /var/lib/archipelago/secrets/fedimint-gateway-hash 2>/dev/null' 2>/dev/null)
|
||||
[ -z "${FEDI_HASH:-}" ] && FEDI_HASH='$2y$10$t9YjjxkiktrlYvjajB/zgOMDnSNVg4HqrbDqh47u7Jf42whNdxNqC'
|
||||
# FED-07: no fallback literal. If the target has not generated its
|
||||
# per-install gateway credential yet, FEDI_HASH stays empty and the
|
||||
# gateway container creation below is skipped, never substituted.
|
||||
if [ -z "${FEDI_HASH:-}" ]; then
|
||||
echo " NOTE: no fedimint-gateway credential on target yet — gateway container creation will be skipped (no shipped default; the daemon generates one on next install/reconcile)"
|
||||
fi
|
||||
|
||||
if [ -z "$BITCOIN_RPC_PASS" ]; then
|
||||
echo " WARNING: Could not read Bitcoin RPC password — skipping container setup"
|
||||
@@ -772,37 +779,45 @@ LNDCONF
|
||||
fi
|
||||
fi
|
||||
if ! \$DOCKER ps -a --format '{{.Names}}' 2>/dev/null | grep -q fedimint-gateway; then
|
||||
echo ' Creating fedimint-gateway...'
|
||||
sudo mkdir -p /var/lib/archipelago/fedimint-gateway
|
||||
FEDI_PASS=\$(sudo cat /var/lib/archipelago/secrets/fedimint-gateway-password 2>/dev/null || echo 'archipelago')
|
||||
LND_CERT=/var/lib/archipelago/lnd/tls.cert
|
||||
LND_MACAROON=/var/lib/archipelago/lnd/data/chain/bitcoin/mainnet/admin.macaroon
|
||||
if \$DOCKER ps --format '{{.Names}}' | grep -q '^lnd\$' && sudo test -f \$LND_CERT && sudo test -f \$LND_MACAROON; then
|
||||
\$DOCKER run -d --name fedimint-gateway --restart unless-stopped \$NET_OPT \
|
||||
--health-cmd 'curl -sf http://localhost:8176/' --health-interval=30s --health-timeout=5s --health-retries=3 \
|
||||
--cap-drop ALL --cap-add CHOWN --cap-add FOWNER --cap-add SETUID --cap-add SETGID --cap-add DAC_OVERRIDE \
|
||||
--security-opt no-new-privileges:true \
|
||||
-p 8176:8176 -v /var/lib/archipelago/fedimint-gateway:/data \
|
||||
-v /var/lib/archipelago/lnd/tls.cert:/lnd/tls.cert:ro \
|
||||
-v /var/lib/archipelago/lnd/data/chain/bitcoin/mainnet/admin.macaroon:/lnd/admin.macaroon:ro \
|
||||
$FEDIMINT_GATEWAY_IMAGE \
|
||||
gatewayd --data-dir /data --listen 0.0.0.0:8176 \
|
||||
--password \"\$FEDI_PASS\" \
|
||||
--network bitcoin --bitcoind-url http://\$TARGET_IP:8332 \
|
||||
--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
|
||||
# FED-07: the gateway is configured from the per-install bcrypt
|
||||
# hash only — no shipped default, and no plaintext --password
|
||||
# flag. If the target has no credential yet, skip creation and
|
||||
# say why rather than starting a gateway with a known password.
|
||||
GW_HASH=\$(sudo cat /var/lib/archipelago/secrets/fedimint-gateway-hash 2>/dev/null)
|
||||
if [ -z \"\$GW_HASH\" ]; then
|
||||
echo ' Skipping fedimint-gateway — no per-install credential on target yet (no shipped default; the daemon generates one on next install/reconcile)'
|
||||
else
|
||||
\$DOCKER run -d --name fedimint-gateway --restart unless-stopped \$NET_OPT \
|
||||
--health-cmd 'curl -sf http://localhost:8176/' --health-interval=30s --health-timeout=5s --health-retries=3 \
|
||||
--cap-drop ALL --cap-add CHOWN --cap-add FOWNER --cap-add SETUID --cap-add SETGID --cap-add DAC_OVERRIDE \
|
||||
--security-opt no-new-privileges:true \
|
||||
-p 8176:8176 -p 9737:9737 -v /var/lib/archipelago/fedimint-gateway:/data \
|
||||
$FEDIMINT_GATEWAY_IMAGE \
|
||||
gatewayd --data-dir /data --listen 0.0.0.0:8176 \
|
||||
--password \"\$FEDI_PASS\" \
|
||||
--network bitcoin --bitcoind-url http://\$TARGET_IP:8332 \
|
||||
--bitcoind-username $BITCOIN_RPC_USER --bitcoind-password $BITCOIN_RPC_PASS \
|
||||
ldk --ldk-lightning-port 9737 --ldk-alias archipelago-gateway
|
||||
echo ' Creating fedimint-gateway...'
|
||||
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
|
||||
if \$DOCKER ps --format '{{.Names}}' | grep -q '^lnd\$' && sudo test -f \$LND_CERT && sudo test -f \$LND_MACAROON; then
|
||||
\$DOCKER run -d --name fedimint-gateway --restart unless-stopped \$NET_OPT \
|
||||
--health-cmd 'curl -sf http://localhost:8176/' --health-interval=30s --health-timeout=5s --health-retries=3 \
|
||||
--cap-drop ALL --cap-add CHOWN --cap-add FOWNER --cap-add SETUID --cap-add SETGID --cap-add DAC_OVERRIDE \
|
||||
--security-opt no-new-privileges:true \
|
||||
-p 8176:8176 -v /var/lib/archipelago/fedimint-gateway:/data \
|
||||
-v /var/lib/archipelago/lnd/tls.cert:/lnd/tls.cert:ro \
|
||||
-v /var/lib/archipelago/lnd/data/chain/bitcoin/mainnet/admin.macaroon:/lnd/admin.macaroon:ro \
|
||||
$FEDIMINT_GATEWAY_IMAGE \
|
||||
gatewayd --data-dir /data --listen 0.0.0.0:8176 \
|
||||
--bcrypt-password-hash \"\$GW_HASH\" \
|
||||
--network bitcoin --bitcoind-url http://\$TARGET_IP:8332 \
|
||||
--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
|
||||
\$DOCKER run -d --name fedimint-gateway --restart unless-stopped \$NET_OPT \
|
||||
--health-cmd 'curl -sf http://localhost:8176/' --health-interval=30s --health-timeout=5s --health-retries=3 \
|
||||
--cap-drop ALL --cap-add CHOWN --cap-add FOWNER --cap-add SETUID --cap-add SETGID --cap-add DAC_OVERRIDE \
|
||||
--security-opt no-new-privileges:true \
|
||||
-p 8176:8176 -p 9737:9737 -v /var/lib/archipelago/fedimint-gateway:/data \
|
||||
$FEDIMINT_GATEWAY_IMAGE \
|
||||
gatewayd --data-dir /data --listen 0.0.0.0:8176 \
|
||||
--bcrypt-password-hash \"\$GW_HASH\" \
|
||||
--network bitcoin --bitcoind-url http://\$TARGET_IP:8332 \
|
||||
--bitcoind-username $BITCOIN_RPC_USER --bitcoind-password $BITCOIN_RPC_PASS \
|
||||
ldk --ldk-lightning-port 9737 --ldk-alias archipelago-gateway
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
+22
-12
@@ -1259,15 +1259,17 @@ BUILDINFO_EOF
|
||||
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
|
||||
# FED-07: no shipped fallback, ever. The canonical per-install gateway
|
||||
# credential (fedimint-gateway-hash / .pw) is generated by the daemon
|
||||
# via container::secrets::ensure_gateway_credential — this deploy script no
|
||||
# longer generates it (removes the htpasswd host dependency too).
|
||||
# Legacy migration only: carry an existing fedimint-gateway-password
|
||||
# value forward to the canonical fedimint-gateway-hash.pw name if that
|
||||
# name does not exist yet; never regenerate a working credential, and
|
||||
# never delete the legacy file (plan 01-16 owns retirement).
|
||||
if [ -f "$SECRETS_DIR/fedimint-gateway-password" ] && [ ! -f "$SECRETS_DIR/fedimint-gateway-hash.pw" ]; then
|
||||
sudo cp "$SECRETS_DIR/fedimint-gateway-password" "$SECRETS_DIR/fedimint-gateway-hash.pw"
|
||||
sudo chmod 600 "$SECRETS_DIR/fedimint-gateway-hash.pw"
|
||||
fi
|
||||
if [ -f "$SECRETS_DIR/fedimint-gateway-hash" ]; then
|
||||
echo "FEDI_HASH=$(sudo cat "$SECRETS_DIR/fedimint-gateway-hash")"
|
||||
@@ -1288,9 +1290,11 @@ BUILDINFO_EOF
|
||||
*) echo " WARNING: Ignoring unexpected variable from server: $key" ;;
|
||||
esac
|
||||
done <<< "$DB_PASSWORDS"
|
||||
# Fallback if hash not available
|
||||
# FED-07: no fallback literal. If the target hasn't generated its
|
||||
# per-install gateway credential yet, FEDI_HASH stays empty and the
|
||||
# Fedimint Gateway creation step below is skipped (not substituted).
|
||||
if [ -z "${FEDI_HASH:-}" ]; then
|
||||
FEDI_HASH='$2y$10$t9YjjxkiktrlYvjajB/zgOMDnSNVg4HqrbDqh47u7Jf42whNdxNqC'
|
||||
echo " NOTE: no fedimint-gateway credential on target yet — gateway container creation will be skipped (no shipped default; the daemon generates one on next install/reconcile)"
|
||||
fi
|
||||
|
||||
progress "Ensuring Bitcoin Knots"
|
||||
@@ -1712,12 +1716,15 @@ print("torrc generated with %d services" % (enabled or 7))
|
||||
|
||||
# Ensure Fedimint Gateway companion container
|
||||
# Auto-detect LND: if running with credentials, use lnd mode; otherwise use ldk (built-in)
|
||||
# FED-07: no shipped fallback — if no per-install credential was read
|
||||
# back from this target above, do not create/recreate the gateway
|
||||
# container at all (an empty --bcrypt-password-hash is never passed).
|
||||
if [ -n '$FEDI_HASH' ]; then
|
||||
\$DOCKER rm -f fedimint-gateway 2>/dev/null || true
|
||||
echo ' Creating fedimint-gateway...'
|
||||
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 "$FEDIMINT_GATEWAY_IMAGE" 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 \$DOCKER ps --format '{{.Names}}' | grep -q '^lnd\$' && sudo test -f \$LND_CERT && sudo test -f \$LND_MACAROON; then
|
||||
echo ' LND detected — using lnd mode'
|
||||
\$DOCKER run -d --name fedimint-gateway --restart unless-stopped \
|
||||
@@ -1747,6 +1754,9 @@ print("torrc generated with %d services" % (enabled or 7))
|
||||
--bitcoind-username $BITCOIN_RPC_USER --bitcoind-password $BITCOIN_RPC_PASS \
|
||||
ldk --ldk-lightning-port 9737 --ldk-alias archipelago-gateway
|
||||
fi
|
||||
else
|
||||
echo ' Skipping fedimint-gateway — no per-install credential on target yet (no shipped default; will create it on a future deploy/reconcile once one is generated)'
|
||||
fi
|
||||
" 2>&1 | sed 's/^/ /') || echo " (Fedimint fix timed out or skipped - run manually if needed)"
|
||||
section_end
|
||||
|
||||
|
||||
@@ -398,32 +398,33 @@ MEMPOOL_DB_PASS=$(cat "$SECRETS_DIR/mempool-db-password")
|
||||
BTCPAY_DB_PASS=$(cat "$SECRETS_DIR/btcpay-db-password")
|
||||
MYSQL_ROOT_PASS=$(cat "$SECRETS_DIR/mysql-root-db-password")
|
||||
|
||||
# Generate Fedimint gateway password and bcrypt hash
|
||||
if [ ! -f "$SECRETS_DIR/fedimint-gateway-password" ]; then
|
||||
FEDI_PASS=$(openssl rand -base64 16)
|
||||
echo "$FEDI_PASS" > "$SECRETS_DIR/fedimint-gateway-password"
|
||||
chmod 600 "$SECRETS_DIR/fedimint-gateway-password"
|
||||
# Pre-compute bcrypt hash (requires htpasswd from apache2-utils)
|
||||
if command -v htpasswd >/dev/null 2>&1; then
|
||||
htpasswd -bnBC 10 "" "$FEDI_PASS" | tr -d ':\n' > "$SECRETS_DIR/fedimint-gateway-hash"
|
||||
chmod 600 "$SECRETS_DIR/fedimint-gateway-hash"
|
||||
fi
|
||||
# Fedimint gateway credential: FED-07 — no shipped fallback, ever. The
|
||||
# canonical per-install credential is the manifest's `fedimint-gateway-hash`
|
||||
# (+ `.pw` plaintext sibling), generated by the daemon's
|
||||
# container::secrets::ensure_gateway_credential (bcrypt, 0600, idempotent,
|
||||
# self-healing). This ISO first-boot path — the site that put the shipped
|
||||
# default on real nodes before this fix — no longer generates the hash
|
||||
# locally, which also removes the htpasswd host dependency entirely and
|
||||
# keeps bcrypt generation in exactly one place.
|
||||
#
|
||||
# Legacy migration only: earlier builds wrote the plaintext under
|
||||
# fedimint-gateway-password instead of the manifest's canonical
|
||||
# fedimint-gateway-hash.pw name. Carry a pre-existing value forward under the
|
||||
# canonical name rather than regenerating (migrations never destroy data or
|
||||
# rotate a working credential); the legacy file is left in place — plan
|
||||
# 01-16 owns its retirement.
|
||||
if [ -f "$SECRETS_DIR/fedimint-gateway-password" ] && [ ! -f "$SECRETS_DIR/fedimint-gateway-hash.pw" ]; then
|
||||
cp "$SECRETS_DIR/fedimint-gateway-password" "$SECRETS_DIR/fedimint-gateway-hash.pw"
|
||||
chmod 600 "$SECRETS_DIR/fedimint-gateway-hash.pw"
|
||||
log "Migrated legacy fedimint-gateway-password -> fedimint-gateway-hash.pw"
|
||||
fi
|
||||
FEDI_PASS=$(cat "$SECRETS_DIR/fedimint-gateway-password")
|
||||
FEDI_HASH=""
|
||||
if [ -f "$SECRETS_DIR/fedimint-gateway-hash" ]; then
|
||||
FEDI_HASH=$(cat "$SECRETS_DIR/fedimint-gateway-hash")
|
||||
else
|
||||
# Fallback: generate hash now
|
||||
if command -v htpasswd >/dev/null 2>&1; then
|
||||
FEDI_HASH=$(htpasswd -bnBC 10 "" "$FEDI_PASS" | tr -d ':\n')
|
||||
echo "$FEDI_HASH" > "$SECRETS_DIR/fedimint-gateway-hash"
|
||||
chmod 600 "$SECRETS_DIR/fedimint-gateway-hash"
|
||||
else
|
||||
log "WARNING: htpasswd not found, using default Fedimint gateway hash"
|
||||
FEDI_HASH='$2y$10$t9YjjxkiktrlYvjajB/zgOMDnSNVg4HqrbDqh47u7Jf42whNdxNqC'
|
||||
fi
|
||||
fi
|
||||
log "Fedimint gateway password stored in $SECRETS_DIR/fedimint-gateway-password"
|
||||
if [ -z "$FEDI_HASH" ]; then
|
||||
log "Fedimint gateway credential not yet generated — the daemon/reconcile will generate a per-install bcrypt hash (no shipped default); the gateway container creation below is skipped until then"
|
||||
fi
|
||||
|
||||
BITCOIN_READY=false
|
||||
TOTAL=0
|
||||
@@ -1018,42 +1019,50 @@ track_container "fedimint"
|
||||
# 5b. Fedimint Gateway (companion to fedimint)
|
||||
# Auto-detect LND: if running with credentials, use lnd mode; otherwise use ldk (built-in)
|
||||
if ! $DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -q fedimint-gateway; then
|
||||
log "Creating Fedimint Gateway..."
|
||||
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
|
||||
if $DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -q '^lnd$' && [ -f "$LND_CERT" ] && [ -f "$LND_MACAROON" ]; then
|
||||
log " LND detected — using lnd mode"
|
||||
$DOCKER run -d --name fedimint-gateway --restart unless-stopped \
|
||||
--health-cmd="curl -sf http://localhost:8176/ || exit 1" --health-interval=120s --health-timeout=5s --health-retries=3 \
|
||||
--memory=$(mem_limit fedimint-gateway) --network archy-net --network-alias fedimint-gateway \
|
||||
--cap-drop ALL --cap-add CHOWN --cap-add FOWNER --cap-add SETUID --cap-add SETGID --cap-add DAC_OVERRIDE \
|
||||
--security-opt no-new-privileges:true \
|
||||
-p 8176:8176 \
|
||||
-v /var/lib/archipelago/fedimint-gateway:/data \
|
||||
-v "$LND_CERT":/lnd/tls.cert:ro \
|
||||
-v "$LND_MACAROON":/lnd/admin.macaroon:ro \
|
||||
"$FEDIMINT_GATEWAY_IMAGE" \
|
||||
gatewayd --data-dir /data --listen 0.0.0.0:8176 \
|
||||
--bcrypt-password-hash "$FEDI_HASH" \
|
||||
--network bitcoin --bitcoind-url "http://$BTC_HOST:$BTC_PORT" \
|
||||
--bitcoind-username "$BTC_RPC_USER" --bitcoind-password "$BTC_RPC_PASS" \
|
||||
lnd --lnd-rpc-host lnd:10009 --lnd-tls-cert /lnd/tls.cert --lnd-macaroon /lnd/admin.macaroon 2>>"$LOG" || true
|
||||
if [ -z "$FEDI_HASH" ]; then
|
||||
# FED-07: no shipped fallback. Without a per-install credential yet, do
|
||||
# not start gatewayd with an empty --bcrypt-password-hash — skip creation
|
||||
# here; reconcile-containers.sh creates it once the daemon has generated
|
||||
# the credential.
|
||||
log " Skipping Fedimint Gateway creation — no per-install credential yet (no shipped default); reconcile will create it once one is generated"
|
||||
else
|
||||
log " No LND found — using ldk (built-in Lightning)"
|
||||
$DOCKER run -d --name fedimint-gateway --restart unless-stopped \
|
||||
--health-cmd="curl -sf http://localhost:8176/ || exit 1" --health-interval=120s --health-timeout=5s --health-retries=3 \
|
||||
--memory=$(mem_limit fedimint-gateway) --network archy-net --network-alias fedimint-gateway \
|
||||
--cap-drop ALL --cap-add CHOWN --cap-add FOWNER --cap-add SETUID --cap-add SETGID --cap-add DAC_OVERRIDE \
|
||||
--security-opt no-new-privileges:true \
|
||||
-p 8176:8176 -p 9737:9737 \
|
||||
-v /var/lib/archipelago/fedimint-gateway:/data \
|
||||
"$FEDIMINT_GATEWAY_IMAGE" \
|
||||
gatewayd --data-dir /data --listen 0.0.0.0:8176 \
|
||||
--bcrypt-password-hash "$FEDI_HASH" \
|
||||
--network bitcoin --bitcoind-url "http://$BTC_HOST:$BTC_PORT" \
|
||||
--bitcoind-username "$BTC_RPC_USER" --bitcoind-password "$BTC_RPC_PASS" \
|
||||
ldk --ldk-lightning-port 9737 --ldk-alias archipelago-gateway 2>>"$LOG" || true
|
||||
log "Creating Fedimint Gateway..."
|
||||
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
|
||||
if $DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -q '^lnd$' && [ -f "$LND_CERT" ] && [ -f "$LND_MACAROON" ]; then
|
||||
log " LND detected — using lnd mode"
|
||||
$DOCKER run -d --name fedimint-gateway --restart unless-stopped \
|
||||
--health-cmd="curl -sf http://localhost:8176/ || exit 1" --health-interval=120s --health-timeout=5s --health-retries=3 \
|
||||
--memory=$(mem_limit fedimint-gateway) --network archy-net --network-alias fedimint-gateway \
|
||||
--cap-drop ALL --cap-add CHOWN --cap-add FOWNER --cap-add SETUID --cap-add SETGID --cap-add DAC_OVERRIDE \
|
||||
--security-opt no-new-privileges:true \
|
||||
-p 8176:8176 \
|
||||
-v /var/lib/archipelago/fedimint-gateway:/data \
|
||||
-v "$LND_CERT":/lnd/tls.cert:ro \
|
||||
-v "$LND_MACAROON":/lnd/admin.macaroon:ro \
|
||||
"$FEDIMINT_GATEWAY_IMAGE" \
|
||||
gatewayd --data-dir /data --listen 0.0.0.0:8176 \
|
||||
--bcrypt-password-hash "$FEDI_HASH" \
|
||||
--network bitcoin --bitcoind-url "http://$BTC_HOST:$BTC_PORT" \
|
||||
--bitcoind-username "$BTC_RPC_USER" --bitcoind-password "$BTC_RPC_PASS" \
|
||||
lnd --lnd-rpc-host lnd:10009 --lnd-tls-cert /lnd/tls.cert --lnd-macaroon /lnd/admin.macaroon 2>>"$LOG" || true
|
||||
else
|
||||
log " No LND found — using ldk (built-in Lightning)"
|
||||
$DOCKER run -d --name fedimint-gateway --restart unless-stopped \
|
||||
--health-cmd="curl -sf http://localhost:8176/ || exit 1" --health-interval=120s --health-timeout=5s --health-retries=3 \
|
||||
--memory=$(mem_limit fedimint-gateway) --network archy-net --network-alias fedimint-gateway \
|
||||
--cap-drop ALL --cap-add CHOWN --cap-add FOWNER --cap-add SETUID --cap-add SETGID --cap-add DAC_OVERRIDE \
|
||||
--security-opt no-new-privileges:true \
|
||||
-p 8176:8176 -p 9737:9737 \
|
||||
-v /var/lib/archipelago/fedimint-gateway:/data \
|
||||
"$FEDIMINT_GATEWAY_IMAGE" \
|
||||
gatewayd --data-dir /data --listen 0.0.0.0:8176 \
|
||||
--bcrypt-password-hash "$FEDI_HASH" \
|
||||
--network bitcoin --bitcoind-url "http://$BTC_HOST:$BTC_PORT" \
|
||||
--bitcoind-username "$BTC_RPC_USER" --bitcoind-password "$BTC_RPC_PASS" \
|
||||
ldk --ldk-lightning-port 9737 --ldk-alias archipelago-gateway 2>>"$LOG" || true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
track_container "fedimint-gateway"
|
||||
|
||||
@@ -409,6 +409,12 @@ reconcile() {
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -n "$SPEC_SKIP_REASON" ]; then
|
||||
skip "$name — $SPEC_SKIP_REASON"
|
||||
COUNT_SKIPPED=$((COUNT_SKIPPED + 1))
|
||||
return
|
||||
fi
|
||||
|
||||
[ "$name" = "portainer" ] && ensure_portainer_host_paths
|
||||
|
||||
# Filter by tier
|
||||
@@ -693,19 +699,31 @@ ensure_secrets() {
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ! -f "$SECRETS_DIR/fedimint-gateway-password" ]; then
|
||||
if ! $CHECK_ONLY; then
|
||||
local fpass
|
||||
fpass=$(openssl rand -base64 16)
|
||||
echo "$fpass" | 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 "" "$fpass" | tr -d ':\n' | sudo tee "$SECRETS_DIR/fedimint-gateway-hash" >/dev/null
|
||||
sudo chmod 600 "$SECRETS_DIR/fedimint-gateway-hash"
|
||||
fi
|
||||
info "Generated fedimint gateway secret"
|
||||
# FED-07: the gateway's bcrypt credential is generated by the daemon's
|
||||
# container::secrets::ensure_gateway_credential (bcrypt, 0600, idempotent,
|
||||
# self-healing) — this script no longer generates it locally (that removed
|
||||
# the htpasswd host dependency AND the shipped-default fallback that used
|
||||
# to fire when htpasswd was absent). It never shipped, and never ships,
|
||||
# a fallback value.
|
||||
#
|
||||
# Legacy migration only: earlier builds wrote the plaintext under
|
||||
# fedimint-gateway-password instead of the manifest's canonical
|
||||
# fedimint-gateway-hash.pw name. Carry a pre-existing value forward under
|
||||
# the canonical name rather than regenerating (migrations never destroy
|
||||
# data or rotate a working credential); the legacy file is left in place —
|
||||
# plan 01-16 owns its retirement.
|
||||
if [ -f "$SECRETS_DIR/fedimint-gateway-password" ] && [ ! -f "$SECRETS_DIR/fedimint-gateway-hash.pw" ]; then
|
||||
if $CHECK_ONLY; then
|
||||
info "Would migrate legacy fedimint-gateway-password -> fedimint-gateway-hash.pw"
|
||||
else
|
||||
sudo cp "$SECRETS_DIR/fedimint-gateway-password" "$SECRETS_DIR/fedimint-gateway-hash.pw"
|
||||
sudo chmod 600 "$SECRETS_DIR/fedimint-gateway-hash.pw"
|
||||
info "Migrated legacy fedimint-gateway-password -> fedimint-gateway-hash.pw"
|
||||
fi
|
||||
fi
|
||||
if [ ! -f "$SECRETS_DIR/fedimint-gateway-hash" ]; then
|
||||
info "fedimint-gateway credential not yet generated — the daemon will generate a per-install bcrypt hash (no shipped default); the gateway container is skipped until then"
|
||||
fi
|
||||
|
||||
# Reload after generation
|
||||
detect_environment
|
||||
|
||||
Reference in New Issue
Block a user