x-env_file: &env_file
  - path: .env.development
    required: true
  - path: .env.local
    required: false
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:27.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'
      - '-maxmempool=5'
    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 '
          bitcoin-cli () {
            command bitcoin-cli -chain=regtest -rpcport=${RPC_PORT} -rpcuser=${RPC_USER} -rpcpassword=${RPC_PASS} "$$@"
          }
          blockcount=$$(bitcoin-cli getblockcount 2>/dev/null)
          nodes=(${LND_ADDR} ${STACKER_LND_ADDR} ${STACKER_CLN_ADDR})
          if (( blockcount <= 0 )); then
            echo "Creating wallet and address..."
            bitcoin-cli createwallet ""
            nodes+=($$(bitcoin-cli getnewaddress))
            echo "Mining 100 blocks to sn_lnd, stacker_lnd, stacker_cln..."
            for addr in  "$${nodes[@]}"; do
              bitcoin-cli generatetoaddress 100 $$addr
              echo "Mining 100 blocks to a random address..."
              bitcoin-cli generatetoaddress 100 $$(bitcoin-cli getnewaddress)
            done
          else
            echo "generating txs for fee rate estimation..."
            while true
            do
              i=0
              range=$$(( $$RANDOM % 11 + 20 ))
              while [ $$i -lt $$range ]
              do
                address=$$(bitcoin-cli getnewaddress)
                bitcoin-cli -named sendtoaddress address=$$address amount=0.01 fee_rate=$$(( $$RANDOM % 25 + 1 ))
                ((++i))
              done
              echo "generating block..."
              bitcoin-cli generatetoaddress 1 "$${nodes[ $$RANDOM % $${#nodes[@]} ]}"
              if [[ $$(bitcoin-cli estimatesmartfee 6) =~ "\\"feerate\\":" ]]; then
                echo "fee estimation succeeded..."
                break
              fi
            done
          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.primal.net'
      - '--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: