# Meshnet public tracker stack for Portainer.
#
# Intended topology when Nginx Proxy Manager (or another nginx reverse proxy)
# runs on the same Docker host:
#   https://YOUR_DOMAIN/v1/*  -> meshnet-tracker:8081
#   https://YOUR_DOMAIN/ws    -> meshnet-tracker:8765  (embedded relay WebSocket)
#   https://YOUR_DOMAIN/rpc/* -> meshnet-tracker:8765  (embedded relay WebSocket)
#
# Before deploying, create or identify the Docker network shared with nginx/NPM,
# then set PUBLIC_PROXY_NETWORK to its name in Portainer environment variables.

services:
  meshnet-tracker:
    build:
      context: ../..
      dockerfile: deploy/docker/Dockerfile
    image: meshnet-tracker-relay:local
    container_name: meshnet-tracker
    restart: unless-stopped
    environment:
      PUBLIC_TRACKER_URL: ${PUBLIC_TRACKER_URL:?set PUBLIC_TRACKER_URL, e.g. https://cloud.neuron.d-popov.com}
      CLUSTER_PEERS: ${CLUSTER_PEERS:-}
      PUBLIC_RELAY_URL: ${PUBLIC_RELAY_URL:-}
      HEARTBEAT_TIMEOUT: ${HEARTBEAT_TIMEOUT:-30}
      ENABLE_BILLING_DB: ${ENABLE_BILLING_DB:-1}
      SOLANA_RPC_URL: ${SOLANA_RPC_URL:-}
      USDT_MINT: ${USDT_MINT:-}
      MESHNET_TREASURY_KEYPAIR_B64: ${MESHNET_TREASURY_KEYPAIR_B64:-}
      SETTLE_PERIOD: ${SETTLE_PERIOD:-86400}
      PAYOUT_THRESHOLD: ${PAYOUT_THRESHOLD:-5}
      PAYOUT_DUST_FLOOR: ${PAYOUT_DUST_FLOOR:-0.01}
    command:
      - /bin/sh
      - -lc
      - |
        set -eu
        PEER_ARGS=""
        if [ -n "$${CLUSTER_PEERS:-}" ]; then
          PEER_ARGS="--cluster-peers $${CLUSTER_PEERS}"
        fi
        RELAY_URL="$${PUBLIC_RELAY_URL:-}"
        if [ -z "$${RELAY_URL}" ]; then
          RELAY_URL="$$(printf '%s' "$${PUBLIC_TRACKER_URL}" | sed 's#^https://#wss://#; s#^http://#ws://#')/ws"
        fi
        BILLING_ARGS=""
        if [ "$${ENABLE_BILLING_DB:-1}" = "1" ]; then
          BILLING_ARGS="--billing-db /var/lib/meshnet/billing.sqlite"
        else
          BILLING_ARGS="--no-billing"
        fi
        TREASURY_ARGS=""
        if [ -n "$${SOLANA_RPC_URL:-}" ] || [ -n "$${USDT_MINT:-}" ] || [ -n "$${MESHNET_TREASURY_KEYPAIR_B64:-}" ]; then
          if [ -z "$${SOLANA_RPC_URL:-}" ] || [ -z "$${USDT_MINT:-}" ] || [ -z "$${MESHNET_TREASURY_KEYPAIR_B64:-}" ]; then
            echo "SOLANA_RPC_URL, USDT_MINT, and MESHNET_TREASURY_KEYPAIR_B64 must all be set together" >&2
            exit 1
          fi
          printf '%s' "$${MESHNET_TREASURY_KEYPAIR_B64}" | base64 -d > /var/lib/meshnet/treasury-keypair.json
          chmod 600 /var/lib/meshnet/treasury-keypair.json
          TREASURY_ARGS="--solana-rpc-url $${SOLANA_RPC_URL} --usdt-mint $${USDT_MINT} --treasury-keypair /var/lib/meshnet/treasury-keypair.json --settle-period $${SETTLE_PERIOD} --payout-threshold $${PAYOUT_THRESHOLD} --payout-dust-floor $${PAYOUT_DUST_FLOOR}"
        fi
        exec meshnet-tracker start \
          --host 0.0.0.0 \
          --port 8081 \
          --heartbeat-timeout "$${HEARTBEAT_TIMEOUT}" \
          --self-url "$${PUBLIC_TRACKER_URL}" \
          --relay-url "$${RELAY_URL}" \
          --embedded-relay \
          --relay-host 0.0.0.0 \
          --relay-port 8765 \
          --stats-db /var/lib/meshnet/tracker-stats.sqlite \
          --accounts-db /var/lib/meshnet/accounts.sqlite \
          $${BILLING_ARGS} \
          $${TREASURY_ARGS} \
          $${PEER_ARGS}
    volumes:
      - meshnet-tracker-data:/var/lib/meshnet
    expose:
      - "8081"
      - "8765"
    healthcheck:
      test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8081/v1/health', timeout=3).read()"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s
    networks:
      - public-proxy

volumes:
  meshnet-tracker-data:

networks:
  public-proxy:
    external: true
    name: ${PUBLIC_PROXY_NETWORK:-proxy_net}
