synor/docker-compose.testnet.yml
Gulshan Yadav 6b5a232a5e feat: Desktop wallet, gas estimator UI, and 30-day monitoring stack
Security (Desktop Wallet):
- Implement BIP39 mnemonic generation with cryptographic RNG
- Add Argon2id password-based key derivation (64MB, 3 iterations)
- Add ChaCha20-Poly1305 authenticated encryption for seed storage
- Add mnemonic auto-clear (60s timeout) and clipboard auto-clear (30s)
- Add sanitized error logging to prevent credential leaks
- Strengthen CSP with object-src, base-uri, form-action, frame-ancestors
- Clear sensitive state on component unmount

Explorer (Gas Estimator):
- Add Gas Estimation page with from/to/amount/data inputs
- Add bech32 address validation (synor1/tsynor1 prefix)
- Add BigInt-based amount parsing to avoid floating point errors
- Add production guard for mock mode (cannot enable in prod builds)

Monitoring (30-day Testnet):
- Add Prometheus config with 30-day retention
- Add comprehensive alert rules for node health, consensus, network, mempool
- Add Alertmanager with severity-based routing and inhibition rules
- Add Grafana with auto-provisioned datasource and dashboard
- Add Synor testnet dashboard with uptime SLA tracking

Docker:
- Update docker-compose.testnet.yml with monitoring profile
- Fix node-exporter for macOS Docker Desktop compatibility
- Change Grafana port to 3001 to avoid conflict
2026-01-10 04:38:09 +05:30

319 lines
9.3 KiB
YAML

# Synor Testnet Docker Compose Configuration
# Deploys 3 seed nodes for initial testnet bootstrap
services:
# ==========================================================================
# Seed Node 1 (Primary Bootstrap)
# ==========================================================================
seed1:
build:
context: .
dockerfile: Dockerfile
container_name: synor-seed1
hostname: seed1
restart: unless-stopped
command:
- "run"
- "--p2p-host=0.0.0.0"
- "--p2p-port=17511"
- "--rpc-host=0.0.0.0"
- "--rpc-port=17110"
- "--ws-port=17111"
- "--mine"
- "--coinbase=tsynor1qz232pysw8kezv2f4qxnhdufrlx5cmq78522mpuf8x5qlxu6j8sgcp05get"
ports:
- "17511:17511" # P2P
- "17110:17110" # HTTP RPC
- "17111:17111" # WebSocket RPC
volumes:
- seed1-data:/data/synor
networks:
synor-testnet:
ipv4_address: 172.20.0.10
environment:
- RUST_LOG=info
- SYNOR_DATA_DIR=/data/synor
- SYNOR_NETWORK=testnet
healthcheck:
test: ["CMD", "synord", "version"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
# ==========================================================================
# Seed Node 2
# ==========================================================================
seed2:
build:
context: .
dockerfile: Dockerfile
container_name: synor-seed2
hostname: seed2
restart: unless-stopped
command:
- "run"
- "--p2p-host=0.0.0.0"
- "--p2p-port=17511"
- "--rpc-host=0.0.0.0"
- "--rpc-port=17110"
- "--ws-port=17111"
- "--seeds=172.20.0.10:17511"
- "--mine"
- "--coinbase=tsynor1qrjdvz69xxc3gyq24d0ejp73wxxxz0nqxjp2zklw3nx6zljunwe75zele44"
ports:
- "17521:17511" # P2P (offset port)
- "17120:17110" # HTTP RPC
- "17121:17111" # WebSocket RPC
volumes:
- seed2-data:/data/synor
networks:
synor-testnet:
ipv4_address: 172.20.0.11
environment:
- RUST_LOG=info
- SYNOR_DATA_DIR=/data/synor
- SYNOR_NETWORK=testnet
depends_on:
seed1:
condition: service_healthy
# ==========================================================================
# Seed Node 3
# ==========================================================================
seed3:
build:
context: .
dockerfile: Dockerfile
container_name: synor-seed3
hostname: seed3
restart: unless-stopped
command:
- "run"
- "--p2p-host=0.0.0.0"
- "--p2p-port=17511"
- "--rpc-host=0.0.0.0"
- "--rpc-port=17110"
- "--ws-port=17111"
- "--seeds=172.20.0.10:17511,172.20.0.11:17511"
- "--mine"
- "--coinbase=tsynor1qq0mt7lhwckdz3hg69dpcv3vxw8j56d7un7z8x93vrjmjqyel5u5yf77vt8"
ports:
- "17531:17511" # P2P (offset port)
- "17130:17110" # HTTP RPC
- "17131:17111" # WebSocket RPC
volumes:
- seed3-data:/data/synor
networks:
synor-testnet:
ipv4_address: 172.20.0.12
environment:
- RUST_LOG=info
- SYNOR_DATA_DIR=/data/synor
- SYNOR_NETWORK=testnet
depends_on:
seed1:
condition: service_healthy
# ==========================================================================
# Testnet Faucet Service
# ==========================================================================
faucet:
build:
context: .
dockerfile: Dockerfile.faucet
container_name: synor-faucet
hostname: faucet
restart: unless-stopped
ports:
- "8080:8080"
environment:
- SYNOR_RPC_URL=http://seed1:17110
- FAUCET_AMOUNT=1000000000 # 10 SYNOR in sompi
- FAUCET_COOLDOWN=3600 # 1 hour between requests per address
- RUST_LOG=info
networks:
- synor-testnet
depends_on:
seed1:
condition: service_healthy
# ==========================================================================
# Block Explorer Backend (optional)
# ==========================================================================
explorer-api:
build:
context: .
dockerfile: Dockerfile.explorer
container_name: synor-explorer-api
hostname: explorer-api
restart: unless-stopped
ports:
- "17200:3000"
environment:
- SYNOR_RPC_URL=http://seed1:17110
- SYNOR_WS_URL=ws://seed1:17111
- DATABASE_URL=postgres://synor:synor@postgres:5432/explorer
- EXPLORER_STATIC_DIR=/var/www/explorer
- EXPLORER_CORS_ORIGINS=*
- RUST_LOG=info
networks:
- synor-testnet
depends_on:
seed1:
condition: service_healthy
postgres:
condition: service_healthy
profiles:
- explorer
# ==========================================================================
# PostgreSQL for Explorer
# ==========================================================================
postgres:
image: postgres:16-alpine
container_name: synor-postgres
restart: unless-stopped
environment:
- POSTGRES_USER=synor
- POSTGRES_PASSWORD=synor
- POSTGRES_DB=explorer
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- synor-testnet
healthcheck:
test: ["CMD-SHELL", "pg_isready -U synor -d explorer"]
interval: 10s
timeout: 5s
retries: 5
profiles:
- explorer
# ==========================================================================
# Security Audit Service
# ==========================================================================
security-audit:
build:
context: .
dockerfile: Dockerfile.security
container_name: synor-security-audit
volumes:
- .:/app:ro
profiles:
- security
# ==========================================================================
# Prometheus - Metrics Collection
# ==========================================================================
prometheus:
image: prom/prometheus:v2.48.0
container_name: synor-prometheus
hostname: prometheus
restart: unless-stopped
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention.time=30d'
- '--web.enable-lifecycle'
ports:
- "9090:9090"
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- ./monitoring/alerts.yml:/etc/prometheus/alerts.yml:ro
- prometheus-data:/prometheus
networks:
- synor-testnet
profiles:
- monitoring
# ==========================================================================
# Grafana - Visualization & Dashboards
# ==========================================================================
grafana:
image: grafana/grafana:10.2.2
container_name: synor-grafana
hostname: grafana
restart: unless-stopped
ports:
- "3001:3000" # Using 3001 to avoid conflict with explorer-api
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=synor123
- GF_USERS_ALLOW_SIGN_UP=false
- GF_SERVER_ROOT_URL=http://localhost:3000
volumes:
- ./monitoring/grafana/provisioning:/etc/grafana/provisioning:ro
- ./monitoring/grafana/dashboards:/var/lib/grafana/dashboards:ro
- grafana-data:/var/lib/grafana
networks:
- synor-testnet
depends_on:
- prometheus
profiles:
- monitoring
# ==========================================================================
# Alertmanager - Alert Routing & Notifications
# ==========================================================================
alertmanager:
image: prom/alertmanager:v0.26.0
container_name: synor-alertmanager
hostname: alertmanager
restart: unless-stopped
command:
- '--config.file=/etc/alertmanager/alertmanager.yml'
- '--storage.path=/alertmanager'
ports:
- "9093:9093"
volumes:
- ./monitoring/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
- alertmanager-data:/alertmanager
networks:
- synor-testnet
profiles:
- monitoring
# ==========================================================================
# Node Exporter - System Metrics (optional but useful)
# Note: Limited functionality on macOS Docker Desktop
# ==========================================================================
node-exporter:
image: prom/node-exporter:v1.7.0
container_name: synor-node-exporter
hostname: node-exporter
restart: unless-stopped
ports:
- "9100:9100"
# Note: Root filesystem mount doesn't work on macOS Docker Desktop
# volumes:
# - /:/host:ro,rslave
# command:
# - '--path.rootfs=/host'
networks:
- synor-testnet
profiles:
- monitoring
# =============================================================================
# Networks
# =============================================================================
networks:
synor-testnet:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.20.0.0/16
# =============================================================================
# Volumes
# =============================================================================
volumes:
seed1-data:
seed2-data:
seed3-data:
postgres-data:
prometheus-data:
grafana-data:
alertmanager-data: