# Meshnet public tracker + relay stack for Portainer without a custom image. # # This stack does NOT use deploy/docker/Dockerfile and does NOT require pushing an # image to a registry. Each service starts from the public python:3.12-slim image, # downloads a source tarball, installs the tracker/relay packages into a named # venv volume, then starts the service. # # Required Portainer variables: # SOURCE_TARBALL_URL URL to a .tar.gz archive of this repo # PUBLIC_TRACKER_URL e.g. https://cloud.neuron.d-popov.com # PUBLIC_PROXY_NETWORK Docker network shared with nginx/NPM, e.g. npm_proxy # # Optional: # CLUSTER_PEERS e.g. https://ai.neuron.d-popov.com # PUBLIC_RELAY_URL defaults to PUBLIC_TRACKER_URL with wss/ws + /ws # SOURCE_STRIP_COMPONENTS defaults to 1 for GitHub/Gitea archive tarballs services: meshnet-tracker: image: python:3.12-slim container_name: meshnet-tracker restart: unless-stopped environment: SOURCE_TARBALL_URL: ${SOURCE_TARBALL_URL:?set SOURCE_TARBALL_URL} SOURCE_STRIP_COMPONENTS: ${SOURCE_STRIP_COMPONENTS:-1} 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 apt-get update apt-get install -y --no-install-recommends ca-certificates curl tar rm -rf /var/lib/apt/lists/* rm -rf /opt/meshnet-src mkdir -p /opt/meshnet-src curl -fsSL "$${SOURCE_TARBALL_URL}" -o /tmp/meshnet-src.tar.gz tar -xzf /tmp/meshnet-src.tar.gz -C /opt/meshnet-src --strip-components "$${SOURCE_STRIP_COMPONENTS:-1}" python -m venv /opt/meshnet-venv /opt/meshnet-venv/bin/python -m pip install --upgrade pip setuptools wheel /opt/meshnet-venv/bin/pip install \ -e /opt/meshnet-src/packages/contracts \ -e /opt/meshnet-src/packages/tracker \ -e /opt/meshnet-src/packages/relay 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 /opt/meshnet-venv/bin/meshnet-tracker start \ --host 0.0.0.0 \ --port 8081 \ --heartbeat-timeout "$${HEARTBEAT_TIMEOUT}" \ --self-url "$${PUBLIC_TRACKER_URL}" \ --relay-url "$${RELAY_URL}" \ --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 - meshnet-tracker-venv:/opt/meshnet-venv expose: - "8081" 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: 60s networks: - public-proxy meshnet-relay: image: python:3.12-slim container_name: meshnet-relay restart: unless-stopped environment: SOURCE_TARBALL_URL: ${SOURCE_TARBALL_URL:?set SOURCE_TARBALL_URL} SOURCE_STRIP_COMPONENTS: ${SOURCE_STRIP_COMPONENTS:-1} command: - /bin/sh - -lc - | set -eu apt-get update apt-get install -y --no-install-recommends ca-certificates curl tar rm -rf /var/lib/apt/lists/* rm -rf /opt/meshnet-src mkdir -p /opt/meshnet-src curl -fsSL "$${SOURCE_TARBALL_URL}" -o /tmp/meshnet-src.tar.gz tar -xzf /tmp/meshnet-src.tar.gz -C /opt/meshnet-src --strip-components "$${SOURCE_STRIP_COMPONENTS:-1}" python -m venv /opt/meshnet-venv /opt/meshnet-venv/bin/python -m pip install --upgrade pip setuptools wheel /opt/meshnet-venv/bin/pip install \ -e /opt/meshnet-src/packages/tracker \ -e /opt/meshnet-src/packages/relay exec /opt/meshnet-venv/bin/meshnet-relay --host 0.0.0.0 --port 8765 --log-level INFO volumes: - meshnet-relay-venv:/opt/meshnet-venv expose: - "8765" healthcheck: test: ["CMD", "python", "-c", "import socket; s=socket.create_connection(('127.0.0.1', 8765), 3); s.close()"] interval: 30s timeout: 5s retries: 3 start_period: 60s networks: - public-proxy volumes: meshnet-tracker-data: meshnet-tracker-venv: meshnet-relay-venv: networks: public-proxy: external: true name: ${PUBLIC_PROXY_NETWORK:-npm_proxy}