SolidHooksSolidHooks
Get Started
Use casesPrivate network delivery

Deliver to endpoints with no public URL

The service that should handle your webhooks often has no business being on the internet. SolidHooks Connect runs a small agent inside your network or cluster and delivers through it, so an event can land on payments.default.svc.cluster.local without that name ever resolving from outside.
Outbound onlyReplicas for HANo inbound firewall rule
What this guide covers
  1. 01What a connector is and where it runs
  2. 02Enrolling replicas so one restart is not an outage
  3. 03Pointing a destination at an in-cluster URL
  4. 04Reading connector and replica health honestly
  5. 05Rotation, disabling, deletion and plan limits

How it works

A connector represents one of your networks. It belongs to the organization rather than a project, so a single cluster connector serves every project you run. Inside that network you run one or more agent replicas. Each dials out to the overlay and stays there.

When a delivery is due, SolidHooks hands it to the connector by name and the agent makes the actual HTTP request from inside your network. Your service sees a request from a local address and needs no changes at all.

Delivery
due to send
Overlay
dialled by name
Agent replica
inside your network
Your service
cluster-local URL
Every arrow starts on your side of the boundary. The agent opens the connection outward and SolidHooks rides it.

Set it up

  1. 1

    Provision the connector

    The response carries an enrollmentKey (cbt_…). It is shown here and on regeneration and nowhere else, so store it before you move on. It does not expire.

    curl
    curl -s "$API/v1/connectors" \  -H "authorization: Bearer $SDHK_KEY" \  -H 'content-type: application/json' \  -d '{ "name": "prod-cluster", "description": "EU production" }' → { "id": "cntr_...", "enrollmentKey": "cbt_...", "provisionedAt": "2026-08-18T09:14:02.000Z" }# The enrollment key is shown once here. Store it now.# provisionedAt reads null only if you read the connector back while this call is still in flight.
  2. 2

    Run the agent in your network

    The dashboard prints the exact docker run or helm install line with your token in it. Each replica self-enrolls by calling the the SolidHooks bootstrap endpoint, receives a per-replica heartbeat token, and joins the connector.

    curl
    # Install using helmhelm repo add interstellar-labs https://interstellar-labs.github.io/charts/helm repo updatehelm install solidhooks-connector interstellar-labs/solidhooks-connector \ --set enrollmentKey="cbt_..." # Install using dockerdocker run -e ENROLLMENT_KEY="cbt_..." \ -v solidhooks-connector:/ziti \ interstellarlabs/solidhooks-connector:latest 
  3. 3

    Add replicas for availability

    Run the same command again elsewhere. Replicas are independent members of one connector, so a rolling restart never leaves the connector with nothing to dial.

  4. 4

    Create a private destination

    Set type: "private" and name the connector. The URL is still validated as a URL, it simply does not have to resolve publicly.

    curl
    curl -s "$API/v1/destinations" \  -H "authorization: Bearer $SDHK_KEY" \  -H 'content-type: application/json' \  -d '{    "name": "In-cluster payments service",    "type": "private",    "connectorId": "cntr_...",    "url": "http://payments.default.svc.cluster.local:8080/hooks",    "method": "POST"  }'
Provisioning takes a few seconds
A new connector carries provisionedAt: null until its overlay infrastructure exists. During that window, creating a private destination against it returns 400 and deleting it returns 409 CONNECTOR_PROVISIONING. Both are retryable by design.

Reading health without guessing

A connector reports a status aggregated over its replicas, and the four values are chosen so that our uncertainty is never reported as your outage.

pendingNo replica has enrolled yet.
connectedAt least one replica is up. Check the replica list to tell 3 of 3 from 1 of 3.
disconnectedReplicas enrolled, all of them reported, none reachable. This one is yours.
unknownSolidHooks could not reach the overlay controller. This says nothing about your agent. Retry the read.
curl
# Aggregate across replicascurl -s "$API/v1/connectors/cntr_..." -H "authorization: Bearer $SDHK_KEY"→ { "status": "connected", "connectedReplicas": 2, "totalReplicas": 3 } # Which one is missingcurl -s "$API/v1/connectors/cntr_.../replicas" -H "authorization: Bearer $SDHK_KEY"

Rotation, disabling and revocation

regenerate-enrollment mints a new bootstrap token and invalidates the previous one. Replicas that already enrolled keep running, so rotating a leaked token is not an outage.

toggle-disabled stops new private destinations being created against the connector. Enrolled replicas keep beating, because disabling is an administrative switch rather than revocation. Deleting a connector is blocked with 400 while any destination still points at it.

A replica is revoked automatically only when it has both been silent past the stale-heartbeat window and failed to appear on the overlay. That window defaults to 24 hours and is set per deployment, so check your own before treating it as a fixed number. Requiring both conditions is what keeps a healthy agent alive when it can serve traffic but cannot reach our API. A revoked replica gets 403 with a machine-readable reason and stops. An unrecognised token gets an opaque 401, so the endpoint cannot be used to probe which credentials are live.

Plan limits and prerequisites

  • Connectors are capped by maxConnectors. Exceeding it returns 403 CONNECTOR_LIMIT_REACHED with the current count.
  • Replicas per connector are capped by maxReplicasPerConnector, enforced at bootstrap. Shrinking a plan never evicts replicas that are already enrolled.
  • Private delivery is an optional platform capability. On a deployment without the overlay configured, connector mutations return 400.

Practices worth adopting

  • Run at least two replicas in different failure domains. One connector with one replica is a single point of failure wearing a plural noun.
  • Store the enrollment key in your secret manager the moment you create the connector. It is never shown again, and the recovery path is regeneration.
  • Alert on connectedReplicas falling below your intended count rather than on the aggregate status. A connector reads connected with one replica of three alive.
  • Treat unknown as a read to retry rather than a page to send. It describes our view of the overlay, not your agent.
  • One connector per network, reused across projects. They are organization-scoped for exactly this reason.

Questions

Reach the service that was never meant to be public

Provision a connector, run the agent, and point a destination at a cluster-local URL.