Documentation Index
Fetch the complete documentation index at: https://ngrok.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
CloudEndpoint custom resource
apiVersion: ngrok.k8s.ngrok.com/v1alpha1
kind: CloudEndpoint
The CloudEndpoint custom resource is used to create centrally managed endpoints in the cloud. Cloud Endpoints are persistent, always-on endpoints that live within the ngrok cloud.
They exist permanently until they are explicitly deleted. Cloud Endpoints do not forward their traffic to an agent by default and instead only use their attached Traffic Policy to handle connections.
Using the Traffic Policy configuration, you may configure your Cloud Endpoints to route to one or more other internal ngrok endpoints.
For more information about Cloud Endpoints in ngrok, refer to the Cloud Endpoints page
CloudEndpoint structure and types
The following outlines the high level structure and typings of a CloudEndpoint
apiVersion: ngrok.k8s.ngrok.com/v1alpha1
kind: CloudEndpoint
metadata:
name: <string>
namespace: <string>
spec:
url: <string> # required
trafficPolicyName: <string> # optional
trafficPolicy: # optional
policy: # required
<Traffic Policy config>
description: <string> # optional, default: "Created by the ngrok-operator"
metadata: <string> # optional, default: "{"owned-by":"ngrok-operator"}"
bindings: <[]string> # optional
poolingEnabled: <bool> # optional, default: false
CloudEndpoint fields
The following sections outline each field of the CloudEndpoint custom resource, whether they are required, what their default values are (if applicable), and a description of their purpose/constraints.
spec
spec defines the desired state of the CloudEndpoint
Type: Object
Required: yes
Default: none
Fields:
| Field Name | Type | Required | Default | Description |
|---|
spec.url | string | yes | none | The unique URL for this CloudEndpoint that defines how the endpoint is accessed |
spec.trafficPolicyName | string | no | none | The name of an NgrokTrafficPolicy custom resource in the same namespace as the CloudEndpoint to use for Traffic Policy configuration |
spec.trafficPolicy | Object | no | none | Allows for a Traffic Policy to be provided to the CloudEndpoint using inline configuration |
spec.description | string | no | "Created by the ngrok-operator" | Human-readable description for this CloudEndpoint to help identify/describe it |
spec.metadata | string | no | "{"owned-by":"ngrok-operator"}" | String of arbitrary data associated with the object in the ngrok API/Dashboard |
spec.bindings | []string (enum) | no | none | List of Binding IDs to associate with the endpoint |
spec.poolingEnabled | bool | no | false | Whether or not the CloudEndpoint should enable pooling with other endpoints sharing the same URL |
spec.url
The unique URL for this Cloud Endpoint. This URL defines how the endpoint is accessed.
Type: string
Required: yes
Default: none
The following formats are accepted:
- Domain
- When using the domain format you are only defining the domain. The scheme and port will be inferred.
- example:
example.org
- Origin
- When using the origin format you are defining the protocol, domain and port. HTTP endpoints accept ports
80 or 443 with respective protocol.
- examples:
https://example.ngrok.app
https://example.ngrok.app:443
tcp://1.tcp.ngrok.io:12345
tls://example.ngrok.app
- Scheme (shorthand)
- When using scheme you are defining the protocol and will receive back a randomly assigned ngrok address.
- examples:
https://
tcp://
tls://
http://
- Empty
When empty your endpoint will default to be https and receive back a randomly assigned ngrok address.
- Internal
- When ending your URL with .internal, an internal endpoint will be created. Internal Endpoints cannot be accessed directly, but rather
can only be accessed using the forward-internal Traffic Policy action.
- example:
some.domain.internal
spec.trafficPolicyName
Reference to an NgrokTrafficPolicy custom resource in the same namespace as the CloudEndpoint to use for Traffic Policy configuration.
It is invalid to configure both spec.trafficPolicyName and spec.trafficPolicy at the same time.
The referenced NgrokTrafficPolicy must be in the same namespace as the CloudEndpoint.
Type: string
Required: no
Default: none
spec.trafficPolicy
Reference to an NgrokTrafficPolicy custom resource in the same namespace as the CloudEndpoint to use for Traffic Policy configuration.
It is invalid to configure both spec.trafficPolicyName and spec.trafficPolicy at the same time.
For more information about writing ngrok Traffic Policies, refer to the Traffic Policy section.
Type: Object
Required: no
Default: none
Fields:
| Field Name | Type | Required | Default | Description |
|---|
spec.trafficPolicy.policy | json.RawMessage | yes | none | The inline Traffic Policy configuration to be used for this CloudEndpoint |
spec.trafficPolicy.policy
Allows you to supply a Traffic Policy for this AgentEndpoint with inline configuration. An example has been included below.
For more information about writing ngrok Traffic Policies, refer to the Traffic Policy section.
Type: json.RawMessage
Required: yes
Default: none
spec.description
Human-readable description of this Cloud Endpoint that can be used to help identify/describe it.
Type: string
Required: no
Default: "Created by the ngrok-operator"
String of arbitrary data associated with the object in the ngrok API/Dashboard.
Type: string
Required: no
Default: "{"owned-by":"ngrok-operator"}"
spec.bindings
List of Binding IDs to associate with the endpoint
Type: string (enum)
Required: no
Default: none
Accepted Values: "public", "internal", or "kubernetes"
- A binding of
"internal" will create an internal AgentEndpoint that is only accessible from other endpoints using the forward-internal Traffic Policy action.
- Aside from setting
bindings: ["internal"], the spec.url of the AgentEndpoint must end in .internal
- Setting
bindings: ["public"] will not work for internal endpoints (endpoints that have a spec.url ending in .internal)
- A binding of
"public" will create a standard AgentEndpoint with its spec.url accessible to the public internet
- Setting
bindings: ["internal"] will not work for public endpoints
- A binding of
"kubernetes" will create a Kubernetes bound endpoint. This causes the endpoint to not be publicly accessible to the public internet
and will be projected into one or more of your Kubernetes clusters that are running the ngrok Operator (depending on their endpoint selector configuration) as Services.
- With a
"kubernetes" binding, the spec.url becomes the name.namespace of the projected Service.
- For example, with a
spec.url of http://my-service.my-namespace then a Service with name my-service in the my-namespace namespace will be created by the ngrok Operator.
Other services within the Kubernetes cluster can make requests to this endpoint. This enables many different use-cases such as being able to project a service in one Kubernetes cluster
to another Kubernetes cluster so that services running in the other cluster can make requests to it. This has the benefit of not needing to expose the endpoint to the public internet behind a publicly accessible URL.
spec.poolingEnabled
Configures whether pooling is always enabled for this CloudEndpoint.
When pooling is enabled, if two different endpoints share the same spec.url then requests will be balanced between them.
This is not limited to endpoints within the same cluster, or endpoints of the same type. For example, a CloudEndpoint can be pooled with an Agent Endpoint created using the ngrok CLI if they both enable pooling and share the same URL.
It is recommended to include a prefix/suffix in the URL to prevent unintended pooling. For example, if you are running a service foo in the namespace bar in two different
Kubernetes clusters, you may want to give each one a slightly different spec.url that includes something such as a cluster identifier to prevent requests from being balanced between them.
You will receive an error back from the ngrok server if you attempt to create two different endpoints using the same URL if they do not both enable pooling.
In this scenario, the older endpoint wins and the newer one will fail to be created.
Type: bool
Required: no
Default: false
Status fields
The CloudEndpoint resource includes status information that reflects the current state of the Cloud Endpoint in the ngrok system.
status.id
The ngrok API ID for this Cloud Endpoint.
Type: string
Example: ep_34iZT0muBP3kpcAXxGjM4uFlgDK
status.domain
(Deprecated) Domain information for the endpoint. This field is deprecated; use status.domainRef instead.
Type: Object
status.domainRef
Reference to the Domain resource associated with this Cloud Endpoint.
Type: Object
Fields:
name - Name of the Domain resource
namespace - Namespace of the Domain resource
Example:
domainRef:
name: example-domain-ngrok-app
namespace: default
status.conditions
Standard Kubernetes conditions that indicate the state of the Cloud Endpoint.
Type: []Condition
Each condition includes:
type - The condition type
status - True, False, or Unknown
reason - A programmatic identifier for the condition state
message - A human-readable description
lastTransitionTime - When the condition last changed
observedGeneration - The resource generation this condition applies to
Condition types
Ready
Indicates whether the Cloud Endpoint is fully operational and ready to use.
Status Values:
True - Cloud endpoint is active and ready
False - Cloud endpoint is not ready (see reason for details)
Reasons:
| Reason | Status | Meaning |
|---|
CloudEndpointActive | True | Cloud endpoint is successfully created and active |
CloudEndpointCreationFailed | False | Failed to create the Cloud Endpoint in ngrok |
Pending | False | Cloud endpoint creation is pending (for example, waiting for domain) |
Unknown | False | Cloud endpoint state is unknown |
DomainNotReady | False | Associated domain is not ready |
Additionally, the Ready condition may reflect reasons from the associated Domain resource when domain issues prevent endpoint creation.
Example:
conditions:
- type: Ready
status: "True"
reason: CloudEndpointActive
message: "Cloud endpoint is active"
lastTransitionTime: "2025-10-29T00:39:16Z"
observedGeneration: 1
Example (Pooling Error):
conditions:
- type: Ready
status: "False"
reason: CloudEndpointCreationFailed
message: |
Failed to create Cloud Endpoint: HTTP 400: The provided Cloud Endpoint was invalid because pooling was set to disabled when another endpoint exists for this url. [ERR_NGROK_18017]
Operation ID: op_34ic9T376GyGAXQ4sIRn7F0xUYP
lastTransitionTime: "2025-10-29T00:39:15Z"
observedGeneration: 2
CloudEndpointCreated
Indicates whether the Cloud Endpoint was successfully created in the ngrok API.
Status Values:
True - Cloud endpoint was successfully created
False - Failed to create Cloud Endpoint
Reasons:
| Reason | Status | Meaning |
|---|
CloudEndpointCreated | True | Cloud endpoint successfully created |
CloudEndpointCreationFailed | False | API call to create Cloud Endpoint failed |
Example:
conditions:
- type: CloudEndpointCreated
status: "True"
reason: CloudEndpointCreated
message: "Cloud endpoint successfully created"
lastTransitionTime: "2025-10-29T00:39:16Z"
observedGeneration: 1
DomainReady
Indicates whether the associated domain is ready for use. This condition propagates the state from the referenced Domain resource.
Status Values:
True - Domain is ready
False - Domain is not ready
Reasons:
This condition propagates reasons from the Domain resource’s Ready condition, including:
DomainActive - Domain is successfully reserved and ready
ProvisioningError - Domain has DNS or certificate provisioning errors
DomainCreationFailed - Domain failed to be created
DomainInvalid - Domain format or configuration is invalid
Example:
conditions:
- type: DomainReady
status: "True"
reason: DomainActive
message: "Domain ready for use"
lastTransitionTime: "2025-10-29T00:39:25Z"
observedGeneration: 1
Example (Domain DNS Error):
conditions:
- type: DomainReady
status: "False"
reason: ProvisioningError
message: 'DNS_ERROR Reserved domain "example.com" NS DNS records are not pointing at the ngrok infrastructure'
lastTransitionTime: "2025-10-29T00:39:24Z"
observedGeneration: 1
Status examples
Successfully created Cloud Endpoint
status:
id: ep_34iZT0muBP3kpcAXxGjM4uFlgDK
domainRef:
name: example-domain-ngrok-app
namespace: default
conditions:
- type: DomainReady
status: "True"
reason: DomainActive
message: "Domain ready for use"
lastTransitionTime: "2025-10-29T00:39:25Z"
observedGeneration: 1
- type: CloudEndpointCreated
status: "True"
reason: CloudEndpointCreated
message: "Cloud endpoint successfully created"
lastTransitionTime: "2025-10-29T00:39:16Z"
observedGeneration: 1
- type: Ready
status: "True"
reason: CloudEndpointActive
message: "Cloud endpoint is active"
lastTransitionTime: "2025-10-29T00:39:16Z"
observedGeneration: 1
Cloud Endpoint with pooling error
status:
domainRef:
name: example-domain-ngrok-app
namespace: default
conditions:
- type: DomainReady
status: "True"
reason: DomainActive
message: "Domain ready for use"
lastTransitionTime: "2025-10-29T00:39:25Z"
observedGeneration: 2
- type: CloudEndpointCreated
status: "False"
reason: CloudEndpointCreationFailed
message: |
Failed to create Cloud Endpoint: HTTP 400: The provided Cloud Endpoint was invalid because pooling was set to disabled when another endpoint exists for this url. [ERR_NGROK_18017]
Operation ID: op_34ic9T376GyGAXQ4sIRn7F0xUYP
lastTransitionTime: "2025-10-29T00:39:25Z"
observedGeneration: 2
- type: Ready
status: "False"
reason: CloudEndpointCreationFailed
message: |
Failed to create Cloud Endpoint: HTTP 400: The provided Cloud Endpoint was invalid because pooling was set to disabled when another endpoint exists for this url. [ERR_NGROK_18017]
Operation ID: op_34ic9T376GyGAXQ4sIRn7F0xUYP
lastTransitionTime: "2025-10-29T00:39:15Z"
observedGeneration: 2
Cloud Endpoint with domain not ready
status:
domainRef:
name: custom-domain-com
namespace: default
conditions:
- type: DomainReady
status: "False"
reason: ProvisioningError
message: 'DNS_ERROR Reserved domain "example.com" NS DNS records are not pointing at the ngrok infrastructure'
lastTransitionTime: "2025-10-29T00:39:24Z"
observedGeneration: 1
- type: CloudEndpointCreated
status: "False"
reason: Pending
message: "Waiting for domain to be ready"
lastTransitionTime: "2025-10-29T00:39:24Z"
observedGeneration: 1
- type: Ready
status: "False"
reason: DomainNotReady
message: "Cloud endpoint cannot be created because domain is not ready"
lastTransitionTime: "2025-10-29T00:39:24Z"
observedGeneration: 1
Checking Cloud Endpoint status
You can check the status of a Cloud Endpoint using kubectl:
# Check if Cloud Endpoint is ready
kubectl get cloudendpoint example-cloud-endpoint -o jsonpath='{.status.conditions[?(@.type=="Ready")]}'
# Watch for Cloud Endpoint to become ready
kubectl wait --for=condition=Ready cloudendpoint/example-cloud-endpoint --timeout=60s
# Get all Cloud Endpoints with their ready status
kubectl get cloudendpoints -A -o custom-columns=\
NAME:.metadata.name,\
NAMESPACE:.metadata.namespace,\
DOMAIN:.status.domainRef.name,\
READY:.status.conditions[?(@.type==\'Ready\')].status,\
REASON:.status.conditions[?(@.type==\'Ready\')].reason
# Check domain readiness for a Cloud Endpoint
kubectl get cloudendpoint example-cloud-endpoint -o jsonpath='{.status.conditions[?(@.type=="DomainReady")]}'
Example CloudEndpoints
CloudEndpoint with inline Traffic Policy
The following CloudEndpoint:
- Accepts traffic on the URL
https://example-cloud-endpoint.ngrok.io
- Adds an inline Traffic Policy that sends back a custom response
apiVersion: ngrok.k8s.ngrok.com/v1alpha1
kind: CloudEndpoint
metadata:
name: example-cloud-endpoint
spec:
url: https://example-cloud-endpoint.ngrok.io
trafficPolicy:
policy:
on_http_request:
- name: example-rule
actions:
- type: custom-response
config:
body: Example response from Traffic Policy
headers:
content-type: text/plain
status_code: 200
CloudEndpoint with referenced Traffic Policy
The following CloudEndpoint:
- Accepts traffic on the URL
https://example-cloud-endpoint.ngrok.io
- Adds a reference to a Traffic Policy that sends back a custom response
apiVersion: ngrok.k8s.ngrok.com/v1alpha1
kind: NgrokTrafficPolicy
metadata:
name: static-response
namespace: default
spec:
policy:
on_http_request:
- name: example-rule
actions:
- type: custom-response
config:
body: Example response from Traffic Policy
headers:
content-type: text/plain
status_code: 200
---
apiVersion: ngrok.k8s.ngrok.com/v1alpha1
kind: CloudEndpoint
metadata:
name: example-cloud-endpoint
spec:
url: https://example-cloud-endpoint.ngrok.io
trafficPolicyName: static-response