stacker.news/docker-compose.yml
ekzyis ae73b0c19f
Support receiving via LNbits (#1278)
* Support receiving with LNbits

* Remove hardcoded LNbits url on server

* Fix saveConfig ignoring save errors

* saveConfig was meant to only ignore validation errors, not save errors
* on server save errors, we redirected as if save was successful
* this is now fixed with a promise chain
* logging payments vs receivals was also moved to correct place

* Fix enabled falsely disabled on SSR

If a wallet was configured for payments but not for receivals and you refreshed the configuration form, enabled was disabled even though payments were enabled.

This was the case since we don't know during SSR if it's enabled since this information is stored on the client.

* Fix missing 'receivals disabled' log message

* Move 'wallet detached for payments' log message

* Fix stale walletId during detach

If page was reloaded, walletId in clearConfig was stale since callback dependency was missing.

* Add missing callback dependencies for saveConfig

* Verify that invoiceKey != adminKey

* Verify LNbits keys are hex-encoded

* Fix local config polluted with server data

* Fix creation of duplicate wallets

* Remove unused dependency

* Fix missing error message in logs

* Fix setPriority

* Rename: localConfig -> clientConfig

* Add description to LNbits autowithdrawals

* Rename: receivals -> receives

* Use try/catch instead of promise chain in saveConfig

* add connect label to lnbits for no url found for lnbits

* Fix adminKey not saved

* Remove hardcoded LNbits url on server again

* Add LNbits ATTACH.md

* Delete old docs to attach LNbits with polar

* Add missing callback dependencies

* Set editable: false

* Only set readOnly if field is configured

---------

Co-authored-by: keyan <keyan.kousha+huumn@gmail.com>
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
2024-08-12 17:23:39 -05:00

555 lines
16 KiB
YAML

x-env_file: &env_file .env.development
x-healthcheck: &healthcheck
interval: 10s
timeout: 10s
retries: 10
start_period: 1m
x-depends-on-db: &depends_on_db
db:
condition: service_healthy
restart: true
x-depends-on-app: &depends_on_app
app:
condition: service_healthy
restart: true
x-depends-on-bitcoin: &depends_on_bitcoin
bitcoin:
condition: service_healthy
restart: true
services:
db:
container_name: db
build: ./docker/db
restart: unless-stopped
healthcheck:
<<: *healthcheck
test: ["CMD-SHELL", "PGPASSWORD=${POSTGRES_PASSWORD} pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB} -h 127.0.0.1 && psql -U ${POSTGRES_USER} ${POSTGRES_DB} -c 'SELECT 1 FROM users LIMIT 1'"]
expose:
- "5432"
ports:
- "5431:5432"
env_file: *env_file
volumes:
- ./docker/db/seed.sql:/docker-entrypoint-initdb.d/seed.sql
- db:/var/lib/postgresql/data
labels:
CONNECT: "localhost:5431"
cpu_shares: "${CPU_SHARES_IMPORTANT}"
app:
container_name: app
stdin_open: true
tty: true
build:
context: ./
args:
- UID=${CURRENT_UID}
- GID=${CURRENT_GID}
restart: unless-stopped
healthcheck:
<<: *healthcheck
test: ["CMD", "curl", "-f", "http://localhost:3000"]
depends_on: *depends_on_db
env_file: *env_file
expose:
- "3000"
ports:
- "3000:3000"
volumes:
- ./:/app
labels:
CONNECT: "localhost:3000"
cpu_shares: "${CPU_SHARES_IMPORTANT}"
capture:
container_name: capture
build:
context: ./capture
restart: unless-stopped
depends_on: *depends_on_app
profiles:
- capture
healthcheck:
<<: *healthcheck
test: ["CMD", "curl", "-f", "http://localhost:5678/health"]
env_file: *env_file
environment:
# configure to screenshot production, because local dev is too slow
- CAPTURE_URL=http://stacker.news
expose:
- "5678"
ports:
- "5678:5678"
labels:
CONNECT: "localhost:5678"
cpu_shares: "${CPU_SHARES_LOW}"
worker:
container_name: worker
build:
context: ./worker
args:
- UID=${CURRENT_UID}
- GID=${CURRENT_GID}
restart: unless-stopped
depends_on:
<<:
- *depends_on_db
- *depends_on_app
env_file: *env_file
volumes:
- ./:/app
entrypoint: ["/bin/sh", "-c"]
command:
- npm run worker:dev
cpu_shares: "${CPU_SHARES_IMPORTANT}"
imgproxy:
container_name: imgproxy
image: darthsim/imgproxy:v3.23.0
profiles:
- images
healthcheck:
<<: *healthcheck
test: [ "CMD", "imgproxy", "health" ]
restart: unless-stopped
env_file: *env_file
ports:
- "3001:8080"
expose:
- "8080"
labels:
- "CONNECT=localhost:3001"
cpu_shares: "${CPU_SHARES_LOW}"
s3:
container_name: s3
image: localstack/localstack:s3-latest
# healthcheck:
# test: ["CMD-SHELL", "awslocal", "s3", "ls", "s3://uploads"]
# interval: 10s
# timeout: 10s
# retries: 10
# start_period: 1m
restart: unless-stopped
profiles:
- images
env_file: *env_file
environment:
- DEBUG=1
ports:
- "4566:4566"
expose:
- "4566"
volumes:
- 's3:/var/lib/localstack'
- './docker/s3/init-s3.sh:/etc/localstack/init/ready.d/init-s3.sh'
- './docker/s3/cors.json:/etc/localstack/init/ready.d/cors.json'
labels:
- "CONNECT=localhost:4566"
cpu_shares: "${CPU_SHARES_LOW}"
opensearch:
image: opensearchproject/opensearch:2.12.0
container_name: opensearch
profiles:
- search
healthcheck:
<<: *healthcheck
test: ["CMD-SHELL", "curl -ku admin:${OPENSEARCH_INITIAL_ADMIN_PASSWORD} --silent --fail localhost:9200/_cluster/health || exit 1"]
restart: unless-stopped
env_file: *env_file
environment:
- OPENSEARCH_INITIAL_ADMIN_PASSWORD=mVchg1T5oA9wudUh
- plugins.security.disabled=true
- discovery.type=single-node
ports:
- 9200:9200 # REST API
- 9600:9600 # Performance Analyzer
volumes:
- os:/usr/share/opensearch/data
labels:
CONNECT: "localhost:9200"
command: >
bash -c '
set -m
/usr/share/opensearch/opensearch-docker-entrypoint.sh &
until curl -sS "http://localhost:9200/_cat/health?h=status" -ku admin:${OPENSEARCH_INITIAL_ADMIN_PASSWORD} | grep -q "green\|yellow"; do
echo "Waiting for OpenSearch to start..."
sleep 1
done
echo "OpenSearch started."
curl \
-H "Content-Type: application/json" \
-X PUT \
-d '{"mappings":{"properties":{"text":{"type":"text","analyzer":"english","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"title":{"type":"text","analyzer":"english","fields":{"keyword":{"type":"keyword","ignore_above":256}}}}}}' \
"http://localhost:9200/item" \
-ku admin:${OPENSEARCH_INITIAL_ADMIN_PASSWORD}
echo "OpenSearch index created."
fg
'
cpu_shares: "${CPU_SHARES_LOW}"
os-dashboard:
image: opensearchproject/opensearch-dashboards:2.12.0
container_name: os-dashboard
restart: unless-stopped
profiles:
- search
depends_on:
opensearch:
condition: service_healthy
restart: true
env_file: *env_file
environment:
- opensearch.ssl.verificationMode=none
- OPENSEARCH_HOSTS=http://opensearch:9200
- server.ssl.enabled=false
ports:
- 5601:5601
links:
- opensearch
labels:
CONNECT: "localhost:5601"
cpu_shares: "${CPU_SHARES_LOW}"
bitcoin:
image: polarlightning/bitcoind:26.0
container_name: bitcoin
restart: unless-stopped
profiles:
- payments
healthcheck:
<<: *healthcheck
test: ["CMD-SHELL", "bitcoin-cli -chain=regtest -rpcport=${RPC_PORT} -rpcuser=${RPC_USER} -rpcpassword=${RPC_PASS} getblockchaininfo"]
command:
- 'bitcoind'
- '-server=1'
- '-regtest=1'
- '-rpcauth=${RPC_USER}:${RPC_AUTH}'
- '-debug=1'
- '-zmqpubrawblock=tcp://0.0.0.0:${ZMQ_BLOCK_PORT}'
- '-zmqpubrawtx=tcp://0.0.0.0:${ZMQ_TX_PORT}'
- '-txindex=1'
- '-dnsseed=0'
- '-upnp=0'
- '-rpcbind=0.0.0.0'
- '-rpcallowip=0.0.0.0/0'
- '-rpcport=${RPC_PORT}'
- '-rest'
- '-listen=1'
- '-listenonion=0'
- '-fallbackfee=0.0002'
- '-blockfilterindex=1'
- '-peerblockfilters=1'
expose:
- "${RPC_PORT}"
- "${P2P_PORT}"
- "${ZMQ_BLOCK_PORT}"
- "${ZMQ_TX_PORT}"
volumes:
- bitcoin:/home/bitcoin/.bitcoin
labels:
ofelia.enabled: "true"
ofelia.job-exec.minecron.schedule: "@every 1m"
ofelia.job-exec.minecron.command: >
bash -c '
blockcount=$$(bitcoin-cli -chain=regtest -rpcport=${RPC_PORT} -rpcuser=${RPC_USER} -rpcpassword=${RPC_PASS} getblockcount 2>/dev/null)
if (( blockcount <= 0 )); then
echo "Mining 10 blocks to sn_lnd, stacker_lnd, stacker_cln..."
bitcoin-cli -chain=regtest -rpcport=${RPC_PORT} -rpcuser=${RPC_USER} -rpcpassword=${RPC_PASS} generatetoaddress 100 ${LND_ADDR}
bitcoin-cli -chain=regtest -rpcport=${RPC_PORT} -rpcuser=${RPC_USER} -rpcpassword=${RPC_PASS} generatetoaddress 100 ${STACKER_LND_ADDR}
bitcoin-cli -chain=regtest -rpcport=${RPC_PORT} -rpcuser=${RPC_USER} -rpcpassword=${RPC_PASS} generatetoaddress 100 ${STACKER_CLN_ADDR}
else
echo "Mining a block to sn_lnd... ${LND_ADDR}"
bitcoin-cli -chain=regtest -rpcport=${RPC_PORT} -rpcuser=${RPC_USER} -rpcpassword=${RPC_PASS} generatetoaddress 1 ${LND_ADDR}
echo "Mining a block to stacker_lnd... ${STACKER_LND_ADDR}"
bitcoin-cli -chain=regtest -rpcport=${RPC_PORT} -rpcuser=${RPC_USER} -rpcpassword=${RPC_PASS} generatetoaddress 1 ${STACKER_LND_ADDR}
echo "Mining a block to stacker_cln... ${STACKER_CLN_ADDR}"
bitcoin-cli -chain=regtest -rpcport=${RPC_PORT} -rpcuser=${RPC_USER} -rpcpassword=${RPC_PASS} generatetoaddress 1 ${STACKER_CLN_ADDR}
fi
'
cpu_shares: "${CPU_SHARES_MODERATE}"
sn_lnd:
build:
context: ./docker/lnd
args:
- LN_NODE_FOR=sn
container_name: sn_lnd
restart: unless-stopped
profiles:
- payments
healthcheck:
<<: *healthcheck
test: ["CMD-SHELL", "lncli", "getinfo"]
depends_on: *depends_on_bitcoin
env_file: *env_file
command:
- 'lnd'
- '--noseedbackup'
- '--trickledelay=5000'
- '--alias=sn_lnd'
- '--externalip=sn_lnd'
- '--tlsextradomain=sn_lnd'
- '--tlsextradomain=host.docker.internal'
- '--listen=0.0.0.0:9735'
- '--rpclisten=0.0.0.0:10009'
- '--restlisten=0.0.0.0:8080'
- '--bitcoin.active'
- '--bitcoin.regtest'
- '--bitcoin.node=bitcoind'
- '--bitcoind.rpchost=bitcoin'
- '--bitcoind.rpcuser=${RPC_USER}'
- '--bitcoind.rpcpass=${RPC_PASS}'
- '--bitcoind.zmqpubrawblock=tcp://bitcoin:${ZMQ_BLOCK_PORT}'
- '--bitcoind.zmqpubrawtx=tcp://bitcoin:${ZMQ_TX_PORT}'
- '--protocol.wumbo-channels'
- '--maxchansize=1000000000'
- '--allow-circular-route'
- '--bitcoin.defaultchanconfs=1'
- '--maxpendingchannels=10'
expose:
- "9735"
ports:
- "${LND_REST_PORT}:8080"
- "${LND_GRPC_PORT}:10009"
volumes:
- sn_lnd:/home/lnd/.lnd
labels:
ofelia.enabled: "true"
ofelia.job-exec.sn_channel_cron.schedule: "@every 1m"
ofelia.job-exec.sn_channel_cron.command: >
su lnd -c bash -c "
if [ $$(lncli getinfo | jq '.num_active_channels + .num_pending_channels') -ge 3 ]; then
exit 0
else
lncli openchannel --node_key=$STACKER_LND_PUBKEY --connect stacker_lnd:9735 --sat_per_vbyte 1 \\
--min_confs 0 --local_amt=1000000000 --push_amt=500000000
fi
"
cpu_shares: "${CPU_SHARES_MODERATE}"
stacker_lnd:
build:
context: ./docker/lnd
args:
- LN_NODE_FOR=stacker
container_name: stacker_lnd
restart: unless-stopped
profiles:
- payments
healthcheck:
<<: *healthcheck
test: ["CMD-SHELL", "lncli", "getinfo"]
depends_on: *depends_on_bitcoin
env_file: *env_file
command:
- 'lnd'
- '--noseedbackup'
- '--trickledelay=5000'
- '--alias=stacker_lnd'
- '--externalip=stacker_lnd'
- '--tlsextradomain=stacker_lnd'
- '--tlsextradomain=host.docker.internal'
- '--listen=0.0.0.0:9735'
- '--rpclisten=0.0.0.0:10009'
- '--rpcmiddleware.enable'
- '--restlisten=0.0.0.0:8080'
- '--bitcoin.active'
- '--bitcoin.regtest'
- '--bitcoin.node=bitcoind'
- '--bitcoind.rpchost=bitcoin'
- '--bitcoind.rpcuser=${RPC_USER}'
- '--bitcoind.rpcpass=${RPC_PASS}'
- '--bitcoind.zmqpubrawblock=tcp://bitcoin:${ZMQ_BLOCK_PORT}'
- '--bitcoind.zmqpubrawtx=tcp://bitcoin:${ZMQ_TX_PORT}'
- '--protocol.wumbo-channels'
- '--maxchansize=1000000000'
- '--allow-circular-route'
- '--bitcoin.defaultchanconfs=1'
- '--maxpendingchannels=10'
expose:
- "9735"
- "10009"
ports:
- "${STACKER_LND_REST_PORT}:8080"
- "${STACKER_LND_GRPC_PORT}:10009"
volumes:
- stacker_lnd:/home/lnd/.lnd
labels:
ofelia.enabled: "true"
ofelia.job-exec.stacker_lnd_channel_cron.schedule: "@every 1m"
ofelia.job-exec.stacker_lnd_channel_cron.command: >
su lnd -c bash -c "
if [ $$(lncli getinfo | jq '.num_active_channels + .num_pending_channels') -ge 3 ]; then
exit 0
else
lncli openchannel --node_key=$LND_PUBKEY --connect sn_lnd:9735 --sat_per_vbyte 1 \\
--min_confs 0 --local_amt=1000000000 --push_amt=500000000
fi
"
cpu_shares: "${CPU_SHARES_MODERATE}"
litd:
container_name: litd
build:
context: ./docker/litd
profiles:
- wallets
restart: unless-stopped
healthcheck:
<<: *healthcheck
test: ["CMD", "curl", "-f", "http://localhost:8443"]
depends_on:
stacker_lnd:
condition: service_healthy
restart: true
volumes:
- stacker_lnd:/lnd
ports:
- "8443:8443"
command:
- 'litd'
- '--httpslisten=0.0.0.0:8444'
- '--insecure-httplisten=0.0.0.0:8443'
- '--uipassword=password'
- '--lnd-mode=remote'
- '--network=regtest'
- '--remote.lit-debuglevel=debug'
- '--remote.lnd.rpcserver=stacker_lnd:10009'
- '--remote.lnd.macaroonpath=/lnd/data/chain/bitcoin/regtest/admin.macaroon'
- '--remote.lnd.tlscertpath=/lnd/tls.cert'
- '--autopilot.disable'
- '--pool.auctionserver=test.pool.lightning.finance:12010'
- '--loop.server.host=test.swap.lightning.today:11010'
labels:
CONNECT: "localhost:8443"
cpu_shares: "${CPU_SHARES_MODERATE}"
stacker_cln:
build:
context: ./docker/cln
container_name: stacker_cln
restart: unless-stopped
profiles:
- payments
healthcheck:
<<: *healthcheck
test: ["CMD-SHELL", "su clightning -c 'lightning-cli --network=regtest getinfo'"]
depends_on: *depends_on_bitcoin
env_file: *env_file
command:
- 'lightningd'
- '--network=regtest'
- '--alias=stacker_cln'
- '--bitcoin-rpcconnect=bitcoin'
- '--bitcoin-rpcuser=${RPC_USER}'
- '--bitcoin-rpcpassword=${RPC_PASS}'
- '--large-channels'
- '--rest-port=3010'
- '--rest-host=0.0.0.0'
- '--log-file=/home/clightning/.lightning/debug.log'
expose:
- "9735"
ports:
- "${STACKER_CLN_REST_PORT}:3010"
volumes:
- stacker_cln:/home/clightning/.lightning
labels:
ofelia.enabled: "true"
ofelia.job-exec.stacker_cln_channel_cron.schedule: "@every 1m"
ofelia.job-exec.stacker_cln_channel_cron.command: >
su clightning -c bash -c "
if [ $$(lightning-cli --regtest getinfo | jq '.num_active_channels + .num_pending_channels') -ge 3 ]; then
exit 0
else
lightning-cli --regtest connect $LND_PUBKEY@sn_lnd:9735
lightning-cli --regtest fundchannel id=$LND_PUBKEY feerate=1000perkb \\
amount=1000000000 push_msat=500000000000 minconf=0
fi
"
cpu_shares: "${CPU_SHARES_MODERATE}"
channdler:
image: mcuadros/ofelia:latest
container_name: channdler
profiles:
- payments
depends_on:
- bitcoin
- sn_lnd
- stacker_lnd
- stacker_cln
restart: unless-stopped
command: daemon --docker -f label=com.docker.compose.project=${COMPOSE_PROJECT_NAME}
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
cpu_shares: "${CPU_SHARES_LOW}"
mailhog:
image: mailhog/mailhog:latest
container_name: mailhog
profiles:
- email
restart: unless-stopped
healthcheck:
<<: *healthcheck
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8025"]
ports:
- "8025:8025"
- "1025:1025"
links:
- app
labels:
CONNECT: "localhost:8025"
cpu_shares: "${CPU_SHARES_LOW}"
nwc:
build:
context: ./docker/nwc
container_name: nwc
profiles:
- wallets
restart: unless-stopped
depends_on:
stacker_lnd:
condition: service_healthy
restart: true
volumes:
- ./docker/lnd/stacker:/root/.lnd
environment:
- RUST_LOG=info
entrypoint:
- 'nostr-wallet-connect-lnd'
- '--relay'
- 'wss://relay.damus.io'
- '--macaroon-file'
- '/root/.lnd/regtest/admin.macaroon'
- '--cert-file'
- '/root/.lnd/tls.cert'
- '--lnd-host'
- 'stacker_lnd'
- '--lnd-port'
- '10009'
- '--max-amount'
- '0'
- '--daily-limit'
- '0'
cpu_shares: "${CPU_SHARES_LOW}"
lnbits:
image: lnbits/lnbits:0.12.5
container_name: lnbits
profiles:
- wallets
restart: unless-stopped
ports:
- "${LNBITS_WEB_PORT}:5000"
depends_on:
- stacker_lnd
environment:
- LNBITS_BACKEND_WALLET_CLASS=LndWallet
- LND_GRPC_ENDPOINT=stacker_lnd
- LND_GRPC_PORT=10009
- LND_GRPC_CERT=/app/.lnd/tls.cert
- LND_GRPC_MACAROON=/app/.lnd/regtest/admin.macaroon
volumes:
- ./docker/lnd/stacker:/app/.lnd
labels:
CONNECT: "localhost:${LNBITS_WEB_PORT}"
cpu_shares: "${CPU_SHARES_LOW}"
volumes:
db:
os:
bitcoin:
sn_lnd:
stacker_lnd:
stacker_cln:
s3: