Kubernetes Operator
The Hookbase Kubernetes Operator lets you manage your entire webhook infrastructure as declarative YAML, right alongside your application manifests.
Overview
Instead of configuring webhook sources, destinations, routes, and tunnels through the dashboard or CLI, platform teams define them as Kubernetes custom resources. The operator watches these resources, reconciles them against the Hookbase API, and keeps the two in sync.
kubectl apply -f webhooks.yaml → Operator reconciles → Hookbase API updatedKey capabilities:
- 10 Custom Resource Definitions covering all Hookbase resources
- Drift detection with configurable reconciliation intervals
- Sidecar injection for tunnel agents
- Ingress controller mode for annotation-based setup
- Per-namespace API key isolation
- Prometheus metrics with ServiceMonitor support
- Helm chart for production deployment
Installation
Prerequisites
- Kubernetes 1.26+
- Helm 3.x
- A Hookbase API key with admin scopes
Install with Helm
Clone the operator repository from GitHub:
git clone https://github.com/HookbaseApp/hookbase-operator.git
cd hookbase-operatorCreate a bootstrap API key Secret:
kubectl create namespace hookbase-system
kubectl create secret generic hookbase-bootstrap-key \
--namespace hookbase-system \
--from-literal=apiKey=whr_your_api_key_hereInstall the operator from the local chart:
helm install hookbase-operator ./chart \
--namespace hookbase-system \
--create-namespace \
--set hookbase.apiKeySecretRef.name=hookbase-bootstrap-key \
--set hookbase.apiKeySecretRef.key=apiKeyDocker Images
The operator images are published to GitHub Container Registry:
- Operator:
ghcr.io/hookbaseapp/hookbase-operator - Tunnel Agent:
ghcr.io/hookbaseapp/hookbase-agent
Verify the operator is running:
kubectl get pods -n hookbase-systemQuick Start
1. Create a Source
apiVersion: hookbase.io/v1alpha1
kind: WebhookSource
metadata:
name: github-webhooks
spec:
name: GitHub Webhooks
slug: github-webhooks
provider: github
verifySignature: true
signingSecretRef:
name: github-webhook-secret
key: secret2. Create a Destination
apiVersion: hookbase.io/v1alpha1
kind: WebhookDestination
metadata:
name: my-api
spec:
name: My API
url: "https://api.example.com/webhooks"
method: POST
authType: bearer
authSecretRef:
name: api-token
key: token3. Create a Route
apiVersion: hookbase.io/v1alpha1
kind: WebhookRoute
metadata:
name: github-to-api
spec:
name: GitHub to API
sourceRef: github-webhooks
destinationRef: my-api4. Apply and Verify
kubectl apply -f webhooks.yaml
kubectl get webhooksources,webhookdestinations,webhookroutesCheck the status:
kubectl describe webhooksource github-webhooks
# Status:
# Conditions:
# Type: Ready
# Status: True
# Reason: SyncedCross-Resource References
CRDs reference each other by name within the same namespace:
apiVersion: hookbase.io/v1alpha1
kind: WebhookRoute
spec:
sourceRef: github-webhooks # References WebhookSource by metadata.name
destinationRef: internal-api # References WebhookDestination by metadata.name
filterRef: production-only # References WebhookFilter by metadata.name
transformRef: strip-headers # References WebhookTransform by metadata.nameThe route controller resolves these names to API IDs at reconciliation time. This is GitOps-friendly -- no raw API IDs in manifests. If a referenced resource is not Ready yet, the route requeues and waits.
API Key Resolution
The operator resolves API keys using a priority chain:
- Explicit
apiKeyRefon the CRD -- reads from a K8s Secret - Default HookbaseAPIKey in the namespace (labeled
hookbase.io/default=true) - Bootstrap key from the Helm installation
This allows teams to start with a shared bootstrap key and progressively isolate with per-namespace scoped keys.
Per-Namespace Keys
Create a scoped API key for a team namespace:
apiVersion: hookbase.io/v1alpha1
kind: HookbaseAPIKey
metadata:
name: team-key
labels:
hookbase.io/default: "true"
spec:
name: Team API Key
scopes:
- sources:read
- sources:write
- events:read
expiresInDays: 90
secretRef:
name: hookbase-team-key
key: apiKeyAfter reconciliation, a Secret named hookbase-team-key appears in the same namespace. All other CRDs in that namespace automatically use it.
Tunnel Sidecar Injection
The WebhookTunnel CRD can automatically inject a lightweight Go-based tunnel agent as a sidecar container into your Deployments:
apiVersion: hookbase.io/v1alpha1
kind: WebhookTunnel
metadata:
name: dev-tunnel
spec:
name: Dev Tunnel
targetPort: 8080
targetService: my-app
sidecarInjection:
deploymentRef: my-app
resources:
requests:
cpu: 10m
memory: 16Mi
limits:
cpu: 100m
memory: 64MiThe operator:
- Creates the tunnel in the Hookbase API
- Stores the auth token in a K8s Secret (
dev-tunnel-tunnel-auth) - Patches the target Deployment to add a
hookbase-agentcontainer - The agent connects via WebSocket and forwards requests to
localhost:8080
On tunnel CRD deletion, the sidecar is automatically removed from the Deployment.
Ingress Controller Mode
For teams that prefer annotations over new CRDs, the operator watches Kubernetes Ingress resources with ingressClassName: hookbase:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-webhooks
annotations:
hookbase.io/source-provider: "stripe"
hookbase.io/source-verify-signature: "true"
hookbase.io/source-signing-secret-ref: "stripe-secret:whsec"
spec:
ingressClassName: hookbase
rules:
- host: webhooks.example.com
http:
paths:
- path: /stripe
pathType: Prefix
backend:
service:
name: payment-service
port:
number: 8080The operator automatically creates the underlying Hookbase source, tunnel, and route.
Available Annotations
| Annotation | Description |
|---|---|
hookbase.io/source-provider | Webhook provider (e.g., stripe, github) |
hookbase.io/source-verify-signature | Enable signature verification (true/false) |
hookbase.io/source-signing-secret-ref | K8s Secret reference for signing secret (name:key) |
hookbase.io/route-transform-ref | Reference to a WebhookTransform CRD |
hookbase.io/api-key-ref | Override API key for this ingress |
Drift Detection
The operator reconciles on a configurable interval (default 5 minutes). If someone modifies a resource through the dashboard or API, the next reconciliation cycle brings it back in line with the YAML definition.
This ensures your Git repository remains the source of truth for webhook infrastructure.
Observability
Prometheus Metrics
| Metric | Type | Description |
|---|---|---|
hookbase_operator_reconcile_total | Counter | Reconciliations by resource type and outcome |
hookbase_operator_reconcile_duration_seconds | Histogram | Reconciliation latency |
hookbase_operator_api_calls_total | Counter | SDK API call counts |
hookbase_operator_managed_resources | Gauge | Number of managed resources |
hookbase_operator_tunnel_connected | Gauge | Tunnel connection status (0/1) |
Enable the ServiceMonitor in Helm values:
metrics:
serviceMonitor:
enabled: trueStatus Conditions
Every CRD has standard Kubernetes conditions:
- Ready -- overall resource health
- Synced -- last successful sync with Hookbase API
kubectl get webhooksources
# NAME SOURCE ID PROVIDER READY AGE
# github-webhooks src_2 github True 5mHealth Probes
The operator exposes:
/healthz-- liveness probe/readyz-- readiness probe
Admission Webhooks
Optional validating and defaulting webhooks enforce constraints at apply time:
- Slug immutability -- prevents changing
.spec.slugafter creation - CIDR validation -- validates IP allowlist/denylist entries
- Mutual exclusion -- prevents setting both
filterRefandfilterConditionson routes - Defaults -- sets
provider=generic,method=POST,filterLogic=AND
Enable in Helm values:
webhook:
enabled: true
certManager:
enabled: trueGitOps Integration
ArgoCD
The operator works out of the box with ArgoCD. Add your webhook manifests to your application repository and ArgoCD will sync them:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: webhook-infra
spec:
source:
repoURL: https://github.com/your-org/infra
path: webhooks/production
destination:
server: https://kubernetes.default.svc
namespace: webhooksFlux
Similarly, Flux Kustomizations will deploy and reconcile webhook CRDs:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: webhook-infra
spec:
sourceRef:
kind: GitRepository
name: infra
path: ./webhooks/productionResources
- GitHub: github.com/HookbaseApp/hookbase-operator
- Announcement: Introducing the Kubernetes Operator
Next Steps
- CRD Reference -- full specification for all 10 CRDs
- Helm Chart Reference -- all Helm values and configuration options
- Tunnels Guide -- more on tunnel functionality