Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions internal/embed/infrastructure/base/templates/erpc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Relocated from helmfile.yaml `erpc-httproute`, `erpc-x402-middleware`,
# and `erpc-metadata` bedag/raw releases. These resources live alongside
# their workload (eRPC in the `erpc` namespace) instead of inlined in
# helmfile so the chart layout is the single source of truth for what
# ships in the erpc namespace.
#
# CRD prerequisites:
# - HTTPRoute -> gateway.networking.k8s.io/v1 (shipped by the Traefik
# v38+ chart's bundled CRDs)
# - Middleware -> traefik.io/v1alpha1 (shipped by the Traefik chart)
# `base` now declares `needs: [traefik/traefik]` in helmfile.yaml to
# guarantee CRDs are present before these templates apply.
#
# The eRPC Deployment + Service themselves still come from the upstream
# `ethereum/erpc` Helm chart (separate release in helmfile.yaml); only
# the routing + discovery metadata is owned here.

---
# eRPC namespace. Pre-created here so resources in this file (HTTPRoute,
# Middleware, ConfigMap) can apply during the `base` release without
# waiting for the `erpc` upstream chart release to create it. The `erpc`
# release still sets `createNamespace: true` — kubectl apply on an
# existing namespace is a no-op.
apiVersion: v1
kind: Namespace
metadata:
name: erpc

---
# eRPC HTTPRoute — gates /rpc through the x402-payment Middleware and
# restricts the route to the obol.stack hostname so it cannot be reached
# via the public cloudflared tunnel (see CLAUDE.md "Security: Tunnel
# Exposure"). Removing the hostnames restriction is a critical security
# regression.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: erpc
namespace: erpc
spec:
hostnames:
- "obol.stack"
parentRefs:
- name: traefik-gateway
namespace: traefik
sectionName: web
rules:
- matches:
- path:
type: PathPrefix
value: /rpc
filters:
- type: ExtensionRef
extensionRef:
group: traefik.io
kind: Middleware
name: x402-payment
backendRefs:
- name: erpc
port: 80

---
# x402 Middleware for the eRPC namespace (ForwardAuth -> central
# verifier). Always deployed; the verifier returns 200 for routes with
# no pricing rules.
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: x402-payment
namespace: erpc
spec:
forwardAuth:
address: http://x402-verifier.x402.svc.cluster.local:8080/verify
authResponseHeaders:
- X-Payment-Response

---
# eRPC metadata ConfigMap for frontend discovery. `.Values.network`
# resolves against the `network` value passed to the `base` release
# (default "mainnet", overridable via helmfile state values).
apiVersion: v1
kind: ConfigMap
metadata:
name: erpc-metadata
namespace: erpc
labels:
app.kubernetes.io/part-of: obol.stack
obol.stack/id: default
obol.stack/app: erpc
data:
metadata.json: |
{
"network": "{{ .Values.network }}",
"endpoints": {
"rpc": {
"external": "http://obol.stack/rpc/{{ .Values.network }}",
"internal": "http://erpc.erpc.svc.cluster.local/rpc/{{ .Values.network }}"
}
}
}
24 changes: 24 additions & 0 deletions internal/embed/infrastructure/base/templates/llm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -298,3 +298,27 @@ spec:
port: 4000
targetPort: http
protocol: TCP

---
# Relocated from helmfile.yaml `llm-buyer-podmonitor` bedag/raw release.
# Lives alongside its workload (litellm + x402-buyer sidecar) instead of
# inlined in helmfile so the chart layout is the single source of truth
# for what ships in the llm namespace. The PodMonitor CRD comes from the
# monitoring release (kube-prometheus-stack), so `base` now declares a
# `needs: [monitoring/monitoring]` in helmfile.yaml to guarantee CRD
# presence before this template applies.
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: litellm-x402-buyer
namespace: llm
labels:
release: monitoring
spec:
selector:
matchLabels:
app: litellm
podMetricsEndpoints:
- port: buyer-http
path: /metrics
interval: 30s
95 changes: 95 additions & 0 deletions internal/embed/infrastructure/base/templates/obol-frontend.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Relocated from helmfile.yaml `obol-frontend-httproute` and
# `obol-frontend-rbac` bedag/raw releases. These resources live
# alongside their workload (the obol-frontend Helm release in the
# `obol-frontend` namespace) instead of inlined in helmfile so the
# chart layout is the single source of truth for what ships in the
# obol-frontend namespace.
#
# The obol-frontend Deployment + Service themselves still come from
# the `obol/obol-app` upstream chart (separate release in
# helmfile.yaml); only the HTTPRoute and discovery RBAC are owned
# here.
#
# CRD prerequisite: HTTPRoute -> gateway.networking.k8s.io/v1
# (shipped by the Traefik v38+ chart's bundled CRDs). `base` now
# declares `needs: [traefik/traefik]` in helmfile.yaml to guarantee
# the CRDs are present before this template applies.

---
# obol-frontend namespace. Pre-created here so the HTTPRoute and
# ClusterRoleBinding subject reference can resolve during the `base`
# release without waiting for the `obol-frontend` upstream chart
# release to create it. The chart release still sets
# `createNamespace: true` — kubectl apply on an existing namespace is
# a no-op.
apiVersion: v1
kind: Namespace
metadata:
name: obol-frontend

---
# obol-frontend HTTPRoute. The `hostnames: ["obol.stack"]` restriction
# keeps the frontend UI off the public cloudflared tunnel — removing
# it is a critical security regression (see CLAUDE.md "Security:
# Tunnel Exposure").
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: obol-frontend
namespace: obol-frontend
spec:
hostnames:
- "obol.stack"
parentRefs:
- name: traefik-gateway
namespace: traefik
sectionName: web
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: obol-frontend-obol-app
port: 3000

---
# obol-frontend RBAC for OpenClaw instance discovery and ServiceOffer
# CRUD from the frontend sell modal. The ClusterRoleBinding subject
# references the `obol-frontend` ServiceAccount that the upstream
# `obol/obol-app` chart creates — the binding applies fine even if
# the SA does not exist yet, and starts granting permissions the
# moment the SA appears.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: obol-frontend-openclaw-discovery
labels:
app.kubernetes.io/name: obol-frontend
rules:
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["pods", "configmaps", "secrets"]
verbs: ["get", "list"]
# ServiceOffer CRD — frontend sell modal creates offers
- apiGroups: ["obol.org"]
resources: ["serviceoffers", "serviceoffers/status"]
verbs: ["get", "list", "create", "update", "patch", "delete"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: obol-frontend-openclaw-discovery
labels:
app.kubernetes.io/name: obol-frontend
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: obol-frontend-openclaw-discovery
subjects:
- kind: ServiceAccount
name: obol-frontend
namespace: obol-frontend
Loading
Loading