mirror of
https://github.com/luxfi/bridge.git
synced 2026-09-24 00:26:46 +00:00
# Conflicts: # cmd/bridge/admin_routes_test.go # cmd/bridge/api.go # cmd/bridge/estate_test.go # cmd/bridge/main.go # cmd/bridge/swaps_handler_test.go # internal/broadcast/client.go # internal/depositcheck/client.go # internal/txassembler/rpc_provider.go # pkg/bridge/package.json # pkg/bridge/src/app/styles/theme.css
473 lines
13 KiB
YAML
473 lines
13 KiB
YAML
services:
|
|
# Infrastructure Services
|
|
nats:
|
|
image: nats:2.10-alpine
|
|
container_name: bridge-nats
|
|
restart: always
|
|
ports:
|
|
- "4222:4222"
|
|
- "8222:8222"
|
|
command: "-js -m 8222 --store_dir /data -c /etc/nats/nats.conf"
|
|
volumes:
|
|
- nats-data:/data
|
|
- ./config/nats/mainnet.conf:/etc/nats/nats.conf:ro
|
|
networks:
|
|
- bridge-network
|
|
healthcheck:
|
|
test: ["CMD", "nc", "-z", "localhost", "4222"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 5
|
|
|
|
consul:
|
|
image: hashicorp/consul:1.17
|
|
container_name: bridge-consul
|
|
restart: always
|
|
ports:
|
|
- "8500:8500"
|
|
- "8600:8600/udp"
|
|
command: "agent -server -bootstrap-expect=3 -ui -client=0.0.0.0 -datacenter=mainnet"
|
|
volumes:
|
|
- consul-data:/consul/data
|
|
- ./config/consul/mainnet.json:/consul/config/mainnet.json:ro
|
|
networks:
|
|
- bridge-network
|
|
environment:
|
|
- CONSUL_BIND_INTERFACE=eth0
|
|
- CONSUL_DATACENTER=mainnet
|
|
healthcheck:
|
|
test: ["CMD", "consul", "members"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 5
|
|
|
|
# Database with replication support
|
|
postgres:
|
|
image: ghcr.io/hanzoai/sql:latest
|
|
container_name: bridge-postgres
|
|
restart: always
|
|
environment:
|
|
- POSTGRES_USER=bridge
|
|
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
|
- POSTGRES_DB=bridge
|
|
- POSTGRES_INITDB_ARGS=--encoding=UTF-8 --locale=en_US.utf8
|
|
- POSTGRES_HOST_AUTH_METHOD=scram-sha-256
|
|
volumes:
|
|
- postgres-data:/var/lib/postgresql/data
|
|
- ./scripts/init.sql:/docker-entrypoint-initdb.d/init.sql
|
|
- ./config/postgres/mainnet.conf:/etc/postgresql/postgresql.conf:ro
|
|
ports:
|
|
- "5432:5432"
|
|
networks:
|
|
- bridge-network
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U bridge"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 5
|
|
|
|
# MPC Nodes - Distributed across different availability zones
|
|
mpc-node-0:
|
|
image: ghcr.io/luxfi/lux-mpc:latest
|
|
container_name: bridge-mpc-0
|
|
restart: always
|
|
environment:
|
|
- NODE_ID=mpc-node-0
|
|
- NODE_PORT=6000
|
|
- NATS_URL=nats://nats:4222
|
|
- CONSUL_URL=http://consul:8500
|
|
- DATA_DIR=/data/mpc
|
|
- LOG_LEVEL=info
|
|
- MPC_THRESHOLD=2
|
|
- MPC_TOTAL_NODES=3
|
|
- MPC_KEY_PREFIX=bridge/mpc/mainnet
|
|
- NETWORK=mainnet
|
|
- ENABLE_TLS=true
|
|
- TLS_CERT_PATH=/certs/tls.crt
|
|
- TLS_KEY_PATH=/certs/tls.key
|
|
volumes:
|
|
- mpc-data-0:/data/mpc
|
|
- ./certs/mpc-0:/certs:ro
|
|
ports:
|
|
- "6000:6000"
|
|
- "9090:9090"
|
|
networks:
|
|
- bridge-network
|
|
depends_on:
|
|
nats:
|
|
condition: service_healthy
|
|
consul:
|
|
condition: service_healthy
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "https://localhost:6000/health", "--insecure"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 3
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '2'
|
|
memory: 4G
|
|
reservations:
|
|
cpus: '1'
|
|
memory: 2G
|
|
|
|
mpc-node-1:
|
|
image: ghcr.io/luxfi/lux-mpc:latest
|
|
container_name: bridge-mpc-1
|
|
restart: always
|
|
environment:
|
|
- NODE_ID=mpc-node-1
|
|
- NODE_PORT=6000
|
|
- NATS_URL=nats://nats:4222
|
|
- CONSUL_URL=http://consul:8500
|
|
- DATA_DIR=/data/mpc
|
|
- LOG_LEVEL=info
|
|
- MPC_THRESHOLD=2
|
|
- MPC_TOTAL_NODES=3
|
|
- MPC_KEY_PREFIX=bridge/mpc/mainnet
|
|
- NETWORK=mainnet
|
|
- ENABLE_TLS=true
|
|
- TLS_CERT_PATH=/certs/tls.crt
|
|
- TLS_KEY_PATH=/certs/tls.key
|
|
volumes:
|
|
- mpc-data-1:/data/mpc
|
|
- ./certs/mpc-1:/certs:ro
|
|
ports:
|
|
- "6001:6000"
|
|
- "9091:9090"
|
|
networks:
|
|
- bridge-network
|
|
depends_on:
|
|
nats:
|
|
condition: service_healthy
|
|
consul:
|
|
condition: service_healthy
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "https://localhost:6000/health", "--insecure"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 3
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '2'
|
|
memory: 4G
|
|
reservations:
|
|
cpus: '1'
|
|
memory: 2G
|
|
|
|
mpc-node-2:
|
|
image: ghcr.io/luxfi/lux-mpc:latest
|
|
container_name: bridge-mpc-2
|
|
restart: always
|
|
environment:
|
|
- NODE_ID=mpc-node-2
|
|
- NODE_PORT=6000
|
|
- NATS_URL=nats://nats:4222
|
|
- CONSUL_URL=http://consul:8500
|
|
- DATA_DIR=/data/mpc
|
|
- LOG_LEVEL=info
|
|
- MPC_THRESHOLD=2
|
|
- MPC_TOTAL_NODES=3
|
|
- MPC_KEY_PREFIX=bridge/mpc/mainnet
|
|
- NETWORK=mainnet
|
|
- ENABLE_TLS=true
|
|
- TLS_CERT_PATH=/certs/tls.crt
|
|
- TLS_KEY_PATH=/certs/tls.key
|
|
volumes:
|
|
- mpc-data-2:/data/mpc
|
|
- ./certs/mpc-2:/certs:ro
|
|
ports:
|
|
- "6002:6000"
|
|
- "9092:9090"
|
|
networks:
|
|
- bridge-network
|
|
depends_on:
|
|
nats:
|
|
condition: service_healthy
|
|
consul:
|
|
condition: service_healthy
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "https://localhost:6000/health", "--insecure"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 3
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '2'
|
|
memory: 4G
|
|
reservations:
|
|
cpus: '1'
|
|
memory: 2G
|
|
|
|
# Bridge Server with HA
|
|
bridge-server:
|
|
image: ghcr.io/luxfi/bridge-server:latest
|
|
container_name: bridge-server
|
|
restart: always
|
|
environment:
|
|
- NODE_ENV=production
|
|
- PORT=3000
|
|
- DATABASE_URL=postgresql://bridge:${POSTGRES_PASSWORD}@postgres:5432/bridge?sslmode=require
|
|
- NATS_URL=nats://nats:4222
|
|
- CONSUL_URL=http://consul:8500
|
|
- NODE_ID=bridge-server-0
|
|
- MPC_THRESHOLD=2
|
|
- MPC_TOTAL_NODES=3
|
|
- MPC_KEY_PREFIX=bridge/mpc/mainnet
|
|
- NETWORK=mainnet
|
|
- ENABLE_METRICS=true
|
|
- METRICS_PORT=9090
|
|
- LOG_LEVEL=info
|
|
- RATE_LIMIT_ENABLED=true
|
|
- RATE_LIMIT_MAX=100
|
|
- RATE_LIMIT_WINDOW=60
|
|
ports:
|
|
- "3000:3000"
|
|
- "9093:9090"
|
|
networks:
|
|
- bridge-network
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
nats:
|
|
condition: service_healthy
|
|
consul:
|
|
condition: service_healthy
|
|
mpc-node-0:
|
|
condition: service_healthy
|
|
mpc-node-1:
|
|
condition: service_healthy
|
|
mpc-node-2:
|
|
condition: service_healthy
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 3
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '4'
|
|
memory: 8G
|
|
reservations:
|
|
cpus: '2'
|
|
memory: 4G
|
|
|
|
# Bridge UI - Mainnet — Vite SPA (ghcr.io/hanzoai/spa serves /dist on :80).
|
|
# BRIDGE_* env documents what the image was built with; the values
|
|
# become real only when baked at build time (app/bridge/Dockerfile).
|
|
bridge-ui:
|
|
image: ghcr.io/luxfi/bridge-ui:latest
|
|
container_name: bridge-ui
|
|
restart: always
|
|
environment:
|
|
- BRIDGE_API_HOST=https://bridge-api.lux.network
|
|
- BRIDGE_ENV=mainnet
|
|
- BRIDGE_CLIENT_ID=lux-bridge
|
|
- BRIDGE_IAM_ORG=lux-network
|
|
ports:
|
|
- "3001:80"
|
|
networks:
|
|
- bridge-network
|
|
depends_on:
|
|
- bridge-server
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '2'
|
|
memory: 2G
|
|
reservations:
|
|
cpus: '1'
|
|
memory: 1G
|
|
|
|
# Bridge unified Go binary (cmd/bridge). Mainnet equivalent of the
|
|
# bridge-go service in compose.testnet.yml and the Deployment in
|
|
# k8s/bridge-deployment.yaml — same image, same env contract, same
|
|
# mainnet chain set (networks.mainnet.yaml mirrors the k8s ConfigMap).
|
|
#
|
|
# Build locally before `docker compose up bridge-go`:
|
|
# docker build -f cmd/bridge/Dockerfile -t ghcr.io/luxfi/bridge:dev .
|
|
# Then export BRIDGE_TAG=dev. For production, pin to a released tag
|
|
# (e.g. BRIDGE_TAG=v1.2.3) rather than :latest so a registry retag
|
|
# can't roll the running stack out from under you.
|
|
#
|
|
# Runs alongside bridge-server + bridge-ui during the §13.6 cutover
|
|
# soak. Once the Go binary handles real traffic without regressions,
|
|
# DNS at bridge.lux.network repoints to this service and the legacy
|
|
# bridge-server + bridge-ui can be retired.
|
|
bridge-go:
|
|
image: ghcr.io/luxfi/bridge:${BRIDGE_TAG:-latest}
|
|
container_name: bridge-go
|
|
restart: always
|
|
ports:
|
|
- "8080:8080"
|
|
environment:
|
|
- BRIDGE_ADDR=:8080
|
|
# The operator listener: /metrics, the swap list, the deposit poll.
|
|
# Deliberately absent from `ports:` — it is reachable on the compose
|
|
# network (prometheus scrapes bridge-go:8081/metrics) and not from
|
|
# the host.
|
|
- BRIDGE_ADMIN_ADDR=:8081
|
|
- BRIDGE_CONFIG=/etc/bridge/networks.yaml
|
|
- BRIDGE_DATA_DIR=/var/lib/lux-bridge
|
|
# Empty disables the legacy backend proxy — all /v1/bridge/*
|
|
# routes resolve through native handlers.
|
|
- BRIDGE_BACKEND_URL=
|
|
# BridgeVM (b-chain) JSON-RPC. Leave unset until BridgeVM exposes
|
|
# its public API; native handlers serve quote + swap state in the
|
|
# meantime.
|
|
- BRIDGE_BCHAIN_URL=
|
|
# MPC daemon. The lux-mpc image exposes its HTTP API on NODE_PORT
|
|
# (default 6000 per the in-compose mpc-node-* env). Override
|
|
# BRIDGE_MPC_URL to point at an external mpcd cluster when not
|
|
# running the in-compose MPC services.
|
|
- BRIDGE_MPC_URL=${BRIDGE_MPC_URL:-http://mpc-node-0:6000}
|
|
- BRIDGE_MPC_TOKEN=${BRIDGE_MPC_TOKEN:-}
|
|
- BRIDGE_MPC_ORG_ID=bridge
|
|
# Mainnet source-chain RPC overrides. Public RPC endpoints are
|
|
# fine for low-volume soak; pin to a private provider (Alchemy /
|
|
# Infura / Quicknode) before high-volume cutover so rate limits
|
|
# don't drop deposit-watcher polls.
|
|
- BRIDGE_SOURCE_RPC_OVERRIDES=ETHEREUM_MAINNET=https://eth.llamarpc.com,LUX_MAINNET=https://api.lux.network/v1/chain/C/rpc,ARBITRUM_MAINNET=https://arb1.arbitrum.io/rpc,OPTIMISM_MAINNET=https://mainnet.optimism.io,BASE_MAINNET=https://mainnet.base.org,POLYGON_MAINNET=https://polygon-rpc.com,BSC_MAINNET=https://bsc-dataseed.binance.org,AVAX_MAINNET=https://api.avax.network/ext/bc/C/rpc
|
|
volumes:
|
|
# Networks + tokens config. Read-only mount so an accidental write
|
|
# inside the container can't corrupt the operator-checked source-
|
|
# of-truth file. Keep this in sync with the inline YAML in
|
|
# k8s/bridge-deployment.yaml's ConfigMap.
|
|
- ./cmd/bridge/networks.mainnet.yaml:/etc/bridge/networks.yaml:ro
|
|
# zapdb-backed swap store + release-wallets.json. Bind-mounted to
|
|
# a host SSD path so the data survives compose down/up and is
|
|
# visible to host-side backup tooling.
|
|
- bridge-go-data:/var/lib/lux-bridge
|
|
networks:
|
|
- bridge-network
|
|
depends_on:
|
|
mpc-node-0:
|
|
condition: service_healthy
|
|
mpc-node-1:
|
|
condition: service_healthy
|
|
mpc-node-2:
|
|
condition: service_healthy
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '4'
|
|
memory: 8G
|
|
reservations:
|
|
cpus: '2'
|
|
memory: 4G
|
|
|
|
# Enhanced Monitoring
|
|
prometheus:
|
|
image: prom/prometheus:latest
|
|
container_name: bridge-prometheus
|
|
restart: always
|
|
volumes:
|
|
- ./monitoring/prometheus/mainnet.yml:/etc/prometheus/prometheus.yml
|
|
- prometheus-data:/prometheus
|
|
ports:
|
|
- "9094:9090"
|
|
networks:
|
|
- bridge-network
|
|
command:
|
|
- '--config.file=/etc/prometheus/prometheus.yml'
|
|
- '--storage.tsdb.path=/prometheus'
|
|
- '--storage.tsdb.retention.time=30d'
|
|
- '--web.enable-lifecycle'
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '1'
|
|
memory: 2G
|
|
|
|
grafana:
|
|
image: grafana/grafana:latest
|
|
container_name: bridge-grafana
|
|
restart: always
|
|
ports:
|
|
- "3002:3000"
|
|
networks:
|
|
- bridge-network
|
|
environment:
|
|
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
|
|
- GF_USERS_ALLOW_SIGN_UP=false
|
|
- GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource
|
|
- GF_SERVER_ROOT_URL=https://metrics.bridge.lux.network
|
|
volumes:
|
|
- grafana-data:/var/lib/grafana
|
|
- ./monitoring/grafana/dashboards:/etc/grafana/provisioning/dashboards
|
|
- ./monitoring/grafana/datasources:/etc/grafana/provisioning/datasources
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '1'
|
|
memory: 1G
|
|
|
|
# Backup Service
|
|
backup:
|
|
image: ghcr.io/luxfi/bridge-backup:latest
|
|
container_name: bridge-backup
|
|
restart: always
|
|
environment:
|
|
- BACKUP_INTERVAL=3600
|
|
- BACKUP_RETENTION_DAYS=30
|
|
- S3_BUCKET=${BACKUP_S3_BUCKET}
|
|
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
|
|
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
|
|
volumes:
|
|
- postgres-data:/data/postgres:ro
|
|
- mpc-data-0:/data/mpc-0:ro
|
|
- mpc-data-1:/data/mpc-1:ro
|
|
- mpc-data-2:/data/mpc-2:ro
|
|
networks:
|
|
- bridge-network
|
|
|
|
volumes:
|
|
nats-data:
|
|
driver: local
|
|
consul-data:
|
|
driver: local
|
|
mpc-data-0:
|
|
driver: local
|
|
driver_opts:
|
|
type: none
|
|
o: bind
|
|
device: /mnt/ssd/bridge/mpc-0
|
|
mpc-data-1:
|
|
driver: local
|
|
driver_opts:
|
|
type: none
|
|
o: bind
|
|
device: /mnt/ssd/bridge/mpc-1
|
|
mpc-data-2:
|
|
driver: local
|
|
driver_opts:
|
|
type: none
|
|
o: bind
|
|
device: /mnt/ssd/bridge/mpc-2
|
|
postgres-data:
|
|
driver: local
|
|
driver_opts:
|
|
type: none
|
|
o: bind
|
|
device: /mnt/ssd/bridge/postgres
|
|
prometheus-data:
|
|
driver: local
|
|
grafana-data:
|
|
driver: local
|
|
bridge-go-data:
|
|
driver: local
|
|
driver_opts:
|
|
type: none
|
|
o: bind
|
|
device: /mnt/ssd/bridge/bridge-go
|
|
|
|
networks:
|
|
bridge-network:
|
|
driver: bridge
|
|
ipam:
|
|
config:
|
|
- subnet: 172.20.0.0/16 |