Files
bridge/k8s/mpc-deployment.yaml
zeekay e661decabb chain routes: /v1/bc -> /v1/chain
luxd serves chain routes under /v1/chain, and the node, cli and sdk releases
already ship it. The deployed gateways still answer the old prefix, so remote
reads break until they are redeployed; the estate moves together rather than
sitting half converted.

Lines that record an observation - a probe, a status code, a past release -
keep the prefix they were written against, as do URLs on hosts that are not
ours. Avalanche endpoints move to /ext/bc, which is the path that host serves.
2026-09-01 08:20:22 -07:00

930 lines
24 KiB
YAML

apiVersion: v1
kind: Namespace
metadata:
name: lux-bridge
---
# KV Store — hanzoai/kv (Redis/Valkey)
# Used for session caching and bridge state. Replaces legacy NATS/Consul.
# MPC nodes use consensus mode (ZAP p2p) and do NOT need NATS or Consul.
apiVersion: apps/v1
kind: Deployment
metadata:
name: kv
namespace: lux-bridge
spec:
replicas: 1
selector:
matchLabels:
app: kv
template:
metadata:
labels:
app: kv
spec:
containers:
- name: kv
image: hanzoai/kv:latest
ports:
- containerPort: 6379
name: redis
volumeMounts:
- name: kv-storage
mountPath: /data
livenessProbe:
tcpSocket:
port: 6379
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
tcpSocket:
port: 6379
initialDelaySeconds: 5
periodSeconds: 5
volumes:
- name: kv-storage
persistentVolumeClaim:
claimName: kv-pvc
---
apiVersion: v1
kind: Service
metadata:
name: kv
namespace: lux-bridge
spec:
selector:
app: kv
ports:
- port: 6379
targetPort: 6379
name: redis
---
# MPC Config
apiVersion: v1
kind: ConfigMap
metadata:
name: mpc-config
namespace: lux-bridge
data:
config.yaml: |
# MPC nodes coordinate via ZAP p2p — no NATS or Consul needed.
environment: mainnet
mpc_threshold: 3
mpc_total_nodes: 5
# badger_password is injected via ZAPDB_PASSWORD env var from mpc-secrets k8s Secret (KMS-managed)
event_initiator_pubkey: "c3f3511cd2f849fd61e81ea62a842fd33367ee8fb5b867bb900877c7fb72ce3b"
max_concurrent_keygen: 3
db_path: /data/mpc
backup_enabled: true
backup_period_seconds: 300
backup_dir: /data/mpc/backups
peers.json: |
{
"node0": "0ce02715-0ead-48ef-9772-2583316cc860",
"node1": "c95c340e-5a18-472d-b9b0-5ac68218213a",
"node2": "ac37e85f-caca-4bee-8a3a-49a0fe35abff",
"node3": "ee42a050-c1e8-4875-ae03-4260047666ff",
"node4": "f67ec0b6-5a2f-410b-b43b-800b99315b41"
}
node0_identity.json: |
{"node_name":"node0","node_id":"0ce02715-0ead-48ef-9772-2583316cc860","public_key":"96e47112bab4cb83e59a0a222964fad096f02a9dc52e449097f8991470a141ab"}
node1_identity.json: |
{"node_name":"node1","node_id":"c95c340e-5a18-472d-b9b0-5ac68218213a","public_key":"d49b5caace90b8317accd728b7b4419baef2ff32a164411d9ac7c1f703e13f7e"}
node2_identity.json: |
{"node_name":"node2","node_id":"ac37e85f-caca-4bee-8a3a-49a0fe35abff","public_key":"e0a570f5e7b52f76ba54aca0578dcd0c7f6569b7640027664af5be2ba8f0cf49"}
node3_identity.json: |
{"node_name":"node3","node_id":"ee42a050-c1e8-4875-ae03-4260047666ff","public_key":"a0082b30a0c5598b0d4d998e80866a6b7d1c4c66d0d8d907fd64ada5dceddd8b"}
node4_identity.json: |
{"node_name":"node4","node_id":"f67ec0b6-5a2f-410b-b43b-800b99315b41","public_key":"9f387cbaba446ffc05d69cc5cd2f35ed82531b860ceae0febc25560251fcdd36"}
---
# IMPORTANT: mpc-identity-keys is managed externally via KMS (kms.hanzo.ai).
# Keys are stored in KMS under: MPC_NODE{0,1,2}_PRIVATE_KEY and MPC_INITIATOR_KEY
# Apply with:
# kubectl create secret generic mpc-identity-keys -n lux-bridge \
# --from-literal="node0_private.key=$(kms get MPC_NODE0_PRIVATE_KEY)" \
# --from-literal="node1_private.key=$(kms get MPC_NODE1_PRIVATE_KEY)" \
# --from-literal="node2_private.key=$(kms get MPC_NODE2_PRIVATE_KEY)" \
# --from-literal="initiator.key=$(kms get MPC_INITIATOR_KEY)" \
# --dry-run=client -o yaml | kubectl apply -f -
# DO NOT add secret values here — never commit keys to git.
---
# MPC Node StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mpc-node
namespace: lux-bridge
spec:
serviceName: mpc-node
replicas: 5
selector:
matchLabels:
app: mpc-node
template:
metadata:
labels:
app: mpc-node
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
initContainers:
- name: setup-identity
image: alpine:latest
command: ["/bin/sh", "-c"]
args:
- |
IDX=$(hostname | sed 's/mpc-node-//')
NODE_NAME="node${IDX}"
echo "Setting up identity for ${NODE_NAME}"
mkdir -p /app/identity
cp /config/config.yaml /app/config.yaml
cp /config/peers.json /app/peers.json
# Copy ALL node identities (needed for verifying peer messages)
for i in 0 1 2 3 4; do
cp /config/node${i}_identity.json /app/identity/node${i}_identity.json
done
# Copy own private key
cp /keys/${NODE_NAME}_private.key /app/identity/${NODE_NAME}_private.key
chmod 600 /app/identity/${NODE_NAME}_private.key
echo "Identity setup complete for ${NODE_NAME}"
volumeMounts:
- name: app-dir
mountPath: /app
- name: mpc-config
mountPath: /config
- name: mpc-keys
mountPath: /keys
containers:
- name: mpc
image: ghcr.io/luxfi/mpc:latest
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
command: ["/bin/sh", "-c"]
args:
- |
IDX=$(hostname | sed 's/mpc-node-//')
NODE_NAME="node${IDX}"
echo "Starting MPC node: ${NODE_NAME}"
cd /app && exec mpcd start -n "${NODE_NAME}"
ports:
- containerPort: 8080
name: http
- containerPort: 9090
name: grpc
env:
- name: LOG_LEVEL
value: info
- name: ZAPDB_PASSWORD
valueFrom:
secretKeyRef:
name: bridge-secrets
key: mpc-db-password
- name: MPC_THRESHOLD
value: "3"
- name: MPC_TOTAL_NODES
value: "5"
volumeMounts:
- name: app-dir
mountPath: /app
- name: mpc-data
mountPath: /data
- name: tmp
mountPath: /tmp
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
volumes:
- name: app-dir
emptyDir: {}
- name: tmp
emptyDir:
sizeLimit: 50Mi
- name: mpc-config
configMap:
name: mpc-config
- name: mpc-keys
secret:
secretName: mpc-identity-keys
volumeClaimTemplates:
- metadata:
name: mpc-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 20Gi
---
apiVersion: v1
kind: Service
metadata:
name: mpc-node
namespace: lux-bridge
spec:
selector:
app: mpc-node
clusterIP: None
ports:
- port: 9651
targetPort: 9651
name: zap
- port: 8080
targetPort: 8080
name: api
---
# MPC API service — bridge-server uses MPC_URL=http://mpc-api-svc.lux-bridge.svc:8081
#
# targetPort MUST be 9800: mpcd's API listener is `mpcd start --api :9800`
# (cmd/mpcd/main.go, --api-listen). Nothing has ever bound :8080 in the pod —
# `netstat -ltn` inside mpc-node-0 shows 7301/9800/9653/9651 only. Because the
# StatefulSet declares no readinessProbe, kube still published all 3 pods as
# ready endpoints on the dead port, so the Service looked healthy while every
# keygen dial hung until timeout.
apiVersion: v1
kind: Service
metadata:
name: mpc-api-svc
namespace: lux-bridge
spec:
selector:
app: mpc-node
ports:
- port: 8081
targetPort: 9800
name: api
---
# Bridge Server Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: bridge-server
namespace: lux-bridge
spec:
replicas: 2
selector:
matchLabels:
app: bridge-server
template:
metadata:
labels:
app: bridge-server
spec:
containers:
- name: bridge
image: ghcr.io/luxfi/bridge-server:latest
ports:
- containerPort: 3000
name: http
env:
- name: NODE_ENV
value: production
- name: PORT
value: "3000"
- name: POSTGRES_URL
valueFrom:
secretKeyRef:
name: bridge-secrets
key: database-url
- name: NODE_ID
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: MPC_THRESHOLD
value: "3"
- name: MPC_TOTAL_NODES
value: "5"
- name: MPC_KEY_PREFIX
value: bridge/mpc
- name: MPC_API_URL
value: http://mpc-api-svc.lux-bridge.svc:8081
- name: MPC_API_TOKEN
valueFrom:
secretKeyRef:
name: bridge-secrets
key: mpc-api-token
- name: MPC_WALLET_ID
valueFrom:
secretKeyRef:
name: bridge-secrets
key: mpc-wallet-id
- name: BRIDGE_FEE_COLLECTOR
valueFrom:
secretKeyRef:
name: bridge-secrets
key: fee-collector-address
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 10
periodSeconds: 5
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
---
apiVersion: v1
kind: Service
metadata:
name: bridge-server
namespace: lux-bridge
spec:
selector:
app: bridge-server
ports:
- port: 3000
targetPort: 3000
name: http
type: ClusterIP
---
# Bridge UI Deployment — Vite SPA served by ghcr.io/hanzoai/spa on :80.
# BRIDGE_* env documents the build-time inlined config; for true
# per-env values the image is built with those VITE_* vars baked in.
apiVersion: apps/v1
kind: Deployment
metadata:
name: bridge-ui
namespace: lux-bridge
spec:
replicas: 2
selector:
matchLabels:
app: bridge-ui
template:
metadata:
labels:
app: bridge-ui
spec:
containers:
- name: ui
image: ghcr.io/luxfi/bridge-ui:latest
ports:
- containerPort: 80
name: http
env:
- name: BRIDGE_API_HOST
value: https://bridge-api.lux.network
- name: BRIDGE_ENV
value: mainnet
- name: BRIDGE_CLIENT_ID
value: lux-bridge
- name: BRIDGE_IAM_ORG
value: lux-network
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: bridge-ui
namespace: lux-bridge
spec:
selector:
app: bridge-ui
ports:
- port: 80
targetPort: 80
name: http
type: ClusterIP
---
# PostgreSQL StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
namespace: lux-bridge
spec:
serviceName: postgres
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: ghcr.io/hanzoai/sql:latest
ports:
- containerPort: 5432
name: postgres
env:
- name: POSTGRES_USER
value: bridge
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: bridge-secrets
key: postgres-password
- name: POSTGRES_DB
value: bridge
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
livenessProbe:
exec:
command: ["pg_isready", "-U", "bridge"]
initialDelaySeconds: 30
periodSeconds: 10
volumeClaimTemplates:
- metadata:
name: postgres-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 50Gi
---
apiVersion: v1
kind: Service
metadata:
name: postgres
namespace: lux-bridge
spec:
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432
---
# bridge-secrets is managed externally via KMS (kms.hanzo.ai).
# Secrets stored in KMS: BRIDGE_DATABASE_URL, BRIDGE_DB_PASSWORD, MPC_DB_PASSWORD
# Apply with:
# kubectl create secret generic bridge-secrets -n lux-bridge \
# --from-literal="database-url=$(kms get BRIDGE_DATABASE_URL)" \
# --from-literal="postgres-password=$(kms get BRIDGE_DB_PASSWORD)" \
# --from-literal="mpc-db-password=$(kms get MPC_DB_PASSWORD)" \
# --dry-run=client -o yaml | kubectl apply -f -
# DO NOT add secret values here — never commit credentials to git.
---
# PersistentVolumeClaim for KV store
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: kv-pvc
namespace: lux-bridge
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
# Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: bridge-ingress
namespace: lux-bridge
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: ingress
tls:
- hosts:
- bridge.lux.network
- bridge-api.lux.network
secretName: bridge-lux-tls
- hosts:
- bridge.zoo.ngo
secretName: bridge-zoo-tls
- hosts:
- bridge.hanzo.ai
secretName: bridge-hanzo-tls
- hosts:
- bridge.pars.network
secretName: bridge-pars-tls
- hosts:
- bridge.spc.network
secretName: bridge-spc-tls
rules:
# Lux Network (primary)
- host: bridge.lux.network
http:
paths:
- path: /v1/
pathType: Prefix
backend:
service:
name: opnet-watcher
port:
number: 8090
- path: /
pathType: Prefix
backend:
service:
name: bridge-ui
port:
number: 80
- host: bridge-api.lux.network
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: bridge-server
port:
number: 3000
# Zoo — white-label
- host: bridge.zoo.ngo
http:
paths:
- path: /v1/
pathType: Prefix
backend:
service:
name: opnet-watcher
port:
number: 8090
- path: /
pathType: Prefix
backend:
service:
name: bridge-ui
port:
number: 80
# Hanzo — white-label
- host: bridge.hanzo.ai
http:
paths:
- path: /v1/
pathType: Prefix
backend:
service:
name: opnet-watcher
port:
number: 8090
- path: /
pathType: Prefix
backend:
service:
name: bridge-ui
port:
number: 80
# Pars — white-label
- host: bridge.pars.network
http:
paths:
- path: /v1/
pathType: Prefix
backend:
service:
name: opnet-watcher
port:
number: 8090
- path: /
pathType: Prefix
backend:
service:
name: bridge-ui
port:
number: 80
# SPC — white-label
- host: bridge.spc.network
http:
paths:
- path: /v1/
pathType: Prefix
backend:
service:
name: opnet-watcher
port:
number: 8090
- path: /
pathType: Prefix
backend:
service:
name: bridge-ui
port:
number: 80
---
# Bridge Tenant ConfigMap — loaded from manifests/tenants/*.yaml
# One key per tenant manifest. opnet-watcher reads BRIDGE_TENANT_DIR.
apiVersion: v1
kind: ConfigMap
metadata:
name: bridge-tenants
namespace: lux-bridge
data:
lux.yaml: |
id: lux
name: "Lux Network"
hostnames: ["bridge.lux.network", "bridge.lux.io"]
home_chain_id: 96369
supported_chains: [lux-c, ethereum, base, opnet, solana, ton]
teleporter_addresses:
"96369": "kms://teleport/lux-c/teleporter"
"1": "kms://teleport/lux-c/teleporter-eth"
"8453": "kms://teleport/lux-c/teleporter-eth"
"4294967299": "kms://teleport/lux-c/teleporter-btc"
"1399811149": "kms://teleport/lux-c/teleporter-sol"
"1414483791": "kms://teleport/lux-c/teleporter-ton"
branding:
logo_url: "/static/lux/logo.svg"
primary_color: "#E84142"
theme: dark
features: {swap: true, yield: true, perps: true}
zoo.yaml: |
id: zoo
name: "Zoo Network"
hostnames: ["bridge.zoo.ngo"]
home_chain_id: 200200
supported_chains: [lux-c, ethereum, base, solana]
teleporter_addresses:
"96369": "kms://teleport/lux-c/teleporter"
"1": "kms://teleport/lux-c/teleporter-eth"
"8453": "kms://teleport/lux-c/teleporter-eth"
"1399811149": "kms://teleport/lux-c/teleporter-sol"
branding:
logo_url: "/static/zoo/logo.svg"
primary_color: "#10B981"
theme: dark
features: {swap: true, yield: true, perps: false}
hanzo.yaml: |
id: hanzo
name: "Hanzo Network"
hostnames: ["bridge.hanzo.ai"]
home_chain_id: 36963
supported_chains: [lux-c, ethereum, base, opnet]
teleporter_addresses:
"96369": "kms://teleport/lux-c/teleporter"
"1": "kms://teleport/lux-c/teleporter-eth"
"8453": "kms://teleport/lux-c/teleporter-eth"
"4294967299": "kms://teleport/lux-c/teleporter-btc"
branding:
logo_url: "/static/hanzo/logo.svg"
primary_color: "#6366F1"
theme: dark
features: {swap: true, yield: true, perps: true}
pars.yaml: |
id: pars
name: "Pars Network"
hostnames: ["bridge.pars.network"]
home_chain_id: 494949
supported_chains: [lux-c, ethereum, base]
teleporter_addresses:
"96369": "kms://teleport/lux-c/teleporter"
"1": "kms://teleport/lux-c/teleporter-eth"
"8453": "kms://teleport/lux-c/teleporter-eth"
branding:
logo_url: "/static/pars/logo.svg"
primary_color: "#F59E0B"
theme: light
features: {swap: true, yield: false, perps: false}
spc.yaml: |
id: spc
name: "SPC Network"
hostnames: ["bridge.spc.network"]
home_chain_id: 36911
supported_chains: [lux-c, ethereum, base]
teleporter_addresses:
"96369": "kms://teleport/lux-c/teleporter"
"1": "kms://teleport/lux-c/teleporter-eth"
"8453": "kms://teleport/lux-c/teleporter-eth"
branding:
logo_url: "/static/spc/logo.svg"
primary_color: "#3B82F6"
theme: dark
features: {swap: true, yield: false, perps: false}
---
# Bridge Chain ConfigMap — loaded from manifests/chains/*.yaml
# One key per chain manifest. opnet-watcher reads BRIDGE_CHAIN_DIR.
apiVersion: v1
kind: ConfigMap
metadata:
name: bridge-chains
namespace: lux-bridge
data:
lux-c.yaml: |
chain_id: 96369
name: "Lux C-Chain"
class: lux_native
tier: yield_enabled
assets:
- ticker: LUX
decimals: 18
recipient_encoding: evm_address
wrapper: {symbol: LUX, contract: "token/LUX.sol", decimals: 18}
finality: {mode: instant, confirmations: 1}
ethereum.yaml: |
chain_id: 1
name: "Ethereum"
class: evm
tier: yield_enabled
assets:
- ticker: ETH
decimals: 18
recipient_encoding: evm_address
wrapper: {symbol: LETH, contract: "liquid/tokens/LETH.sol", decimals: 18}
- ticker: USDC
decimals: 6
recipient_encoding: evm_address
wrapper: {symbol: LUSD, contract: "liquid/tokens/LUSD.sol", decimals: 18}
- ticker: USDT
decimals: 6
recipient_encoding: evm_address
wrapper: {symbol: LUSD, contract: "liquid/tokens/LUSD.sol", decimals: 18}
- ticker: DAI
decimals: 18
recipient_encoding: evm_address
wrapper: {symbol: LUSD, contract: "liquid/tokens/LUSD.sol", decimals: 18}
finality: {mode: slot_finalized, confirmations: 64}
base.yaml: |
chain_id: 8453
name: "Base"
class: evm
tier: yield_enabled
assets:
- ticker: ETH
decimals: 18
recipient_encoding: evm_address
wrapper: {symbol: LETH, contract: "liquid/tokens/LETH.sol", decimals: 18}
- ticker: USDC
decimals: 6
recipient_encoding: evm_address
wrapper: {symbol: LUSD, contract: "liquid/tokens/LUSD.sol", decimals: 18}
finality: {mode: block_depth, confirmations: 12}
opnet.yaml: |
chain_id: 4294967299
name: "OP_NET"
class: bitcoin_script
tier: yield_enabled
assets:
- ticker: BTC
decimals: 8
recipient_encoding: bech32
wrapper: {symbol: LBTC, contract: "liquid/tokens/LBTC.sol", decimals: 18}
finality: {mode: block_depth, confirmations: 6}
solana.yaml: |
chain_id: 1399811149
name: "Solana"
class: account_native
tier: locale_only
assets:
- ticker: SOL
decimals: 9
recipient_encoding: base58
wrapper: {symbol: LSOL, contract: "liquid/tokens/LSOL.sol", decimals: 18}
finality: {mode: slot_finalized, confirmations: 32}
ton.yaml: |
chain_id: 1414483791
name: "TON"
class: account_native
tier: locale_only
assets:
- ticker: TON
decimals: 9
recipient_encoding: raw_bytes
wrapper: {symbol: LTON, contract: "liquid/tokens/LTON.sol", decimals: 18}
finality: {mode: block_depth, confirmations: 1}
---
# OPNET Watcher ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: opnet-watcher-config
namespace: lux-bridge
data:
config.yaml: |
lux_rpc: https://api.lux.network/v1/chain/C/rpc
zoo_rpc: https://api.zoo.network/v1/chain/C/rpc
opnet_rpc: https://opnet.lux.network/rpc
teleporter_address: ""
lux_chain_id: 96369
zoo_chain_id: 200200
opnet_chain_id: 4294967299
poll_interval_seconds: 12
confirmations: 6
health_port: 8080
---
# OPNET Watcher Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: opnet-watcher
namespace: lux-bridge
spec:
replicas: 1
selector:
matchLabels:
app: opnet-watcher
template:
metadata:
labels:
app: opnet-watcher
spec:
containers:
- name: opnet-watcher
image: ghcr.io/luxfi/opnet-watcher:latest
args: ["--config", "/config/config.yaml"]
ports:
- containerPort: 8080
name: health
- containerPort: 8090
name: api
env:
- name: MPC_API_URL
value: http://mpc-api-svc.lux-bridge.svc:8081
- name: MPC_API_TOKEN
valueFrom:
secretKeyRef:
name: bridge-secrets
key: mpc-api-token
- name: KMS_KEY_SHARES
valueFrom:
secretKeyRef:
name: opnet-watcher-secrets
key: kms-key-shares
- name: BRIDGE_TENANT_DIR
value: /etc/bridge/tenants
- name: BRIDGE_CHAIN_DIR
value: /etc/bridge/chains
volumeMounts:
- name: config
mountPath: /config
readOnly: true
- name: tenants
mountPath: /etc/bridge/tenants
readOnly: true
- name: chains
mountPath: /etc/bridge/chains
readOnly: true
livenessProbe:
httpGet:
path: /health
port: 8090
initialDelaySeconds: 10
periodSeconds: 15
readinessProbe:
httpGet:
path: /health
port: 8090
initialDelaySeconds: 5
periodSeconds: 10
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "250m"
volumes:
- name: config
configMap:
name: opnet-watcher-config
- name: tenants
configMap:
name: bridge-tenants
- name: chains
configMap:
name: bridge-chains
---
# opnet-watcher-secrets is managed externally via KMS (kms.hanzo.ai).
# Apply with:
# kubectl create secret generic opnet-watcher-secrets -n lux-bridge \
# --from-literal="kms-key-shares=$(kms get OPNET_WATCHER_KMS_KEY_SHARES)" \
# --dry-run=client -o yaml | kubectl apply -f -
# DO NOT add secret values here -- never commit keys to git.
---
apiVersion: v1
kind: Service
metadata:
name: opnet-watcher
namespace: lux-bridge
spec:
selector:
app: opnet-watcher
ports:
- port: 8080
targetPort: 8080
name: health
- port: 8090
targetPort: 8090
name: api