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.
A microservices gateway coordinates ingress traffic for distributed services without requiring a full service mesh.
It handles north-south traffic (public internet to your services) with JWT authentication and intelligent routing, providing a central place to route, secure, and monitor distributed microservices.
With this setup, you can:
- Handle public API traffic with JWT authentication and rate limiting
- Route requests to different microservices based on URL paths
- Apply consistent authentication and authorization policies
- Deploy and test services independently without rewriting routing logic
- Debug distributed request flows from a central gateway
1. Install the ngrok Kubernetes Operator
Install the ngrok Kubernetes Operator in your cluster. For detailed installation instructions, see the Kubernetes CRDs getting started guide.
2. Create AgentEndpoints for your microservices
Create AgentEndpoint CRDs to expose your microservices. These create internal endpoints that are not publicly accessible but can be routed through your gateway.
User service:
apiVersion: ngrok.k8s.ngrok.com/v1alpha1
kind: AgentEndpoint
metadata:
name: user-service
namespace: default
spec:
url: https://user-service.internal
upstream:
url: http://user-service.default.svc.cluster.local:8080
description: "User service"
Order service:
apiVersion: ngrok.k8s.ngrok.com/v1alpha1
kind: AgentEndpoint
metadata:
name: order-service
namespace: default
spec:
url: https://order-service.internal
upstream:
url: http://order-service.default.svc.cluster.local:8080
description: "Order service"
Notification service:
apiVersion: ngrok.k8s.ngrok.com/v1alpha1
kind: AgentEndpoint
metadata:
name: notification-service
namespace: default
spec:
url: https://notification-service.internal
upstream:
url: http://notification-service.default.svc.cluster.local:8080
description: "Notification service"
Apply these configurations:
kubectl apply -f user-service.yaml
kubectl apply -f order-service.yaml
kubectl apply -f notification-service.yaml
3. Reserve a domain
Navigate to the Domains section of the ngrok dashboard and click New + to reserve a free static domain like or a custom domain you already own.
We’ll refer to this domain as $NGROK_DOMAIN from here on out.
4. Create a Cloud Endpoint
Navigate to the Endpoints section of the ngrok dashboard, then click New + and Cloud Endpoint.
In the URL field, enter the domain you just reserved to finish creating your Cloud Endpoint.
5. (Optional) Create secrets for authentication
Store your JWT validation keys using Traffic Policy Secrets.
# Create vault for microservices auth
ngrok api vaults create --name "microservices-auth" --description "Microservices authentication secrets"
# Add JWT validation key
ngrok api secrets create \
--name "jwt-public-key" \
--value "-----BEGIN PUBLIC KEY-----\nYour JWT validation public key here\n-----END PUBLIC KEY-----" \
--vault-id "$VAULT_ID"
6. Apply Traffic Policy to your Cloud Endpoint
Configure your Cloud Endpoint with JWT authentication and routing to your microservices.
Make sure you change each of the following values:
$JWT_ISSUER: Replace with your JWT issuer URL
$JWT_AUDIENCE: Replace with your JWT audience claim
$JWT_PUBLIC_KEY_URL: Replace with your JWKS endpoint URL
- Service URLs: Replace with your actual internal service endpoints
on_http_request:
# WAF-like protection using OWASP CRS
- actions:
- type: owasp-crs-request
config:
on_error: halt
# JWT validation for public API access
- actions:
- type: jwt-validation
config:
issuer:
allow_list:
- value: "https://$JWT_ISSUER"
audience:
allow_list:
- value: "$JWT_AUDIENCE"
http:
tokens:
- type: "access_token"
method: "header"
name: "Authorization"
prefix: "Bearer "
jws:
allowed_algorithms: ["RS256", "ES256"]
keys:
sources:
additional_jkus: ["$JWT_PUBLIC_KEY_URL"]
# Rate limiting per JWT subject
- actions:
- type: rate-limit
config:
name: "API rate limiting per user"
algorithm: "sliding_window"
capacity: 1000
rate: "1h"
bucket_key: ["actions.ngrok.jwt_validation.tokens[0].payload.sub"]
# Route to user service
- expressions:
- "req.url.path.startsWith('/api/users')"
actions:
- type: forward-internal
config:
url: https://user-service.internal
# Route to order service
- expressions:
- "req.url.path.startsWith('/api/orders')"
actions:
- type: forward-internal
config:
url: https://order-service.internal
# Route to notification service
- expressions:
- "req.url.path.startsWith('/api/notifications')"
actions:
- type: forward-internal
config:
url: https://notification-service.internal
on_http_response:
# OWASP protection for responses
- actions:
- type: owasp-crs-response
config:
on_error: halt
# Add service tracing headers
- actions:
- type: add-headers
config:
headers:
x-service-version: "v1.0"
x-processed-at: "${time.now}"
x-client-ip: "${conn.client_ip}"
What’s happening here?
This policy creates a secure, centralized API gateway for your microservices architecture.
On every HTTP request, the policy first applies OWASP Core Rule Set protection to block malicious requests like SQL injection and XSS attacks, then validates JWT tokens to ensure only authenticated users can access your APIs, and applies per-user rate limiting based on the JWT subject to prevent abuse.
The gateway intelligently routes traffic to the appropriate microservice based on URL paths—user management requests go to the user service, order-related requests to the order service, and notification requests to the notification service.
On responses, it applies OWASP protection to scan outgoing content for vulnerabilities and adds service tracing headers for observability and debugging across your distributed system.
7. Try out your microservices gateway
Visit the domain you reserved either in the browser or in the terminal using a tool like curl.
You should see the app or service at the port connected to your internal Agent Endpoint.
Test the public API gateway:
# Get a JWT token (replace with your auth provider)
JWT_TOKEN="your_jwt_token_here"
# Test user service
curl -H "Authorization: Bearer $JWT_TOKEN" \
"https://$NGROK_DOMAIN/api/users/123"
# Test order service
curl -H "Authorization: Bearer $JWT_TOKEN" \
"https://$NGROK_DOMAIN/api/orders/456"
# Test notification service
curl -H "Authorization: Bearer $JWT_TOKEN" \
"https://$NGROK_DOMAIN/api/notifications/789"
What’s next?