From 1a1cad971fba2c503ff1c4d2d6407517f3d8093d Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 13 Mar 2025 10:09:47 -0400 Subject: [PATCH 001/137] Restructure Universal Gateway > Concepts > Domains wip --- .../domains/what-are-domains.mdx | 200 ++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 docs/universal-gateway/domains/what-are-domains.mdx diff --git a/docs/universal-gateway/domains/what-are-domains.mdx b/docs/universal-gateway/domains/what-are-domains.mdx new file mode 100644 index 0000000000..39312323b3 --- /dev/null +++ b/docs/universal-gateway/domains/what-are-domains.mdx @@ -0,0 +1,200 @@ +--- +title: What are Domains? +--- + +Domains enable you to create public endpoints with hostnames matching the +domain. For example, after you create the domain `your-name.ngrok.app`, you may create the Endpoint `https://your-name.ngrok.app` + +Domain names may be a subdomain of an [ngrok-managed +domain](#ngrok-managed-domains) like `foo.ngrok.app` or you can [bring your own domain](#branded-domains) like `example.your-domain.com` by creating a CNAME DNS record with your domain's DNS provider. + +Domains also enable you to configure other domain-level behaviors including: + +- [**Global Load Balancer configuration**](#global-load-balancer) - Choose which points of presence handle traffic to a Domain's matching endpoints. +- [**TLS Certificate management**](#tls-certificates) - Configure automatic certificate provisioning or select a certificate you uploaded yourself. +- [**Dedicated IP address configuration**](#dedicated-ips) - Attach static, dedicated IPs for a Domain's matching endpoints receive traffic on. + +You can manage Domains on your [ngrok Dashboard](https://dashboard.ngrok.com/domains) +or via the [ngrok API](#api). + +## Public endpoints + +A Domain's primary responsibility is to enable you to create [public +endpoints](/universal-gateway/public-endpoints/) with a hostname matching the +domain. These are called "matching endpoints". For example, after you create +the Domain `app.example.com`, you can create the Endpoint +`https://app.example.com`. + +When you create a Domain, you may create matching public endpoints with the +following constraints: + +| Endpoint Protocol | Allowed Endpoints | +| ----------------- | ------------------------------------------------------------------------------------------------ | +| `http` | Matching endpoints on port `80` of the Domain. | +| `https` | Matching endpoints on port `443` of the Domain. | +| `tls` | Matching endpoints on port `443` of the Domain. | +| `tcp` | Not allowed. Public TCP endpoints must match a [TCP Address](/universal-gateway/tcp-addresses/). | + +If you configure your Domain to use [dedicated IPs](#dedicated-ips), these +restrictions are removed and you may create matching endpoints on any ports. + +### Wildcard Domains + +You may create a Domain with a wildcard name, e.g. `*.example.com`. A wildcard +domain enables you to: + +- Create an endpoint which receives traffic for all of its subdomains, e.g. + `https://*.example.com`. Consult the documentation for [wildcard + endpoints](/universal-gateway/http/#wildcard-endpoints) to understand + the rules for matching and precedence. + +- Create an endpoint on any subdomain which matches the wildcard, e.g. + `https://foo.example.com` or `https://foo.bar.baz.example.com` + +The wildcard `*` character may only be used as the first part of a +domain, you may not create domains like `app.*.example.com` or +`*-app.example.com`. + +### Ownership + +Your account exclusively owns its Domains and all of their nested subdomains +within ngrok. That means: + +- No account may create a Domain with a name that is a subdomain of your Domains. +- No other account may create endpoints with a hostname matching your Domain or + any of its nested subdomains. + +For example, if you create a Domain with the name `foo.ngrok.app`: + +- No other account create the Domains `foo.ngrok.app` or `bar.foo.ngrok.app`. +- No other account may create the endpoints `https://foo.ngrok.app` or `https://bar.foo.ngrok.app`. + +## Bring your own domain {#branded-domains} + +You can use any domain name that you already own with ngrok, e.g. +`app.your-domain.com`. To do so, you will create a CNAME record for that domain +to point traffic from the domain to ngrok's cloud service. When you create a +Domain, you will be presented with a target value for the CNAME record you need +to create. If you [create the Domain via +API](/api/resources/reserved-domains/), this value is the `cname_target` field. + +If you bring your own [wildcard domain](#wildcard-domains), you will need to +create a second DNS CNAME record for [wildcard TLS Certificate +provisioning](/universal-gateway/tls-certificates/#wildcard-domains). + +ngrok is not a domain registrar; you must already own a domain name to use it +with ngrok. + +### Apex domains + +If you want to use an apex domain (e.g. `example.com`) with ngrok, you must use +a DNS provider that supports an ALIAS record or CNAME flattening because the +DNS RFC does not permit CNAME records for apex domains. Because of how +ALIAS/CNAME flattening is implemented, apex domains will not take advantage of +the [Global Load Balancer](#global-load-balancer). If you are trying to create +your apex domain because you need to create endpoints for multiple subdomains, +use a [wildcard domain](#wildcard-domains) instead. + +## Global Load Balancer + +The [Global Load Balancer](/universal-gateway/global-load-balancer) +uses latency-aware DNS records to direct clients to the IPs of the nearest +[points of presence](/universal-gateway/points-of-presence/). + +Domains allow you to configure which points of presence the Global Load +Balancer may resolve clients to. This allows you to select which points of +presence will receive traffic for the Domain's matching endpoints. To disable +the Global Load Balancer, you may configure a domain to only resolve a single +point of presence. + +:::info Coming Soon + +Per-region global load balancer configuration is coming soon, [request access +to the developer preview](https://dashboard.ngrok.com/developer-preview). + +::: + +## TLS Certificates + +Domains manage the [TLS Certificate](/universal-gateway/tls-certificates/) used +to terminate TLS connections to the Domain's matching endpoints. When you +create a Domain, you may choose to allow ngrok to automatically provision TLS +certificates for you or to upload your own TLS certificate. + +Consult the documentation on [TLS +Certificates](/universal-gateway/tls-certificates/) for additional details on +certificate provisioning and management. + +## Dedicated IPs + +By default, a Domain's matching Endpoints receive traffic on a set of +multi-tenant [IP addresses](/universal-gateway/ip-addresses) that are +shared among all ngrok accounts. You may instead configure a Domain's matching +endpoints to receive traffic on IP addresses that are dedicated to your +account. + +If your Domain uses dedicated IPs, you may create public endpoints on _any_ +port numbers, not just 80 and 443. + +:::info Coming Soon + +Dedicated, static IPs for your domains are coming soon, [request access to the +developer preview](https://dashboard.ngrok.com/developer-preview). + +::: + +## ngrok Managed Domains + +If you don't own a domain that you want to use with ngrok, you can create a +Domain that is a subdomain of an ngrok-managed base domain. The ngrok-managed +base domains are: + +| Domain | Availability | HSTS Global Preload | +| ------------------ | ------------------------------------------------- | ------------------- | +| `ngrok.app` | Available to paying accounts | Yes | +| `ngrok.dev` | Available to paying accounts | Yes | +| `ngrok.pizza` | Available to paying accounts | No | +| `ngrok-free.app` | Used by free accounts | Yes | +| `ngrok-free.dev` | Used by free accounts | Yes | +| `ngrok-free.pizza` | Used by free accounts (coming soon) | No | +| `ngrok.io` | Discontinued and only available to older accounts | No | + +### Public Suffix List + +The ngrok-managed base domains are on the [Public Suffix +List](https://publicsuffix.org/). Browsers use the Public Suffix List to +guarantee that cookies from one subdomain cannot be accessed by other +subdomains. + +### HSTS Preload + +Some of the ngrok-managed base domains are on the global +[HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) preload +list. If the domain of the URL is on the [global HSTS preload +list](https://hstspreload.org/), modern browsers automatically convert requests +with an `http` scheme to `https`. + +If you need to create unencrypted `http` endpoints, you should create them with +hostnames that are not on the HSTS Global Preload like `ngrok.io` and +`ngrok.pizza`. + +ngrok does not prohibit you from creating `http` endpoints with hostnames whose +base domain is on the global HSTS preload list because non-browser clients +(like `curl`) can still be used to make unencrypted HTTP requests to them. + +## API + +Domains are programatically managed via: + +- [`/reserved_domains` API Resource](/api/resources/reserved-domains/) + +## Pricing + +Domains are available on all plans. Some Domain features require upgrades. See +the [Pricing page](https://ngrok.com/pricing) for details. + +| Feature | Plans | +| ---------------------- | --------------------------------------------------------------------------------- | +| Domains | All plans. The Domain name is assigned on Free, you may choose it on other plans. | +| Bring-your-own domains | Personal, Pro, Enterprise, Pay-as-you-go | +| Wildcard Domains | Enterprise | From 948048e04c9d8d1cd5b0cca233c06a8034165b24 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 13 Mar 2025 10:44:36 -0400 Subject: [PATCH 002/137] nav structure --- .../domains/how-do-i-use-my-own-domain.mdx | 27 ++++ .../domains/what-are-domains.mdx | 117 ------------------ .../domains/what-are-public-endpoints.mdx | 53 ++++++++ .../domains/what-are-the-managed-domains.mdx | 40 ++++++ 4 files changed, 120 insertions(+), 117 deletions(-) create mode 100644 docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx create mode 100644 docs/universal-gateway/domains/what-are-public-endpoints.mdx create mode 100644 docs/universal-gateway/domains/what-are-the-managed-domains.mdx diff --git a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx new file mode 100644 index 0000000000..c018affa21 --- /dev/null +++ b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx @@ -0,0 +1,27 @@ +--- +title: How do I Use My Own Domain? +--- + +You can use any domain name that you already own with ngrok, e.g. +`app.your-domain.com`. To do so, you will create a CNAME record for that domain +to point traffic from the domain to ngrok's cloud service. When you create a +Domain, you will be presented with a target value for the CNAME record you need +to create. If you [create the Domain via +API](/api/resources/reserved-domains/), this value is the `cname_target` field. + +If you bring your own [wildcard domain](#wildcard-domains), you will need to +create a second DNS CNAME record for [wildcard TLS Certificate +provisioning](/universal-gateway/tls-certificates/#wildcard-domains). + +ngrok is not a domain registrar; you must already own a domain name to use it +with ngrok. + +### Apex domains + +If you want to use an apex domain (e.g. `example.com`) with ngrok, you must use +a DNS provider that supports an ALIAS record or CNAME flattening because the +DNS RFC does not permit CNAME records for apex domains. Because of how +ALIAS/CNAME flattening is implemented, apex domains will not take advantage of +the [Global Load Balancer](#global-load-balancer). If you are trying to create +your apex domain because you need to create endpoints for multiple subdomains, +use a [wildcard domain](#wildcard-domains) instead. diff --git a/docs/universal-gateway/domains/what-are-domains.mdx b/docs/universal-gateway/domains/what-are-domains.mdx index 39312323b3..ce8d733120 100644 --- a/docs/universal-gateway/domains/what-are-domains.mdx +++ b/docs/universal-gateway/domains/what-are-domains.mdx @@ -17,84 +17,6 @@ Domains also enable you to configure other domain-level behaviors including: You can manage Domains on your [ngrok Dashboard](https://dashboard.ngrok.com/domains) or via the [ngrok API](#api). -## Public endpoints - -A Domain's primary responsibility is to enable you to create [public -endpoints](/universal-gateway/public-endpoints/) with a hostname matching the -domain. These are called "matching endpoints". For example, after you create -the Domain `app.example.com`, you can create the Endpoint -`https://app.example.com`. - -When you create a Domain, you may create matching public endpoints with the -following constraints: - -| Endpoint Protocol | Allowed Endpoints | -| ----------------- | ------------------------------------------------------------------------------------------------ | -| `http` | Matching endpoints on port `80` of the Domain. | -| `https` | Matching endpoints on port `443` of the Domain. | -| `tls` | Matching endpoints on port `443` of the Domain. | -| `tcp` | Not allowed. Public TCP endpoints must match a [TCP Address](/universal-gateway/tcp-addresses/). | - -If you configure your Domain to use [dedicated IPs](#dedicated-ips), these -restrictions are removed and you may create matching endpoints on any ports. - -### Wildcard Domains - -You may create a Domain with a wildcard name, e.g. `*.example.com`. A wildcard -domain enables you to: - -- Create an endpoint which receives traffic for all of its subdomains, e.g. - `https://*.example.com`. Consult the documentation for [wildcard - endpoints](/universal-gateway/http/#wildcard-endpoints) to understand - the rules for matching and precedence. - -- Create an endpoint on any subdomain which matches the wildcard, e.g. - `https://foo.example.com` or `https://foo.bar.baz.example.com` - -The wildcard `*` character may only be used as the first part of a -domain, you may not create domains like `app.*.example.com` or -`*-app.example.com`. - -### Ownership - -Your account exclusively owns its Domains and all of their nested subdomains -within ngrok. That means: - -- No account may create a Domain with a name that is a subdomain of your Domains. -- No other account may create endpoints with a hostname matching your Domain or - any of its nested subdomains. - -For example, if you create a Domain with the name `foo.ngrok.app`: - -- No other account create the Domains `foo.ngrok.app` or `bar.foo.ngrok.app`. -- No other account may create the endpoints `https://foo.ngrok.app` or `https://bar.foo.ngrok.app`. - -## Bring your own domain {#branded-domains} - -You can use any domain name that you already own with ngrok, e.g. -`app.your-domain.com`. To do so, you will create a CNAME record for that domain -to point traffic from the domain to ngrok's cloud service. When you create a -Domain, you will be presented with a target value for the CNAME record you need -to create. If you [create the Domain via -API](/api/resources/reserved-domains/), this value is the `cname_target` field. - -If you bring your own [wildcard domain](#wildcard-domains), you will need to -create a second DNS CNAME record for [wildcard TLS Certificate -provisioning](/universal-gateway/tls-certificates/#wildcard-domains). - -ngrok is not a domain registrar; you must already own a domain name to use it -with ngrok. - -### Apex domains - -If you want to use an apex domain (e.g. `example.com`) with ngrok, you must use -a DNS provider that supports an ALIAS record or CNAME flattening because the -DNS RFC does not permit CNAME records for apex domains. Because of how -ALIAS/CNAME flattening is implemented, apex domains will not take advantage of -the [Global Load Balancer](#global-load-balancer). If you are trying to create -your apex domain because you need to create endpoints for multiple subdomains, -use a [wildcard domain](#wildcard-domains) instead. - ## Global Load Balancer The [Global Load Balancer](/universal-gateway/global-load-balancer) @@ -143,45 +65,6 @@ developer preview](https://dashboard.ngrok.com/developer-preview). ::: -## ngrok Managed Domains - -If you don't own a domain that you want to use with ngrok, you can create a -Domain that is a subdomain of an ngrok-managed base domain. The ngrok-managed -base domains are: - -| Domain | Availability | HSTS Global Preload | -| ------------------ | ------------------------------------------------- | ------------------- | -| `ngrok.app` | Available to paying accounts | Yes | -| `ngrok.dev` | Available to paying accounts | Yes | -| `ngrok.pizza` | Available to paying accounts | No | -| `ngrok-free.app` | Used by free accounts | Yes | -| `ngrok-free.dev` | Used by free accounts | Yes | -| `ngrok-free.pizza` | Used by free accounts (coming soon) | No | -| `ngrok.io` | Discontinued and only available to older accounts | No | - -### Public Suffix List - -The ngrok-managed base domains are on the [Public Suffix -List](https://publicsuffix.org/). Browsers use the Public Suffix List to -guarantee that cookies from one subdomain cannot be accessed by other -subdomains. - -### HSTS Preload - -Some of the ngrok-managed base domains are on the global -[HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) preload -list. If the domain of the URL is on the [global HSTS preload -list](https://hstspreload.org/), modern browsers automatically convert requests -with an `http` scheme to `https`. - -If you need to create unencrypted `http` endpoints, you should create them with -hostnames that are not on the HSTS Global Preload like `ngrok.io` and -`ngrok.pizza`. - -ngrok does not prohibit you from creating `http` endpoints with hostnames whose -base domain is on the global HSTS preload list because non-browser clients -(like `curl`) can still be used to make unencrypted HTTP requests to them. - ## API Domains are programatically managed via: diff --git a/docs/universal-gateway/domains/what-are-public-endpoints.mdx b/docs/universal-gateway/domains/what-are-public-endpoints.mdx new file mode 100644 index 0000000000..a99ca97c11 --- /dev/null +++ b/docs/universal-gateway/domains/what-are-public-endpoints.mdx @@ -0,0 +1,53 @@ +--- +title: What are Public Endpoints? +--- + +A Domain's primary responsibility is to enable you to create [public +endpoints](/universal-gateway/public-endpoints/) with a hostname matching the +domain. These are called "matching endpoints". For example, after you create +the Domain `app.example.com`, you can create the Endpoint +`https://app.example.com`. + +When you create a Domain, you may create matching public endpoints with the +following constraints: + +| Endpoint Protocol | Allowed Endpoints | +| ----------------- | ------------------------------------------------------------------------------------------------ | +| `http` | Matching endpoints on port `80` of the Domain. | +| `https` | Matching endpoints on port `443` of the Domain. | +| `tls` | Matching endpoints on port `443` of the Domain. | +| `tcp` | Not allowed. Public TCP endpoints must match a [TCP Address](/universal-gateway/tcp-addresses/). | + +If you configure your Domain to use [dedicated IPs](#dedicated-ips), these +restrictions are removed and you may create matching endpoints on any ports. + +### Wildcard Domains + +You may create a Domain with a wildcard name, e.g. `*.example.com`. A wildcard +domain enables you to: + +- Create an endpoint which receives traffic for all of its subdomains, e.g. + `https://*.example.com`. Consult the documentation for [wildcard + endpoints](/universal-gateway/http/#wildcard-endpoints) to understand + the rules for matching and precedence. + +- Create an endpoint on any subdomain which matches the wildcard, e.g. + `https://foo.example.com` or `https://foo.bar.baz.example.com` + +The wildcard `*` character may only be used as the first part of a +domain, you may not create domains like `app.*.example.com` or +`*-app.example.com`. + +### Ownership + +Your account exclusively owns its Domains and all of their nested subdomains +within ngrok. That means: + +- No account may create a Domain with a name that is a subdomain of your Domains. +- No other account may create endpoints with a hostname matching your Domain or + any of its nested subdomains. + +For example, if you create a Domain with the name `foo.ngrok.app`: + +- No other account create the Domains `foo.ngrok.app` or `bar.foo.ngrok.app`. +- No other account may create the endpoints `https://foo.ngrok.app` or `https://bar.foo.ngrok.app`. diff --git a/docs/universal-gateway/domains/what-are-the-managed-domains.mdx b/docs/universal-gateway/domains/what-are-the-managed-domains.mdx new file mode 100644 index 0000000000..6b9583813a --- /dev/null +++ b/docs/universal-gateway/domains/what-are-the-managed-domains.mdx @@ -0,0 +1,40 @@ +--- +title: What are the Managed Domains? +--- + +If you don't own a domain that you want to use with ngrok, you can create a +Domain that is a subdomain of an ngrok-managed base domain. The ngrok-managed +base domains are: + +| Domain | Availability | HSTS Global Preload | +| ------------------ | ------------------------------------------------- | ------------------- | +| `ngrok.app` | Available to paying accounts | Yes | +| `ngrok.dev` | Available to paying accounts | Yes | +| `ngrok.pizza` | Available to paying accounts | No | +| `ngrok-free.app` | Used by free accounts | Yes | +| `ngrok-free.dev` | Used by free accounts | Yes | +| `ngrok-free.pizza` | Used by free accounts (coming soon) | No | +| `ngrok.io` | Discontinued and only available to older accounts | No | + +### Public Suffix List + +The ngrok-managed base domains are on the [Public Suffix +List](https://publicsuffix.org/). Browsers use the Public Suffix List to +guarantee that cookies from one subdomain cannot be accessed by other +subdomains. + +### HSTS Preload + +Some of the ngrok-managed base domains are on the global +[HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) preload +list. If the domain of the URL is on the [global HSTS preload +list](https://hstspreload.org/), modern browsers automatically convert requests +with an `http` scheme to `https`. + +If you need to create unencrypted `http` endpoints, you should create them with +hostnames that are not on the HSTS Global Preload like `ngrok.io` and +`ngrok.pizza`. + +ngrok does not prohibit you from creating `http` endpoints with hostnames whose +base domain is on the global HSTS preload list because non-browser clients +(like `curl`) can still be used to make unencrypted HTTP requests to them. From c705a26fd265795365db7c0dd28d5dc24f6d5cc0 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 13 Mar 2025 12:29:25 -0400 Subject: [PATCH 003/137] finished top-level page --- docs/pricing-limits/index.mdx | 12 ++- .../domains/how-do-i-use-my-own-domain.mdx | 2 +- .../domains/what-are-domains.mdx | 73 ++++--------------- .../domains/what-are-public-endpoints.mdx | 4 +- .../domains/what-are-the-managed-domains.mdx | 4 +- .../global-load-balancer.mdx | 8 ++ docs/universal-gateway/ip-addresses.mdx | 19 +++-- docs/universal-gateway/tls-certificates.mdx | 5 +- 8 files changed, 53 insertions(+), 74 deletions(-) diff --git a/docs/pricing-limits/index.mdx b/docs/pricing-limits/index.mdx index 97e7f969be..c591bc5cf6 100644 --- a/docs/pricing-limits/index.mdx +++ b/docs/pricing-limits/index.mdx @@ -14,7 +14,7 @@ For information on free plans, see [Free Plan Limts](/pricing-limits/free-plan-l | Feature | Free Users | Development Plans (Personal, Pro, Enterprise) | Production Pay-as-You-Go Plans | | --------------------------------------------- | ------------------- | --------------------------------------------- | ---------------------------------------------------------------- | -| **Domains** | 1 static domain | 1 per license | No limit, priced on-demand | +| **[Domains](#domain-configuration-pricing)** | 1 static domain | 1 per license | No limit, priced on-demand | | **Endpoints** | 3 | 3 per license | No limit, priced on-demand | | **Cloud Endpoints** | 3 | NA | No limit, priced on-demand | | **TCP Addresses** | 1 with verification | 1 per license | Priced on-demand, platform limit of 100. Contact us to increase. | @@ -42,6 +42,16 @@ For information on free plans, see [Free Plan Limts](/pricing-limits/free-plan-l You can check your usage [in the Usage page in the dashboard](https://dashboard.ngrok.com/usage). ::: +## Domain configuration pricing + +Domains are available on all plans. Some Domain features require upgrades. See the [Pricing page](https://ngrok.com/pricing) for details. + +| Feature | Plans | +| ---------------------- | --------------------------------------------------------------------------------- | +| Domains | All plans. The Domain name is assigned on Free, you may choose it on other plans. | +| Bring-your-own domains | Personal, Pro, Enterprise, Pay-as-you-go | +| Wildcard Domains | Enterprise | + ## General limits Each license at ngrok roughly represents a developer using an ngrok agent for building an application. It includes the ability to run an ngrok agent (or use the agent SDKs or ngrok Kubernetes Operator) with a custom domain or TCP Address. diff --git a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx index c018affa21..42db69d9e4 100644 --- a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx +++ b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx @@ -16,7 +16,7 @@ provisioning](/universal-gateway/tls-certificates/#wildcard-domains). ngrok is not a domain registrar; you must already own a domain name to use it with ngrok. -### Apex domains +## Apex domains If you want to use an apex domain (e.g. `example.com`) with ngrok, you must use a DNS provider that supports an ALIAS record or CNAME flattening because the diff --git a/docs/universal-gateway/domains/what-are-domains.mdx b/docs/universal-gateway/domains/what-are-domains.mdx index ce8d733120..9a249f6753 100644 --- a/docs/universal-gateway/domains/what-are-domains.mdx +++ b/docs/universal-gateway/domains/what-are-domains.mdx @@ -2,68 +2,26 @@ title: What are Domains? --- -Domains enable you to create public endpoints with hostnames matching the -domain. For example, after you create the domain `your-name.ngrok.app`, you may create the Endpoint `https://your-name.ngrok.app` +Domains enable you to create [public endpoints](/universal-gateway/domains/what-are-public-endpoints/) with hostnames matching the domain. For example, after you create the domain `your-name.ngrok.app`, you may create the Endpoint `https://your-name.ngrok.app`. -Domain names may be a subdomain of an [ngrok-managed -domain](#ngrok-managed-domains) like `foo.ngrok.app` or you can [bring your own domain](#branded-domains) like `example.your-domain.com` by creating a CNAME DNS record with your domain's DNS provider. +Valid Domain names include: -Domains also enable you to configure other domain-level behaviors including: +- [ngrok-managed domains](/docs/universal-gateway/domains/what-are-the-managed-domains), like `foo.ngrok.app`. +- Your own [custom domains](/docs/universal-gateway/domains/how-do-i-use-my-own-domain/), like `example.your-domain.com`, by creating a `CNAME` DNS record with your domain's DNS provider. -- [**Global Load Balancer configuration**](#global-load-balancer) - Choose which points of presence handle traffic to a Domain's matching endpoints. -- [**TLS Certificate management**](#tls-certificates) - Configure automatic certificate provisioning or select a certificate you uploaded yourself. -- [**Dedicated IP address configuration**](#dedicated-ips) - Attach static, dedicated IPs for a Domain's matching endpoints receive traffic on. +## Configuration -You can manage Domains on your [ngrok Dashboard](https://dashboard.ngrok.com/domains) -or via the [ngrok API](#api). +Domains also enable you to configure other domain-level behaviors, including: -## Global Load Balancer +- [**Global Load Balancer configuration**](/universal-gateway/global-load-balancer/#domains) - Choose which points of presence handle traffic to a Domain's matching endpoints. + :::info Coming Soon + Per-region global load balancer configuration is coming soon, [request access + to the developer preview](https://dashboard.ngrok.com/developer-preview). + ::: +- [**TLS Certificate management**](/universal-gateway/tls-certificates/) - Configure automatic certificate provisioning or select a certificate you uploaded yourself. +- [**Dedicated IP address configuration**](/universal-gateway/ip-addresses#dedicated-ips) - Attach static, dedicated IPs for a Domain's matching endpoints receive traffic on. -The [Global Load Balancer](/universal-gateway/global-load-balancer) -uses latency-aware DNS records to direct clients to the IPs of the nearest -[points of presence](/universal-gateway/points-of-presence/). - -Domains allow you to configure which points of presence the Global Load -Balancer may resolve clients to. This allows you to select which points of -presence will receive traffic for the Domain's matching endpoints. To disable -the Global Load Balancer, you may configure a domain to only resolve a single -point of presence. - -:::info Coming Soon - -Per-region global load balancer configuration is coming soon, [request access -to the developer preview](https://dashboard.ngrok.com/developer-preview). - -::: - -## TLS Certificates - -Domains manage the [TLS Certificate](/universal-gateway/tls-certificates/) used -to terminate TLS connections to the Domain's matching endpoints. When you -create a Domain, you may choose to allow ngrok to automatically provision TLS -certificates for you or to upload your own TLS certificate. - -Consult the documentation on [TLS -Certificates](/universal-gateway/tls-certificates/) for additional details on -certificate provisioning and management. - -## Dedicated IPs - -By default, a Domain's matching Endpoints receive traffic on a set of -multi-tenant [IP addresses](/universal-gateway/ip-addresses) that are -shared among all ngrok accounts. You may instead configure a Domain's matching -endpoints to receive traffic on IP addresses that are dedicated to your -account. - -If your Domain uses dedicated IPs, you may create public endpoints on _any_ -port numbers, not just 80 and 443. - -:::info Coming Soon - -Dedicated, static IPs for your domains are coming soon, [request access to the -developer preview](https://dashboard.ngrok.com/developer-preview). - -::: +You can manage Domains on your [ngrok Dashboard](https://dashboard.ngrok.com/domains) or via the [ngrok API](#api). ## API @@ -73,8 +31,7 @@ Domains are programatically managed via: ## Pricing -Domains are available on all plans. Some Domain features require upgrades. See -the [Pricing page](https://ngrok.com/pricing) for details. +Domains are available on all plans. Some Domain features require upgrades. See the [Pricing page](https://ngrok.com/pricing) for details. | Feature | Plans | | ---------------------- | --------------------------------------------------------------------------------- | diff --git a/docs/universal-gateway/domains/what-are-public-endpoints.mdx b/docs/universal-gateway/domains/what-are-public-endpoints.mdx index a99ca97c11..1c8b6d5933 100644 --- a/docs/universal-gateway/domains/what-are-public-endpoints.mdx +++ b/docs/universal-gateway/domains/what-are-public-endpoints.mdx @@ -21,7 +21,7 @@ following constraints: If you configure your Domain to use [dedicated IPs](#dedicated-ips), these restrictions are removed and you may create matching endpoints on any ports. -### Wildcard Domains +## Wildcard Domains You may create a Domain with a wildcard name, e.g. `*.example.com`. A wildcard domain enables you to: @@ -38,7 +38,7 @@ The wildcard `*` character may only be used as the first part of a domain, you may not create domains like `app.*.example.com` or `*-app.example.com`. -### Ownership +## Ownership Your account exclusively owns its Domains and all of their nested subdomains within ngrok. That means: diff --git a/docs/universal-gateway/domains/what-are-the-managed-domains.mdx b/docs/universal-gateway/domains/what-are-the-managed-domains.mdx index 6b9583813a..3b48a48ac3 100644 --- a/docs/universal-gateway/domains/what-are-the-managed-domains.mdx +++ b/docs/universal-gateway/domains/what-are-the-managed-domains.mdx @@ -16,14 +16,14 @@ base domains are: | `ngrok-free.pizza` | Used by free accounts (coming soon) | No | | `ngrok.io` | Discontinued and only available to older accounts | No | -### Public Suffix List +## Public Suffix List The ngrok-managed base domains are on the [Public Suffix List](https://publicsuffix.org/). Browsers use the Public Suffix List to guarantee that cookies from one subdomain cannot be accessed by other subdomains. -### HSTS Preload +## HSTS Preload Some of the ngrok-managed base domains are on the global [HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) preload diff --git a/docs/universal-gateway/global-load-balancer.mdx b/docs/universal-gateway/global-load-balancer.mdx index 6779a5c469..8d6072f40b 100644 --- a/docs/universal-gateway/global-load-balancer.mdx +++ b/docs/universal-gateway/global-load-balancer.mdx @@ -140,6 +140,14 @@ you must select the point of presence where it will accept traffic. Unlike ngrok's globally routed domains, traffic to TCP addresses always enters ngrok's network from that point of presence. +## Domains + +[Domains](/universal-gateway/domains/what-are-domains) allow you to configure which points of presence the Global Load +Balancer may resolve clients to. This allows you to select which points of +presence will receive traffic for the Domain's matching endpoints. To disable +the Global Load Balancer, you may configure a domain to only resolve a single +point of presence. + ## Agents ngrok's GSLB automatically improves the performance and resiliency of your diff --git a/docs/universal-gateway/ip-addresses.mdx b/docs/universal-gateway/ip-addresses.mdx index 87ccc460ca..7a8d5d25f9 100644 --- a/docs/universal-gateway/ip-addresses.mdx +++ b/docs/universal-gateway/ip-addresses.mdx @@ -17,15 +17,22 @@ Global Load Balancing. ## Dedicated IPs If you need a static IP for your public endpoints, you may attach static, -[dedicated IPs for Domains](/universal-gateway/domains/#dedicated-ips). You may -also set up dedicated IPs for [Agent Connect -URLs](/agent/ingress/#dedicated-ips). +dedicated IPs for: -:::info Coming Soon +- [Domains](#domains) +- [Agent Connect URLs](/agent/ingress/#dedicated-ips). -Dedicated, static IPs for public endpoints coming soon, [request access to the -developer preview](https://dashboard.ngrok.com/developer-preview). +### Domains + +By default, a [Domain's](/universal-gateway/domains/) matching Endpoints receive traffic on a set of +multi-tenant IP addresses that are shared among all ngrok accounts. You may instead configure a Domain's matching endpoints to receive traffic on IP addresses that are dedicated to your account. +If your Domain uses dedicated IPs, you may create public endpoints on _any_ +port numbers, not just `80` and `443`. + +:::info Coming Soon +Dedicated, static IPs for your domains are coming soon, [request access to the +developer preview](https://dashboard.ngrok.com/developer-preview). ::: ## IPv6 diff --git a/docs/universal-gateway/tls-certificates.mdx b/docs/universal-gateway/tls-certificates.mdx index b6d8dafcec..360d38dae2 100644 --- a/docs/universal-gateway/tls-certificates.mdx +++ b/docs/universal-gateway/tls-certificates.mdx @@ -25,10 +25,7 @@ When TLS connections to an endpoint are terminated, ngrok uses the TLS Certificate attached to the [domain](/universal-gateway/domains) matching the endpoint's URL for termination. -Each [domain](/universal-gateway/domains/) has an attached TLS certificate that -is referenced by its [`certificate_id` field](/api/resources/reserved-domains). -If the domain object does reference any certificate, or if there is no matching -domain object for an endpoint's URL, ngrok selects its own TLS certificate for +Each [domain](/universal-gateway/domains/) has an attached TLS certificate that is referenced by its [`certificate_id` field](/api/resources/reserved-domains). If the domain object does reference any certificate, or if there is no matching domain object for an endpoint's URL, ngrok selects its own TLS certificate for termination. You may override the certificate used for TLS termination by explicitly From f7a2d4160d22c649b1a8bfaf4c88e6646539a2a5 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 13 Mar 2025 12:59:14 -0400 Subject: [PATCH 004/137] Added items to sidebar --- sidebars.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sidebars.js b/sidebars.js index 1bf3aeeb4c..adfbfd1ed4 100644 --- a/sidebars.js +++ b/sidebars.js @@ -44,6 +44,19 @@ const sidebars = { link: { type: "doc", id: "universal-gateway/overview" }, items: [ "universal-gateway/overview", + { + label: "What are Domains?", + type: "category", + link: { + type: "doc", + id: "universal-gateway/domains/what-are-domains", + }, + items: [ + "universal-gateway/domains/what-are-public-endpoints", + "universal-gateway/domains/how-do-i-use-my-own-domain", + "universal-gateway/domains/what-are-the-managed-domains", + ], + }, { label: "Concepts", type: "category", From dd7b3aa6d1b2aa1e93ddedacfbd9b422fbad8f75 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 13 Mar 2025 13:19:22 -0400 Subject: [PATCH 005/137] checkpoint --- .../domains/how-do-i-use-my-own-domain.mdx | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx index 42db69d9e4..9e6c675d46 100644 --- a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx +++ b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx @@ -3,11 +3,18 @@ title: How do I Use My Own Domain? --- You can use any domain name that you already own with ngrok, e.g. -`app.your-domain.com`. To do so, you will create a CNAME record for that domain -to point traffic from the domain to ngrok's cloud service. When you create a -Domain, you will be presented with a target value for the CNAME record you need -to create. If you [create the Domain via -API](/api/resources/reserved-domains/), this value is the `cname_target` field. +`app.your-domain.com`. To do so: + +1. Create a Domain in the ngrok dashboard. [You can do so by going here](https://dashboard.ngrok.com/domains). +1. When you create a Domain, you'll be given a `CNAME` value such as `exampledata.otherdata.ngrok-cname.com`. Copy it. +1. In a new tab, navigate to your domain hosting provider's dashboard and create a CNAME record. Check your hosting provider's support content or documentation to learn how. + - Typically, this process includes creating a [DNS record](https://en.wikipedia.org/wiki/List_of_DNS_record_types). +1. When configuring the record, use the following values: + - Its **type** should be `CNAME` + - Its **name** should be `@` + - Its **value** should be the `CNAME` value you copied from the ngrok dashboard. +1. Add the `CNAME` value you copied from to point traffic from the domain to ngrok's cloud service. When you create a Domain, you will be presented with a target value for the CNAME record you need to create. If you [create the Domain via + API](/api/resources/reserved-domains/), this value is the `cname_target` field. If you bring your own [wildcard domain](#wildcard-domains), you will need to create a second DNS CNAME record for [wildcard TLS Certificate From ed09d8ef2b307984e2c70a2fd41bc5e40a73c0cb Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 13 Mar 2025 14:20:52 -0400 Subject: [PATCH 006/137] Finish public endpoints guide --- .../domains/how-do-i-use-my-own-domain.mdx | 26 +++++++++---------- .../domains/what-are-public-endpoints.mdx | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx index 9e6c675d46..c969d8b05b 100644 --- a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx +++ b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx @@ -6,8 +6,10 @@ You can use any domain name that you already own with ngrok, e.g. `app.your-domain.com`. To do so: 1. Create a Domain in the ngrok dashboard. [You can do so by going here](https://dashboard.ngrok.com/domains). -1. When you create a Domain, you'll be given a `CNAME` value such as `exampledata.otherdata.ngrok-cname.com`. Copy it. -1. In a new tab, navigate to your domain hosting provider's dashboard and create a CNAME record. Check your hosting provider's support content or documentation to learn how. + - You can also create a Domain via the [ngrok API](/api/resources/reserved-domains/#request). +1. When you create a Domain in the dashboard, you'll be given a `CNAME` value such as `exampledata.otherdata.ngrok-cname.com`. Copy it. + - This value will be in the `"cname_target"` field of [the response object](/api/resources/reserved-domains/#response) if you create a Domain via the API. +1. In a new browser tab, navigate to your domain hosting provider's dashboard and create a CNAME record. Check your hosting provider's support content or documentation to learn how. - Typically, this process includes creating a [DNS record](https://en.wikipedia.org/wiki/List_of_DNS_record_types). 1. When configuring the record, use the following values: - Its **type** should be `CNAME` @@ -16,19 +18,17 @@ You can use any domain name that you already own with ngrok, e.g. 1. Add the `CNAME` value you copied from to point traffic from the domain to ngrok's cloud service. When you create a Domain, you will be presented with a target value for the CNAME record you need to create. If you [create the Domain via API](/api/resources/reserved-domains/), this value is the `cname_target` field. -If you bring your own [wildcard domain](#wildcard-domains), you will need to -create a second DNS CNAME record for [wildcard TLS Certificate -provisioning](/universal-gateway/tls-certificates/#wildcard-domains). - +:::note ngrok is not a domain registrar; you must already own a domain name to use it with ngrok. +::: + +## Wildcard domains + +If you bring your own [wildcard domain](/universal-gateway/what-are-public-endpoints#wildcard-domains), e.g. `*.example.com`, you will need to create a second `CNAME` record with your domain host for [wildcard TLS Certificate provisioning](/universal-gateway/tls-certificates/#wildcard-domains). ## Apex domains -If you want to use an apex domain (e.g. `example.com`) with ngrok, you must use -a DNS provider that supports an ALIAS record or CNAME flattening because the -DNS RFC does not permit CNAME records for apex domains. Because of how -ALIAS/CNAME flattening is implemented, apex domains will not take advantage of -the [Global Load Balancer](#global-load-balancer). If you are trying to create -your apex domain because you need to create endpoints for multiple subdomains, -use a [wildcard domain](#wildcard-domains) instead. +Because it's not possible to create `CNAME` records for apex domains, if you want to use an apex domain, e.g. `example.com`, you must use a DNS provider that supports an `ALIAS` record or `CNAME` flattening. + +Because of how `ALIAS`/`CNAME` flattening is implemented, apex domains will not take advantage of the [Global Load Balancer](/universal-gateway/global-load-balancer/#domains). If you're trying to create your apex domain because you need to create endpoints for multiple subdomains, use a [wildcard domain](/universal-gateway/what-are-public-endpoints#wildcard-domains) instead. diff --git a/docs/universal-gateway/domains/what-are-public-endpoints.mdx b/docs/universal-gateway/domains/what-are-public-endpoints.mdx index 1c8b6d5933..d98d7a5dcb 100644 --- a/docs/universal-gateway/domains/what-are-public-endpoints.mdx +++ b/docs/universal-gateway/domains/what-are-public-endpoints.mdx @@ -21,7 +21,7 @@ following constraints: If you configure your Domain to use [dedicated IPs](#dedicated-ips), these restrictions are removed and you may create matching endpoints on any ports. -## Wildcard Domains +## Wildcard domains You may create a Domain with a wildcard name, e.g. `*.example.com`. A wildcard domain enables you to: From 9e23f0e7ff122021683cfbd926c5fb162168e1b5 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 13 Mar 2025 14:33:48 -0400 Subject: [PATCH 007/137] managed domains done --- .../domains/what-are-domains.mdx | 2 +- .../domains/what-are-managed-domains.mdx | 30 ++++++++++++++ .../domains/what-are-the-managed-domains.mdx | 40 ------------------- sidebars.js | 2 +- 4 files changed, 32 insertions(+), 42 deletions(-) create mode 100644 docs/universal-gateway/domains/what-are-managed-domains.mdx delete mode 100644 docs/universal-gateway/domains/what-are-the-managed-domains.mdx diff --git a/docs/universal-gateway/domains/what-are-domains.mdx b/docs/universal-gateway/domains/what-are-domains.mdx index 9a249f6753..58a3011435 100644 --- a/docs/universal-gateway/domains/what-are-domains.mdx +++ b/docs/universal-gateway/domains/what-are-domains.mdx @@ -6,7 +6,7 @@ Domains enable you to create [public endpoints](/universal-gateway/domains/what- Valid Domain names include: -- [ngrok-managed domains](/docs/universal-gateway/domains/what-are-the-managed-domains), like `foo.ngrok.app`. +- [ngrok-managed domains](/docs/universal-gateway/domains/what-are-managed-domains), like `foo.ngrok.app`. - Your own [custom domains](/docs/universal-gateway/domains/how-do-i-use-my-own-domain/), like `example.your-domain.com`, by creating a `CNAME` DNS record with your domain's DNS provider. ## Configuration diff --git a/docs/universal-gateway/domains/what-are-managed-domains.mdx b/docs/universal-gateway/domains/what-are-managed-domains.mdx new file mode 100644 index 0000000000..c60de2217c --- /dev/null +++ b/docs/universal-gateway/domains/what-are-managed-domains.mdx @@ -0,0 +1,30 @@ +--- +title: What are Managed Domains? +--- + +If you don't [already own a Domain](/universal-gateway/how-do-i-use-my-own-domain) that you want to use with ngrok, you can create a domain that is a subdomain of an ngrok-managed base domain. + +| Domain | Availability | HSTS Global Preload | +| ------------------ | ------------------------------------------------- | ------------------- | +| `ngrok.app` | [Paid accounts](https://ngrok.com/pricing) | Yes | +| `ngrok.dev` | [Paid accounts](https://ngrok.com/pricing) | Yes | +| `ngrok.pizza` | [Paid accounts](https://ngrok.com/pricing) | No | +| `ngrok-free.app` | Free accounts | Yes | +| `ngrok-free.dev` | Free accounts | Yes | +| `ngrok-free.pizza` | Free accounts (coming soon) | No | +| `ngrok.io` | Discontinued and only available to older accounts | No | + +## Public Suffix List + +The ngrok-managed base domains are on the [Public Suffix List](https://publicsuffix.org/). Browsers use the Public Suffix List to guarantee that cookies from one subdomain cannot be accessed by other subdomains. + +## HSTS preload + +Some of the ngrok-managed base domains are on the [global HSTS preload list](https://hstspreload.org/), which means modern browsers automatically convert requests to these domains using an `http` scheme to `https`. + +If you need to create unencrypted `http` endpoints, you should create them with hostnames that are not on the HSTS Global Preload like `ngrok.io` and +`ngrok.pizza`. + +:::tip +ngrok does not prohibit you from creating `http` endpoints with hostnames whose base domain is on the global HSTS preload list. Non-browser clients (like `curl`) can still be used to make unencrypted HTTP requests to them. +::: diff --git a/docs/universal-gateway/domains/what-are-the-managed-domains.mdx b/docs/universal-gateway/domains/what-are-the-managed-domains.mdx deleted file mode 100644 index 3b48a48ac3..0000000000 --- a/docs/universal-gateway/domains/what-are-the-managed-domains.mdx +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: What are the Managed Domains? ---- - -If you don't own a domain that you want to use with ngrok, you can create a -Domain that is a subdomain of an ngrok-managed base domain. The ngrok-managed -base domains are: - -| Domain | Availability | HSTS Global Preload | -| ------------------ | ------------------------------------------------- | ------------------- | -| `ngrok.app` | Available to paying accounts | Yes | -| `ngrok.dev` | Available to paying accounts | Yes | -| `ngrok.pizza` | Available to paying accounts | No | -| `ngrok-free.app` | Used by free accounts | Yes | -| `ngrok-free.dev` | Used by free accounts | Yes | -| `ngrok-free.pizza` | Used by free accounts (coming soon) | No | -| `ngrok.io` | Discontinued and only available to older accounts | No | - -## Public Suffix List - -The ngrok-managed base domains are on the [Public Suffix -List](https://publicsuffix.org/). Browsers use the Public Suffix List to -guarantee that cookies from one subdomain cannot be accessed by other -subdomains. - -## HSTS Preload - -Some of the ngrok-managed base domains are on the global -[HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) preload -list. If the domain of the URL is on the [global HSTS preload -list](https://hstspreload.org/), modern browsers automatically convert requests -with an `http` scheme to `https`. - -If you need to create unencrypted `http` endpoints, you should create them with -hostnames that are not on the HSTS Global Preload like `ngrok.io` and -`ngrok.pizza`. - -ngrok does not prohibit you from creating `http` endpoints with hostnames whose -base domain is on the global HSTS preload list because non-browser clients -(like `curl`) can still be used to make unencrypted HTTP requests to them. diff --git a/sidebars.js b/sidebars.js index adfbfd1ed4..f3924a6907 100644 --- a/sidebars.js +++ b/sidebars.js @@ -54,7 +54,7 @@ const sidebars = { items: [ "universal-gateway/domains/what-are-public-endpoints", "universal-gateway/domains/how-do-i-use-my-own-domain", - "universal-gateway/domains/what-are-the-managed-domains", + "universal-gateway/domains/what-are-managed-domains", ], }, { From 78e2dde81b38c49859e2e77595335f5d6ab8efc0 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 13 Mar 2025 14:49:15 -0400 Subject: [PATCH 008/137] Rough draft done --- .../domains/what-are-domains.mdx | 26 +++++++++ .../domains/what-are-matching-endpoints.mdx | 20 +++++++ .../domains/what-are-public-endpoints.mdx | 53 ------------------- docs/universal-gateway/public-endpoints.mdx | 2 + sidebars.js | 2 +- 5 files changed, 49 insertions(+), 54 deletions(-) create mode 100644 docs/universal-gateway/domains/what-are-matching-endpoints.mdx delete mode 100644 docs/universal-gateway/domains/what-are-public-endpoints.mdx diff --git a/docs/universal-gateway/domains/what-are-domains.mdx b/docs/universal-gateway/domains/what-are-domains.mdx index 58a3011435..71554fd458 100644 --- a/docs/universal-gateway/domains/what-are-domains.mdx +++ b/docs/universal-gateway/domains/what-are-domains.mdx @@ -23,6 +23,32 @@ Domains also enable you to configure other domain-level behaviors, including: You can manage Domains on your [ngrok Dashboard](https://dashboard.ngrok.com/domains) or via the [ngrok API](#api). +## Wildcard domains + +You may create a Domain with a wildcard name, e.g. `*.example.com`. A wildcard domain enables you to: + +- Create an endpoint which receives traffic for all of its subdomains, e.g. `https://*.example.com`. See [Wildcard Endpoints](/universal-gateway/http/#wildcard-endpoints) to understand the rules for matching and precedence. +- Create an endpoint on any subdomain which matches the wildcard, e.g. `https://foo.example.com` or `https://foo.bar.baz.example.com` + +:::note +The wildcard `*` character may only be used as the first part of a +domain, you may not create domains like `app.*.example.com` or +`*-app.example.com`. +::: + +## Ownership + +Your account exclusively owns its Domains and all of their nested subdomains +within ngrok. That means: + +- No account may create a Domain with a name that is a subdomain of your Domains. +- No other account may create endpoints with a hostname matching your Domain or any of its nested subdomains. + +For example, if you create a Domain with the name `foo.ngrok.app`: + +- No other account create the Domains `foo.ngrok.app` or `bar.foo.ngrok.app`. +- No other account may create the endpoints `https://foo.ngrok.app` or `https://bar.foo.ngrok.app`. + ## API Domains are programatically managed via: diff --git a/docs/universal-gateway/domains/what-are-matching-endpoints.mdx b/docs/universal-gateway/domains/what-are-matching-endpoints.mdx new file mode 100644 index 0000000000..2ff2cb32e7 --- /dev/null +++ b/docs/universal-gateway/domains/what-are-matching-endpoints.mdx @@ -0,0 +1,20 @@ +--- +title: What are Matching Endpoints? +--- + +A [Domain's](/universal-gateway/what-are-domains) primary responsibility is to enable you to create [public endpoints](/universal-gateway/public-endpoints/) with a [hostname](https://en.wikipedia.org/wiki/Hostname.) matching the domain. These are called "matching endpoints". + +For example, after you create the Domain `app.example.com`, you can create the [Endpoint](/universal-gateway/endpoints) `https://app.example.com`. + +When you create a Domain, you may create matching public endpoints with the following constraints: + +| Endpoint Protocol | Allowed Endpoints | +| ----------------- | ------------------------------------------------------------------------------------------------ | +| `http` | Matching endpoints on port `80` of the Domain. | +| `https` | Matching endpoints on port `443` of the Domain. | +| `tls` | Matching endpoints on port `443` of the Domain. | +| `tcp` | Not allowed. Public TCP endpoints must match a [TCP Address](/universal-gateway/tcp-addresses/). | + +::tip +If you configure your Domain to use [dedicated IPs](/universal-gateway/ip-addresses/#dedicated-ips), these restrictions are removed and you may create matching endpoints on any ports. +::: diff --git a/docs/universal-gateway/domains/what-are-public-endpoints.mdx b/docs/universal-gateway/domains/what-are-public-endpoints.mdx deleted file mode 100644 index d98d7a5dcb..0000000000 --- a/docs/universal-gateway/domains/what-are-public-endpoints.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: What are Public Endpoints? ---- - -A Domain's primary responsibility is to enable you to create [public -endpoints](/universal-gateway/public-endpoints/) with a hostname matching the -domain. These are called "matching endpoints". For example, after you create -the Domain `app.example.com`, you can create the Endpoint -`https://app.example.com`. - -When you create a Domain, you may create matching public endpoints with the -following constraints: - -| Endpoint Protocol | Allowed Endpoints | -| ----------------- | ------------------------------------------------------------------------------------------------ | -| `http` | Matching endpoints on port `80` of the Domain. | -| `https` | Matching endpoints on port `443` of the Domain. | -| `tls` | Matching endpoints on port `443` of the Domain. | -| `tcp` | Not allowed. Public TCP endpoints must match a [TCP Address](/universal-gateway/tcp-addresses/). | - -If you configure your Domain to use [dedicated IPs](#dedicated-ips), these -restrictions are removed and you may create matching endpoints on any ports. - -## Wildcard domains - -You may create a Domain with a wildcard name, e.g. `*.example.com`. A wildcard -domain enables you to: - -- Create an endpoint which receives traffic for all of its subdomains, e.g. - `https://*.example.com`. Consult the documentation for [wildcard - endpoints](/universal-gateway/http/#wildcard-endpoints) to understand - the rules for matching and precedence. - -- Create an endpoint on any subdomain which matches the wildcard, e.g. - `https://foo.example.com` or `https://foo.bar.baz.example.com` - -The wildcard `*` character may only be used as the first part of a -domain, you may not create domains like `app.*.example.com` or -`*-app.example.com`. - -## Ownership - -Your account exclusively owns its Domains and all of their nested subdomains -within ngrok. That means: - -- No account may create a Domain with a name that is a subdomain of your Domains. -- No other account may create endpoints with a hostname matching your Domain or - any of its nested subdomains. - -For example, if you create a Domain with the name `foo.ngrok.app`: - -- No other account create the Domains `foo.ngrok.app` or `bar.foo.ngrok.app`. -- No other account may create the endpoints `https://foo.ngrok.app` or `https://bar.foo.ngrok.app`. diff --git a/docs/universal-gateway/public-endpoints.mdx b/docs/universal-gateway/public-endpoints.mdx index 37fd6ed878..ba9a3e5cc4 100644 --- a/docs/universal-gateway/public-endpoints.mdx +++ b/docs/universal-gateway/public-endpoints.mdx @@ -33,6 +33,8 @@ To keep such services both public and secure, you can add a Traffic Policy to yo - [IP restrictions](/docs/traffic-policy/actions/restrict-ips/) - [Mutual TLS](/docs/traffic-policy/actions/terminate-tls/#example-traffic-policy-document) +## Domains + ## URLs When you create a public endpoint, the URL you create it with is validated diff --git a/sidebars.js b/sidebars.js index f3924a6907..e88e979dd0 100644 --- a/sidebars.js +++ b/sidebars.js @@ -52,7 +52,7 @@ const sidebars = { id: "universal-gateway/domains/what-are-domains", }, items: [ - "universal-gateway/domains/what-are-public-endpoints", + "universal-gateway/domains/what-are-matching-endpoints", "universal-gateway/domains/how-do-i-use-my-own-domain", "universal-gateway/domains/what-are-managed-domains", ], From 4b2803284958427d2be87496e63288c4cf97be7f Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 13 Mar 2025 15:55:39 -0400 Subject: [PATCH 009/137] Some link fixes --- docs/guides/api-gateway/get-started.mdx | 2 +- docs/universal-gateway/http.mdx | 2 +- docs/universal-gateway/points-of-presence.mdx | 2 +- docs/universal-gateway/tls-certificates.mdx | 2 +- sidebars.js | 1 - 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/guides/api-gateway/get-started.mdx b/docs/guides/api-gateway/get-started.mdx index a2e61b6a87..42d7b4c0a6 100644 --- a/docs/guides/api-gateway/get-started.mdx +++ b/docs/guides/api-gateway/get-started.mdx @@ -79,7 +79,7 @@ ngrok api reserved-domains create --domain {YOUR_NGROK_DOMAIN} This example uses an [ngrok-managed domain](/universal-gateway/domains/#ngrok-managed-domains), but you can use -your own [branded domain](/universal-gateway/domains/#branded-domains) when you're ready for production. +your own [branded domain](/universal-gateway/how-do-i-use-my-own-domain) when you're ready for production. In that case, substitute your branded domain for `{YOUR_NGROK_DOMAIN}` in the command above, and [follow the steps](/guides/other-guides/how-to-set-up-a-custom-domain/#create-cname-record-in-domain-dns) to configure DNS. diff --git a/docs/universal-gateway/http.mdx b/docs/universal-gateway/http.mdx index 0d25c73709..884f2a3ef5 100644 --- a/docs/universal-gateway/http.mdx +++ b/docs/universal-gateway/http.mdx @@ -287,7 +287,7 @@ existing Domain object. ### Bring your own domain {#bring-your-own-domain} If you want to bring your own domain, first [create a Domain record and set up -a DNS CNAME record](/universal-gateway/domains/#branded-domains). Then +a DNS CNAME record](/universal-gateway/how-do-i-use-my-own-domain). Then create an endpoint on that domain by specifying a URL with a matching hostname. For example, to create an HTTPS endpoint on `https://app.example.com`, [create diff --git a/docs/universal-gateway/points-of-presence.mdx b/docs/universal-gateway/points-of-presence.mdx index f7e54c4227..44c02a395c 100644 --- a/docs/universal-gateway/points-of-presence.mdx +++ b/docs/universal-gateway/points-of-presence.mdx @@ -36,7 +36,7 @@ Region codes are used by the following features: - [Global Load Balancer](/universal-gateway/global-load-balancer/) - [`conn.server_region` Traffic Policy variable](/traffic-policy/variables/connection/#connserver_region) - [`region` Agent Configuration property](/agent/config/v2/#region) -- [Domain Global Load Balancer configuration](/universal-gateway/domains#global-load-balancer) +- [Domain Global Load Balancer configuration](/universal-gateway/global-load-balancer) They are correspondingly used in the following APIs: diff --git a/docs/universal-gateway/tls-certificates.mdx b/docs/universal-gateway/tls-certificates.mdx index 360d38dae2..8646ac4ee9 100644 --- a/docs/universal-gateway/tls-certificates.mdx +++ b/docs/universal-gateway/tls-certificates.mdx @@ -67,7 +67,7 @@ provisioning job. ### Bring your own domain -When you [bring your own domain](/universal-gateway/domains/#branded-domains) +When you [bring your own domain](/universal-gateway/how-do-i-use-my-own-domain) (e.g. `api.your-domain.com`) you must create a CNAME DNS record in your DNS provider. Certificate provisioning will not begin until your create this CNAME DNS record. diff --git a/sidebars.js b/sidebars.js index e88e979dd0..24d7462673 100644 --- a/sidebars.js +++ b/sidebars.js @@ -61,7 +61,6 @@ const sidebars = { label: "Concepts", type: "category", items: [ - { id: "universal-gateway/domains", type: "doc", label: "Domains" }, { id: "universal-gateway/tcp-addresses", type: "doc", From fbad4ed43185eca223b57f6c03681037ba62868b Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 13 Mar 2025 15:55:56 -0400 Subject: [PATCH 010/137] Delete domains.mdx --- docs/universal-gateway/domains.mdx | 207 ----------------------------- 1 file changed, 207 deletions(-) delete mode 100644 docs/universal-gateway/domains.mdx diff --git a/docs/universal-gateway/domains.mdx b/docs/universal-gateway/domains.mdx deleted file mode 100644 index dea7076d02..0000000000 --- a/docs/universal-gateway/domains.mdx +++ /dev/null @@ -1,207 +0,0 @@ ---- -title: Domains ---- - -# Domains - -## Overview - -Domains enable you to create public endpoints with hostnames matching the -domain. For example, after you create the domain `your-name.ngrok.app`, you may -create the Endpoint `https://your-name.ngrok.app` - -Domain names may be a subdomain of an [ngrok-managed -domain](#ngrok-managed-domains) like `foo.ngrok.app` or you can [bring your own -domain](#branded-domains) like `example.your-domain.com` by creating a CNAME -DNS record with your domain's DNS provider. - -Domains also enable you configure other domain-level behaviors including: - -- [**Global Load Balancer configuration**](#global-load-balancer) - Choose which points of presence handle traffic to a Domain's matching endpoints. -- [**TLS Certificate management**](#tls-certificates) - Configure automatic certificate provisioning or select a certificate you uploaded yourself. -- [**Dedicated IP address configuration**](#dedicated-ips) - Attach static, dedicated IPs for a Domain's matching endpoints receive traffic on. - -You can manage Domains on your [ngrok Dashboard](https://dashboard.ngrok.com/domains) -or via the [ngrok API](#api). - -## Public endpoints - -A Domain's primary responsibility is to enable you to create [public -endpoints](/universal-gateway/public-endpoints/) with a hostname matching the -domain. These are called "matching endpoints". For example, after you create -the Domain `app.example.com`, you can create the Endpoint -`https://app.example.com`. - -When you create a Domain, you may create matching public endpoints with the -following constraints: - -| Endpoint Protocol | Allowed Endpoints | -| ----------------- | ------------------------------------------------------------------------------------------------ | -| `http` | Matching endpoints on port `80` of the Domain. | -| `https` | Matching endpoints on port `443` of the Domain. | -| `tls` | Matching endpoints on port `443` of the Domain. | -| `tcp` | Not allowed. Public TCP endpoints must match a [TCP Address](/universal-gateway/tcp-addresses/). | - -If you configure your Domain to use [dedicated IPs](#dedicated-ips), these -restrictions are removed and you may create matching endpoints on any ports. - -### Wildcard Domains - -You may create a Domain with a wildcard name, e.g. `*.example.com`. A wildcard -domain enables you to: - -- Create an endpoint which receives traffic for all of its subdomains, e.g. - `https://*.example.com`. Consult the documentation for [wildcard - endpoints](/universal-gateway/http/#wildcard-endpoints) to understand - the rules for matching and precedence. - -- Create an endpoint on any subdomain which matches the wildcard, e.g. - `https://foo.example.com` or `https://foo.bar.baz.example.com` - -The wildcard `*` character may only be used as the first part of a -domain, you may not create domains like `app.*.example.com` or -`*-app.example.com`. - -### Ownership - -Your account exclusively owns its Domains and all of their nested subdomains -within ngrok. That means: - -- No account may create a Domain with a name that is a subdomain of your Domains. -- No other account may create endpoints with a hostname matching your Domain or - any of its nested subdomains. - -For example, if you create a Domain with the name `foo.ngrok.app`: - -- No other account create the Domains `foo.ngrok.app` or `bar.foo.ngrok.app`. -- No other account may create the endpoints `https://foo.ngrok.app` or `https://bar.foo.ngrok.app`. - -## Bring your own domain {#branded-domains} - -You can use any domain name that you already own with ngrok, e.g. -`app.your-domain.com`. To do so, you will create a CNAME record for that domain -to point traffic from the domain to ngrok's cloud service. When you create a -Domain, you will be presented with a target value for the CNAME record you need -to create. If you [create the Domain via -API](/api/resources/reserved-domains/), this value is the `cname_target` field. - -If you bring your own [wildcard domain](#wildcard-domains), you will need to -create a second DNS CNAME record for [wildcard TLS Certificate -provisioning](/universal-gateway/tls-certificates/#wildcard-domains). - -ngrok is not a domain registrar; you must already own a domain name to use it -with ngrok. - -### Apex domains - -If you want to use an apex domain (e.g. `example.com`) with ngrok, you must use -a DNS provider that supports an ALIAS record or CNAME flattening because the -DNS RFC does not permit CNAME records for apex domains. Because of how -ALIAS/CNAME flattening is implemented, apex domains will not take advantage of -the [Global Load Balancer](#global-load-balancer). If you are trying to create -your apex domain because you need to create endpoints for multiple subdomains, -use a [wildcard domain](#wildcard-domains) instead. - -## Global Load Balancer - -The [Global Load Balancer](/universal-gateway/global-load-balancer) -uses latency-aware DNS records to direct clients to the IPs of the nearest -[points of presence](/universal-gateway/points-of-presence/). - -Domains allow you to configure which points of presence the Global Load -Balancer may resolve clients to. This allows you to select which points of -presence will receive traffic for the Domain's matching endpoints. To disable -the Global Load Balancer, you may configure a domain to only resolve a single -point of presence. - -:::info Coming Soon - -Per-region global load balancer configuration is coming soon, [request access -to the developer preview](https://dashboard.ngrok.com/developer-preview). - -::: - -## TLS Certificates - -Domains manage the [TLS Certificate](/universal-gateway/tls-certificates/) used -to terminate TLS connections to the Domain's matching endpoints. When you -create a Domain, you may choose to allow ngrok to automatically provision TLS -certificates for you or to upload your own TLS certificate. - -Consult the documentation on [TLS -Certificates](/universal-gateway/tls-certificates/) for additional details on -certificate provisioning and management. - -## Dedicated IPs - -By default, a Domain's matching Endpoints receive traffic on a set of -multi-tenant [IP addresses](/universal-gateway/ip-addresses) that are -shared among all ngrok accounts. You may instead configure a Domain's matching -endpoints to receive traffic on IP addresses that are dedicated to your -account. - -If your Domain uses dedicated IPs, you may create public endpoints on _any_ -port numbers, not just 80 and 443. - -:::info Coming Soon - -Dedicated, static IPs for your domains are coming soon, [request access to the -developer preview](https://dashboard.ngrok.com/developer-preview). - -::: - -## ngrok Managed Domains - -If you don't own a domain that you want to use with ngrok, you can create a -Domain that is a subdomain of an ngrok-managed base domain. The ngrok-managed -base domains are: - -| Domain | Availability | HSTS Global Preload | -| ------------------ | ------------------------------------------------- | ------------------- | -| `ngrok.app` | Available to paying accounts | Yes | -| `ngrok.dev` | Available to paying accounts | Yes | -| `ngrok.pizza` | Available to paying accounts | No | -| `ngrok-free.app` | Used by free accounts | Yes | -| `ngrok-free.dev` | Used by free accounts | Yes | -| `ngrok-free.pizza` | Used by free accounts (coming soon) | No | -| `ngrok.io` | Discontinued and only available to older accounts | No | - -### Public Suffix List - -The ngrok-managed base domains are on the [Public Suffix -List](https://publicsuffix.org/). Browsers use the Public Suffix List to -guarantee that cookies from one subdomain cannot be accessed by other -subdomains. - -### HSTS Preload - -Some of the ngrok-managed base domains are on the global -[HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) preload -list. If the domain of the URL is on the [global HSTS preload -list](https://hstspreload.org/), modern browsers automatically convert requests -with an `http` scheme to `https`. - -If you need to create unencrypted `http` endpoints, you should create them with -hostnames that are not on the HSTS Global Preload like `ngrok.io` and -`ngrok.pizza`. - -ngrok does not prohibit you from creating `http` endpoints with hostnames whose -base domain is on the global HSTS preload list because non-browser clients -(like `curl`) can still be used to make unencrypted HTTP requests to them. - -## API - -Domains are programatically managed via: - -- [`/reserved_domains` API Resource](/api/resources/reserved-domains/) - -## Pricing - -Domains are available on all plans. Some Domain features require upgrades. See -the [Pricing page](https://ngrok.com/pricing) for details. - -| Feature | Plans | -| ---------------------- | --------------------------------------------------------------------------------- | -| Domains | All plans. The Domain name is assigned on Free, you may choose it on other plans. | -| Bring-your-own domains | Personal, Pro, Enterprise, Pay-as-you-go | -| Wildcard Domains | Enterprise | From cfdd45b5b6c9ca3212f603a835b6de3baa7a664e Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 14 Mar 2025 09:53:16 -0400 Subject: [PATCH 011/137] Remove outdated links --- docs/guides/api-gateway/get-started.mdx | 2 +- docs/guides/device-gateway/agent.md | 2 +- docs/guides/device-gateway/arm64.md | 2 +- docs/guides/site-to-site-connectivity/apis-mtls.mdx | 2 +- docs/guides/site-to-site-connectivity/apis.mdx | 2 +- docs/guides/site-to-site-connectivity/dbs-mtls.mdx | 2 +- docs/guides/site-to-site-connectivity/end-customers.mdx | 2 +- docs/integrations/digitalocean/gslb.mdx | 2 +- docs/integrations/linode/gslb.mdx | 2 +- docs/universal-gateway/http.mdx | 6 +++--- docs/universal-gateway/ip-addresses.mdx | 2 +- docs/universal-gateway/overview.mdx | 4 ++-- docs/universal-gateway/public-endpoints.mdx | 6 +++--- docs/universal-gateway/tcp-addresses.mdx | 2 +- docs/universal-gateway/tls-certificates.mdx | 8 ++++---- docs/universal-gateway/tls-termination.mdx | 4 ++-- 16 files changed, 25 insertions(+), 25 deletions(-) diff --git a/docs/guides/api-gateway/get-started.mdx b/docs/guides/api-gateway/get-started.mdx index 42d7b4c0a6..30c6c6aaab 100644 --- a/docs/guides/api-gateway/get-started.mdx +++ b/docs/guides/api-gateway/get-started.mdx @@ -78,7 +78,7 @@ ngrok api reserved-domains create --domain {YOUR_NGROK_DOMAIN} ``` This example uses an -[ngrok-managed domain](/universal-gateway/domains/#ngrok-managed-domains), but you can use +[ngrok-managed domain](/universal-gateway/domains/what-are-managed-domains), but you can use your own [branded domain](/universal-gateway/how-do-i-use-my-own-domain) when you're ready for production. In that case, substitute your branded domain for `{YOUR_NGROK_DOMAIN}` in the command above, and [follow the steps](/guides/other-guides/how-to-set-up-a-custom-domain/#create-cname-record-in-domain-dns) diff --git a/docs/guides/device-gateway/agent.md b/docs/guides/device-gateway/agent.md index 27340a4100..1ddb14a013 100644 --- a/docs/guides/device-gateway/agent.md +++ b/docs/guides/device-gateway/agent.md @@ -123,7 +123,7 @@ https://api.ngrok.com/agent_ingresses ## Create a custom wildcard domain -Next, create a custom [wildcard domain](/universal-gateway/domains/#wildcard-domains), which will allow you to +Next, create a custom [wildcard domain](/universal-gateway/domains/what-are-domains/#wildcard-domains), which will allow you to create endpoints and receive traffic on any subdomain of your domain. For example, you might create `*.customer1.{YOUR_DOMAIN}`. You would then be able to create endpoints diff --git a/docs/guides/device-gateway/arm64.md b/docs/guides/device-gateway/arm64.md index f9ce8bc75d..19fdc3b87d 100644 --- a/docs/guides/device-gateway/arm64.md +++ b/docs/guides/device-gateway/arm64.md @@ -102,7 +102,7 @@ If you already established a TCP tunnel for SSH access, you'll either need to cr Forwarding https://12345.ngrok.app -> http://localhost:8080 ``` -1. Optionally, you can reserve a [static subdomain](/universal-gateway/domains/) like so: +1. Optionally, you can reserve a [static subdomain](/universal-gateway/domains/what-are-domains/) like so: ``` ngrok http 8080 --url https://example.ngrok.app diff --git a/docs/guides/site-to-site-connectivity/apis-mtls.mdx b/docs/guides/site-to-site-connectivity/apis-mtls.mdx index 921257ed5e..bb11110aa3 100644 --- a/docs/guides/site-to-site-connectivity/apis-mtls.mdx +++ b/docs/guides/site-to-site-connectivity/apis-mtls.mdx @@ -131,7 +131,7 @@ https://api.ngrok.com/agent_ingresses ## Create a custom wildcard domain -Next, create a custom [wildcard domain](/universal-gateway/domains/#wildcard-domains), which will allow you to +Next, create a custom [wildcard domain](/universal-gateway/domains/what-are-domains/#wildcard-domains), which will allow you to create endpoints and receive traffic on any subdomain of your domain. For example, you might create `*.customer1.{YOUR_DOMAIN}`. You would then be able to create endpoints diff --git a/docs/guides/site-to-site-connectivity/apis.mdx b/docs/guides/site-to-site-connectivity/apis.mdx index dc2c163701..bba7c17354 100644 --- a/docs/guides/site-to-site-connectivity/apis.mdx +++ b/docs/guides/site-to-site-connectivity/apis.mdx @@ -113,7 +113,7 @@ https://api.ngrok.com/agent_ingresses ## Create a custom wildcard domain -Next, create a custom [wildcard domain](/universal-gateway/domains/#wildcard-domains), which will allow you to +Next, create a custom [wildcard domain](/universal-gateway/domains/what-are-domains/#wildcard-domains), which will allow you to create endpoints and receive traffic on any subdomain of your domain. For example, you might create `*.customer1.{YOUR_DOMAIN}`. You would then be able to create endpoints diff --git a/docs/guides/site-to-site-connectivity/dbs-mtls.mdx b/docs/guides/site-to-site-connectivity/dbs-mtls.mdx index 8a30ae8078..8fdde312fa 100644 --- a/docs/guides/site-to-site-connectivity/dbs-mtls.mdx +++ b/docs/guides/site-to-site-connectivity/dbs-mtls.mdx @@ -134,7 +134,7 @@ https://api.ngrok.com/agent_ingresses ## Create a custom wildcard domain -Next, create a custom [wildcard domain](/universal-gateway/domains/#wildcard-domains), which will allow you to +Next, create a custom [wildcard domain](/universal-gateway/domains/what-are-domains/#wildcard-domains), which will allow you to create endpoints and receive traffic on any subdomain of your domain. For example, you might create `*.customer1.{YOUR_DOMAIN}`. You would then be able to create endpoints diff --git a/docs/guides/site-to-site-connectivity/end-customers.mdx b/docs/guides/site-to-site-connectivity/end-customers.mdx index 6b3752ad25..c8d7a49284 100644 --- a/docs/guides/site-to-site-connectivity/end-customers.mdx +++ b/docs/guides/site-to-site-connectivity/end-customers.mdx @@ -196,7 +196,7 @@ Your vendor can also work with ngrok to provision dedicated IPs for their custom At this point, you can block the default agent ingress address at `connect.ngrok-agent.com:443`, which all agents use by default to connect outbound to ngrok’s network. This address resolves to a dynamic set of IP addresses, and blocking it at your network prevents any usage outside of this site-to-site connectivity use case in partnership with your vendor, such as developers utilizing ngrok to tunnel local development environments to the public internet. -You should also block the [ngrok-managed public domains](/universal-gateway/domains/#ngrok-managed-domains), e.g. `ngrok.app`, `ngrok.io`, etc. +You should also block the [ngrok-managed public domains](/universal-gateway/domains/what-are-managed-domains), e.g. `ngrok.app`, `ngrok.io`, etc. Work with your vendor to design an architecture that [prevents unauthorized use](#how-can-i-prevent-ngrok-from-being-used-for-any-purpose-other-than-in-site-to-site-connectivity-with-my-vendor?) diff --git a/docs/integrations/digitalocean/gslb.mdx b/docs/integrations/digitalocean/gslb.mdx index fb842e6d6e..507eb9dacc 100644 --- a/docs/integrations/digitalocean/gslb.mdx +++ b/docs/integrations/digitalocean/gslb.mdx @@ -44,7 +44,7 @@ To simplify authenticating your account with the ngrok API, export the API key o export NGROK_API_KEY= ``` -Next, create a domain that is a subdomain of an [ngrok-managed domain](/universal-gateway/domains/). For an example deployment like this, `YOUR_COMPANY-digitalocean-gslb.ngrok.app` would work great. +Next, create a domain that is a subdomain of an [ngrok-managed domain](/universal-gateway/domains/what-are-domains/). For an example deployment like this, `YOUR_COMPANY-digitalocean-gslb.ngrok.app` would work great. You can reserve your domain in one of two ways: with the [ngrok API](/api/), or in the [ngrok dashboard](https://dashboard.ngrok.com/domains). diff --git a/docs/integrations/linode/gslb.mdx b/docs/integrations/linode/gslb.mdx index 0c7f3018e1..40be5a02bc 100644 --- a/docs/integrations/linode/gslb.mdx +++ b/docs/integrations/linode/gslb.mdx @@ -44,7 +44,7 @@ To simplify authenticating your account with the ngrok API, export the API key o export NGROK_API_KEY= ``` -Next, create a domain that is a subdomain of an [ngrok-managed domain](/universal-gateway/domains/). For an example deployment like this, `YOUR_COMPANY-linode-gslb.ngrok.app` would work great. +Next, create a domain that is a subdomain of an [ngrok-managed domain](/universal-gateway/domains/what-are-domains/). For an example deployment like this, `YOUR_COMPANY-linode-gslb.ngrok.app` would work great. You can reserve your domain in one of two ways: with the [ngrok API](/api/), or in the [ngrok dashboard](https://dashboard.ngrok.com/domains). diff --git a/docs/universal-gateway/http.mdx b/docs/universal-gateway/http.mdx index 884f2a3ef5..604af167c6 100644 --- a/docs/universal-gateway/http.mdx +++ b/docs/universal-gateway/http.mdx @@ -277,7 +277,7 @@ If you would like to listen for both http and https traffic, create two endpoint #### Domains When you create a public endpoint, it must match a -[Domain](/universal-gateway/domains) on your account. Domains help you set up +[Domain](/universal-gateway/domains/what-are-domains) on your account. Domains help you set up branded domains and manage TLS certificates. You may create endpoints with wildcard domains as well. @@ -326,7 +326,7 @@ your domain: You can create an endpoint which will receive traffic for all of the subdomains matching a given wildcard domain like `*.example.com`. You must create a -[wildcard domain](/universal-gateway/domains/#wildcard-domains) to create a +[wildcard domain](/universal-gateway/domains/what-are-domains/#wildcard-domains) to create a public wildcard endpoint. For example, if you create the wildcard endpoint `https://*.example.com`, it @@ -816,7 +816,7 @@ additional details. #### `/.well-known/acme-challenge` ngrok takes over handling of this path of any HTTP endpoint matching a -[Domain](/universal-gateway/domains) with automated certificate management +[Domain](/universal-gateway/domains/what-are-domains) with automated certificate management enabled. You may disable this behavior by uploading your own certificate on the matching Domain. diff --git a/docs/universal-gateway/ip-addresses.mdx b/docs/universal-gateway/ip-addresses.mdx index 7a8d5d25f9..ef7ade9c4c 100644 --- a/docs/universal-gateway/ip-addresses.mdx +++ b/docs/universal-gateway/ip-addresses.mdx @@ -24,7 +24,7 @@ dedicated IPs for: ### Domains -By default, a [Domain's](/universal-gateway/domains/) matching Endpoints receive traffic on a set of +By default, a [Domain's](/universal-gateway/domains/what-are-domains/) matching Endpoints receive traffic on a set of multi-tenant IP addresses that are shared among all ngrok accounts. You may instead configure a Domain's matching endpoints to receive traffic on IP addresses that are dedicated to your account. If your Domain uses dedicated IPs, you may create public endpoints on _any_ diff --git a/docs/universal-gateway/overview.mdx b/docs/universal-gateway/overview.mdx index 200cd6a1dd..e7f98363af 100644 --- a/docs/universal-gateway/overview.mdx +++ b/docs/universal-gateway/overview.mdx @@ -1,6 +1,6 @@ --- title: Overview -pagination_next: universal-gateway/domains +pagination_next: universal-gateway/domains/what-are-domains --- # Universal Gateway @@ -18,7 +18,7 @@ Bindings, Pools and Domains to understand how they work. Learn more about Universal Gateway Concepts: -- [Domains →](/universal-gateway/domains/) +- [Domains →](/universal-gateway/domains/what-are-domains/) - [TCP Addresses →](/universal-gateway/tcp-addresses/) - [TLS Certificates →](/universal-gateway/tls-certificates/) - [Edges →](/universal-gateway/edges/) diff --git a/docs/universal-gateway/public-endpoints.mdx b/docs/universal-gateway/public-endpoints.mdx index ba9a3e5cc4..4575ec78d4 100644 --- a/docs/universal-gateway/public-endpoints.mdx +++ b/docs/universal-gateway/public-endpoints.mdx @@ -9,7 +9,7 @@ Public endpoints enable you to receive traffic from the internet via ngrok’s [ Public endpoint URLs must: -- Use either a [Domain](/universal-gateway/domains/) or [TCP Address](/universal-gateway/tcp-addresses/) +- Use either a [Domain](/universal-gateway/domains/what-are-domains/) or [TCP Address](/universal-gateway/tcp-addresses/) - Use the `public` [binding](/docs/universal-gateway/bindings/) ## Get started @@ -42,7 +42,7 @@ differently based on the protocol of the URL. ### `http` -- The hostname must match a [Domain](/universal-gateway/domains/) in your account. +- The hostname must match a [Domain](/universal-gateway/domains/what-are-domains/) in your account. - The hostname must be a domain with a valid [public suffix](https://publicsuffix.org/). - The port must be `80`. If you do not specify a port, the default `80` will be used for you. @@ -57,7 +57,7 @@ differently based on the protocol of the URL. ### `https`, `tls` -- The hostname must match a [Domain](/universal-gateway/domains/) in your account. +- The hostname must match a [Domain](/universal-gateway/domains/what-are-domains/) in your account. - The hostname must be a domain with a valid [public suffix](https://publicsuffix.org/). - The port must be `443`. If you do not specify a port, the default `443` will be used for you. diff --git a/docs/universal-gateway/tcp-addresses.mdx b/docs/universal-gateway/tcp-addresses.mdx index 10ea6b6562..ade552bc75 100644 --- a/docs/universal-gateway/tcp-addresses.mdx +++ b/docs/universal-gateway/tcp-addresses.mdx @@ -23,7 +23,7 @@ endpoints with a hostname and port matching the address. These are called `tcp://1.tcp.jp.ngrok.io:12345`. Only TCP endpoints may be created on TCP Addresses. To create other endpoint -types, create a [Domain](/universal-gateway/domains/). +types, create a [Domain](/universal-gateway/domains/what-are-domains/). ## Address assignment diff --git a/docs/universal-gateway/tls-certificates.mdx b/docs/universal-gateway/tls-certificates.mdx index 8646ac4ee9..86d38c46ca 100644 --- a/docs/universal-gateway/tls-certificates.mdx +++ b/docs/universal-gateway/tls-certificates.mdx @@ -12,7 +12,7 @@ TLS certificates are a tuple of a private key and certificate that are presented by the ngrok cloud service during a TLS handshakes to terminate TLS connections to [HTTPS endpoints](/universal-gateway/http) and [TLS endpoints](/universal-gateway/tls). TLS certificates are attached to -[domains](/universal-gateway/domains/) for termination of TLS connections to +[domains](/universal-gateway/domains/what-are-domains/) for termination of TLS connections to endpoints whose URLs match that domain. ngrok can automatically provision certificates for you or you can upload your own. @@ -22,10 +22,10 @@ documentation for details on how and when ngrok terminates TLS connections. ## Certificate Selection When TLS connections to an endpoint are terminated, ngrok uses the TLS -Certificate attached to the [domain](/universal-gateway/domains) matching the +Certificate attached to the [domain](/universal-gateway/domains/what-are-domains) matching the endpoint's URL for termination. -Each [domain](/universal-gateway/domains/) has an attached TLS certificate that is referenced by its [`certificate_id` field](/api/resources/reserved-domains). If the domain object does reference any certificate, or if there is no matching domain object for an endpoint's URL, ngrok selects its own TLS certificate for +Each [domain](/universal-gateway/domains/what-are-domains/) has an attached TLS certificate that is referenced by its [`certificate_id` field](/api/resources/reserved-domains). If the domain object does reference any certificate, or if there is no matching domain object for an endpoint's URL, ngrok selects its own TLS certificate for termination. You may override the certificate used for TLS termination by explicitly @@ -34,7 +34,7 @@ action](/traffic-policy/actions/terminate-tls/). ## Certificate Provisioning -Whenever you create a [domain](/universal-gateway/domains/) you choose how +Whenever you create a [domain](/universal-gateway/domains/what-are-domains/) you choose how a TLS certificate will be provisioned. Either: - [Automatic TLS certificates](#automated) (default) - ngrok automatically diff --git a/docs/universal-gateway/tls-termination.mdx b/docs/universal-gateway/tls-termination.mdx index 655016577d..07ae37a36c 100644 --- a/docs/universal-gateway/tls-termination.mdx +++ b/docs/universal-gateway/tls-termination.mdx @@ -49,7 +49,7 @@ ngrok's cloud service terminates TLS, it: - Uses latest and most secure version of TLS - Uses the [TLS Certificate](/universal-gateway/tls-certificates/) attached to the - [Domain](/universal-gateway/domains/) which matches the Endpoint URL's + [Domain](/universal-gateway/domains/what-are-domains/) which matches the Endpoint URL's hostname - Accelerates your traffic by using the global load balancer to terminate at its closest point of presence @@ -210,7 +210,7 @@ balancer](/universal-gateway/global-load-balancer). When the ngrok cloud service terminates TLS connections, it does so with the [TLS Certificate](/universal-gateway/tls-certificates/) attached to the -[Domain](/universal-gateway/domains/) which matches the Endpoint URL's +[Domain](/universal-gateway/domains/what-are-domains/) which matches the Endpoint URL's hostname. See the documentation on [TLS Certificates](/universal-gateway/tls-certificates/) for more details on how they are From 9e428722269b0b85939cd52daf803f578580923c Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 14 Mar 2025 11:39:14 -0400 Subject: [PATCH 012/137] Checkpoint; broke up the first few sections of the page and moved them around --- .../domains/what-are-matching-endpoints.mdx | 16 +++---- docs/universal-gateway/tcp-addresses.mdx | 38 ++++----------- .../how-are-tcp-addresses-assigned.mdx | 13 ++++++ .../tcp-addresses/what-are-tcp-addresses.mdx | 46 +++++++++++++++++++ 4 files changed, 75 insertions(+), 38 deletions(-) create mode 100644 docs/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned.mdx create mode 100644 docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx diff --git a/docs/universal-gateway/domains/what-are-matching-endpoints.mdx b/docs/universal-gateway/domains/what-are-matching-endpoints.mdx index 2ff2cb32e7..9e6692c4fe 100644 --- a/docs/universal-gateway/domains/what-are-matching-endpoints.mdx +++ b/docs/universal-gateway/domains/what-are-matching-endpoints.mdx @@ -2,18 +2,18 @@ title: What are Matching Endpoints? --- -A [Domain's](/universal-gateway/what-are-domains) primary responsibility is to enable you to create [public endpoints](/universal-gateway/public-endpoints/) with a [hostname](https://en.wikipedia.org/wiki/Hostname.) matching the domain. These are called "matching endpoints". +A matching endpoint is a public endpoint with a [hostname](https://en.wikipedia.org/wiki/Hostname.) matching a [Domain](/universal-gateway/what-are-domains) or [TCP Address](/universal-gateway/what-are-tcp-addresses) you've configured with ngrok. For example, after you create the Domain `app.example.com`, you can create the [Endpoint](/universal-gateway/endpoints) `https://app.example.com`. -When you create a Domain, you may create matching public endpoints with the following constraints: +Matching endpoints are subject to the following restrictions: -| Endpoint Protocol | Allowed Endpoints | -| ----------------- | ------------------------------------------------------------------------------------------------ | -| `http` | Matching endpoints on port `80` of the Domain. | -| `https` | Matching endpoints on port `443` of the Domain. | -| `tls` | Matching endpoints on port `443` of the Domain. | -| `tcp` | Not allowed. Public TCP endpoints must match a [TCP Address](/universal-gateway/tcp-addresses/). | +| Endpoint Protocol | Required Port | +| ----------------- | ------------- | +| `http` | `80` | +| `https` | `443` | +| `tls` | `443` | +| `tcp` | Any | ::tip If you configure your Domain to use [dedicated IPs](/universal-gateway/ip-addresses/#dedicated-ips), these restrictions are removed and you may create matching endpoints on any ports. diff --git a/docs/universal-gateway/tcp-addresses.mdx b/docs/universal-gateway/tcp-addresses.mdx index ade552bc75..15eb28b491 100644 --- a/docs/universal-gateway/tcp-addresses.mdx +++ b/docs/universal-gateway/tcp-addresses.mdx @@ -1,40 +1,18 @@ --- -title: Universal Gateway > TCP Addresses +title: What are TCP Addresses? --- -# TCP Addresses +TCP Addresses enable you to create public [TCP Endpoints](/universal-gateway/tcp/) on a fixed address. TCP Addresses are a combination of a hostname and a port, such as `1.tcp.eu.ngrok.io:12345`. -## Overview +You can manage TCP Addresses with: -TCP Addresses enable you to create public [TCP -Endpoints](/universal-gateway/tcp/) on a fixed address. TCP Addresses -are a host and port tuple, for example `1.tcp.eu.ngrok.io:12345`. +- [The Dashboard](https://dashboard.ngrok.com/tcp-addresses) +- [The API](#api). -You can manage TCP Addresses on your [ngrok -Dashboard](https://dashboard.ngrok.com/tcp-addresses) or via the [ngrok -API](#api). - -## Public endpoint creation - -A TCP Address's primary responsibility is to enable you to create public TCP -endpoints with a hostname and port matching the address. These are called -"matching endpoints". For example, after you create the TCP Address -`1.tcp.jp.ngrok.io:12345`, you can create the Endpoint -`tcp://1.tcp.jp.ngrok.io:12345`. - -Only TCP endpoints may be created on TCP Addresses. To create other endpoint +:::note +Only TCP Endpoints may be created on TCP Addresses. To create other endpoint types, create a [Domain](/universal-gateway/domains/what-are-domains/). - -## Address assignment - -The hostname and port of the TCP Address are randomly assigned when you create -it, after which it will not change. You may not choose the hostname or port. -If you delete a TCP Address, there is no way to provision the same one again. -TCP Addresses may be managed via the dashboard and via API. - -The port of your TCP Address is uniquely assigned to your account, but other -ports on that same hostname may be assigned to other accounts. While the -hostname and port of a TCP Address is fixed, they do not have static IPs. +::: ## Global Load Balancer diff --git a/docs/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned.mdx b/docs/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned.mdx new file mode 100644 index 0000000000..9b1c96e81a --- /dev/null +++ b/docs/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned.mdx @@ -0,0 +1,13 @@ +--- +title: How are TCP Addresses Assigned? +description: Learn how ngrok assignes TCP Addresses. +--- + +You can create TCP Addresses in [the dashboard](https://dashboard.ngrok.com/tcp-addresses) or via [the API](/api/resources/reserved-addrs/). The following limitations apply: + +- When you create a TCP Address, the hostname and port are randomly assigned. Both are permanent. + - You may not choose the hostname or port. +- If you delete a TCP Address, there is no way to provision the same one again. +- TCP Addresses may be managed via the dashboard or API. +- The port of your TCP Address is uniquely assigned to your account, but other ports on that same hostname may be assigned to other accounts. +- While the hostname and port of a TCP Address is fixed, they do not have static IPs. diff --git a/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx b/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx new file mode 100644 index 0000000000..ccfff74bde --- /dev/null +++ b/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx @@ -0,0 +1,46 @@ +--- +title: What are TCP Addresses? +--- + +TCP Addresses enable you to create public [TCP Endpoints](/universal-gateway/tcp/) on a fixed address. TCP Addresses are a combination of a hostname and a port, such as `1.tcp.eu.ngrok.io:12345`. + +You can manage TCP Addresses with: + +- [The Dashboard](https://dashboard.ngrok.com/tcp-addresses) + - [Learn how TCP Addresses are assigned](/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned/). +- [The API](#api). + +:::note +Only TCP Endpoints may be created on TCP Addresses. To create other endpoint +types, create a [Domain](/universal-gateway/domains/what-are-domains/). +::: + +## Global Load Balancer + +TCP Addresses are not supported by the [global load +balancer](/universal-gateway/global-load-balancer). + +You must select a [Point of +Presence](/universal-gateway/points-of-presence) when you create a TCP +Address. Connections to matching TCP Endpoints on a TCP Address will always +route to the TCP Address's point of presence, no matter where those connections +originated in the world. + +You may create Agent Endpoints from an agent connected to a different point of +presence than the matching TCP Address. For example, the following will work +properly: + +```sh +ngrok tcp 3389 --region jp --url tcp://1.tcp.eu.ngrok.io:12345 +``` + +## API + +TCP Addresses are programatically managed via: + +- [`/reserved_addrs` API Resource](/api/resources/reserved-addrs/) + +## Pricing + +TCP Addresses are available on paid plans only, they are not available on the +free plan. From 824a3050c0cac80313a037ea4376831ecf9ed9a9 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 14 Mar 2025 11:52:22 -0400 Subject: [PATCH 013/137] Need to do sidebar --- .../global-load-balancer.mdx | 13 ++++++---- docs/universal-gateway/tcp-addresses.mdx | 24 ++----------------- .../tcp-addresses/what-are-tcp-addresses.mdx | 19 --------------- 3 files changed, 11 insertions(+), 45 deletions(-) diff --git a/docs/universal-gateway/global-load-balancer.mdx b/docs/universal-gateway/global-load-balancer.mdx index 8d6072f40b..df753bc81c 100644 --- a/docs/universal-gateway/global-load-balancer.mdx +++ b/docs/universal-gateway/global-load-balancer.mdx @@ -135,10 +135,15 @@ of presence. ### TCP Endpoints TCP Endpoints do not support GSLB. Unlike domains, TCP addresses are -provisioned for a specific point of presence. When you create a TCP Address, -you must select the point of presence where it will accept traffic. Unlike -ngrok's globally routed domains, traffic to TCP addresses always enters ngrok's -network from that point of presence. +provisioned for a specific [Point of Presence](/universal-gateway/points-of-presence). When you create a TCP Address, you must select the point of presence where it will accept traffic. Connections to matching TCP Endpoints on a TCP Address will always route to the TCP Address's point of presence, no matter where those connections originated in the world. + +#### TCP Addresses + +Though TCP Endpoints can't be load balanced, you may create [Agent Endpoints](#agents) from an agent connected to a different point of presence than the matching TCP Address. For example, the following example creates an agent in the `jp` region that connects to a TCP address in the `eu` region: + +```sh +ngrok tcp 3389 --region jp --url tcp://1.tcp.eu.ngrok.io:12345 +``` ## Domains diff --git a/docs/universal-gateway/tcp-addresses.mdx b/docs/universal-gateway/tcp-addresses.mdx index 15eb28b491..5415a7ffc1 100644 --- a/docs/universal-gateway/tcp-addresses.mdx +++ b/docs/universal-gateway/tcp-addresses.mdx @@ -7,7 +7,7 @@ TCP Addresses enable you to create public [TCP Endpoints](/universal-gateway/tcp You can manage TCP Addresses with: - [The Dashboard](https://dashboard.ngrok.com/tcp-addresses) -- [The API](#api). +- [The API](/api/resources/reserved-addrs/) :::note Only TCP Endpoints may be created on TCP Addresses. To create other endpoint @@ -17,27 +17,7 @@ types, create a [Domain](/universal-gateway/domains/what-are-domains/). ## Global Load Balancer TCP Addresses are not supported by the [global load -balancer](/universal-gateway/global-load-balancer). - -You must select a [Point of -Presence](/universal-gateway/points-of-presence) when you create a TCP -Address. Connections to matching TCP Endpoints on a TCP Address will always -route to the TCP Address's point of presence, no matter where those connections -originated in the world. - -You may create Agent Endpoints from an agent connected to a different point of -presence than the matching TCP Address. For example, the following will work -properly: - -```sh -ngrok tcp 3389 --region jp --url tcp://1.tcp.eu.ngrok.io:12345 -``` - -## API - -TCP Addresses are programatically managed via: - -- [`/reserved_addrs` API Resource](/api/resources/reserved-addrs/) +balancer](/universal-gateway/global-load-balancer#tcp-addresses). ## Pricing diff --git a/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx b/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx index ccfff74bde..4fb4be4d28 100644 --- a/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx +++ b/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx @@ -15,25 +15,6 @@ Only TCP Endpoints may be created on TCP Addresses. To create other endpoint types, create a [Domain](/universal-gateway/domains/what-are-domains/). ::: -## Global Load Balancer - -TCP Addresses are not supported by the [global load -balancer](/universal-gateway/global-load-balancer). - -You must select a [Point of -Presence](/universal-gateway/points-of-presence) when you create a TCP -Address. Connections to matching TCP Endpoints on a TCP Address will always -route to the TCP Address's point of presence, no matter where those connections -originated in the world. - -You may create Agent Endpoints from an agent connected to a different point of -presence than the matching TCP Address. For example, the following will work -properly: - -```sh -ngrok tcp 3389 --region jp --url tcp://1.tcp.eu.ngrok.io:12345 -``` - ## API TCP Addresses are programatically managed via: From 401cb1b6101d97186fa85235e22e89ddb9a440f3 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 14 Mar 2025 11:54:36 -0400 Subject: [PATCH 014/137] Ok now ready for sidebar --- docs/universal-gateway/tcp-addresses.mdx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/universal-gateway/tcp-addresses.mdx b/docs/universal-gateway/tcp-addresses.mdx index 5415a7ffc1..26e6a45959 100644 --- a/docs/universal-gateway/tcp-addresses.mdx +++ b/docs/universal-gateway/tcp-addresses.mdx @@ -16,8 +16,9 @@ types, create a [Domain](/universal-gateway/domains/what-are-domains/). ## Global Load Balancer -TCP Addresses are not supported by the [global load -balancer](/universal-gateway/global-load-balancer#tcp-addresses). +ngrok does not support global load balancing for TCP Addresses, but you can connect TCP Addresses to Agent Endpoints in different [Points of Presence](/universal-gateway/points-of-presence). + +See [the global load balancer documentation](/universal-gateway/global-load-balancer#tcp-addresses) for more information. ## Pricing From 96776c7eccc870a0eac6702996a164eec33d040b Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 14 Mar 2025 12:51:39 -0400 Subject: [PATCH 015/137] Removed TCP from sidebar; added new content --- .../universal-gateway/global-load-balancer.mdx | 8 -------- docs/universal-gateway/tcp-addresses.mdx | 8 ++++++-- .../tcp-addresses/what-are-tcp-addresses.mdx | 16 +++++----------- .../what-are-matching-endpoints.mdx | 3 ++- sidebars.js | 18 ++++++++++++------ 5 files changed, 25 insertions(+), 28 deletions(-) rename docs/universal-gateway/{domains => }/what-are-matching-endpoints.mdx (90%) diff --git a/docs/universal-gateway/global-load-balancer.mdx b/docs/universal-gateway/global-load-balancer.mdx index df753bc81c..1f621b7955 100644 --- a/docs/universal-gateway/global-load-balancer.mdx +++ b/docs/universal-gateway/global-load-balancer.mdx @@ -137,14 +137,6 @@ of presence. TCP Endpoints do not support GSLB. Unlike domains, TCP addresses are provisioned for a specific [Point of Presence](/universal-gateway/points-of-presence). When you create a TCP Address, you must select the point of presence where it will accept traffic. Connections to matching TCP Endpoints on a TCP Address will always route to the TCP Address's point of presence, no matter where those connections originated in the world. -#### TCP Addresses - -Though TCP Endpoints can't be load balanced, you may create [Agent Endpoints](#agents) from an agent connected to a different point of presence than the matching TCP Address. For example, the following example creates an agent in the `jp` region that connects to a TCP address in the `eu` region: - -```sh -ngrok tcp 3389 --region jp --url tcp://1.tcp.eu.ngrok.io:12345 -``` - ## Domains [Domains](/universal-gateway/domains/what-are-domains) allow you to configure which points of presence the Global Load diff --git a/docs/universal-gateway/tcp-addresses.mdx b/docs/universal-gateway/tcp-addresses.mdx index 26e6a45959..60b18baad2 100644 --- a/docs/universal-gateway/tcp-addresses.mdx +++ b/docs/universal-gateway/tcp-addresses.mdx @@ -16,9 +16,13 @@ types, create a [Domain](/universal-gateway/domains/what-are-domains/). ## Global Load Balancer -ngrok does not support global load balancing for TCP Addresses, but you can connect TCP Addresses to Agent Endpoints in different [Points of Presence](/universal-gateway/points-of-presence). +ngrok does not support global load balancing for TCP Addresses, but you can connect TCP Addresses to [Agent Endpoints](/agent/) in different [Points of Presence](/universal-gateway/points-of-presence). This allows you to accept traffic to a TCP Address in one region, then forward it to an Agent in a different region. -See [the global load balancer documentation](/universal-gateway/global-load-balancer#tcp-addresses) for more information. +The following example [CLI command](/agent/cli) creates an agent in the `jp` region that connects to a TCP address in the `eu` region: + +```sh +ngrok tcp 3389 --region jp --url tcp://1.tcp.eu.ngrok.io:12345 +``` ## Pricing diff --git a/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx b/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx index 4fb4be4d28..43cfd5f72f 100644 --- a/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx +++ b/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx @@ -2,26 +2,20 @@ title: What are TCP Addresses? --- -TCP Addresses enable you to create public [TCP Endpoints](/universal-gateway/tcp/) on a fixed address. TCP Addresses are a combination of a hostname and a port, such as `1.tcp.eu.ngrok.io:12345`. +[TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol) Addresses enable you to create public [TCP Endpoints](/universal-gateway/tcp/) on static addresses. All TCP Addresses contain both their hostname and port, such as `1.tcp.eu.ngrok.io:12345`. You can manage TCP Addresses with: - [The Dashboard](https://dashboard.ngrok.com/tcp-addresses) - - [Learn how TCP Addresses are assigned](/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned/). -- [The API](#api). + - Learn [how TCP Addresses are assigned](/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned/). +- [The API](/api/resources/reserved-addrs/). :::note -Only TCP Endpoints may be created on TCP Addresses. To create other endpoint +Only TCP Endpoints may be created on TCP Addresses. For other endpoint types, create a [Domain](/universal-gateway/domains/what-are-domains/). ::: -## API - -TCP Addresses are programatically managed via: - -- [`/reserved_addrs` API Resource](/api/resources/reserved-addrs/) - ## Pricing TCP Addresses are available on paid plans only, they are not available on the -free plan. +free plan. See [the pricing page](https://ngrok.com/pricing) for more information. diff --git a/docs/universal-gateway/domains/what-are-matching-endpoints.mdx b/docs/universal-gateway/what-are-matching-endpoints.mdx similarity index 90% rename from docs/universal-gateway/domains/what-are-matching-endpoints.mdx rename to docs/universal-gateway/what-are-matching-endpoints.mdx index 9e6692c4fe..43c023af40 100644 --- a/docs/universal-gateway/domains/what-are-matching-endpoints.mdx +++ b/docs/universal-gateway/what-are-matching-endpoints.mdx @@ -1,5 +1,6 @@ --- title: What are Matching Endpoints? +description: Learn about endpoints that match the domain or TCP address they're created on. --- A matching endpoint is a public endpoint with a [hostname](https://en.wikipedia.org/wiki/Hostname.) matching a [Domain](/universal-gateway/what-are-domains) or [TCP Address](/universal-gateway/what-are-tcp-addresses) you've configured with ngrok. @@ -15,6 +16,6 @@ Matching endpoints are subject to the following restrictions: | `tls` | `443` | | `tcp` | Any | -::tip +:::tip If you configure your Domain to use [dedicated IPs](/universal-gateway/ip-addresses/#dedicated-ips), these restrictions are removed and you may create matching endpoints on any ports. ::: diff --git a/sidebars.js b/sidebars.js index 24d7462673..7084cdf7c0 100644 --- a/sidebars.js +++ b/sidebars.js @@ -52,20 +52,26 @@ const sidebars = { id: "universal-gateway/domains/what-are-domains", }, items: [ - "universal-gateway/domains/what-are-matching-endpoints", "universal-gateway/domains/how-do-i-use-my-own-domain", "universal-gateway/domains/what-are-managed-domains", ], }, + "universal-gateway/what-are-matching-endpoints", + { + label: "What are TCP Addresses?", + type: "category", + link: { + type: "doc", + id: "universal-gateway/tcp-addresses/what-are-tcp-addresses", + }, + items: [ + "universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned", + ], + }, { label: "Concepts", type: "category", items: [ - { - id: "universal-gateway/tcp-addresses", - type: "doc", - label: "TCP Addresses", - }, "universal-gateway/tls-certificates", "universal-gateway/edges", ], From 9f4c1ac5198a1871c9c17488d7eedbaaee1d4238 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 14 Mar 2025 13:06:34 -0400 Subject: [PATCH 016/137] Cleanup before doing redirects/link removal --- .../global-load-balancer.mdx | 2 ++ docs/universal-gateway/tcp-addresses.mdx | 30 ------------------- .../tcp-addresses/what-are-tcp-addresses.mdx | 10 +++++++ 3 files changed, 12 insertions(+), 30 deletions(-) delete mode 100644 docs/universal-gateway/tcp-addresses.mdx diff --git a/docs/universal-gateway/global-load-balancer.mdx b/docs/universal-gateway/global-load-balancer.mdx index 1f621b7955..c1e1d22b18 100644 --- a/docs/universal-gateway/global-load-balancer.mdx +++ b/docs/universal-gateway/global-load-balancer.mdx @@ -137,6 +137,8 @@ of presence. TCP Endpoints do not support GSLB. Unlike domains, TCP addresses are provisioned for a specific [Point of Presence](/universal-gateway/points-of-presence). When you create a TCP Address, you must select the point of presence where it will accept traffic. Connections to matching TCP Endpoints on a TCP Address will always route to the TCP Address's point of presence, no matter where those connections originated in the world. +[Learn more about TCP Address load balancing](/universal-gateway/tcp-addresses/what-are-tcp-addresses/#tcp-address-load-balancing). + ## Domains [Domains](/universal-gateway/domains/what-are-domains) allow you to configure which points of presence the Global Load diff --git a/docs/universal-gateway/tcp-addresses.mdx b/docs/universal-gateway/tcp-addresses.mdx deleted file mode 100644 index 60b18baad2..0000000000 --- a/docs/universal-gateway/tcp-addresses.mdx +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: What are TCP Addresses? ---- - -TCP Addresses enable you to create public [TCP Endpoints](/universal-gateway/tcp/) on a fixed address. TCP Addresses are a combination of a hostname and a port, such as `1.tcp.eu.ngrok.io:12345`. - -You can manage TCP Addresses with: - -- [The Dashboard](https://dashboard.ngrok.com/tcp-addresses) -- [The API](/api/resources/reserved-addrs/) - -:::note -Only TCP Endpoints may be created on TCP Addresses. To create other endpoint -types, create a [Domain](/universal-gateway/domains/what-are-domains/). -::: - -## Global Load Balancer - -ngrok does not support global load balancing for TCP Addresses, but you can connect TCP Addresses to [Agent Endpoints](/agent/) in different [Points of Presence](/universal-gateway/points-of-presence). This allows you to accept traffic to a TCP Address in one region, then forward it to an Agent in a different region. - -The following example [CLI command](/agent/cli) creates an agent in the `jp` region that connects to a TCP address in the `eu` region: - -```sh -ngrok tcp 3389 --region jp --url tcp://1.tcp.eu.ngrok.io:12345 -``` - -## Pricing - -TCP Addresses are available on paid plans only, they are not available on the -free plan. diff --git a/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx b/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx index 43cfd5f72f..5e9621ebf9 100644 --- a/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx +++ b/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx @@ -15,6 +15,16 @@ Only TCP Endpoints may be created on TCP Addresses. For other endpoint types, create a [Domain](/universal-gateway/domains/what-are-domains/). ::: +## TCP Address load balancing + +ngrok does not support global load balancing for TCP Addresses, but you can connect TCP Addresses to [Agent Endpoints](/agent/) in different [Points of Presence](/universal-gateway/points-of-presence). This allows you to accept traffic to a TCP Address in one region, then forward it to an Agent in a different region. + +The following example [CLI command](/agent/cli) creates an agent in the `jp` region that connects to a TCP address in the `eu` region: + +```sh +ngrok tcp 3389 --region jp --url tcp://1.tcp.eu.ngrok.io:12345 +``` + ## Pricing TCP Addresses are available on paid plans only, they are not available on the From 1fde9a8c406e788b2d886731dd7f5d4dd3720c3c Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 14 Mar 2025 13:16:22 -0400 Subject: [PATCH 017/137] Links and redirects for TCP done; need to do domains --- docs/faq/faq.mdx | 2 +- docs/universal-gateway/overview.mdx | 2 +- docs/universal-gateway/public-endpoints.mdx | 4 ++-- docs/universal-gateway/tcp.mdx | 2 +- docs/whats-new.mdx | 2 +- static/scripts/fix-redirect.js | 10 +++++----- .../redirects/question-answer-redirects.js | 16 ++++++++++++++++ 7 files changed, 27 insertions(+), 11 deletions(-) create mode 100644 static/scripts/redirects/question-answer-redirects.js diff --git a/docs/faq/faq.mdx b/docs/faq/faq.mdx index 2a93a37f2f..24da8e9de6 100644 --- a/docs/faq/faq.mdx +++ b/docs/faq/faq.mdx @@ -66,7 +66,7 @@ and port 443 as well for TLS endpoints. This behavior is not configurable. TCP endpoints use the port of the TCP address that was assigned when you acquires the TCP address. [This port is assigned and not -configurable](/universal-gateway/tcp-addresses/#address-assignment). +configurable](/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned/). ## Will the ngrok agent work if my network changes? {#network-changes} diff --git a/docs/universal-gateway/overview.mdx b/docs/universal-gateway/overview.mdx index e7f98363af..9de6465f05 100644 --- a/docs/universal-gateway/overview.mdx +++ b/docs/universal-gateway/overview.mdx @@ -19,7 +19,7 @@ Bindings, Pools and Domains to understand how they work. Learn more about Universal Gateway Concepts: - [Domains →](/universal-gateway/domains/what-are-domains/) -- [TCP Addresses →](/universal-gateway/tcp-addresses/) +- [TCP Addresses →](/universal-gateway/tcp-addresses/what-are-tcp-addresses/) - [TLS Certificates →](/universal-gateway/tls-certificates/) - [Edges →](/universal-gateway/edges/) diff --git a/docs/universal-gateway/public-endpoints.mdx b/docs/universal-gateway/public-endpoints.mdx index 4575ec78d4..1c974471c2 100644 --- a/docs/universal-gateway/public-endpoints.mdx +++ b/docs/universal-gateway/public-endpoints.mdx @@ -9,7 +9,7 @@ Public endpoints enable you to receive traffic from the internet via ngrok’s [ Public endpoint URLs must: -- Use either a [Domain](/universal-gateway/domains/what-are-domains/) or [TCP Address](/universal-gateway/tcp-addresses/) +- Use either a [Domain](/universal-gateway/domains/what-are-domains/) or [TCP Address](/universal-gateway/tcp-addresses/what-are-tcp-addresses/) - Use the `public` [binding](/docs/universal-gateway/bindings/) ## Get started @@ -74,7 +74,7 @@ differently based on the protocol of the URL. - You must specify a port number in TCP URLs. - The hostname and port must match the address of a [TCP - Address](/universal-gateway/tcp-addresses) in your account. + Address](/universal-gateway/tcp-addresses/what-are-tcp-addresses/) in your account. **Examples** diff --git a/docs/universal-gateway/tcp.mdx b/docs/universal-gateway/tcp.mdx index 27591fd0d7..a68f7eaf9c 100644 --- a/docs/universal-gateway/tcp.mdx +++ b/docs/universal-gateway/tcp.mdx @@ -111,7 +111,7 @@ There is no standard scheme for TCP URLs so ngrok renders them as `tcp://`. ### Static URLs If you would like a public TCP endpoint to have a static URL, you must first -create a [TCP Address](/universal-gateway/tcp-addresses). When you create a TCP +create a [TCP Address](/universal-gateway/tcp-addresses/what-are-tcp-addresses/). When you create a TCP address, a random hostname and port will be assigned to you, e.g. `1.tcp.ngrok.io:12345`. diff --git a/docs/whats-new.mdx b/docs/whats-new.mdx index 7a1047ddfc..953c93cb77 100644 --- a/docs/whats-new.mdx +++ b/docs/whats-new.mdx @@ -175,7 +175,7 @@ You can expect this page to update regularly (at least monthly). We'll include t - 2023-12-20 - Removed the ability to use ngrok without an account. All users need to register for an account and use a valid authtoken to use ngrok. - 2023-12-11 - Added the ability to use [HTTP/2 between the agent and your upstream service](/universal-gateway/http/#http2-forwarding). - 2023-12-06 - Release [ngrok Agent JavaScript SDK](https://ngrok.com/blog-post/ngrok-js) and [ngrok Agent Python SDK](https://ngrok.com/blog-post/ngrok-python) allowing developers to integrate ngrok natively into their application. -- 2023-12-04 - [Cross Region TCP Endpoints](/universal-gateway/tcp-addresses/#global-load-balancer) are available meaning ngrok TCP addresses can be served from agents in any region. +- 2023-12-04 - [Cross Region TCP Endpoints](/universal-gateway/tcp-addresses/what-are-tcp-addresses/#tcp-address-load-balancing) are available meaning ngrok TCP addresses can be served from agents in any region. - 2023-12-01 - Released [ngrok Agent 3.5.0](/agent/changelog/#ngrok-agent-350---2023-12-01) - 2023-12-01 - [ngrok-go 1.7.0 Released](https://github.com/ngrok/ngrok-go/releases/tag/v1.7.0) diff --git a/static/scripts/fix-redirect.js b/static/scripts/fix-redirect.js index 635e141643..4712027fb5 100644 --- a/static/scripts/fix-redirect.js +++ b/static/scripts/fix-redirect.js @@ -1,17 +1,17 @@ -const getNormalizedPaths = (from, path) => { +export const getNormalizedPaths = (from, path) => { return { normalizedFrom: from.endsWith('/') ? from.slice(0, -1) : from, normalizedPath: path.endsWith('/') ? path.slice(0, -1) : path } } -const fromExact = (from) => (path) => { +export const fromExact = (from) => (path) => { const {normalizedFrom, normalizedPath} = getNormalizedPaths(from, path); return [ normalizedFrom, normalizedPath === normalizedFrom ] // [xyz] } -const fromIncludes = (from) => (path) => { +export const fromIncludes = (from) => (path) => { // Normalize both paths by removing trailing slashes if present const {normalizedFrom, normalizedPath} = getNormalizedPaths(from, path); @@ -19,8 +19,8 @@ const fromIncludes = (from) => (path) => { return [normalizedFrom, normalizedPath.includes(normalizedFrom)]; }; -const toExact = (to) => () => to // x -> y -const toReplace = (to) => (path, from) => path.replace(from, to) // abc/x -> xyz/x +export const toExact = (to) => () => to // x -> y +export const toReplace = (to) => (path, from) => path.replace(from, to) // abc/x -> xyz/x // List of redirects // String values are treated as exacts by default. diff --git a/static/scripts/redirects/question-answer-redirects.js b/static/scripts/redirects/question-answer-redirects.js new file mode 100644 index 0000000000..9babcc6789 --- /dev/null +++ b/static/scripts/redirects/question-answer-redirects.js @@ -0,0 +1,16 @@ +import { fromExact, fromIncludes } from "../fix-redirect" + +export default [ + /** + * Universal Gateway > Concepts + */ + // Domains + [ fromExact('/docs/universal-gateway/domains/'), '/docs/universal-gateway/domains/what-are-domains/' ], + + // TCP Addresses + [ fromExact('/docs/universal-gateway/tcp-addresses/'), '/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses/' ], + // hashes + [ fromExact('/docs/universal-gateway/tcp-addresses/#public-endpoint-creation'), '/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses/' ], + [ fromExact('/docs/universal-gateway/tcp-addresses/#address-assignment'), '/docs/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned/' ], + [ fromExact('/docs/universal-gateway/tcp-addresses/#global-load-balancer/'), '/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses/#tcp-address-load-balancing' ], +] From f8051ac7e8283b091da68c96a27f5307645a9266 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 14 Mar 2025 13:49:30 -0400 Subject: [PATCH 018/137] Hashes and redirects for domains --- docs/universal-gateway/domains/what-are-domains.mdx | 2 +- docs/universal-gateway/public-endpoints.mdx | 2 -- static/scripts/redirects/question-answer-redirects.js | 7 +++++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/universal-gateway/domains/what-are-domains.mdx b/docs/universal-gateway/domains/what-are-domains.mdx index 71554fd458..9d756e87d3 100644 --- a/docs/universal-gateway/domains/what-are-domains.mdx +++ b/docs/universal-gateway/domains/what-are-domains.mdx @@ -2,7 +2,7 @@ title: What are Domains? --- -Domains enable you to create [public endpoints](/universal-gateway/domains/what-are-public-endpoints/) with hostnames matching the domain. For example, after you create the domain `your-name.ngrok.app`, you may create the Endpoint `https://your-name.ngrok.app`. +Domains enable you to create [public endpoints](/universal-gateway/domains/public-endpoints/) with hostnames matching the domain. For example, after you create the domain `your-name.ngrok.app`, you may create the Endpoint `https://your-name.ngrok.app`. Valid Domain names include: diff --git a/docs/universal-gateway/public-endpoints.mdx b/docs/universal-gateway/public-endpoints.mdx index 1c974471c2..ceae862bee 100644 --- a/docs/universal-gateway/public-endpoints.mdx +++ b/docs/universal-gateway/public-endpoints.mdx @@ -33,8 +33,6 @@ To keep such services both public and secure, you can add a Traffic Policy to yo - [IP restrictions](/docs/traffic-policy/actions/restrict-ips/) - [Mutual TLS](/docs/traffic-policy/actions/terminate-tls/#example-traffic-policy-document) -## Domains - ## URLs When you create a public endpoint, the URL you create it with is validated diff --git a/static/scripts/redirects/question-answer-redirects.js b/static/scripts/redirects/question-answer-redirects.js index 9babcc6789..28d6d50c54 100644 --- a/static/scripts/redirects/question-answer-redirects.js +++ b/static/scripts/redirects/question-answer-redirects.js @@ -6,6 +6,13 @@ export default [ */ // Domains [ fromExact('/docs/universal-gateway/domains/'), '/docs/universal-gateway/domains/what-are-domains/' ], + // hashes + [ fromExact('/docs/universal-gateway/domains/#branded-domains'), '/docs/universal-gateway/domains/how-do-i-use-my-own-domain/' ], + [ fromExact('/docs/universal-gateway/domains/#global-load-balancer'), '/docs/universal-gateway/global-load-balancer/' ], + [ fromExact('/docs/universal-gateway/domains/#public-endpoints'), '/docs/universal-gateway/public-endpoints/' ], + [ fromExact('/docs/universal-gateway/domains/#ngrok-managed-domains'), '/docs/universal-gateway/domains/what-are-managed-domains/' ], + [ fromExact('/docs/universal-gateway/domains/#hsts-preload'), '/docs/universal-gateway/domains/what-are-managed-domains/#hsts-preload' ], + [ fromExact('/docs/universal-gateway/domains/#public-suffix-list'), '/docs/universal-gateway/domains/what-are-managed-domains/#public-suffix-list' ], // TCP Addresses [ fromExact('/docs/universal-gateway/tcp-addresses/'), '/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses/' ], From c804aa836ebcd5205491ac589e8d268b18dc2e01 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 14 Mar 2025 13:50:13 -0400 Subject: [PATCH 019/137] Add redirects to fix-redirect --- static/scripts/fix-redirect.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/static/scripts/fix-redirect.js b/static/scripts/fix-redirect.js index 4712027fb5..303c5a6ecd 100644 --- a/static/scripts/fix-redirect.js +++ b/static/scripts/fix-redirect.js @@ -1,3 +1,4 @@ +import questionAnswerRedirects from "./redirects/question-answer-redirects"; export const getNormalizedPaths = (from, path) => { return { @@ -296,7 +297,7 @@ const redirects = [ [ fromExact('/docs/http/'), '/docs/universal-gateway/http/'], [ fromExact('/docs/tcp/'), '/docs/universal-gateway/tcp/'], [ fromExact('/docs/tls/'), '/docs/universal-gateway/tls/'], - + ...questionAnswerRedirects, ] // get current href from window From 720473373f1b9341bfe62fce86cf78184b5272c4 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 14 Mar 2025 14:24:36 -0400 Subject: [PATCH 020/137] Set up TLS top-level page --- .../domains/how-do-i-use-my-own-domain.mdx | 1 + .../domains/what-are-domains.mdx | 1 + .../domains/what-are-managed-domains.mdx | 1 + .../tcp-addresses/what-are-tcp-addresses.mdx | 1 + docs/universal-gateway/tls-certificates.mdx | 5 ---- .../how-does-ngrok-handle-tls.mdx | 24 +++++++++++++++++++ 6 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx diff --git a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx index c969d8b05b..6a25958a7d 100644 --- a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx +++ b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx @@ -1,5 +1,6 @@ --- title: How do I Use My Own Domain? +description: Learn how to use your own domain with ngrok. --- You can use any domain name that you already own with ngrok, e.g. diff --git a/docs/universal-gateway/domains/what-are-domains.mdx b/docs/universal-gateway/domains/what-are-domains.mdx index 9d756e87d3..ec21aedadc 100644 --- a/docs/universal-gateway/domains/what-are-domains.mdx +++ b/docs/universal-gateway/domains/what-are-domains.mdx @@ -1,5 +1,6 @@ --- title: What are Domains? +description: Learn how to create domains in your ngrok account. --- Domains enable you to create [public endpoints](/universal-gateway/domains/public-endpoints/) with hostnames matching the domain. For example, after you create the domain `your-name.ngrok.app`, you may create the Endpoint `https://your-name.ngrok.app`. diff --git a/docs/universal-gateway/domains/what-are-managed-domains.mdx b/docs/universal-gateway/domains/what-are-managed-domains.mdx index c60de2217c..537467f02f 100644 --- a/docs/universal-gateway/domains/what-are-managed-domains.mdx +++ b/docs/universal-gateway/domains/what-are-managed-domains.mdx @@ -1,5 +1,6 @@ --- title: What are Managed Domains? +description: Learn about the free and paid domains that ngrok provides. --- If you don't [already own a Domain](/universal-gateway/how-do-i-use-my-own-domain) that you want to use with ngrok, you can create a domain that is a subdomain of an ngrok-managed base domain. diff --git a/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx b/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx index 5e9621ebf9..0e2d6ddf80 100644 --- a/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx +++ b/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx @@ -1,5 +1,6 @@ --- title: What are TCP Addresses? +description: Learn how to use TCP Addresses with ngrok. --- [TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol) Addresses enable you to create public [TCP Endpoints](/universal-gateway/tcp/) on static addresses. All TCP Addresses contain both their hostname and port, such as `1.tcp.eu.ngrok.io:12345`. diff --git a/docs/universal-gateway/tls-certificates.mdx b/docs/universal-gateway/tls-certificates.mdx index 86d38c46ca..7bc2b3bf91 100644 --- a/docs/universal-gateway/tls-certificates.mdx +++ b/docs/universal-gateway/tls-certificates.mdx @@ -176,8 +176,3 @@ ngrok encrypts your uploaded private keys at rest with TLS certificates are managed programatically via: - [`/tls_certificates` API Resource](/api/resources/tls-certificates/) - -## Pricing - -TLS certificates are available on all plans. Bringing your own certificates is -available on the Enterprise plan. diff --git a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx new file mode 100644 index 0000000000..97f164e6a3 --- /dev/null +++ b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx @@ -0,0 +1,24 @@ +--- +title: How Does ngrok Handle TLS Certificates? +description: Learn how ngrok handles TLS certificates. +--- + +ngrok automatically handles TLS (SSL) certificate management and termination +for you with no configuration required in most cases. You can allow ngrok to automatically provision certificates for you, or you can [use your own](/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates). + +You can manage TLS certificates with: + +- [The Dashboard](https://dashboard.ngrok.com/tls-certs) +- [The API](/api/resources/tls-certificates/). + +## How certificates work + +TLS certificates are composed of a private key and certificate. These are presented by the ngrok cloud service during [TLS handshakes](https://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_handshake) to terminate TLS connections to [HTTPS endpoints](/universal-gateway/http) and [TLS endpoints](/universal-gateway/tls). + +## Certificates with domains + +TLS certificates are attached to [domains](/universal-gateway/domains/what-are-domains/) for [termination of TLS connections to endpoints](/universal-gateway/tls-termination/) whose URLs match that domain. + +## Pricing + +TLS certificates are available on all plans. Bringing your own certificates is available on the Enterprise plan. See the [pricing page](https://ngrok.com/pricing) for details. From 472ae71dba5e6357749f433a5cded8554149df59 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Mon, 17 Mar 2025 10:10:08 -0400 Subject: [PATCH 021/137] Finished with how tls certs get selected --- .../how-are-certificates-selected.mdx | 15 +++++++++++++++ .../how-does-ngrok-handle-tls.mdx | 4 +++- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 docs/universal-gateway/tls-certificates/how-are-certificates-selected.mdx diff --git a/docs/universal-gateway/tls-certificates/how-are-certificates-selected.mdx b/docs/universal-gateway/tls-certificates/how-are-certificates-selected.mdx new file mode 100644 index 0000000000..27ccb11946 --- /dev/null +++ b/docs/universal-gateway/tls-certificates/how-are-certificates-selected.mdx @@ -0,0 +1,15 @@ +--- +title: How are Certificates Selected? +description: Learn how ngrok selects certificates for TLS termination. +--- + +When TLS connections to an endpoint are terminated, ngrok uses the TLS certificate attached to the [Domain](/universal-gateway/domains/what-are-domains) matching the endpoint's URL. + +Each [domain](/universal-gateway/domains/what-are-domains/) on ngrok has an attached TLS certificate, which you can find by: + +- [Fetching the domain object from the API](/api/resources/reserved-domains#request-2) +- [Viewing the domain in the dashboard](https://dashboard.ngrok.com/domains) + +If the domain object doesn't reference any certificate, or if there is no matching domain object for an endpoint's URL, ngrok selects its own TLS certificate for termination. + +You may override the certificate used for TLS termination by explicitly terminating TLS yourself with the [`terminate-tls` traffic policy action](/traffic-policy/actions/terminate-tls/). diff --git a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx index 97f164e6a3..69ca8e10b7 100644 --- a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx +++ b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx @@ -4,13 +4,15 @@ description: Learn how ngrok handles TLS certificates. --- ngrok automatically handles TLS (SSL) certificate management and termination -for you with no configuration required in most cases. You can allow ngrok to automatically provision certificates for you, or you can [use your own](/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates). +for you out of the box, but you can also [customize how termination works](/traffic-policy/actions/terminate-tls/) and [use your own certificates](/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates). You can manage TLS certificates with: - [The Dashboard](https://dashboard.ngrok.com/tls-certs) - [The API](/api/resources/tls-certificates/). +You can also [specify the local path to a certificate file](/agent/cli/#example-10) when starting a TLS endpoint with the Agent CLI. + ## How certificates work TLS certificates are composed of a private key and certificate. These are presented by the ngrok cloud service during [TLS handshakes](https://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_handshake) to terminate TLS connections to [HTTPS endpoints](/universal-gateway/http) and [TLS endpoints](/universal-gateway/tls). From b70305943f860ce986ae8c28e9b9c3a0fb76d064 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Mon, 17 Mar 2025 11:16:28 -0400 Subject: [PATCH 022/137] halfway through automated certs --- .../how-are-certificates-selected.mdx | 3 +- .../how-does-ngrok-handle-tls.mdx | 5 +- ...at-is-automatic-certificate-management.mdx | 50 +++++++++++++++++++ 3 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx diff --git a/docs/universal-gateway/tls-certificates/how-are-certificates-selected.mdx b/docs/universal-gateway/tls-certificates/how-are-certificates-selected.mdx index 27ccb11946..f546fcce09 100644 --- a/docs/universal-gateway/tls-certificates/how-are-certificates-selected.mdx +++ b/docs/universal-gateway/tls-certificates/how-are-certificates-selected.mdx @@ -8,7 +8,8 @@ When TLS connections to an endpoint are terminated, ngrok uses the TLS certifica Each [domain](/universal-gateway/domains/what-are-domains/) on ngrok has an attached TLS certificate, which you can find by: - [Fetching the domain object from the API](/api/resources/reserved-domains#request-2) -- [Viewing the domain in the dashboard](https://dashboard.ngrok.com/domains) + - Or [listing all TLS Certificates](/api/resources/tls-certificates/#list-tls-certificates) +- [Viewing your TLS Certificates in the dashboard](https://dashboard.ngrok.com/tls-certs) If the domain object doesn't reference any certificate, or if there is no matching domain object for an endpoint's URL, ngrok selects its own TLS certificate for termination. diff --git a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx index 69ca8e10b7..53b8ec34a7 100644 --- a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx +++ b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx @@ -3,8 +3,7 @@ title: How Does ngrok Handle TLS Certificates? description: Learn how ngrok handles TLS certificates. --- -ngrok automatically handles TLS (SSL) certificate management and termination -for you out of the box, but you can also [customize how termination works](/traffic-policy/actions/terminate-tls/) and [use your own certificates](/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates). +ngrok [automatically handles](/universal-gateway/tls-certificates/what-is-automatic-certificate-management) TLS (SSL) certificate management and termination for you out of the box, but you can also [customize how termination works](/traffic-policy/actions/terminate-tls/) and [use your own certificates](/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates). You can manage TLS certificates with: @@ -15,7 +14,7 @@ You can also [specify the local path to a certificate file](/agent/cli/#example- ## How certificates work -TLS certificates are composed of a private key and certificate. These are presented by the ngrok cloud service during [TLS handshakes](https://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_handshake) to terminate TLS connections to [HTTPS endpoints](/universal-gateway/http) and [TLS endpoints](/universal-gateway/tls). +TLS certificates are composed of a private key and a certificate. These are presented by the ngrok cloud service during [TLS handshakes](https://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_handshake) to terminate TLS connections to [HTTPS endpoints](/universal-gateway/http) and [TLS endpoints](/universal-gateway/tls). ## Certificates with domains diff --git a/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx b/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx new file mode 100644 index 0000000000..78a507dca1 --- /dev/null +++ b/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx @@ -0,0 +1,50 @@ +--- +title: What is automatic certificate management? +description: Learn how ngrok provisions TLS certificates. +--- + +Whenever you create a [domain](/universal-gateway/domains/what-are-domains/), ngrok automatically provisions and manages your TLS certificates by default. Your TLS certificates will be automatically provisioned **and renewed** with [Let's Encrypt](https://letsencrypt.org/about/), an ACME-compliant certificate authority. + +Alternatively, you can [bring your own TLS certificates](/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates) and [use your own certificate authority](/api/resources/certificate-authorities/). + +:::tip +It is recommended that you choose automatic TLS certificate management unless you have special requirements. +::: + +## Let's Encrypt + +ngrok is a [Let's Encrypt sponsor](https://letsencrypt.org/sponsors/). + +When provisioning TLS certificates with Let's Encrypt, ngrok uses a [HTTP01 challenge](https://letsencrypt.org/docs/challenge-types/#http-01-challenge) for most domains. When you create a [wildcard domain](#using-wildcard-domains), ngrok uses a [DNS01 challenge](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge) instead. + +## How long does provisoning take? + +TLS certificates are provisioned asynchronously. Depending on the speed of the ACME certificate authority, it can take anywhere between a few seconds to 10 minutes for your certificate to be provisioned. + +You can check the status of a certificate provisioning job by [requesting the domain with ngrok's API](/api/resources/reserved-domains/#get-reserved-domain). Each domain object contains a `certificate_management_status` property. + +## Using your own domain + +When you [bring your own domain](/universal-gateway/how-do-i-use-my-own-domain) (e.g. `api.your-domain.com`) you must create a `CNAME` DNS record in your DNS provider. Automatic certificate provisioning will not begin until your create this `CNAME` DNS record. + +## Using wildcard domains + +When you bring your own wildcard domain (e.g. `*.app.example.com`), ngrok uses a DNS01 challenge for TLS certificate provisioning which means that you must create two CNAME records when creating branded wildcard domains instead of just one. + +For example, If your domain is `*.app.example.com` you will be required to create the following two CNAME records: + +- `*.app.example.com` +- `_acme-challenge.app.example.com` + +Certificate provisioning will not begin until you have created both DNS +records. + +### Private Keys + +When using automatic TLS certificates, ngrok generates a private key for your +domain and encrypts it at rest with with [NaCL](https://nacl.cr.yp.to/). + +When you configure a domain to use automated certificates, you may electively +choose whether ngrok will create an ECDSA private key (the default) or RSA +private key. If you choose an RSA private key, it is created with a size of +4096 bits. From e82151428b6b2d02821620a9558d2c4c0a7dd60b Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Mon, 17 Mar 2025 11:58:50 -0400 Subject: [PATCH 023/137] Rough draft of automatic certs --- ...at-is-automatic-certificate-management.mdx | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx b/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx index 78a507dca1..91468529e7 100644 --- a/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx +++ b/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx @@ -3,7 +3,7 @@ title: What is automatic certificate management? description: Learn how ngrok provisions TLS certificates. --- -Whenever you create a [domain](/universal-gateway/domains/what-are-domains/), ngrok automatically provisions and manages your TLS certificates by default. Your TLS certificates will be automatically provisioned **and renewed** with [Let's Encrypt](https://letsencrypt.org/about/), an ACME-compliant certificate authority. +Whenever you create a [domain](/universal-gateway/domains/what-are-domains/), ngrok automatically provisions and manages your TLS certificates by default. Your TLS certificates will be automatically provisioned **and renewed** with [Let's Encrypt](https://letsencrypt.org/about/), an ACME-compliant certificate authority. Others may be supported in the future. Alternatively, you can [bring your own TLS certificates](/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates) and [use your own certificate authority](/api/resources/certificate-authorities/). @@ -11,13 +11,13 @@ Alternatively, you can [bring your own TLS certificates](/universal-gateway/tls- It is recommended that you choose automatic TLS certificate management unless you have special requirements. ::: -## Let's Encrypt +## Provisioning with Let's Encrypt ngrok is a [Let's Encrypt sponsor](https://letsencrypt.org/sponsors/). When provisioning TLS certificates with Let's Encrypt, ngrok uses a [HTTP01 challenge](https://letsencrypt.org/docs/challenge-types/#http-01-challenge) for most domains. When you create a [wildcard domain](#using-wildcard-domains), ngrok uses a [DNS01 challenge](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge) instead. -## How long does provisoning take? +### How long does provisioning take? TLS certificates are provisioned asynchronously. Depending on the speed of the ACME certificate authority, it can take anywhere between a few seconds to 10 minutes for your certificate to be provisioned. @@ -25,11 +25,11 @@ You can check the status of a certificate provisioning job by [requesting the do ## Using your own domain -When you [bring your own domain](/universal-gateway/how-do-i-use-my-own-domain) (e.g. `api.your-domain.com`) you must create a `CNAME` DNS record in your DNS provider. Automatic certificate provisioning will not begin until your create this `CNAME` DNS record. +When you [bring your own domain](/universal-gateway/how-do-i-use-my-own-domain) (e.g. `api.your-domain.com`), automatic certificate provisioning will not begin until your create a `CNAME` DNS record with your domain provider. -## Using wildcard domains +### Using wildcard domains -When you bring your own wildcard domain (e.g. `*.app.example.com`), ngrok uses a DNS01 challenge for TLS certificate provisioning which means that you must create two CNAME records when creating branded wildcard domains instead of just one. +With wild card domains (e.g. `*.app.example.com`), ngrok uses a [DNS01 challenge](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge) for TLS certificate provisioning. This means you must create two `CNAME` records when adding wildcard domains to your ngrok account. For example, If your domain is `*.app.example.com` you will be required to create the following two CNAME records: @@ -42,9 +42,10 @@ records. ### Private Keys When using automatic TLS certificates, ngrok generates a private key for your -domain and encrypts it at rest with with [NaCL](https://nacl.cr.yp.to/). +domain and encrypts it [at rest](https://en.wikipedia.org/wiki/Data_at_rest) with [NaCL](https://nacl.cr.yp.to/). -When you configure a domain to use automated certificates, you may electively -choose whether ngrok will create an ECDSA private key (the default) or RSA -private key. If you choose an RSA private key, it is created with a size of -4096 bits. +When you configure a domain to use automated certificates, you can choose which type of private key will be generated for it. Options include: + +- [ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) (default) +- [RSA]() + - If you choose an RSA private key, it will be created with a size of `4096` bits. From 6a15d713fe8ab5c503d91cdc5349d54ce1281420 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Mon, 17 Mar 2025 13:17:55 -0400 Subject: [PATCH 024/137] Still working on bring-your-own certificates --- .../how-do-i-use-my-own-certificates.mdx | 116 ++++++++++++++++++ ...at-is-automatic-certificate-management.mdx | 26 ++-- 2 files changed, 128 insertions(+), 14 deletions(-) create mode 100644 docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx diff --git a/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx b/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx new file mode 100644 index 0000000000..bc59acc799 --- /dev/null +++ b/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx @@ -0,0 +1,116 @@ +--- +title: How do I use my own certificates? +description: Learn how to use your own TLS certificates rather than automatic certificate management. +--- + +ngrok [manages TLS certificates for your domains automatically](/universal-gateway/tls-certificates/what-is-automatic-certificate-management) by default, and in general automatic management is recommended. However, you may also upload and manage your own TLS certificates. + +:::warning +You cannot use your own certificates with [ngrok's managed domains](/universal-gateway/domains/what-are-managed-domains). +::: + +Uploading your own certificates may be the right choice if you are: + +- Issuing certificates from your own preferred certificate authority +- Using an [EV certificate](https://en.wikipedia.org/wiki/Extended_Validation_Certificate) + +## Using your own certificate + +To use your own TLS certificates with ngrok, you first need to upload the certificate, then attach it to a domain. To do so: + +1. Upload a certificate bundle and a private key. You can do this with one of the following: + - [The TLS section of the Dashboard](https://dashboard.ngrok.com/tls-certs) + - [The API](/api/resources/tls-certificates/#create-tls-certificate): + ```bash + curl \ + -X POST \ + -H "Authorization: Bearer {API_KEY}" \ + -H "Content-Type: application/json" \ + -H "Ngrok-Version: 2" \ + -d '{"certificate_pem":"-----BEGIN CERTIFICATE-----\ncertificate-here\n-----END CERTIFICATE-----","private_key_pem":"-----BEGIN PRIVATE KEY-----\nprivate-key-here\n-----END PRIVATE KEY-----"}' \ + https://api.ngrok.com/tls_certificates + ``` +1. After you create your TLS certificate, you must attach it to one or more domains on ngrok before it can be used for termination. You can do so with one of the following: + - [The Domains section of the dashboard](https://dashboard.ngrok.com/domains) + 1. Select your domain. + 1. Expand the dropdown that says "Automated TLS Certificates" to choose the "Use an uploaded certificate" option. + - [With the Domains API resource](/api/resources/reserved-domains/#update-reserved-domain), using the `certificate_id` property in the request body. You must have already uploaded your TLS certificate with the API or dashboard. + ```bash + curl \ + -X PATCH \ + -H "Authorization: Bearer {API_KEY}" \ + -H "Content-Type: application/json" \ + -H "Ngrok-Version: 2" \ + -d '{"certificate_id":"id-for-certificate-here' \ + https://api.ngrok.com/reserved_domains/rd_2uBNwCkQlImhoyji1BWWiMGAHwc + ``` + +### Certificate Bundles {#certificate-bundles} + +Unlike automatic TLS certificates, when you are using custom TLS certificates, you are responsible for managing the renewal and rotation of new certificates. + +When uploading your own TLS certificates to ngrok, you are expected to provide +a certificate bundle of all certificates necessary to establish a chain of +trust to a trusted root certificate authority. Many TLS certificate vendors +will provide you with a constructed certificate bundle, but some will return +the leaf certificate and the intermediate certificates separately and you must +concatenate them to construct the bundle yourself. This is the +`certificate_pem` field in the [TLS Certificate Create +API](/api/resources/tls-certificates/). + +Certificate bundles are a series of PEM-encoded X.509 certificates that have +been concatenated together. **The order of this bundle is significant.** + +The first certificate in the bundle must be the leaf certificate. The leaf +certificate is the one which is signed for your domain and [the private +key](#private-keys) you will upload. + +After the leaf certificate are the intermediates certificates, if any. Each +intermediate certificate signs the certificate preceding it in the bundle. As +an example, the first intermediate will sign the leaf, and that signature is +part of the leaf certificate itself. The final certificate will be signed by +the root certificate authority. You may also included the root certificate in +the bundle as well, but it is not necessary or common practice to do so. + +A certificate bundle will look like the following: + +```pem +-----BEGIN CERTIFICATE----- +... +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +... +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +... +-----END CERTIFICATE----- +``` + +### Private Keys {#private-keys} + +ngrok accepts the following formats for the private key of an uploaded TLS +certificate. This is the `private_key_pem` field in the [TLS Certificate Create +API](/api/resources/tls-certificates/). + +- RSA, in either PKCS#1 or PKCS#8 form. +- ECDSA, in either SEC 1 or PKCS#8 form. +- Ed25519, in PKCS#8 form. + +Regardless of the format you choose, the private key must be formatted as ASN.1 +DER, encoded as PEM. ngrok will not accept any private keys that are encrypted +(e.g. with DES). + +ngrok encrypts your uploaded private keys at rest with +[NaCL](https://nacl.cr.yp.to/). + +## Using wildcard domains + +With wild card domains (e.g. `*.app.example.com`), ngrok uses a [DNS01 challenge](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge) for TLS certificate provisioning. This means you must create two `CNAME` records when adding wildcard domains to your ngrok account. + +For example, If your domain is `*.app.example.com` you will be required to create the following two CNAME records: + +- `*.app.example.com` +- `_acme-challenge.app.example.com` + +Certificate provisioning will not begin until you have created both DNS +records. diff --git a/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx b/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx index 91468529e7..90ab6c2446 100644 --- a/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx +++ b/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx @@ -11,7 +11,7 @@ Alternatively, you can [bring your own TLS certificates](/universal-gateway/tls- It is recommended that you choose automatic TLS certificate management unless you have special requirements. ::: -## Provisioning with Let's Encrypt +## Let's Encrypt provisioning ngrok is a [Let's Encrypt sponsor](https://letsencrypt.org/sponsors/). @@ -23,21 +23,19 @@ TLS certificates are provisioned asynchronously. Depending on the speed of the A You can check the status of a certificate provisioning job by [requesting the domain with ngrok's API](/api/resources/reserved-domains/#get-reserved-domain). Each domain object contains a `certificate_management_status` property. -## Using your own domain +## Configuring automatic management -When you [bring your own domain](/universal-gateway/how-do-i-use-my-own-domain) (e.g. `api.your-domain.com`), automatic certificate provisioning will not begin until your create a `CNAME` DNS record with your domain provider. +You can use the API to configure automatic TLS certificate management for a domain by sending a request with the `"certificate_management_policy"` property to [`/reserved_domains/{id}`](https://ngrok.com/docs/api/resources/reserved-domains/#update-reserved-domain). -### Using wildcard domains - -With wild card domains (e.g. `*.app.example.com`), ngrok uses a [DNS01 challenge](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge) for TLS certificate provisioning. This means you must create two `CNAME` records when adding wildcard domains to your ngrok account. - -For example, If your domain is `*.app.example.com` you will be required to create the following two CNAME records: - -- `*.app.example.com` -- `_acme-challenge.app.example.com` - -Certificate provisioning will not begin until you have created both DNS -records. +```bash +curl \ +-X PATCH \ +-H "Authorization: Bearer {API_KEY}" \ +-H "Content-Type: application/json" \ +-H "Ngrok-Version: 2" \ +-d '{"certificate_management_policy":{"authority":"letsencrypt"},"description":"point-of-sale new york #302","http_endpoint_configuration_id":"ec_2uBNwE5PEQsAgI7WQkwC8mL1a2x","https_endpoint_configuration_id":"ec_2uBNwBytfQIshIWu9bdcD0Buy78","metadata":"{env: \"staging\", \"connector_id\":\"64698fcc-5f5c-4b63-910e-8669d04bd943\"}"}' \ +https://api.ngrok.com/reserved_domains/rd_2uBNwCkQlImhoyji1BWWiMGAHwc +``` ### Private Keys From 2913be27e209de8bb0c488838dd92f8a5d801cb1 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Mon, 17 Mar 2025 15:50:10 -0400 Subject: [PATCH 025/137] More cleanup --- .../how-do-i-use-my-own-certificates.mdx | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx b/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx index bc59acc799..e37df3222b 100644 --- a/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx +++ b/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx @@ -45,17 +45,11 @@ To use your own TLS certificates with ngrok, you first need to upload the certif https://api.ngrok.com/reserved_domains/rd_2uBNwCkQlImhoyji1BWWiMGAHwc ``` -### Certificate Bundles {#certificate-bundles} +### Certificate bundles -Unlike automatic TLS certificates, when you are using custom TLS certificates, you are responsible for managing the renewal and rotation of new certificates. +Unlike [automatic certificate management](/universal-gateway/tls-certificates/what-is-automatic-certificate-management), when you use custom TLS certificates, you must manage the renewal and rotation of new certificates yourself. -When uploading your own TLS certificates to ngrok, you are expected to provide -a certificate bundle of all certificates necessary to establish a chain of -trust to a trusted root certificate authority. Many TLS certificate vendors -will provide you with a constructed certificate bundle, but some will return -the leaf certificate and the intermediate certificates separately and you must -concatenate them to construct the bundle yourself. This is the -`certificate_pem` field in the [TLS Certificate Create +When uploading your own TLS certificates to ngrok, you are expected to provide a certificate bundle of all certificates necessary to establish a chain of trust to a trusted root certificate authority. Many TLS certificate vendors will provide you with a constructed certificate bundle, but some will return the leaf certificate and the intermediate certificates separately and you must concatenate them to construct the bundle yourself. This is the `certificate_pem` field in the [TLS Certificate Create API](/api/resources/tls-certificates/). Certificate bundles are a series of PEM-encoded X.509 certificates that have From bd186d0ee28bc9147a0a8314ce1432fb157adfe3 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 18 Mar 2025 13:50:19 -0400 Subject: [PATCH 026/137] Finished what-is-a-certificate-bundle --- .../how-do-i-use-my-own-certificates.mdx | 68 +------------------ .../what-is-a-certificate-bundle.mdx | 60 ++++++++++++++++ .../what-is-a-private-key.mdx | 31 +++++++++ 3 files changed, 93 insertions(+), 66 deletions(-) create mode 100644 docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx create mode 100644 docs/universal-gateway/tls-certificates/what-is-a-private-key.mdx diff --git a/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx b/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx index e37df3222b..000188585b 100644 --- a/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx +++ b/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx @@ -3,7 +3,7 @@ title: How do I use my own certificates? description: Learn how to use your own TLS certificates rather than automatic certificate management. --- -ngrok [manages TLS certificates for your domains automatically](/universal-gateway/tls-certificates/what-is-automatic-certificate-management) by default, and in general automatic management is recommended. However, you may also upload and manage your own TLS certificates. +ngrok [manages TLS certificates for your domains automatically](/universal-gateway/tls-certificates/what-is-automatic-certificate-management) by default, and in general automatic management is recommended. However, you may also upload and manage the renewal and rotation of your TLS certificates yourself. :::warning You cannot use your own certificates with [ngrok's managed domains](/universal-gateway/domains/what-are-managed-domains). @@ -18,7 +18,7 @@ Uploading your own certificates may be the right choice if you are: To use your own TLS certificates with ngrok, you first need to upload the certificate, then attach it to a domain. To do so: -1. Upload a certificate bundle and a private key. You can do this with one of the following: +1. Upload a [certificate bundle](/universal-gateway/tls-certificates/what-is-a-cerficate-bundle) and a [private key](/universal-gateway/tls-certificates/what-is-a-private-key). You can do this with one of the following: - [The TLS section of the Dashboard](https://dashboard.ngrok.com/tls-certs) - [The API](/api/resources/tls-certificates/#create-tls-certificate): ```bash @@ -44,67 +44,3 @@ To use your own TLS certificates with ngrok, you first need to upload the certif -d '{"certificate_id":"id-for-certificate-here' \ https://api.ngrok.com/reserved_domains/rd_2uBNwCkQlImhoyji1BWWiMGAHwc ``` - -### Certificate bundles - -Unlike [automatic certificate management](/universal-gateway/tls-certificates/what-is-automatic-certificate-management), when you use custom TLS certificates, you must manage the renewal and rotation of new certificates yourself. - -When uploading your own TLS certificates to ngrok, you are expected to provide a certificate bundle of all certificates necessary to establish a chain of trust to a trusted root certificate authority. Many TLS certificate vendors will provide you with a constructed certificate bundle, but some will return the leaf certificate and the intermediate certificates separately and you must concatenate them to construct the bundle yourself. This is the `certificate_pem` field in the [TLS Certificate Create -API](/api/resources/tls-certificates/). - -Certificate bundles are a series of PEM-encoded X.509 certificates that have -been concatenated together. **The order of this bundle is significant.** - -The first certificate in the bundle must be the leaf certificate. The leaf -certificate is the one which is signed for your domain and [the private -key](#private-keys) you will upload. - -After the leaf certificate are the intermediates certificates, if any. Each -intermediate certificate signs the certificate preceding it in the bundle. As -an example, the first intermediate will sign the leaf, and that signature is -part of the leaf certificate itself. The final certificate will be signed by -the root certificate authority. You may also included the root certificate in -the bundle as well, but it is not necessary or common practice to do so. - -A certificate bundle will look like the following: - -```pem ------BEGIN CERTIFICATE----- -... ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -... ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -... ------END CERTIFICATE----- -``` - -### Private Keys {#private-keys} - -ngrok accepts the following formats for the private key of an uploaded TLS -certificate. This is the `private_key_pem` field in the [TLS Certificate Create -API](/api/resources/tls-certificates/). - -- RSA, in either PKCS#1 or PKCS#8 form. -- ECDSA, in either SEC 1 or PKCS#8 form. -- Ed25519, in PKCS#8 form. - -Regardless of the format you choose, the private key must be formatted as ASN.1 -DER, encoded as PEM. ngrok will not accept any private keys that are encrypted -(e.g. with DES). - -ngrok encrypts your uploaded private keys at rest with -[NaCL](https://nacl.cr.yp.to/). - -## Using wildcard domains - -With wild card domains (e.g. `*.app.example.com`), ngrok uses a [DNS01 challenge](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge) for TLS certificate provisioning. This means you must create two `CNAME` records when adding wildcard domains to your ngrok account. - -For example, If your domain is `*.app.example.com` you will be required to create the following two CNAME records: - -- `*.app.example.com` -- `_acme-challenge.app.example.com` - -Certificate provisioning will not begin until you have created both DNS -records. diff --git a/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx b/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx new file mode 100644 index 0000000000..51659fccce --- /dev/null +++ b/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx @@ -0,0 +1,60 @@ +--- +title: What is a certificate bundle? +description: Learn what a certificate bundle is and how to upload one to ngrok. +--- + +When [uploading your own TLS certificates to ngrok](/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates), you must also upload a certificate bundle. + +Certificate bundles are a combination of all TLS certificates necessary to establish a chain of trust to a trusted root certificate authority. They consist of a series of [PEM-encoded X.509](https://en.wikipedia.org/wiki/X.509) certificates that have been concatenated together. **The certificates must be arranged in the proper order.** + +## Creating a certificate bundle + +You can construct a bundle by pasting each certificate in order into a single file. + +A certificate bundle will look like the following, with the leaf certificate first, followed by any intermediate certificates, and, optionally, the root certificate: + +```bash +-----BEGIN CERTIFICATE----- +... +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +... +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +... +-----END CERTIFICATE----- +``` + +### Using the API + +When uploading a certificate bundle [with the API](/api/resources/tls-certificates#create-tls-certificate), you can use the `certificate_pem` field to provide the certificate bundle. + +```bash +curl \ +-X POST \ +-H "Authorization: Bearer {API_KEY}" \ +-H "Content-Type: application/json" \ +-H "Ngrok-Version: 2" \ +-d '{"certificate_pem":"-----BEGIN CERTIFICATE-----\nMIIDDTCCAfWgAwIBAgIUBUunDdA4gjgtEbZA8w9Ljhvl3bEwDQYJKoZIhvcNAQEL\nBQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wHhcNMjAwMzI0MTgxODE5WhcNMjAw\nNDIzMTgxODE5WjAWMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcN\nAQEBBQADggEPADCCAQoCggEBAPKVkkKYNl3d9cqrz4tIFlwsohED5W4y1dcBixy4\nGANFFnw43nc2wPyKwYXumJqJIFrcW/NkUZL07bd+dou6mT6Gh/zbaTW91IkREPXL\n7b3KfVu4XkFosVXpWs0U6o4GrZ81CLiKBWI+H03x/ij5OSiJ1l71pqLeTJLOydAR\nAl8kpp7axeHU4UbDrAZkW5SnuZTjIKwVg0UNsBg1yNfUOu1Uah3BYaqPgQitC0Yg\nLW+NUGu/T91bkD7tLsVInkQXeQGdXBAqOycfJ7wj8OlIpyuXjTnGFA0izVmbQw5f\nrQnZ0geGyhLamvz9Gcd7mIlD/+/AEN9Lht82tAOzKG98/O8CAwEAAaNTMFEwHQYD\nVR0OBBYEFKv6RsvEC6T+zCtJZwB0FCR1sEkhMB8GA1UdIwQYMBaAFKv6RsvEC6T+\nzCtJZwB0FCR1sEkhMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB\nAC5fBrouinespo5+9AipjhY/HOKTg+OCnppFnSnqeU1eXZZJ0oakdHTpTNxtbQP9\ntOJTA2f3KWvmpNDMohEQXZz8wHDkdbrIXJKVp6zs1pEp+0BIjA4y9mSywa5xuyk0\noGeChRgGqp2JujDyPCb7LEaKKQEEdMqy73QG+jEAh14+wKixlAf1nATBdeCUvssK\n2x1uZMyqjJFB5y/5EdnWQzD4WJkrsCkxsZHVMN1d+dqf2sf3dTRV8fzsFGOG17NS\n6u2n9iGcFdBA82XN8yeLIWhy1t3GWutG1sdxENbFRRXea+iUqzDsmRtkaBma2GLQ\nd6JTpFbsCtwDjP23UEi7SZo=\n-----END CERTIFICATE-----","private_key_pem":"-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDylZJCmDZd3fXK\nq8+LSBZcLKIRA+VuMtXXAYscuBgDRRZ8ON53NsD8isGF7piaiSBa3FvzZFGS9O23\nfnaLupk+hof822k1vdSJERD1y+29yn1buF5BaLFV6VrNFOqOBq2fNQi4igViPh9N\n8f4o+TkoidZe9aai3kySzsnQEQJfJKae2sXh1OFGw6wGZFuUp7mU4yCsFYNFDbAY\nNcjX1DrtVGodwWGqj4EIrQtGIC1vjVBrv0/dW5A+7S7FSJ5EF3kBnVwQKjsnHye8\nI/DpSKcrl405xhQNIs1Zm0MOX60J2dIHhsoS2pr8/RnHe5iJQ//vwBDfS4bfNrQD\nsyhvfPzvAgMBAAECggEBALLv7YE98exvi5zB+0fMFuJK8gkHDLequ93q/4hhqyTO\nU3WyJTdepiAi4fk/NEXZnIopPZJdj2aNUMQnfp43OE7MwYac+hBwRFQOyKnmkSmM\nMcf0SWKKLTUn+piIMzQsbOmhHxuwg6QiGslOFaJ3o9fpRL2rCg3dWDJ6Ypcd1NgE\nK0uy7gg+DwIpU6MeG6lA+HbxbGi+yd2x88Gjn9dGr7FZK34RUDooH60BCX9P8N9X\nT+n10MzzX7ZQOsLfe8FKc1/X8AybI5SYm1GMyfKD4QBt6JG4HKAjPHzBzcIpfN3d\n7BM11Imkrz7LcbUG+F23NVsi6n5IIGT1WqwCRIH2PpECgYEA/SJ5Ra4d0hUS5RYB\nzABquM3sp7JsKxCn7O5PqNLB4TgH9dXtWFhaFVB6juMGyHbvktVH0j4lps/Te0rk\nVU2zU1XxvCTFhtcCYUtNk0cRw6LH8feKiorXHdDRB33t0c47QSD/6AGOjBtxqD7B\n3ZxyR3P+7RdQopLLRFN+FHAnmzsCgYEA9VSGZDFSK+fbg4CgwkWdzuHrAXaUEv0U\novqqWd/yXB9wauEvRHnOrSgW6hFZQiatJOXx0KnalJQzohz/SLGO0MqGtwQbYWVT\nWiJgjUbNeiPEHBeUA6U55lVQr26kQSUWdXEtRbDz+hqV1K+6tTEMzaSPmJiHNgki\nlNMO2gqGQd0CgYBJ268qx5zn2UJEGWG41j5NYbg1TfgFsLxugzI2/heX0TNxZVP1\nPQI7ydmYq2ElSJ6qZxSnoX5255i7FqT8xskV/bOkw83mhAGrxb8Cw+/I90wDq8h+\nl/ggOPdkijfDybq8TBae6SVgd/l3r6f9M1KcypmNMApVBSPN8daNvBOyVQKBgQDo\nsj2utyFrx8Xsm4rf+kxOuPbBMooM4MQ8OmpuSP6G5sMofWLqHmcs0sO5TK9PEYRV\nZU3ST+ml2FSJRdvWRaRi4laZLWoTHZrL+aN/HVM0sMwIoUyhkIy0ruOTIuzlZZpB\n1xHL8qXX6nOHgw8jYdz1CUuyv6owVMXaR77kjer+eQKBgByYZlR/eNTzlot0SdFl\nIbgQ9bV7VLIo+vKzOXE3trfzRJMgUosLTp+5wdSVSW/VBdYZ7Ir3n0bbpY/dGinI\nVShxPbChhCZnhvG2lEEiekI44m5jHSA6hhtRdt/CrhL65Rw2SE5lMEe8htg1UGus\nwzLHWHBl72FjbjdhvEgrq60W\n-----END PRIVATE KEY-----"}' \ +https://api.ngrok.com/tls_certificates +``` + +## Structure + +Many TLS certificate vendors will provide you with a constructed certificate bundle, but some provide the [leaf certificate](https://letsencrypt.org/docs/glossary/#def-certificate) and the [intermediate certificates](https://letsencrypt.org/docs/glossary/#def-intermediate) separately. + +### Leaf certificates + +The first certificate in the bundle must be the leaf certificate. The leaf certificate is the one which is signed for your domain and [the private key](#private-keys) you will upload. + +### Intermediate certificates + +After the leaf certificate are the intermediate certificates, if any. Each intermediate certificate signs the certificate preceding it in the bundle. As an example, the first intermediate will sign the leaf, and that signature is part of the leaf certificate itself. + +### Root certificates + +The final certificate will be signed by the root certificate authority. You may include the root certificate in the bundle as well, but it is not necessary or common practice to do so. + +``` + +``` diff --git a/docs/universal-gateway/tls-certificates/what-is-a-private-key.mdx b/docs/universal-gateway/tls-certificates/what-is-a-private-key.mdx new file mode 100644 index 0000000000..e92b5d405e --- /dev/null +++ b/docs/universal-gateway/tls-certificates/what-is-a-private-key.mdx @@ -0,0 +1,31 @@ +--- +title: What is a private key? +description: Learn what a private key is and how to upload one to ngrok. +--- + +ngrok accepts the following formats for the private key of an uploaded TLS +certificate. This is the `private_key_pem` field in the [TLS Certificate Create +API](/api/resources/tls-certificates/). + +- RSA, in either PKCS#1 or PKCS#8 form. +- ECDSA, in either SEC 1 or PKCS#8 form. +- Ed25519, in PKCS#8 form. + +Regardless of the format you choose, the private key must be formatted as ASN.1 +DER, encoded as PEM. ngrok will not accept any private keys that are encrypted +(e.g. with DES). + +ngrok encrypts your uploaded private keys at rest with +[NaCL](https://nacl.cr.yp.to/). + +## Using wildcard domains + +With wild card domains (e.g. `*.app.example.com`), ngrok uses a [DNS01 challenge](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge) for TLS certificate provisioning. This means you must create two `CNAME` records when adding wildcard domains to your ngrok account. + +For example, If your domain is `*.app.example.com` you will be required to create the following two CNAME records: + +- `*.app.example.com` +- `_acme-challenge.app.example.com` + +Certificate provisioning will not begin until you have created both DNS +records. From 604cb57b57cf6714814b8a71164bcb974126f419 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 18 Mar 2025 14:20:33 -0400 Subject: [PATCH 027/137] finished what is a private key --- .../what-is-a-certificate-bundle.mdx | 2 +- .../what-is-a-private-key.mdx | 41 ++++++++++--------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx b/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx index 51659fccce..d5e4ae16cb 100644 --- a/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx +++ b/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx @@ -5,7 +5,7 @@ description: Learn what a certificate bundle is and how to upload one to ngrok. When [uploading your own TLS certificates to ngrok](/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates), you must also upload a certificate bundle. -Certificate bundles are a combination of all TLS certificates necessary to establish a chain of trust to a trusted root certificate authority. They consist of a series of [PEM-encoded X.509](https://en.wikipedia.org/wiki/X.509) certificates that have been concatenated together. **The certificates must be arranged in the proper order.** +Certificate bundles are a combination of all TLS certificates necessary to establish a [chain of trust](https://letsencrypt.org/certificates/) to a trusted root certificate authority. They consist of a series of [PEM-encoded X.509](https://en.wikipedia.org/wiki/X.509) certificates that have been concatenated together. **The certificates must be arranged in the proper order.** ## Creating a certificate bundle diff --git a/docs/universal-gateway/tls-certificates/what-is-a-private-key.mdx b/docs/universal-gateway/tls-certificates/what-is-a-private-key.mdx index e92b5d405e..077c8f1186 100644 --- a/docs/universal-gateway/tls-certificates/what-is-a-private-key.mdx +++ b/docs/universal-gateway/tls-certificates/what-is-a-private-key.mdx @@ -1,31 +1,34 @@ --- title: What is a private key? -description: Learn what a private key is and how to upload one to ngrok. +description: Learn what a TLS Certificate private key is and how to upload one to ngrok. --- -ngrok accepts the following formats for the private key of an uploaded TLS -certificate. This is the `private_key_pem` field in the [TLS Certificate Create -API](/api/resources/tls-certificates/). +When [uploading your own TLS certificates to ngrok](/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates), you must also upload a private key. -- RSA, in either PKCS#1 or PKCS#8 form. -- ECDSA, in either SEC 1 or PKCS#8 form. -- Ed25519, in PKCS#8 form. +You can do so with the `private_key_pem` field when uploading a TLS certificate [with the API](/api/resources/tls-certificates/). -Regardless of the format you choose, the private key must be formatted as ASN.1 -DER, encoded as PEM. ngrok will not accept any private keys that are encrypted -(e.g. with DES). +```bash +curl \ +-X POST \ +-H "Authorization: Bearer {API_KEY}" \ +-H "Content-Type: application/json" \ +-H "Ngrok-Version: 2" \ +-d '{"certificate_pem":"-----BEGIN CERTIFICATE-----\nMIIDDTCCAfWgAwIBAgIUBUunDdA4gjgtEbZA8w9Ljhvl3bEwDQYJKoZIhvcNAQEL\nBQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wHhcNMjAwMzI0MTgxODE5WhcNMjAw\nNDIzMTgxODE5WjAWMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcN\nAQEBBQADggEPADCCAQoCggEBAPKVkkKYNl3d9cqrz4tIFlwsohED5W4y1dcBixy4\nGANFFnw43nc2wPyKwYXumJqJIFrcW/NkUZL07bd+dou6mT6Gh/zbaTW91IkREPXL\n7b3KfVu4XkFosVXpWs0U6o4GrZ81CLiKBWI+H03x/ij5OSiJ1l71pqLeTJLOydAR\nAl8kpp7axeHU4UbDrAZkW5SnuZTjIKwVg0UNsBg1yNfUOu1Uah3BYaqPgQitC0Yg\nLW+NUGu/T91bkD7tLsVInkQXeQGdXBAqOycfJ7wj8OlIpyuXjTnGFA0izVmbQw5f\nrQnZ0geGyhLamvz9Gcd7mIlD/+/AEN9Lht82tAOzKG98/O8CAwEAAaNTMFEwHQYD\nVR0OBBYEFKv6RsvEC6T+zCtJZwB0FCR1sEkhMB8GA1UdIwQYMBaAFKv6RsvEC6T+\nzCtJZwB0FCR1sEkhMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB\nAC5fBrouinespo5+9AipjhY/HOKTg+OCnppFnSnqeU1eXZZJ0oakdHTpTNxtbQP9\ntOJTA2f3KWvmpNDMohEQXZz8wHDkdbrIXJKVp6zs1pEp+0BIjA4y9mSywa5xuyk0\noGeChRgGqp2JujDyPCb7LEaKKQEEdMqy73QG+jEAh14+wKixlAf1nATBdeCUvssK\n2x1uZMyqjJFB5y/5EdnWQzD4WJkrsCkxsZHVMN1d+dqf2sf3dTRV8fzsFGOG17NS\n6u2n9iGcFdBA82XN8yeLIWhy1t3GWutG1sdxENbFRRXea+iUqzDsmRtkaBma2GLQ\nd6JTpFbsCtwDjP23UEi7SZo=\n-----END CERTIFICATE-----","private_key_pem":"-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDylZJCmDZd3fXK\nq8+LSBZcLKIRA+VuMtXXAYscuBgDRRZ8ON53NsD8isGF7piaiSBa3FvzZFGS9O23\nfnaLupk+hof822k1vdSJERD1y+29yn1buF5BaLFV6VrNFOqOBq2fNQi4igViPh9N\n8f4o+TkoidZe9aai3kySzsnQEQJfJKae2sXh1OFGw6wGZFuUp7mU4yCsFYNFDbAY\nNcjX1DrtVGodwWGqj4EIrQtGIC1vjVBrv0/dW5A+7S7FSJ5EF3kBnVwQKjsnHye8\nI/DpSKcrl405xhQNIs1Zm0MOX60J2dIHhsoS2pr8/RnHe5iJQ//vwBDfS4bfNrQD\nsyhvfPzvAgMBAAECggEBALLv7YE98exvi5zB+0fMFuJK8gkHDLequ93q/4hhqyTO\nU3WyJTdepiAi4fk/NEXZnIopPZJdj2aNUMQnfp43OE7MwYac+hBwRFQOyKnmkSmM\nMcf0SWKKLTUn+piIMzQsbOmhHxuwg6QiGslOFaJ3o9fpRL2rCg3dWDJ6Ypcd1NgE\nK0uy7gg+DwIpU6MeG6lA+HbxbGi+yd2x88Gjn9dGr7FZK34RUDooH60BCX9P8N9X\nT+n10MzzX7ZQOsLfe8FKc1/X8AybI5SYm1GMyfKD4QBt6JG4HKAjPHzBzcIpfN3d\n7BM11Imkrz7LcbUG+F23NVsi6n5IIGT1WqwCRIH2PpECgYEA/SJ5Ra4d0hUS5RYB\nzABquM3sp7JsKxCn7O5PqNLB4TgH9dXtWFhaFVB6juMGyHbvktVH0j4lps/Te0rk\nVU2zU1XxvCTFhtcCYUtNk0cRw6LH8feKiorXHdDRB33t0c47QSD/6AGOjBtxqD7B\n3ZxyR3P+7RdQopLLRFN+FHAnmzsCgYEA9VSGZDFSK+fbg4CgwkWdzuHrAXaUEv0U\novqqWd/yXB9wauEvRHnOrSgW6hFZQiatJOXx0KnalJQzohz/SLGO0MqGtwQbYWVT\nWiJgjUbNeiPEHBeUA6U55lVQr26kQSUWdXEtRbDz+hqV1K+6tTEMzaSPmJiHNgki\nlNMO2gqGQd0CgYBJ268qx5zn2UJEGWG41j5NYbg1TfgFsLxugzI2/heX0TNxZVP1\nPQI7ydmYq2ElSJ6qZxSnoX5255i7FqT8xskV/bOkw83mhAGrxb8Cw+/I90wDq8h+\nl/ggOPdkijfDybq8TBae6SVgd/l3r6f9M1KcypmNMApVBSPN8daNvBOyVQKBgQDo\nsj2utyFrx8Xsm4rf+kxOuPbBMooM4MQ8OmpuSP6G5sMofWLqHmcs0sO5TK9PEYRV\nZU3ST+ml2FSJRdvWRaRi4laZLWoTHZrL+aN/HVM0sMwIoUyhkIy0ruOTIuzlZZpB\n1xHL8qXX6nOHgw8jYdz1CUuyv6owVMXaR77kjer+eQKBgByYZlR/eNTzlot0SdFl\nIbgQ9bV7VLIo+vKzOXE3trfzRJMgUosLTp+5wdSVSW/VBdYZ7Ir3n0bbpY/dGinI\nVShxPbChhCZnhvG2lEEiekI44m5jHSA6hhtRdt/CrhL65Rw2SE5lMEe8htg1UGus\nwzLHWHBl72FjbjdhvEgrq60W\n-----END PRIVATE KEY-----"}' \ +https://api.ngrok.com/tls_certificates +``` -ngrok encrypts your uploaded private keys at rest with -[NaCL](https://nacl.cr.yp.to/). +## Accepted formats -## Using wildcard domains +ngrok accepts the following private key formats: -With wild card domains (e.g. `*.app.example.com`), ngrok uses a [DNS01 challenge](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge) for TLS certificate provisioning. This means you must create two `CNAME` records when adding wildcard domains to your ngrok account. +- [RSA](), in either `PKCS#1` or `PKCS#8` form. +- [ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm), in either `SEC 1` or `PKCS#8` form. +- [Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519), in PKCS#8 form. -For example, If your domain is `*.app.example.com` you will be required to create the following two CNAME records: +Regardless of the format you choose, the private key must be formatted as [`ASN.1 DER`](https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/), encoded as `PEM`. -- `*.app.example.com` -- `_acme-challenge.app.example.com` +## Encryption -Certificate provisioning will not begin until you have created both DNS -records. +ngrok will not accept any private keys that are encrypted (e.g. with `DES`). + +ngrok encrypts your uploaded private keys [at rest](https://en.wikipedia.org/wiki/Data_at_rest) with [NaCL](https://nacl.cr.yp.to/). From 1728f562d20ec65d9d29ba843355fab20f8247be Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 18 Mar 2025 14:31:51 -0400 Subject: [PATCH 028/137] Set up sidebar --- .../how-do-i-use-my-own-certificates.mdx | 2 +- .../how-does-ngrok-handle-tls.mdx | 8 +++++++- ...e-key.mdx => what-are-private-tls-keys.mdx} | 2 +- sidebars.js | 18 +++++++++++++++--- 4 files changed, 24 insertions(+), 6 deletions(-) rename docs/universal-gateway/tls-certificates/{what-is-a-private-key.mdx => what-are-private-tls-keys.mdx} (99%) diff --git a/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx b/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx index 000188585b..a71b719576 100644 --- a/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx +++ b/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx @@ -18,7 +18,7 @@ Uploading your own certificates may be the right choice if you are: To use your own TLS certificates with ngrok, you first need to upload the certificate, then attach it to a domain. To do so: -1. Upload a [certificate bundle](/universal-gateway/tls-certificates/what-is-a-cerficate-bundle) and a [private key](/universal-gateway/tls-certificates/what-is-a-private-key). You can do this with one of the following: +1. Upload a [certificate bundle](/universal-gateway/tls-certificates/what-is-a-cerficate-bundle) and a [private key](/universal-gateway/tls-certificates/what-are-private-tls-keys). You can do this with one of the following: - [The TLS section of the Dashboard](https://dashboard.ngrok.com/tls-certs) - [The API](/api/resources/tls-certificates/#create-tls-certificate): ```bash diff --git a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx index 53b8ec34a7..c0b7052227 100644 --- a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx +++ b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx @@ -1,5 +1,5 @@ --- -title: How Does ngrok Handle TLS Certificates? +title: How Does ngrok Handle TLS? description: Learn how ngrok handles TLS certificates. --- @@ -20,6 +20,12 @@ TLS certificates are composed of a private key and a certificate. These are pres TLS certificates are attached to [domains](/universal-gateway/domains/what-are-domains/) for [termination of TLS connections to endpoints](/universal-gateway/tls-termination/) whose URLs match that domain. +## API + +TLS certificates are managed programatically via: + +- [`/tls_certificates` API Resource](/api/resources/tls-certificates/) + ## Pricing TLS certificates are available on all plans. Bringing your own certificates is available on the Enterprise plan. See the [pricing page](https://ngrok.com/pricing) for details. diff --git a/docs/universal-gateway/tls-certificates/what-is-a-private-key.mdx b/docs/universal-gateway/tls-certificates/what-are-private-tls-keys.mdx similarity index 99% rename from docs/universal-gateway/tls-certificates/what-is-a-private-key.mdx rename to docs/universal-gateway/tls-certificates/what-are-private-tls-keys.mdx index 077c8f1186..6370920454 100644 --- a/docs/universal-gateway/tls-certificates/what-is-a-private-key.mdx +++ b/docs/universal-gateway/tls-certificates/what-are-private-tls-keys.mdx @@ -1,5 +1,5 @@ --- -title: What is a private key? +title: What are private TLS keys? description: Learn what a TLS Certificate private key is and how to upload one to ngrok. --- diff --git a/sidebars.js b/sidebars.js index 7084cdf7c0..93ae4449e4 100644 --- a/sidebars.js +++ b/sidebars.js @@ -69,13 +69,25 @@ const sidebars = { ], }, { - label: "Concepts", + label: "How Does ngrok Handle TLS?", type: "category", + link: { + type: "doc", + id: "universal-gateway/tls-certificates/how-does-ngrok-handle-tls", + }, items: [ - "universal-gateway/tls-certificates", - "universal-gateway/edges", + "universal-gateway/tls-certificates/what-is-automatic-certificate-management", + "universal-gateway/tls-certificates/how-are-certificates-selected", + "universal-gateway/tls-certificates/how-do-i-use-my-own-certificate", + "universal-gateway/tls-certificates/what-is-a-certificate-bundle", + "universal-gateway/tls-certificates/what-are-private-tls-keys", ], }, + { + label: "Concepts", + type: "category", + items: ["universal-gateway/edges"], + }, { label: "Endpoints", type: "category", From 8050a639de20df758915e8ca202e082566f7bcbd Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 18 Mar 2025 14:34:03 -0400 Subject: [PATCH 029/137] Fix sidebar typo --- sidebars.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sidebars.js b/sidebars.js index 93ae4449e4..cf978274e7 100644 --- a/sidebars.js +++ b/sidebars.js @@ -78,7 +78,7 @@ const sidebars = { items: [ "universal-gateway/tls-certificates/what-is-automatic-certificate-management", "universal-gateway/tls-certificates/how-are-certificates-selected", - "universal-gateway/tls-certificates/how-do-i-use-my-own-certificate", + "universal-gateway/tls-certificates/how-do-i-use-my-own-certificates", "universal-gateway/tls-certificates/what-is-a-certificate-bundle", "universal-gateway/tls-certificates/what-are-private-tls-keys", ], From fa9e55fa3c1bffd32742b8fbe0e7441b8d1b3686 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 18 Mar 2025 14:41:35 -0400 Subject: [PATCH 030/137] Updated page titles --- docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx | 2 +- docs/universal-gateway/domains/what-are-domains.mdx | 2 +- docs/universal-gateway/domains/what-are-managed-domains.mdx | 2 +- .../tcp-addresses/how-are-tcp-addresses-assigned.mdx | 2 +- .../tcp-addresses/what-are-tcp-addresses.mdx | 2 +- .../tls-certificates/how-are-certificates-selected.mdx | 2 +- .../tls-certificates/how-do-i-use-my-own-certificates.mdx | 4 ++-- .../tls-certificates/what-are-private-tls-keys.mdx | 2 +- .../tls-certificates/what-is-a-certificate-bundle.mdx | 2 +- .../what-is-automatic-certificate-management.mdx | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx index 6a25958a7d..d77684ab5d 100644 --- a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx +++ b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx @@ -1,5 +1,5 @@ --- -title: How do I Use My Own Domain? +title: How Do I Use My Own Domain? description: Learn how to use your own domain with ngrok. --- diff --git a/docs/universal-gateway/domains/what-are-domains.mdx b/docs/universal-gateway/domains/what-are-domains.mdx index ec21aedadc..1d1b500f51 100644 --- a/docs/universal-gateway/domains/what-are-domains.mdx +++ b/docs/universal-gateway/domains/what-are-domains.mdx @@ -1,5 +1,5 @@ --- -title: What are Domains? +title: What Are Domains? description: Learn how to create domains in your ngrok account. --- diff --git a/docs/universal-gateway/domains/what-are-managed-domains.mdx b/docs/universal-gateway/domains/what-are-managed-domains.mdx index 537467f02f..94a998dd4f 100644 --- a/docs/universal-gateway/domains/what-are-managed-domains.mdx +++ b/docs/universal-gateway/domains/what-are-managed-domains.mdx @@ -1,5 +1,5 @@ --- -title: What are Managed Domains? +title: What Are Managed Domains? description: Learn about the free and paid domains that ngrok provides. --- diff --git a/docs/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned.mdx b/docs/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned.mdx index 9b1c96e81a..76b82beb18 100644 --- a/docs/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned.mdx +++ b/docs/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned.mdx @@ -1,5 +1,5 @@ --- -title: How are TCP Addresses Assigned? +title: How Are TCP Addresses Assigned? description: Learn how ngrok assignes TCP Addresses. --- diff --git a/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx b/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx index 0e2d6ddf80..e2d72a5f77 100644 --- a/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx +++ b/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx @@ -1,5 +1,5 @@ --- -title: What are TCP Addresses? +title: What Are TCP Addresses? description: Learn how to use TCP Addresses with ngrok. --- diff --git a/docs/universal-gateway/tls-certificates/how-are-certificates-selected.mdx b/docs/universal-gateway/tls-certificates/how-are-certificates-selected.mdx index f546fcce09..94280beb9c 100644 --- a/docs/universal-gateway/tls-certificates/how-are-certificates-selected.mdx +++ b/docs/universal-gateway/tls-certificates/how-are-certificates-selected.mdx @@ -1,5 +1,5 @@ --- -title: How are Certificates Selected? +title: How Are Certificates Selected? description: Learn how ngrok selects certificates for TLS termination. --- diff --git a/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx b/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx index a71b719576..8f3d337252 100644 --- a/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx +++ b/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx @@ -1,5 +1,5 @@ --- -title: How do I use my own certificates? +title: How Do I Use My Own Certificates? description: Learn how to use your own TLS certificates rather than automatic certificate management. --- @@ -18,7 +18,7 @@ Uploading your own certificates may be the right choice if you are: To use your own TLS certificates with ngrok, you first need to upload the certificate, then attach it to a domain. To do so: -1. Upload a [certificate bundle](/universal-gateway/tls-certificates/what-is-a-cerficate-bundle) and a [private key](/universal-gateway/tls-certificates/what-are-private-tls-keys). You can do this with one of the following: +1. Upload a [certificate bundle](/universal-gateway/tls-certificates/what-is-a-certificate-bundle/) and a [private key](/universal-gateway/tls-certificates/what-are-private-tls-keys). You can do this with one of the following: - [The TLS section of the Dashboard](https://dashboard.ngrok.com/tls-certs) - [The API](/api/resources/tls-certificates/#create-tls-certificate): ```bash diff --git a/docs/universal-gateway/tls-certificates/what-are-private-tls-keys.mdx b/docs/universal-gateway/tls-certificates/what-are-private-tls-keys.mdx index 6370920454..afadc89335 100644 --- a/docs/universal-gateway/tls-certificates/what-are-private-tls-keys.mdx +++ b/docs/universal-gateway/tls-certificates/what-are-private-tls-keys.mdx @@ -1,5 +1,5 @@ --- -title: What are private TLS keys? +title: What Are Private TLS Keys? description: Learn what a TLS Certificate private key is and how to upload one to ngrok. --- diff --git a/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx b/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx index d5e4ae16cb..0601c07c73 100644 --- a/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx +++ b/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx @@ -1,5 +1,5 @@ --- -title: What is a certificate bundle? +title: What Is a Certificate Bundle? description: Learn what a certificate bundle is and how to upload one to ngrok. --- diff --git a/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx b/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx index 90ab6c2446..40d2d8aace 100644 --- a/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx +++ b/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx @@ -1,5 +1,5 @@ --- -title: What is automatic certificate management? +title: What Is Automatic Certificate Management? description: Learn how ngrok provisions TLS certificates. --- From faddbe2759909c54c0d5a6b888f3c3f1a8748536 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 18 Mar 2025 15:46:09 -0400 Subject: [PATCH 031/137] Fix redirects, remove dead links --- .../other-guides/securing-your-tunnels.mdx | 2 +- docs/obs/events/reference.mdx | 144 +++++++++--------- .../domains/how-do-i-use-my-own-domain.mdx | 2 +- .../domains/what-are-domains.mdx | 2 +- docs/universal-gateway/http.mdx | 2 +- docs/universal-gateway/overview.mdx | 4 +- .../how-does-ngrok-handle-tls.mdx | 16 ++ docs/universal-gateway/tls-termination.mdx | 8 +- docs/universal-gateway/tls.mdx | 2 +- .../redirects/question-answer-redirects.js | 9 ++ 10 files changed, 108 insertions(+), 83 deletions(-) diff --git a/docs/guides/other-guides/securing-your-tunnels.mdx b/docs/guides/other-guides/securing-your-tunnels.mdx index a8829c491a..148587ef95 100644 --- a/docs/guides/other-guides/securing-your-tunnels.mdx +++ b/docs/guides/other-guides/securing-your-tunnels.mdx @@ -26,7 +26,7 @@ For our HTTP tunnel type, use `scheme https` to configure the ngrok agent to ope If your local service is not running on the same machine as the ngrok agent, we recommend that you set up TLS encryption for the ngrok agent to upstream service leg of the tunnel using our [local HTTPS feature](/universal-gateway/http/#https-forwarding). -For custom domains, use ngrok's [Automated TLS certificates](/universal-gateway/tls-certificates/#automated) to have ngrok automatically provision a TLS certificate for your endpoint from Let's Encrypt. +For custom domains, use ngrok's [Automated TLS certificates](/universal-gateway/tls-certificates/what-is-automatic-certificate-management/) to have ngrok automatically provision a TLS certificate for your endpoint from Let's Encrypt. :::note diff --git a/docs/obs/events/reference.mdx b/docs/obs/events/reference.mdx index 8aa385be95..99d0bb1031 100644 --- a/docs/obs/events/reference.mdx +++ b/docs/obs/events/reference.mdx @@ -898,88 +898,88 @@ Triggers when a TCP address is updated Triggers when a TLS certificate is created -| Field | Type | Description | -| ------------------------------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------- | -| `id` | string | unique identifier for this TLS certificate | -| `uri` | string | URI of the TLS certificate API resource | -| `created_at` | string | timestamp when the TLS certificate was created, RFC 3339 format | -| `description` | string | human-readable description of this TLS certificate. optional, max 255 bytes. | -| `metadata` | string | arbitrary user-defined machine-readable data of this TLS certificate. optional, max 4096 bytes. | -| `certificate_pem` | string | chain of PEM-encoded certificates, leaf first. See [Certificate Bundles](/universal-gateway/tls-certificates/#certificate-bundles). | -| `subject_common_name` | string | subject common name from the leaf of this TLS certificate | -| `subject_alternative_names.dns_names` | List<string> | set of additional domains (including wildcards) this TLS certificate is valid for | -| `subject_alternative_names.ips` | List<string> | set of IP addresses this TLS certificate is also valid for | -| `issued_at` | string | timestamp (in RFC 3339 format) when this TLS certificate was issued automatically, or null if this certificate was user-uploaded | -| `not_before` | string | timestamp when this TLS certificate becomes valid, RFC 3339 format | -| `not_after` | string | timestamp when this TLS certificate becomes invalid, RFC 3339 format | -| `key_usages` | List<string> | set of actions the private key of this TLS certificate can be used for | -| `extended_key_usages` | List<string> | extended set of actions the private key of this TLS certificate can be used for | -| `private_key_type` | string | type of the private key of this TLS certificate. One of rsa, ecdsa, or ed25519. | -| `issuer_common_name` | string | issuer common name from the leaf of this TLS certificate | -| `serial_number` | string | serial number of the leaf of this TLS certificate | -| `subject_organization` | string | subject organization from the leaf of this TLS certificate | -| `subject_organizational_unit` | string | subject organizational unit from the leaf of this TLS certificate | -| `subject_locality` | string | subject locality from the leaf of this TLS certificate | -| `subject_province` | string | subject province from the leaf of this TLS certificate | -| `subject_country` | string | subject country from the leaf of this TLS certificate | +| Field | Type | Description | +| ------------------------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | string | unique identifier for this TLS certificate | +| `uri` | string | URI of the TLS certificate API resource | +| `created_at` | string | timestamp when the TLS certificate was created, RFC 3339 format | +| `description` | string | human-readable description of this TLS certificate. optional, max 255 bytes. | +| `metadata` | string | arbitrary user-defined machine-readable data of this TLS certificate. optional, max 4096 bytes. | +| `certificate_pem` | string | chain of PEM-encoded certificates, leaf first. See [Certificate Bundles](/universal-gateway/tls-certificates/what-is-a-certificate-bundle/). | +| `subject_common_name` | string | subject common name from the leaf of this TLS certificate | +| `subject_alternative_names.dns_names` | List<string> | set of additional domains (including wildcards) this TLS certificate is valid for | +| `subject_alternative_names.ips` | List<string> | set of IP addresses this TLS certificate is also valid for | +| `issued_at` | string | timestamp (in RFC 3339 format) when this TLS certificate was issued automatically, or null if this certificate was user-uploaded | +| `not_before` | string | timestamp when this TLS certificate becomes valid, RFC 3339 format | +| `not_after` | string | timestamp when this TLS certificate becomes invalid, RFC 3339 format | +| `key_usages` | List<string> | set of actions the private key of this TLS certificate can be used for | +| `extended_key_usages` | List<string> | extended set of actions the private key of this TLS certificate can be used for | +| `private_key_type` | string | type of the private key of this TLS certificate. One of rsa, ecdsa, or ed25519. | +| `issuer_common_name` | string | issuer common name from the leaf of this TLS certificate | +| `serial_number` | string | serial number of the leaf of this TLS certificate | +| `subject_organization` | string | subject organization from the leaf of this TLS certificate | +| `subject_organizational_unit` | string | subject organizational unit from the leaf of this TLS certificate | +| `subject_locality` | string | subject locality from the leaf of this TLS certificate | +| `subject_province` | string | subject province from the leaf of this TLS certificate | +| `subject_country` | string | subject country from the leaf of this TLS certificate | #### tls_certificate_deleted.v0 Triggers when a TLS certificate is deleted -| Field | Type | Description | -| ------------------------------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------- | -| `id` | string | unique identifier for this TLS certificate | -| `uri` | string | URI of the TLS certificate API resource | -| `created_at` | string | timestamp when the TLS certificate was created, RFC 3339 format | -| `description` | string | human-readable description of this TLS certificate. optional, max 255 bytes. | -| `metadata` | string | arbitrary user-defined machine-readable data of this TLS certificate. optional, max 4096 bytes. | -| `certificate_pem` | string | chain of PEM-encoded certificates, leaf first. See [Certificate Bundles](/universal-gateway/tls-certificates/#certificate-bundles). | -| `subject_common_name` | string | subject common name from the leaf of this TLS certificate | -| `subject_alternative_names.dns_names` | List<string> | set of additional domains (including wildcards) this TLS certificate is valid for | -| `subject_alternative_names.ips` | List<string> | set of IP addresses this TLS certificate is also valid for | -| `issued_at` | string | timestamp (in RFC 3339 format) when this TLS certificate was issued automatically, or null if this certificate was user-uploaded | -| `not_before` | string | timestamp when this TLS certificate becomes valid, RFC 3339 format | -| `not_after` | string | timestamp when this TLS certificate becomes invalid, RFC 3339 format | -| `key_usages` | List<string> | set of actions the private key of this TLS certificate can be used for | -| `extended_key_usages` | List<string> | extended set of actions the private key of this TLS certificate can be used for | -| `private_key_type` | string | type of the private key of this TLS certificate. One of rsa, ecdsa, or ed25519. | -| `issuer_common_name` | string | issuer common name from the leaf of this TLS certificate | -| `serial_number` | string | serial number of the leaf of this TLS certificate | -| `subject_organization` | string | subject organization from the leaf of this TLS certificate | -| `subject_organizational_unit` | string | subject organizational unit from the leaf of this TLS certificate | -| `subject_locality` | string | subject locality from the leaf of this TLS certificate | -| `subject_province` | string | subject province from the leaf of this TLS certificate | -| `subject_country` | string | subject country from the leaf of this TLS certificate | +| Field | Type | Description | +| ------------------------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | string | unique identifier for this TLS certificate | +| `uri` | string | URI of the TLS certificate API resource | +| `created_at` | string | timestamp when the TLS certificate was created, RFC 3339 format | +| `description` | string | human-readable description of this TLS certificate. optional, max 255 bytes. | +| `metadata` | string | arbitrary user-defined machine-readable data of this TLS certificate. optional, max 4096 bytes. | +| `certificate_pem` | string | chain of PEM-encoded certificates, leaf first. See [Certificate Bundles](/universal-gateway/tls-certificates/what-is-a-certificate-bundle/). | +| `subject_common_name` | string | subject common name from the leaf of this TLS certificate | +| `subject_alternative_names.dns_names` | List<string> | set of additional domains (including wildcards) this TLS certificate is valid for | +| `subject_alternative_names.ips` | List<string> | set of IP addresses this TLS certificate is also valid for | +| `issued_at` | string | timestamp (in RFC 3339 format) when this TLS certificate was issued automatically, or null if this certificate was user-uploaded | +| `not_before` | string | timestamp when this TLS certificate becomes valid, RFC 3339 format | +| `not_after` | string | timestamp when this TLS certificate becomes invalid, RFC 3339 format | +| `key_usages` | List<string> | set of actions the private key of this TLS certificate can be used for | +| `extended_key_usages` | List<string> | extended set of actions the private key of this TLS certificate can be used for | +| `private_key_type` | string | type of the private key of this TLS certificate. One of rsa, ecdsa, or ed25519. | +| `issuer_common_name` | string | issuer common name from the leaf of this TLS certificate | +| `serial_number` | string | serial number of the leaf of this TLS certificate | +| `subject_organization` | string | subject organization from the leaf of this TLS certificate | +| `subject_organizational_unit` | string | subject organizational unit from the leaf of this TLS certificate | +| `subject_locality` | string | subject locality from the leaf of this TLS certificate | +| `subject_province` | string | subject province from the leaf of this TLS certificate | +| `subject_country` | string | subject country from the leaf of this TLS certificate | #### tls_certificate_updated.v0 Triggers when a TLS certificate is updated -| Field | Type | Description | -| ------------------------------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------- | -| `id` | string | unique identifier for this TLS certificate | -| `uri` | string | URI of the TLS certificate API resource | -| `created_at` | string | timestamp when the TLS certificate was created, RFC 3339 format | -| `description` | string | human-readable description of this TLS certificate. optional, max 255 bytes. | -| `metadata` | string | arbitrary user-defined machine-readable data of this TLS certificate. optional, max 4096 bytes. | -| `certificate_pem` | string | chain of PEM-encoded certificates, leaf first. See [Certificate Bundles](/universal-gateway/tls-certificates/#certificate-bundles). | -| `subject_common_name` | string | subject common name from the leaf of this TLS certificate | -| `subject_alternative_names.dns_names` | List<string> | set of additional domains (including wildcards) this TLS certificate is valid for | -| `subject_alternative_names.ips` | List<string> | set of IP addresses this TLS certificate is also valid for | -| `issued_at` | string | timestamp (in RFC 3339 format) when this TLS certificate was issued automatically, or null if this certificate was user-uploaded | -| `not_before` | string | timestamp when this TLS certificate becomes valid, RFC 3339 format | -| `not_after` | string | timestamp when this TLS certificate becomes invalid, RFC 3339 format | -| `key_usages` | List<string> | set of actions the private key of this TLS certificate can be used for | -| `extended_key_usages` | List<string> | extended set of actions the private key of this TLS certificate can be used for | -| `private_key_type` | string | type of the private key of this TLS certificate. One of rsa, ecdsa, or ed25519. | -| `issuer_common_name` | string | issuer common name from the leaf of this TLS certificate | -| `serial_number` | string | serial number of the leaf of this TLS certificate | -| `subject_organization` | string | subject organization from the leaf of this TLS certificate | -| `subject_organizational_unit` | string | subject organizational unit from the leaf of this TLS certificate | -| `subject_locality` | string | subject locality from the leaf of this TLS certificate | -| `subject_province` | string | subject province from the leaf of this TLS certificate | -| `subject_country` | string | subject country from the leaf of this TLS certificate | +| Field | Type | Description | +| ------------------------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | string | unique identifier for this TLS certificate | +| `uri` | string | URI of the TLS certificate API resource | +| `created_at` | string | timestamp when the TLS certificate was created, RFC 3339 format | +| `description` | string | human-readable description of this TLS certificate. optional, max 255 bytes. | +| `metadata` | string | arbitrary user-defined machine-readable data of this TLS certificate. optional, max 4096 bytes. | +| `certificate_pem` | string | chain of PEM-encoded certificates, leaf first. See [Certificate Bundles](/universal-gateway/tls-certificates/what-is-a-certificate-bundle/). | +| `subject_common_name` | string | subject common name from the leaf of this TLS certificate | +| `subject_alternative_names.dns_names` | List<string> | set of additional domains (including wildcards) this TLS certificate is valid for | +| `subject_alternative_names.ips` | List<string> | set of IP addresses this TLS certificate is also valid for | +| `issued_at` | string | timestamp (in RFC 3339 format) when this TLS certificate was issued automatically, or null if this certificate was user-uploaded | +| `not_before` | string | timestamp when this TLS certificate becomes valid, RFC 3339 format | +| `not_after` | string | timestamp when this TLS certificate becomes invalid, RFC 3339 format | +| `key_usages` | List<string> | set of actions the private key of this TLS certificate can be used for | +| `extended_key_usages` | List<string> | extended set of actions the private key of this TLS certificate can be used for | +| `private_key_type` | string | type of the private key of this TLS certificate. One of rsa, ecdsa, or ed25519. | +| `issuer_common_name` | string | issuer common name from the leaf of this TLS certificate | +| `serial_number` | string | serial number of the leaf of this TLS certificate | +| `subject_organization` | string | subject organization from the leaf of this TLS certificate | +| `subject_organizational_unit` | string | subject organizational unit from the leaf of this TLS certificate | +| `subject_locality` | string | subject locality from the leaf of this TLS certificate | +| `subject_province` | string | subject province from the leaf of this TLS certificate | +| `subject_country` | string | subject country from the leaf of this TLS certificate | ### Tunnel Credential diff --git a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx index d77684ab5d..0f4aab7b95 100644 --- a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx +++ b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx @@ -26,7 +26,7 @@ with ngrok. ## Wildcard domains -If you bring your own [wildcard domain](/universal-gateway/what-are-public-endpoints#wildcard-domains), e.g. `*.example.com`, you will need to create a second `CNAME` record with your domain host for [wildcard TLS Certificate provisioning](/universal-gateway/tls-certificates/#wildcard-domains). +If you bring your own [wildcard domain](/universal-gateway/what-are-public-endpoints#wildcard-domains), e.g. `*.example.com`, you will need to create a second `CNAME` record with your domain host for [wildcard TLS Certificate provisioning](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/#wildcard-domains). ## Apex domains diff --git a/docs/universal-gateway/domains/what-are-domains.mdx b/docs/universal-gateway/domains/what-are-domains.mdx index 1d1b500f51..dc63c5bd15 100644 --- a/docs/universal-gateway/domains/what-are-domains.mdx +++ b/docs/universal-gateway/domains/what-are-domains.mdx @@ -19,7 +19,7 @@ Domains also enable you to configure other domain-level behaviors, including: Per-region global load balancer configuration is coming soon, [request access to the developer preview](https://dashboard.ngrok.com/developer-preview). ::: -- [**TLS Certificate management**](/universal-gateway/tls-certificates/) - Configure automatic certificate provisioning or select a certificate you uploaded yourself. +- [**TLS Certificate management**](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) - Configure automatic certificate provisioning or select a certificate you uploaded yourself. - [**Dedicated IP address configuration**](/universal-gateway/ip-addresses#dedicated-ips) - Attach static, dedicated IPs for a Domain's matching endpoints receive traffic on. You can manage Domains on your [ngrok Dashboard](https://dashboard.ngrok.com/domains) or via the [ngrok API](#api). diff --git a/docs/universal-gateway/http.mdx b/docs/universal-gateway/http.mdx index 604af167c6..998eff4f54 100644 --- a/docs/universal-gateway/http.mdx +++ b/docs/universal-gateway/http.mdx @@ -832,7 +832,7 @@ application, use a [TLS Endpoint](/universal-gateway/tls) instead. Consult the following documentation for additional details on how ngrok handles TLS termination and certificiate management: -- [TLS Certificates](/universal-gateway/tls-certificates) +- [TLS Certificates](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls) - [TLS Termination](/universal-gateway/tls-termination) ## Upstream Headers diff --git a/docs/universal-gateway/overview.mdx b/docs/universal-gateway/overview.mdx index 9de6465f05..1ed7a90e46 100644 --- a/docs/universal-gateway/overview.mdx +++ b/docs/universal-gateway/overview.mdx @@ -20,7 +20,7 @@ Learn more about Universal Gateway Concepts: - [Domains →](/universal-gateway/domains/what-are-domains/) - [TCP Addresses →](/universal-gateway/tcp-addresses/what-are-tcp-addresses/) -- [TLS Certificates →](/universal-gateway/tls-certificates/) +- [TLS Certificates →](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) - [Edges →](/universal-gateway/edges/) ## Endpoints @@ -47,7 +47,7 @@ and traffic to their URL is balanced among them. ngrok automatically handles TLS (SSL) termination and certificate management for you. There is typically nothing to setup, configure or manage. -- [Learn more about TLS Certificates →](/universal-gateway/tls-certificates/) +- [Learn more about TLS Certificates →](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) - [Learn more about the TLS Termination →](/universal-gateway/tls-termination/) ## Global Load Balancer diff --git a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx index c0b7052227..3ef6d46af1 100644 --- a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx +++ b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx @@ -20,6 +20,22 @@ TLS certificates are composed of a private key and a certificate. These are pres TLS certificates are attached to [domains](/universal-gateway/domains/what-are-domains/) for [termination of TLS connections to endpoints](/universal-gateway/tls-termination/) whose URLs match that domain. +## Wildcard Domains + +When you bring your own wildcard domain (e.g. `*.app.example.com`), ngrok uses +a DNS01 challenge for TLS certificate provisioning which means that you must +create two CNAME records when creating branded wildcard domains instead of just +one. + +For example, If your domain is `*.app.example.com` you will be required to create the +following two CNAME records: + +- `*.app.example.com` +- `_acme-challenge.app.example.com` + +Certificate provisioning will not begin until you have created both DNS +records. + ## API TLS certificates are managed programatically via: diff --git a/docs/universal-gateway/tls-termination.mdx b/docs/universal-gateway/tls-termination.mdx index 07ae37a36c..b515a61d2f 100644 --- a/docs/universal-gateway/tls-termination.mdx +++ b/docs/universal-gateway/tls-termination.mdx @@ -48,7 +48,7 @@ ngrok's cloud service terminates TLS, it: - Uses latest and most secure version of TLS - Uses the [TLS - Certificate](/universal-gateway/tls-certificates/) attached to the + Certificate](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) attached to the [Domain](/universal-gateway/domains/what-are-domains/) which matches the Endpoint URL's hostname - Accelerates your traffic by using the global load balancer to terminate at its @@ -209,12 +209,12 @@ balancer](/universal-gateway/global-load-balancer). ## Certificates When the ngrok cloud service terminates TLS connections, it does so with the -[TLS Certificate](/universal-gateway/tls-certificates/) attached to the +[TLS Certificate](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) attached to the [Domain](/universal-gateway/domains/what-are-domains/) which matches the Endpoint URL's hostname. See the documentation on [TLS -Certificates](/universal-gateway/tls-certificates/) for more details on +Certificates](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) for more details on how they are -[selected](/universal-gateway/tls-certificates/#certificate-selection), +[selected](/universal-gateway/tls-certificates/how-are-certificates-selected), managed, provisioned and renewed. You may customize which TLS certificate is chosen for termination with the diff --git a/docs/universal-gateway/tls.mdx b/docs/universal-gateway/tls.mdx index 6443f9ff5c..285df1693d 100644 --- a/docs/universal-gateway/tls.mdx +++ b/docs/universal-gateway/tls.mdx @@ -252,7 +252,7 @@ by terminating at the agent or upstream service, you become responsible for provisioning, managing and distributing certificates. Consult the documentation on [TLS -Certificates](/universal-gateway/tls-certificates/) for details about +Certificates](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) for details about certificate selection, provisioning and management. ## Agent Forwarding diff --git a/static/scripts/redirects/question-answer-redirects.js b/static/scripts/redirects/question-answer-redirects.js index 28d6d50c54..4d4eb88899 100644 --- a/static/scripts/redirects/question-answer-redirects.js +++ b/static/scripts/redirects/question-answer-redirects.js @@ -20,4 +20,13 @@ export default [ [ fromExact('/docs/universal-gateway/tcp-addresses/#public-endpoint-creation'), '/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses/' ], [ fromExact('/docs/universal-gateway/tcp-addresses/#address-assignment'), '/docs/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned/' ], [ fromExact('/docs/universal-gateway/tcp-addresses/#global-load-balancer/'), '/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses/#tcp-address-load-balancing' ], + + //TLS Certificates + [fromExact('/docs/universal-gateway/tls-certificates/'), '/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls' ], + // hashes + [fromExact('/docs/universal-gateway/tls-certificates/#automated'), '/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management' ], + [fromExact('/docs/universal-gateway/tls-certificates/#certificate-selection'), '/docs/universal-gateway/tls-certificates/how-are-certificates-selected' ], + [fromExact('/docs/universal-gateway/tls-certificates/#certificate-provisioning'), '/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls#how-certificates-work' ], + [fromExact('/docs/universal-gateway/tls-certificates/#certificate-bundles'), '/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle/' ], + [fromExact('/docs/universal-gateway/tls-certificates/#private-keys'), '/docs/universal-gateway/tls-certificates/what-are-private-tls-keys/' ], ] From b17776c94a776a5bcbbc9d6a01343eb6c12f2baa Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 18 Mar 2025 15:52:17 -0400 Subject: [PATCH 032/137] Remove tls-certificates page; move edges to deprecated --- docs/universal-gateway/tls-certificates.mdx | 178 -------------------- sidebars.js | 10 +- 2 files changed, 5 insertions(+), 183 deletions(-) delete mode 100644 docs/universal-gateway/tls-certificates.mdx diff --git a/docs/universal-gateway/tls-certificates.mdx b/docs/universal-gateway/tls-certificates.mdx deleted file mode 100644 index 7bc2b3bf91..0000000000 --- a/docs/universal-gateway/tls-certificates.mdx +++ /dev/null @@ -1,178 +0,0 @@ -# TLS Certificates - -ngrok automatically handles TLS (SSL) certificate management and termination -for you. There is typically nothing to setup, configure or manage. - -You can manage TLS certificates on your [ngrok -dashboard](https://dashboard.ngrok.com/tls-certs) or via the [ngrok API](#api). - -## Overview - -TLS certificates are a tuple of a private key and certificate that are -presented by the ngrok cloud service during a TLS handshakes to terminate TLS -connections to [HTTPS endpoints](/universal-gateway/http) and [TLS -endpoints](/universal-gateway/tls). TLS certificates are attached to -[domains](/universal-gateway/domains/what-are-domains/) for termination of TLS connections to -endpoints whose URLs match that domain. ngrok can automatically provision -certificates for you or you can upload your own. - -See the [TLS Termination](/universal-gateway/tls-termination/) -documentation for details on how and when ngrok terminates TLS connections. - -## Certificate Selection - -When TLS connections to an endpoint are terminated, ngrok uses the TLS -Certificate attached to the [domain](/universal-gateway/domains/what-are-domains) matching the -endpoint's URL for termination. - -Each [domain](/universal-gateway/domains/what-are-domains/) has an attached TLS certificate that is referenced by its [`certificate_id` field](/api/resources/reserved-domains). If the domain object does reference any certificate, or if there is no matching domain object for an endpoint's URL, ngrok selects its own TLS certificate for -termination. - -You may override the certificate used for TLS termination by explicitly -terminating TLS yourself with the [`terminate-tls` traffic policy -action](/traffic-policy/actions/terminate-tls/). - -## Certificate Provisioning - -Whenever you create a [domain](/universal-gateway/domains/what-are-domains/) you choose how -a TLS certificate will be provisioned. Either: - -- [Automatic TLS certificates](#automated) (default) - ngrok automatically - provisions a TLS certificate from an ACME provider like Let's Encrypt. -- [Bring your own TLS certificates](#custom) - Upload your own TLS certificate - -It is recommended that you choose automatic TLS certificates unless you have -special requirements. - -## Automatic Provisioning {#automated} - -When you choose automatic TLS certificate management for a domain (this is the -default), ngrok automatically provisions **and renews** TLS certificates from -an ACME-compliant certificate authority like Let's Encrypt. - -ngrok uses an HTTP01 challenge for TLS certificate provisioning of most -domains. When you create a [wildcard domain](#wildcard-domains) ngrok uses a -DNS01 challenge instead. - -ngrok is a [Let's Encrypt sponsor](https://letsencrypt.org/sponsors/). - -### Status - -TLS certificates are provisioned asynchronously. Depending on the speed of the -ACME certificate authority, it can take anywhere between a few seconds to 10 -minutes for your certificate to be provisioned. The domain's -`certificate_management_status` field on the [TLS Certificate API -Resource](/api/resources/tls-certificates/) contains the status of the -provisioning job. - -### Bring your own domain - -When you [bring your own domain](/universal-gateway/how-do-i-use-my-own-domain) -(e.g. `api.your-domain.com`) you must create a CNAME DNS record in your DNS -provider. Certificate provisioning will not begin until your create this CNAME -DNS record. - -### Wildcard Domains - -When you bring your own wildcard domain (e.g. `*.app.example.com`), ngrok uses -a DNS01 challenge for TLS certificate provisioning which means that you must -create two CNAME records when creating branded wildcard domains instead of just -one. - -For example, If your domain is `*.app.example.com` you will be required to create the -following two CNAME records: - -- `*.app.example.com` -- `_acme-challenge.app.example.com` - -Certificate provisioning will not begin until you have created both DNS -records. - -### Private Keys - -When using automatic TLS certificates, ngrok generates a private key for your -domain and encrypts it at rest with with [NaCL](https://nacl.cr.yp.to/). - -When you configure a domain to use automated certificates, you may electively -choose whether ngrok will create an ECDSA private key (the default) or RSA -private key. If you choose an RSA private key, it is created with a size of -4096 bits. - -## Bring your own certificates {#custom} - -You may upload your own TLS certificates if you don't want to use the TLS -certificates that ngrok automatically provisions for you. Uploading your own -certificates may be the right choice if you are issuing certificates from your -own certificate authority or if you are using an EV certificate. - -To bring your own TLS certificate, upload a [certificate -bundle](#certificate-bundles) and a [private key](#private-keys). Keep in mind -that after you create your TLS certificate, you must attach it to one or more -domains before it will be used for termination. When working with the API, this -is done by updating the `certificate_id` property of the [Domain API -Resource](/api/resources/reserved-domains). - -Unlike automatic TLS certificates, when you are using custom TLS certificates, -you are responsible for managing the renewal and rotation of new certificates. - -### Certificate Bundles {#certificate-bundles} - -When uploading your own TLS certificates to ngrok, you are expected to provide -a certificate bundle of all certificates necessary to establish a chain of -trust to a trusted root certificate authority. Many TLS certificate vendors -will provide you with a constructed certificate bundle, but some will return -the leaf certificate and the intermediate certificates separately and you must -concatenate them to construct the bundle yourself. This is the -`certificate_pem` field in the [TLS Certificate Create -API](/api/resources/tls-certificates/). - -Certificate bundles are a series of PEM-encoded X.509 certificates that have -been concatenated together. **The order of this bundle is significant.** - -The first certificate in the bundle must be the leaf certificate. The leaf -certificate is the one which is signed for your domain and [the private -key](#private-keys) you will upload. - -After the leaf certificate are the intermediates certificates, if any. Each -intermediate certificate signs the certificate preceding it in the bundle. As -an example, the first intermediate will sign the leaf, and that signature is -part of the leaf certificate itself. The final certificate will be signed by -the root certificate authority. You may also included the root certificate in -the bundle as well, but it is not necessary or common practice to do so. - -A certificate bundle will look like the following: - -```pem ------BEGIN CERTIFICATE----- -... ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -... ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -... ------END CERTIFICATE----- -``` - -### Private Keys {#private-keys} - -ngrok accepts the following formats for the private key of an uploaded TLS -certificate. This is the `private_key_pem` field in the [TLS Certificate Create -API](/api/resources/tls-certificates/). - -- RSA, in either PKCS#1 or PKCS#8 form. -- ECDSA, in either SEC 1 or PKCS#8 form. -- Ed25519, in PKCS#8 form. - -Regardless of the format you choose, the private key must be formatted as ASN.1 -DER, encoded as PEM. ngrok will not accept any private keys that are encrypted -(e.g. with DES). - -ngrok encrypts your uploaded private keys at rest with -[NaCL](https://nacl.cr.yp.to/). - -## API - -TLS certificates are managed programatically via: - -- [`/tls_certificates` API Resource](/api/resources/tls-certificates/) diff --git a/sidebars.js b/sidebars.js index cf978274e7..89e4a6b169 100644 --- a/sidebars.js +++ b/sidebars.js @@ -83,11 +83,6 @@ const sidebars = { "universal-gateway/tls-certificates/what-are-private-tls-keys", ], }, - { - label: "Concepts", - type: "category", - items: ["universal-gateway/edges"], - }, { label: "Endpoints", type: "category", @@ -622,6 +617,11 @@ const sidebars = { value: "", }, "faq/faq", + { + label: "Deprecated", + type: "category", + items: ["universal-gateway/edges"], + }, ], }; From c7b7678209a8ba0d7f2277bf8434ceb769cfd9f9 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Mon, 24 Mar 2025 10:08:30 -0400 Subject: [PATCH 033/137] Setting up sidebar for endpoints --- docs/universal-gateway/bindings.mdx | 2 +- docs/universal-gateway/endpoints.mdx | 13 +++++++++--- sidebars.js | 30 ++++++++++++++++++++++++---- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/docs/universal-gateway/bindings.mdx b/docs/universal-gateway/bindings.mdx index e9a9b21260..019d260d15 100644 --- a/docs/universal-gateway/bindings.mdx +++ b/docs/universal-gateway/bindings.mdx @@ -1,5 +1,5 @@ --- -title: Endpoint Bindings +title: What are Endpoint Bindings? --- [Endpoints](/universal-gateway/endpoints) have a **binding**, which dictates how traffic can access it. diff --git a/docs/universal-gateway/endpoints.mdx b/docs/universal-gateway/endpoints.mdx index ec2d5ccacd..d022684c05 100644 --- a/docs/universal-gateway/endpoints.mdx +++ b/docs/universal-gateway/endpoints.mdx @@ -1,13 +1,20 @@ --- sidebar_position: 0 -title: Endpoints +title: What are Endpoints? --- import TypesComparison from "@site/shared/types-comparison.mdx"; An **ngrok Endpoint** is a URL that enables network traffic to reach your services. -You can think of endpoints as a gateway to anything you want to enable access for—whether that's a local development server on your laptop, a production Kubernetes cluster, a database behind a corporate firewall, or a cloud API. Endpoints bridge the gap between your resources and the traffic that needs to reach them. +You can think of endpoints as a gateway for anything you want to enable access to, including but not limited to: + +- A local development server on your laptop +- A production Kubernetes cluster +- A database behind a corporate firewall +- A cloud API + +Endpoints bridge the gap between your resources and the traffic that needs to reach them. ## Why endpoints matter @@ -69,7 +76,7 @@ ngrok http 8080 This command will start an Agent Endpoint that forwards traffic through the ngrok CLI agent to your locally running application on port 8080. -To learn more, follow ngrok's [Quickstart](/getting-started/). +To learn more, follow the [Quickstart](/getting-started/). ## Load balancing with Endpoint Pooling diff --git a/sidebars.js b/sidebars.js index 89e4a6b169..1838981300 100644 --- a/sidebars.js +++ b/sidebars.js @@ -84,15 +84,37 @@ const sidebars = { ], }, { - label: "Endpoints", + id: "universal-gateway/endpoints", + type: "doc", + label: "What are Endpoints?", + }, + { + label: "What are Endpoint Bindings?", type: "category", - link: { type: "doc", id: "universal-gateway/endpoints" }, + link: { type: "doc", id: "universal-gateway/bindings" }, items: [ { - id: "universal-gateway/endpoints", + id: "universal-gateway/public-endpoints", type: "doc", - label: "Overview", + label: "What are Public Endpoints?", }, + { + id: "universal-gateway/internal-endpoints", + type: "doc", + label: "What are Internal Endpoints?", + }, + { + id: "universal-gateway/kubernetes-endpoints", + type: "doc", + label: "What are Kubernetes Endpoints?", + }, + ], + }, + { + label: "Endpoints", + type: "category", + link: { type: "doc", id: "universal-gateway/endpoints" }, + items: [ { label: "Types", type: "category", From 544cb558575c4f414e2a3fdd7e74b13f008126e9 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Mon, 24 Mar 2025 11:00:01 -0400 Subject: [PATCH 034/137] More sidebar work --- docs/universal-gateway/cloud-endpoints/quickstart.mdx | 2 +- sidebars.js | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/universal-gateway/cloud-endpoints/quickstart.mdx b/docs/universal-gateway/cloud-endpoints/quickstart.mdx index b9d5366e2a..9ba70dece7 100644 --- a/docs/universal-gateway/cloud-endpoints/quickstart.mdx +++ b/docs/universal-gateway/cloud-endpoints/quickstart.mdx @@ -1,5 +1,5 @@ --- -title: Cloud Endpoints Quickstart +title: How Do I Create a Cloud Endpoint? sidebar_label: Quickstart description: Set up your first ngrok Cloud Endpoint to start managing traffic to your services. --- diff --git a/sidebars.js b/sidebars.js index 1838981300..fe0a656ba1 100644 --- a/sidebars.js +++ b/sidebars.js @@ -110,6 +110,11 @@ const sidebars = { }, ], }, + { + id: "universal-gateway/cloud-endpoints/quickstart", + type: "doc", + label: "How Do I Create a Cloud Endpoint?", + }, { label: "Endpoints", type: "category", From bde9eb10834a652119a620759ae883fb02e510e8 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Mon, 24 Mar 2025 11:55:13 -0400 Subject: [PATCH 035/137] Adding cloud endpoint quickstart; fixing old link --- docs/agent/cli.mdx | 2 +- sidebars.js | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/agent/cli.mdx b/docs/agent/cli.mdx index 0bf15b5ccd..9b02a7c9e3 100644 --- a/docs/agent/cli.mdx +++ b/docs/agent/cli.mdx @@ -610,7 +610,7 @@ of a tunnel-group backend. Endpoint configurations containing a tunnel-group backend will cause traffic to their associated reserved domain or address to be forwarded to the tunnel-group. -See the [Tunnel Group backends](/network-edge/edges/#tunnel-group) and [Edges](/network-edge/edges/) pages for more information. +See the [Tunnel Group backends](/universal-gateway/edges/#tunnel-group) and [Edges](/universal-gateway/edges/) pages for more information. ### Usage diff --git a/sidebars.js b/sidebars.js index fe0a656ba1..9794dd547f 100644 --- a/sidebars.js +++ b/sidebars.js @@ -115,6 +115,11 @@ const sidebars = { type: "doc", label: "How Do I Create a Cloud Endpoint?", }, + { + id: "universal-gateway/cloud-endpoints/quickstart", + type: "doc", + label: "How Do I Accept Traffic from Another Endpoint?", + }, { label: "Endpoints", type: "category", From fdf0811217c729e06c3cc0f9195a9875d40db29d Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Mon, 24 Mar 2025 12:40:00 -0400 Subject: [PATCH 036/137] Add internal endpoints, urls, etc --- docs/universal-gateway/bindings.mdx | 2 +- docs/universal-gateway/endpoints.mdx | 6 +- .../create-internal-endpoints.mdx | 63 +++++++++++++ .../index.mdx} | 69 +------------- docs/universal-gateway/overview.mdx | 4 +- docs/universal-gateway/public-endpoints.mdx | 94 ------------------- .../public-endpoints/index.mdx | 43 +++++++++ .../public-endpoints/urls.mdx | 64 +++++++++++++ sidebars.js | 50 ++++++---- 9 files changed, 213 insertions(+), 182 deletions(-) create mode 100644 docs/universal-gateway/internal-endpoints/create-internal-endpoints.mdx rename docs/universal-gateway/{internal-endpoints.mdx => internal-endpoints/index.mdx} (62%) delete mode 100644 docs/universal-gateway/public-endpoints.mdx create mode 100644 docs/universal-gateway/public-endpoints/index.mdx create mode 100644 docs/universal-gateway/public-endpoints/urls.mdx diff --git a/docs/universal-gateway/bindings.mdx b/docs/universal-gateway/bindings.mdx index 019d260d15..46a845e778 100644 --- a/docs/universal-gateway/bindings.mdx +++ b/docs/universal-gateway/bindings.mdx @@ -6,7 +6,7 @@ title: What are Endpoint Bindings? ## Public Endpoints -Endpoints with a `public` binding have a publicly addressable URL that receives traffic from the internet via the ngrok cloud service's global points of presence. e.g. These endpoints might use an ngrok subdomain or a custom domain. +Endpoints with a `public` binding have a publicly addressable [URL](/universal-gateway/public-endpoints/urls) that receives traffic from the internet via the ngrok cloud service's global points of presence. e.g. These endpoints might use an ngrok subdomain or a custom domain. Example URLs: diff --git a/docs/universal-gateway/endpoints.mdx b/docs/universal-gateway/endpoints.mdx index d022684c05..f12f797d37 100644 --- a/docs/universal-gateway/endpoints.mdx +++ b/docs/universal-gateway/endpoints.mdx @@ -30,7 +30,7 @@ Endpoints are ngrok's universal gateways, letting you: Endpoints enable traffic flow and management through three core features: -- **URL:** The entry point for traffic to reach your services. This could be any URL, such as `https://your-app.ngrok.io` or `tcp://your-api.internal`. +- **[URL](/universal-gateway/public-endpoints/urls):** The entry point for traffic to reach your services. This could be any URL, such as `https://your-app.ngrok.io` or `tcp://your-api.internal`. - **[Binding](#control-access-with-bindings):** The source or origin of incoming traffic. - **[Traffic Policy](/traffic-policy/):** Configuration to manage, manipulate and secure traffic. @@ -105,9 +105,7 @@ Agent Endpoints are also accessible in a read-only capacity via: ## Pricing -Paid plans (Personal, Pro and Enterprise) include a fixed number of -endpoints that you may create based on the number of licenses you have -purchased. +[Paid plans](/pricing-limits/) (Personal, Pro and Enterprise) include a fixed number of endpoints that you may create based on the number of licenses you have purchased. On the Pay-as-you-go plan, there is no limit on the number of endpoints you can create. An endpoint that transmits data in a billing period is counted as an active endpoint for billing purposes. diff --git a/docs/universal-gateway/internal-endpoints/create-internal-endpoints.mdx b/docs/universal-gateway/internal-endpoints/create-internal-endpoints.mdx new file mode 100644 index 0000000000..92fdae91c5 --- /dev/null +++ b/docs/universal-gateway/internal-endpoints/create-internal-endpoints.mdx @@ -0,0 +1,63 @@ +--- +title: How Do I Create An Internal Endpoint? +--- + +## Agent Endpoints + +When you create an [agent endpoint](/docs/universal-gateway/agent-endpoints), you can set the binding to `internal` to make it an internal endpoint. + +```bash +ngrok http 8080 --url "https://example.internal" --binding internal +``` + +## Cloud Endpoints + +You can also create internal [cloud endpoints](/docs/universal-gateway/cloud-endpoints/). + +Specify a binding of `internal` when you create the cloud endpoint. + +```bash +ngrok api create \ + --type cloud \ + --binding internal \ + --url "https://example.internal" \ + --traffic-policy "$(cat traffic-policy.yml)" +``` + +#### `traffic-policy.yml` + +```yaml +on_http_request: + - actions: + - type: custom-response + config: + status_code: 200 + headers: + content-type: text/plain + content: "Hello world!" +``` + +## Forwarding + +Internal endpoints aren’t directly accessible. To send traffic to an Internal Endpoint, you must create an endpoint that uses the [`forward-internal` Traffic Policy action](/docs/traffic-policy/actions/forward-internal/). + +For example, to route public traffic to your internal endpoint, you can use the following traffic policy: + +```yaml +on_http_request: + - actions: + - type: forward-internal + config: + url: https://example.internal +``` + +And you can add it to a Cloud Endpoint with the following terminal command: + +```bash +ngrok api create \ + --type cloud \ + --url "https://your-name.ngrok.app" \ + --traffic-policy "$(cat traffic-policy.yml)" +``` + +This configuration lets you manage how traffic reaches your service without requiring it to be directly accessible on the public internet. diff --git a/docs/universal-gateway/internal-endpoints.mdx b/docs/universal-gateway/internal-endpoints/index.mdx similarity index 62% rename from docs/universal-gateway/internal-endpoints.mdx rename to docs/universal-gateway/internal-endpoints/index.mdx index 618c0e0f84..cc85fd791c 100644 --- a/docs/universal-gateway/internal-endpoints.mdx +++ b/docs/universal-gateway/internal-endpoints/index.mdx @@ -1,5 +1,5 @@ --- -title: Internal Endpoints +title: What are Internal Endpoints? description: Learn about staging internal services and applications using internal endpoints. --- @@ -10,72 +10,13 @@ Internal endpoint URLs must: - End with the `.internal` domain extension - Use the `internal` [binding](/docs/universal-gateway/bindings/) +:::tip A common practice is to use a [public](/docs/universal-gateway/public-endpoints) [cloud endpoints](/docs/universal-gateway/cloud-endpoints/) to manage a centralized Traffic Policy, then forward traffic to one or more internal [endpoints](/docs/universal-gateway/endpoints/). See [the guide on using cloud endpoints with internal endpoints](/docs/guides/other-guides/forwarding-and-load-balancing-with-cloud-endpoints/) to learn more. +::: -## Quickstart +## Get started -### Agent Endpoint - -Create an internal agent endpoint by specifying a binding of `internal` when -you create an endpoint. - -```bash -ngrok http 8080 --url "https://example.internal" --binding internal -``` - -### Cloud Endpoint - -Instead of an agent endpoint, you can create an internal cloud endpoint. - -Specify a binding of `internal` when you create the cloud endpoint. - -```bash -ngrok api create \ - --type cloud \ - --binding internal \ - --url "https://example.internal" \ - --traffic-policy "$(cat traffic-policy.yml)" -``` - -##### `traffic-policy.yml` - -```yaml -on_http_request: - - actions: - - type: custom-response - config: - status_code: 200 - headers: - content-type: text/plain - content: "Hello world!" -``` - -### Forwarding - -Internal endpoints aren’t directly accessible. To send traffic to an Internal Endpoint, you must create an endpoint that uses the Traffic Policy to forward traffic using the [`forward-internal` action](/docs/traffic-policy/actions/forward-internal/). - -For example, to route public traffic to your internal endpoint, use the following command and traffic policy to create a Public Cloud Endpoint that forwards requests to your Internal Endpoint: - -```bash -ngrok api create \ - --type cloud \ - --url "https://your-name.ngrok.app" \ - --traffic-policy "$(cat traffic-policy.yml)" -``` - -##### `traffic-policy.yml` - -```yaml -on_http_request: - - actions: - - type: forward-internal - config: - url: https://example.internal -``` - -Now, when you make a request to `https://your-name.ngrok.app`, ngrok applies the specified traffic policy. This policy instructs ngrok to use the forward-internal action, routing the incoming HTTP request directly to your internal endpoint at `https://example.internal`. - -This configuration lets you manage how traffic reaches your service without requiring it to be directly accessible on the public internet. +See [the quickstart](/docs/universal-gateway/internal-endpoints/create-internal-endpoints) to create your first Internal Endpoint. ## Inferred Binding diff --git a/docs/universal-gateway/overview.mdx b/docs/universal-gateway/overview.mdx index 1ed7a90e46..786be626a2 100644 --- a/docs/universal-gateway/overview.mdx +++ b/docs/universal-gateway/overview.mdx @@ -1,10 +1,8 @@ --- -title: Overview +title: What is a Universal Gateway? pagination_next: universal-gateway/domains/what-are-domains --- -# Universal Gateway - ngrok's Universal Gateway is a globally distributed API Gateway. It secures, accelerates and protects and accelerates your applications. We call it a Universal Gateway because it also supports diff --git a/docs/universal-gateway/public-endpoints.mdx b/docs/universal-gateway/public-endpoints.mdx deleted file mode 100644 index ceae862bee..0000000000 --- a/docs/universal-gateway/public-endpoints.mdx +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: Public Endpoints -description: Learn about enabling internet traffic to your services with public endpoints. ---- - -Public endpoints enable your services to receive geo-balanced internet traffic using [ngrok's global points of presence](/docs/universal-gateway/edges/). - -Public endpoints enable you to receive traffic from the internet via ngrok’s [global points of presence](/docs/universal-gateway/edges/). This is the most common type of endpoint and the easiest way to start. - -Public endpoint URLs must: - -- Use either a [Domain](/universal-gateway/domains/what-are-domains/) or [TCP Address](/universal-gateway/tcp-addresses/what-are-tcp-addresses/) -- Use the `public` [binding](/docs/universal-gateway/bindings/) - -## Get started - -You can create a public endpoint using: - -- [The dashboard](https://dashboard.ngrok.com/endpoints) -- [The API](/docs/api/resources/endpoints/#create-endpoint). - -Follow the [Getting Started](/docs/getting-started/) guide to set up an ngrok account and create your first public endpoint. - -## Authentication - -Public endpoints are useful out of the box for content you don’t want to restrict access to, such as blogs or marketing sites; but they can also be used for services that require strict access control such as dashboards or private APIs. - -To keep such services both public and secure, you can add a Traffic Policy to your endpoint for authentication and authorization. Traffic Policy actions enable you to do the following with your endpoints: - -- [JWT Validation](/docs/traffic-policy/actions/jwt-validation/) -- [OAuth](/docs/traffic-policy/actions/oauth/) -- [OIDC](/docs/traffic-policy/actions/oidc/) -- [IP restrictions](/docs/traffic-policy/actions/restrict-ips/) -- [Mutual TLS](/docs/traffic-policy/actions/terminate-tls/#example-traffic-policy-document) - -## URLs - -When you create a public endpoint, the URL you create it with is validated -differently based on the protocol of the URL. - -### `http` - -- The hostname must match a [Domain](/universal-gateway/domains/what-are-domains/) in your account. -- The hostname must be a domain with a valid [public suffix](https://publicsuffix.org/). -- The port must be `80`. If you do not specify a port, the default `80` will be used for you. - -**Examples** - -- `http://example.ngrok.app` -- `http://example.ngrok.app:80` -- `http://example.party` -- `http://example.ngrok.app:81` - invalid port, must be `80`, not `81` -- `http://example.doesnotexist` - invalid hostname: `.doesnotexist` is not a public suffix domain -- `http://example.internal` - invalid hostname: `.internal` is not a public suffix domain - -### `https`, `tls` - -- The hostname must match a [Domain](/universal-gateway/domains/what-are-domains/) in your account. -- The hostname must be a domain with a valid [public suffix](https://publicsuffix.org/). -- The port must be `443`. If you do not specify a port, the default `443` will be used for you. - -**Examples** - -- `https://example.ngrok.app` -- `https://example.ngrok.app:443` -- `https://example.party` -- `https://example.ngrok.app:8443` - invalid port, must be `443` -- `https://example.nosuchtld` - invalid hostname, `.nosuchtld` is not a public suffix domain -- `https://example.internal` - invalid hostname, public endpoints cannot use `.internal` - -### `tcp` - -- You must specify a port number in TCP URLs. -- The hostname and port must match the address of a [TCP - Address](/universal-gateway/tcp-addresses/what-are-tcp-addresses/) in your account. - -**Examples** - -- `tcp://1.tcp.ngrok.io:12345` -- `tcp://1.tcp.eu.ngrok.io:12345` -- `tcp://1.tcp.ngrok.io` - invalid, does not specify a port number -- `tcp://example.ngrok.app:12345` - invalid, does not match a TCP Address -- `tcp://your-domain.com:12345` - invalid, does not match a TCP Address - -## API - -Public endpoints can be created programatically. Consult the documentation on -[Endpoint APIs](/api/resources/endpoints/). - -## Pricing - -Public endpoints are available on all plans. Consult the [Endpoints -Pricing](/universal-gateway/endpoints/#pricing) documentation for -billing details. diff --git a/docs/universal-gateway/public-endpoints/index.mdx b/docs/universal-gateway/public-endpoints/index.mdx new file mode 100644 index 0000000000..562bdb5ed9 --- /dev/null +++ b/docs/universal-gateway/public-endpoints/index.mdx @@ -0,0 +1,43 @@ +--- +title: What are Public Endpoints? +description: Learn about enabling internet traffic to your services with public endpoints. +--- + +Public endpoints enable your services to receive geo-balanced internet traffic using [ngrok's global points of presence](/docs/universal-gateway/edges/). This is the most common type of endpoint and the easiest way to start. + +[Public endpoint URLs](/docs/universal-gateway/public-endpoints/urls/) must: + +- Use either a [Domain](/universal-gateway/domains/what-are-domains/) or [TCP Address](/universal-gateway/tcp-addresses/what-are-tcp-addresses/) +- Use the `public` [binding](/docs/universal-gateway/bindings/) + +## Get started + +You can create a public endpoint using: + +- [The dashboard](https://dashboard.ngrok.com/endpoints) +- [The API](/docs/api/resources/endpoints/#create-endpoint). + +Follow the [Getting Started](/docs/getting-started/) guide to set up an ngrok account and create your first public endpoint. + +## Authentication + +Public endpoints are useful out of the box for content you don't want to restrict access to, such as blogs or marketing sites; but they can also be used for services that require strict access control such as dashboards or private APIs. + +To keep such services both public and secure, you can add a Traffic Policy to your endpoint for authentication and authorization. Traffic Policy actions enable you to do the following with your endpoints: + +- [JWT Validation](/docs/traffic-policy/actions/jwt-validation/) +- [OAuth](/docs/traffic-policy/actions/oauth/) +- [OIDC](/docs/traffic-policy/actions/oidc/) +- [IP restrictions](/docs/traffic-policy/actions/restrict-ips/) +- [Mutual TLS](/docs/traffic-policy/actions/terminate-tls/#example-traffic-policy-document) + +## API + +Public endpoints can be created programatically. Consult the documentation on +[Endpoint APIs](/api/resources/endpoints/). + +## Pricing + +Public endpoints are available on all plans. Consult the [Endpoints +Pricing](/universal-gateway/endpoints/#pricing) documentation for +billing details. diff --git a/docs/universal-gateway/public-endpoints/urls.mdx b/docs/universal-gateway/public-endpoints/urls.mdx new file mode 100644 index 0000000000..d7a9e7caad --- /dev/null +++ b/docs/universal-gateway/public-endpoints/urls.mdx @@ -0,0 +1,64 @@ +--- +title: What are Public Endpoint URLs? +--- + +When you create a [Public Endpoint], the URL you create it with is validated differently based on the protocol of the URL. + +## `http` + +- The hostname must match a [Domain](/universal-gateway/domains/what-are-domains/) in your account. +- The hostname must be a domain with a valid [public suffix](https://publicsuffix.org/). +- The port must be `80`, which is the default when creating public endpoints. + +### Examples + +Valid: + +- `http://example.ngrok.app` +- `http://example.ngrok.app:80` +- `http://example.party` + +Invalid: + +- `http://example.ngrok.app:81` - invalid port, must be `80`, not `81` +- `http://example.doesnotexist` - invalid hostname: `.doesnotexist` is not a public suffix domain +- `http://example.internal` - invalid hostname: `.internal` is not a public suffix domain + +## `https`, `tls` + +- The hostname must match a [Domain](/universal-gateway/domains/what-are-domains/) in your account. +- The hostname must be a domain with a valid [public suffix](https://publicsuffix.org/). +- The port must be `443`. If you do not specify a port, the default `443` will be used for you. + +### Examples + +Valid: + +- `https://example.ngrok.app` +- `https://example.ngrok.app:443` +- `https://example.party` + +Invalid: + +- `https://example.ngrok.app:8443` - invalid port, must be `443` +- `https://example.nosuchtld` - invalid hostname, `.nosuchtld` is not a public suffix domain +- `https://example.internal` - invalid hostname, public endpoints cannot use `.internal` + +## `tcp` + +- You must specify a port number in TCP URLs. +- The hostname and port must match the address of a [TCP + Address](/universal-gateway/tcp-addresses/what-are-tcp-addresses/) in your account. + +### Examples + +Valid: + +- `tcp://1.tcp.ngrok.io:12345` +- `tcp://1.tcp.eu.ngrok.io:12345` + +Invalid: + +- `tcp://1.tcp.ngrok.io` - invalid, does not specify a port number +- `tcp://example.ngrok.app:12345` - invalid, does not match a TCP Address +- `tcp://your-domain.com:12345` - invalid, does not match a TCP Address diff --git a/sidebars.js b/sidebars.js index 9794dd547f..db1a50cc40 100644 --- a/sidebars.js +++ b/sidebars.js @@ -84,36 +84,54 @@ const sidebars = { ], }, { + label: "What are Endpoints?", id: "universal-gateway/endpoints", type: "doc", - label: "What are Endpoints?", }, { label: "What are Endpoint Bindings?", + type: "doc", + id: "universal-gateway/bindings", + }, + { + link: { type: "doc", id: "universal-gateway/public-endpoints/index" }, type: "category", - link: { type: "doc", id: "universal-gateway/bindings" }, + label: "What are Public Endpoints?", items: [ { - id: "universal-gateway/public-endpoints", - type: "doc", - label: "What are Public Endpoints?", - }, - { - id: "universal-gateway/internal-endpoints", - type: "doc", - label: "What are Internal Endpoints?", - }, - { - id: "universal-gateway/kubernetes-endpoints", + id: "universal-gateway/public-endpoints/urls", type: "doc", - label: "What are Kubernetes Endpoints?", + label: "What are Public Endpoint URLs?", }, ], }, { - id: "universal-gateway/cloud-endpoints/quickstart", + link: { + type: "doc", + id: "universal-gateway/internal-endpoints/index", + }, + type: "category", + label: "What are Internal Endpoints?", + items: [ + "universal-gateway/internal-endpoints/create-internal-endpoints", + ], + }, + { + id: "universal-gateway/kubernetes-endpoints", type: "doc", - label: "How Do I Create a Cloud Endpoint?", + label: "What are Kubernetes Endpoints?", + }, + { + label: "What are Cloud Endpoints?", + type: "category", + link: { type: "doc", id: "universal-gateway/cloud-endpoints/index" }, + items: [ + { + id: "universal-gateway/cloud-endpoints/quickstart", + type: "doc", + label: "How Do I Create a Cloud Endpoint?", + }, + ], }, { id: "universal-gateway/cloud-endpoints/quickstart", From 3fc91c98db18e0a8dcd416cb058dd2360fe1c68b Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Mon, 24 Mar 2025 15:19:31 -0400 Subject: [PATCH 037/137] Fixing the sidebar --- docs/universal-gateway/bindings.mdx | 2 +- docs/universal-gateway/endpoints.mdx | 2 +- .../create-internal-endpoints.mdx | 10 +++++ .../internal-endpoints/index.mdx | 36 +++------------ .../public-endpoints/index.mdx | 2 +- .../urls.mdx => what-are-endpoint-urls.mdx} | 33 +++++++++++--- sidebars.js | 44 +++---------------- 7 files changed, 51 insertions(+), 78 deletions(-) rename docs/universal-gateway/{public-endpoints/urls.mdx => what-are-endpoint-urls.mdx} (60%) diff --git a/docs/universal-gateway/bindings.mdx b/docs/universal-gateway/bindings.mdx index 46a845e778..b711bdf1b2 100644 --- a/docs/universal-gateway/bindings.mdx +++ b/docs/universal-gateway/bindings.mdx @@ -6,7 +6,7 @@ title: What are Endpoint Bindings? ## Public Endpoints -Endpoints with a `public` binding have a publicly addressable [URL](/universal-gateway/public-endpoints/urls) that receives traffic from the internet via the ngrok cloud service's global points of presence. e.g. These endpoints might use an ngrok subdomain or a custom domain. +Endpoints with a `public` binding have a publicly addressable [URL](/universal-gateway/what-are-endpoint-urls) that receives traffic from the internet via the ngrok cloud service's global points of presence. e.g. These endpoints might use an ngrok subdomain or a custom domain. Example URLs: diff --git a/docs/universal-gateway/endpoints.mdx b/docs/universal-gateway/endpoints.mdx index f12f797d37..8c3e45c75e 100644 --- a/docs/universal-gateway/endpoints.mdx +++ b/docs/universal-gateway/endpoints.mdx @@ -30,7 +30,7 @@ Endpoints are ngrok's universal gateways, letting you: Endpoints enable traffic flow and management through three core features: -- **[URL](/universal-gateway/public-endpoints/urls):** The entry point for traffic to reach your services. This could be any URL, such as `https://your-app.ngrok.io` or `tcp://your-api.internal`. +- **[URL](/universal-gateway/what-are-endpoint-urls):** The entry point for traffic to reach your services. This could be any URL, such as `https://your-app.ngrok.io` or `tcp://your-api.internal`. - **[Binding](#control-access-with-bindings):** The source or origin of incoming traffic. - **[Traffic Policy](/traffic-policy/):** Configuration to manage, manipulate and secure traffic. diff --git a/docs/universal-gateway/internal-endpoints/create-internal-endpoints.mdx b/docs/universal-gateway/internal-endpoints/create-internal-endpoints.mdx index 92fdae91c5..8020764357 100644 --- a/docs/universal-gateway/internal-endpoints/create-internal-endpoints.mdx +++ b/docs/universal-gateway/internal-endpoints/create-internal-endpoints.mdx @@ -10,6 +10,16 @@ When you create an [agent endpoint](/docs/universal-gateway/agent-endpoints), yo ngrok http 8080 --url "https://example.internal" --binding internal ``` +### Inferred Binding + +ngrok automatically infers an `internal` binding for any endpoint created with a `.internal` hostname, so you can omit the `binding` property in most cases. + +For example, the following command creates an endpoint with an internal binding: + +```bash +ngrok http 8080 --url "https://example.internal" +``` + ## Cloud Endpoints You can also create internal [cloud endpoints](/docs/universal-gateway/cloud-endpoints/). diff --git a/docs/universal-gateway/internal-endpoints/index.mdx b/docs/universal-gateway/internal-endpoints/index.mdx index cc85fd791c..18dfd5d706 100644 --- a/docs/universal-gateway/internal-endpoints/index.mdx +++ b/docs/universal-gateway/internal-endpoints/index.mdx @@ -18,37 +18,12 @@ A common practice is to use a [public](/docs/universal-gateway/public-endpoints) See [the quickstart](/docs/universal-gateway/internal-endpoints/create-internal-endpoints) to create your first Internal Endpoint. -## Inferred Binding - -ngrok automatically infers an `internal` binding for any endpoint created with a `.internal` hostname, so you can omit the `binding` property in most cases. - -For example, the following command creates an endpoint with an internal binding: - -```bash -ngrok http 8080 --url "https://example.internal" -``` - -## URLs - -- **Scheme** - Internal endpoints support all [Endpoint Protocols](/universal-gateway/protocols) (`http`, `https`, `tcp` and `tls`). -- **Hostname** - Hostnames **must** end with `.internal` and may contain up to 5 subdomains. You must specify a URL with a hostname, randomly-assigned hostnames are not supported. You may specify wildcard hostnames. -- **Port** - All port numbers [1-65535] are valid. For `tcp` endpoints, you **must** specify a port. -- **Namespacing** - Internal endpoints are namespaced on a per-account basis. - This means that, two different accounts may have internal endpoints with the same URL (e.g. `https://api.internal`) without conflict or interference in [endpoint pooling](/universal-gateway/endpoint-pooling). - -#### Examples - -- `https://example.internal` -- `https://example.foo.bar.internal` -- `https://example.internal:12345` -- `tls://example.internal` -- `tls://example.internal:12345` -- `tcp://example.internal:12345` - ## Type and Pooling -- Internal endpoints support both [Endpoint Types](/universal-gateway/types): `agent` and `cloud`. -- Internal endpoints support [Endpoint Pooling](/universal-gateway/endpoint-pooling). +Internal endpoints support: + +- Both [Endpoint Types](/universal-gateway/types): `agent` and `cloud`. +- [Endpoint Pooling](/universal-gateway/endpoint-pooling). ## HTTP/S `on_tcp_connect` phase @@ -58,8 +33,7 @@ This is because when you use the [`forward-internal` action](/docs/traffic-polic ## API -Internal endpoints can be managed programatically. To get started, consult the -[Endpoints API documentation](/api/resources/endpoints/). +Internal endpoints can be managed programatically. To get started, consult the [Endpoints API documentation](/api/resources/endpoints/). ## Pricing diff --git a/docs/universal-gateway/public-endpoints/index.mdx b/docs/universal-gateway/public-endpoints/index.mdx index 562bdb5ed9..7aeea295cf 100644 --- a/docs/universal-gateway/public-endpoints/index.mdx +++ b/docs/universal-gateway/public-endpoints/index.mdx @@ -5,7 +5,7 @@ description: Learn about enabling internet traffic to your services with public Public endpoints enable your services to receive geo-balanced internet traffic using [ngrok's global points of presence](/docs/universal-gateway/edges/). This is the most common type of endpoint and the easiest way to start. -[Public endpoint URLs](/docs/universal-gateway/public-endpoints/urls/) must: +[Public endpoint URLs](/docs/universal-gateway/what-are-endpoint-urls/) must: - Use either a [Domain](/universal-gateway/domains/what-are-domains/) or [TCP Address](/universal-gateway/tcp-addresses/what-are-tcp-addresses/) - Use the `public` [binding](/docs/universal-gateway/bindings/) diff --git a/docs/universal-gateway/public-endpoints/urls.mdx b/docs/universal-gateway/what-are-endpoint-urls.mdx similarity index 60% rename from docs/universal-gateway/public-endpoints/urls.mdx rename to docs/universal-gateway/what-are-endpoint-urls.mdx index d7a9e7caad..adec00e1e0 100644 --- a/docs/universal-gateway/public-endpoints/urls.mdx +++ b/docs/universal-gateway/what-are-endpoint-urls.mdx @@ -1,16 +1,20 @@ --- -title: What are Public Endpoint URLs? +title: What are Endpoint URLs? --- +URLs are the entry point for traffic to reach the services connected to your endpoints. This could be any URL, such as `https://your-app.ngrok.io` or `tcp://your-api.internal`. + +## Public Endpoints + When you create a [Public Endpoint], the URL you create it with is validated differently based on the protocol of the URL. -## `http` +### `http` - The hostname must match a [Domain](/universal-gateway/domains/what-are-domains/) in your account. - The hostname must be a domain with a valid [public suffix](https://publicsuffix.org/). - The port must be `80`, which is the default when creating public endpoints. -### Examples +#### Examples Valid: @@ -24,13 +28,13 @@ Invalid: - `http://example.doesnotexist` - invalid hostname: `.doesnotexist` is not a public suffix domain - `http://example.internal` - invalid hostname: `.internal` is not a public suffix domain -## `https`, `tls` +### `https`, `tls` - The hostname must match a [Domain](/universal-gateway/domains/what-are-domains/) in your account. - The hostname must be a domain with a valid [public suffix](https://publicsuffix.org/). - The port must be `443`. If you do not specify a port, the default `443` will be used for you. -### Examples +#### Examples Valid: @@ -44,7 +48,7 @@ Invalid: - `https://example.nosuchtld` - invalid hostname, `.nosuchtld` is not a public suffix domain - `https://example.internal` - invalid hostname, public endpoints cannot use `.internal` -## `tcp` +### `tcp` - You must specify a port number in TCP URLs. - The hostname and port must match the address of a [TCP @@ -62,3 +66,20 @@ Invalid: - `tcp://1.tcp.ngrok.io` - invalid, does not specify a port number - `tcp://example.ngrok.app:12345` - invalid, does not match a TCP Address - `tcp://your-domain.com:12345` - invalid, does not match a TCP Address + +## Internal Endpoints + +- **Scheme** - Internal endpoints support all [Endpoint Protocols](/universal-gateway/protocols) (`http`, `https`, `tcp` and `tls`). +- **Hostname** - Hostnames **must** end with `.internal` and may contain up to 5 subdomains. You must specify a URL with a hostname, randomly-assigned hostnames are not supported. You may specify wildcard hostnames. +- **Port** - All port numbers [1-65535] are valid. For `tcp` endpoints, you **must** specify a port. +- **Namespacing** - Internal endpoints are namespaced on a per-account basis. + This means that, two different accounts may have internal endpoints with the same URL (e.g. `https://api.internal`) without conflict or interference in [endpoint pooling](/universal-gateway/endpoint-pooling). + +#### Examples + +- `https://example.internal` +- `https://example.foo.bar.internal` +- `https://example.internal:12345` +- `tls://example.internal` +- `tls://example.internal:12345` +- `tcp://example.internal:12345` diff --git a/sidebars.js b/sidebars.js index db1a50cc40..90a56ae965 100644 --- a/sidebars.js +++ b/sidebars.js @@ -83,44 +83,12 @@ const sidebars = { "universal-gateway/tls-certificates/what-are-private-tls-keys", ], }, - { - label: "What are Endpoints?", - id: "universal-gateway/endpoints", - type: "doc", - }, - { - label: "What are Endpoint Bindings?", - type: "doc", - id: "universal-gateway/bindings", - }, - { - link: { type: "doc", id: "universal-gateway/public-endpoints/index" }, - type: "category", - label: "What are Public Endpoints?", - items: [ - { - id: "universal-gateway/public-endpoints/urls", - type: "doc", - label: "What are Public Endpoint URLs?", - }, - ], - }, - { - link: { - type: "doc", - id: "universal-gateway/internal-endpoints/index", - }, - type: "category", - label: "What are Internal Endpoints?", - items: [ - "universal-gateway/internal-endpoints/create-internal-endpoints", - ], - }, - { - id: "universal-gateway/kubernetes-endpoints", - type: "doc", - label: "What are Kubernetes Endpoints?", - }, + "universal-gateway/endpoints", + "universal-gateway/bindings", + "universal-gateway/public-endpoints/index", + "universal-gateway/what-are-endpoint-urls", + "universal-gateway/internal-endpoints/index", + "universal-gateway/kubernetes-endpoints", { label: "What are Cloud Endpoints?", type: "category", From 0710d9dd35138d071d9199da15c762444e6f5846 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Mon, 24 Mar 2025 15:44:20 -0400 Subject: [PATCH 038/137] Splitting up kubernetes --- .../cloud-endpoints/quickstart.mdx | 3 +- ...-internal-endpoints.mdx => quickstart.mdx} | 2 +- .../kubernetes-endpoints.mdx | 169 ------------------ .../kubernetes-endpoints/index.mdx | 38 ++++ .../kubernetes-endpoints/quickstart.mdx | 42 +++++ .../kubernetes-endpoints/selector.mdx | 17 ++ .../kubernetes-endpoints/services.mdx | 44 +++++ .../what-are-endpoint-urls.mdx | 36 +++- sidebars.js | 34 ++-- 9 files changed, 202 insertions(+), 183 deletions(-) rename docs/universal-gateway/internal-endpoints/{create-internal-endpoints.mdx => quickstart.mdx} (97%) delete mode 100644 docs/universal-gateway/kubernetes-endpoints.mdx create mode 100644 docs/universal-gateway/kubernetes-endpoints/index.mdx create mode 100644 docs/universal-gateway/kubernetes-endpoints/quickstart.mdx create mode 100644 docs/universal-gateway/kubernetes-endpoints/selector.mdx create mode 100644 docs/universal-gateway/kubernetes-endpoints/services.mdx diff --git a/docs/universal-gateway/cloud-endpoints/quickstart.mdx b/docs/universal-gateway/cloud-endpoints/quickstart.mdx index 9ba70dece7..04633bd3b3 100644 --- a/docs/universal-gateway/cloud-endpoints/quickstart.mdx +++ b/docs/universal-gateway/cloud-endpoints/quickstart.mdx @@ -1,6 +1,5 @@ --- -title: How Do I Create a Cloud Endpoint? -sidebar_label: Quickstart +title: Cloud Endpoint Quickstart description: Set up your first ngrok Cloud Endpoint to start managing traffic to your services. --- diff --git a/docs/universal-gateway/internal-endpoints/create-internal-endpoints.mdx b/docs/universal-gateway/internal-endpoints/quickstart.mdx similarity index 97% rename from docs/universal-gateway/internal-endpoints/create-internal-endpoints.mdx rename to docs/universal-gateway/internal-endpoints/quickstart.mdx index 8020764357..f5d68933cd 100644 --- a/docs/universal-gateway/internal-endpoints/create-internal-endpoints.mdx +++ b/docs/universal-gateway/internal-endpoints/quickstart.mdx @@ -1,5 +1,5 @@ --- -title: How Do I Create An Internal Endpoint? +title: Internal Endpoint Quickstart --- ## Agent Endpoints diff --git a/docs/universal-gateway/kubernetes-endpoints.mdx b/docs/universal-gateway/kubernetes-endpoints.mdx deleted file mode 100644 index 639217037b..0000000000 --- a/docs/universal-gateway/kubernetes-endpoints.mdx +++ /dev/null @@ -1,169 +0,0 @@ -# Kubernetes Endpoints - -:::info Coming Soon - -Kubernetes endpoints are not available yet, [request access to the developer -preview](https://dashboard.ngrok.com/developer-preview) for early access. - -::: - -## Overview - -Kubernetes endpoints are secure, private endpoints that are only addressable -inside of Kubernetes clusters where you install the [Kubernetes -operator](/k8s/). They enable you to connect to ngrok endpoints without making -them publicly addressable. - -Kubernetes endpoints have a -[binding](/universal-gateway/bindings) of `kubernetes`. - -## Quickstart - -Create a Kubernetes endpoint by specifying binding of `kubernetes` when you -create an endpoint. - -#### Step 1: Install the ngrok Kubernetes Operator - -```bash -helm install ngrok-operator ngrok/kubernetes-operator \ - --namespace ngrok-operator \ - --create-namespace \ - --set description="example operator" \ - --set binding.enabled=true \ - --set credentials.apiKey=$NGROK_API_KEY \ - --set credentials.authtoken=$NGROK_AUTHTOKEN -``` - -#### Step 2: Create an ngrok endpoint - -Run the following command in the same ngrok account to create the kubernetes -bound endpoint. After the command completes, the ngrok operator will [create -`Service` objects](#service-creation) in the kubernetes cluster matching the -endpoint's URL. - -```bash -ngrok http 80 --url http://customer-2.prod --binding kubernetes -``` - -#### Step 3: Connect to the endpoint - -Other pods in the Kubernetes cluster where the ngrok operator is running can -connect to the bound endpoint. - -```bash -$ kubectl run -i --tty --rm debug --restart=Never --image=appropriate/curl -- /bin/sh -# curl http://customer-2.prod -``` - -Congraulations, you just connected to your application via a private kubernetes -endpoint! - -## URLs - -Kubernetes endpoint URL hostnames must be in the following format: - -- `[http|tcp]://name.namespace[:port]` - -The following restrictions are enforced: - -- **Scheme** - Must be `http` or `tcp`. `https` and `tls` are not supported. -- **Hostname** - Hostnames must always be two parts separated by a single dot, - e.g. `foo.bar`. Wildcard hostnames are not allowed. -- **Port** - All port numbers [1-65535] are valid. Port must be specified for - `tcp` endpoints. -- **Namespacing** - Kubernetes endpoints are namespaced on a per-account basis. - Two accounts may have kubernetes endpoints with the same URL (e.g. - http://api.internal). Those endpoints will not conflict or - [pool](/universal-gateway/endpoint-pooling). - -#### Examples - -- `http://app.example` -- `http://app.example:12345` -- `tcp://app.example:443` -- `tcp://app.example:12345` -- `https://app.example` - invalid scheme `https` -- `tls://app.example:12345` - invalid scheme `tls` -- `http://app.foo.bar` - invalid hostname, must have only two parts -- `tcp://app.example` - tcp endpoint must specify port number - -## Type and Pooling - -- Kubernetes endpoints support all [Endpoint - Types](/universal-gateway/types) (`agent` and `cloud`). -- Kubernetes endpoints support [Endpoint - Pooling](/universal-gateway/endpoint-pooling). - -## `Service` Creation - -After a kubernetes-bound endpoint is created, the ngrok cloud service notifies -Kubernetes Operators that a new kubernetes-bound endpoint exists. Kubernetes -Operators create `v1.Service` objects in their Kubernetes clusters which -forward traffic they receive to the operators' pods. - -#### `ClusterIP` Service - -A Cluster IP service is created in the operator's namespace. - -```yaml -apiVersion: v1 -kind: Service -metadata: - name: # the endpoint's ID - namespace: ngrok-operator -spec: - selector: - app.kubernetes.io/name: ngrok-operator-forwarder - ports: - - protocol: TCP - port: 80 # the endpoint url's port - targetPort: # assigned by operator to target the ngrok-operator-forwarder container -``` - -#### `ExternalName` Service - -An ExternalName service is created in the namespace targeted by the second part -of the URL's hostname. - -```yaml -apiVersion: v1 -kind: Service -metadata: - name: customer-2 # first part of the URL's hostname - namespace: prod ## second part of the URL's hostname -spec: - # Point service at the Operator Forwarder - type: ExternalName - externalName: .ngrok-operator.svc.cluster.local -``` - -## Endpoint Selector - -If you don't want all kubernetes endpoints in your account to appear inside of -a cluster, you may specify an Endpoint Selector which filters which Kubernetes -endpoints are projected into the cluster it runs in. Endpoint Selectors are a -CEL expression which is evaluated against each Kubernetes Endpoint in your -account. The operator will only projects endpoints that the selector returns -`true` for. - -For example, to only project kubernetes endpoints in the billing namespace, you would -add the following flag when installing the Kubernetes Operator: - -```bash - --set binding.endpointSelector="ep.hostname.endsWith('.billing')" \ -``` - -## Coming Soon - -This feature is in developer preview, more documentation is coming soon. - -## API - -Kubernetes endpoints can be created programatically. Consult the documentation -on [Endpoint APIs](/api/resources/endpoints/). - -## Pricing - -Kubernetes endpoints are available on the Pay-as-you-go plan. Consult the -[Endpoints Pricing](/universal-gateway/endpoints/#pricing) -documentation for billing details. diff --git a/docs/universal-gateway/kubernetes-endpoints/index.mdx b/docs/universal-gateway/kubernetes-endpoints/index.mdx new file mode 100644 index 0000000000..30010d17fa --- /dev/null +++ b/docs/universal-gateway/kubernetes-endpoints/index.mdx @@ -0,0 +1,38 @@ +--- +title: What are Kubernetes Endpoints? +--- + +:::info Coming Soon + +Kubernetes endpoints are not available yet, [request access to the developer +preview](https://dashboard.ngrok.com/developer-preview) for early access. + +::: + +Kubernetes endpoints are secure, private endpoints that are only addressable +inside of Kubernetes clusters where you install the [Kubernetes +Operator](/k8s/). They enable you to connect to ngrok endpoints without making them publicly addressable. + +Kubernetes endpoints have a [binding](/universal-gateway/bindings) of `kubernetes`. + +## Type and Pooling + +- Kubernetes endpoints support all [Endpoint + Types](/universal-gateway/types) (`agent` and `cloud`). +- Kubernetes endpoints support [Endpoint + Pooling](/universal-gateway/endpoint-pooling). + +## Coming Soon + +This feature is in developer preview, more documentation is coming soon. + +## API + +Kubernetes endpoints can be created programatically. Consult the documentation +on [Endpoint APIs](/api/resources/endpoints/). + +## Pricing + +Kubernetes endpoints are available on the Pay-as-you-go plan. Consult the +[Endpoints Pricing](/universal-gateway/endpoints/#pricing) +documentation for billing details. diff --git a/docs/universal-gateway/kubernetes-endpoints/quickstart.mdx b/docs/universal-gateway/kubernetes-endpoints/quickstart.mdx new file mode 100644 index 0000000000..e577ae2bd5 --- /dev/null +++ b/docs/universal-gateway/kubernetes-endpoints/quickstart.mdx @@ -0,0 +1,42 @@ +--- +title: Kubernetes Endpoints Quickstart +--- + +Create a Kubernetes endpoint by specifying binding of `kubernetes` when you +create an endpoint. + +#### Step 1: Install the ngrok Kubernetes Operator + +```bash +helm install ngrok-operator ngrok/kubernetes-operator \ + --namespace ngrok-operator \ + --create-namespace \ + --set description="example operator" \ + --set binding.enabled=true \ + --set credentials.apiKey=$NGROK_API_KEY \ + --set credentials.authtoken=$NGROK_AUTHTOKEN +``` + +#### Step 2: Create an ngrok endpoint + +Run the following command in the same ngrok account to create the kubernetes +bound endpoint. After the command completes, the ngrok operator will [create +`Service` objects](#service-creation) in the kubernetes cluster matching the +endpoint's URL. + +```bash +ngrok http 80 --url http://customer-2.prod --binding kubernetes +``` + +#### Step 3: Connect to the endpoint + +Other pods in the Kubernetes cluster where the ngrok operator is running can +connect to the bound endpoint. + +```bash +$ kubectl run -i --tty --rm debug --restart=Never --image=appropriate/curl -- /bin/sh +# curl http://customer-2.prod +``` + +Congraulations, you just connected to your application via a private kubernetes +endpoint! diff --git a/docs/universal-gateway/kubernetes-endpoints/selector.mdx b/docs/universal-gateway/kubernetes-endpoints/selector.mdx new file mode 100644 index 0000000000..c7b1ac4d6c --- /dev/null +++ b/docs/universal-gateway/kubernetes-endpoints/selector.mdx @@ -0,0 +1,17 @@ +--- +title: How Do I Select Endpoints for a Cluster? +--- + +If you don't want all kubernetes endpoints in your account to appear inside of +a cluster, you may specify an Endpoint Selector which filters which Kubernetes +endpoints are projected into the cluster it runs in. Endpoint Selectors are a +CEL expression which is evaluated against each Kubernetes Endpoint in your +account. The operator will only projects endpoints that the selector returns +`true` for. + +For example, to only project kubernetes endpoints in the billing namespace, you would +add the following flag when installing the Kubernetes Operator: + +```bash + --set binding.endpointSelector="ep.hostname.endsWith('.billing')" \ +``` diff --git a/docs/universal-gateway/kubernetes-endpoints/services.mdx b/docs/universal-gateway/kubernetes-endpoints/services.mdx new file mode 100644 index 0000000000..d9503e15dd --- /dev/null +++ b/docs/universal-gateway/kubernetes-endpoints/services.mdx @@ -0,0 +1,44 @@ +--- +title: How are Kubernetes Services Created? +--- + +After a kubernetes-bound endpoint is created, the ngrok cloud service notifies +Kubernetes Operators that a new kubernetes-bound endpoint exists. Kubernetes +Operators create `v1.Service` objects in their Kubernetes clusters which +forward traffic they receive to the operators' pods. + +### `ClusterIP` Service + +A Cluster IP service is created in the operator's namespace. + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: # the endpoint's ID + namespace: ngrok-operator +spec: + selector: + app.kubernetes.io/name: ngrok-operator-forwarder + ports: + - protocol: TCP + port: 80 # the endpoint url's port + targetPort: # assigned by operator to target the ngrok-operator-forwarder container +``` + +### `ExternalName` Service + +An ExternalName service is created in the namespace targeted by the second part +of the URL's hostname. + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: customer-2 # first part of the URL's hostname + namespace: prod ## second part of the URL's hostname +spec: + # Point service at the Operator Forwarder + type: ExternalName + externalName: .ngrok-operator.svc.cluster.local +``` diff --git a/docs/universal-gateway/what-are-endpoint-urls.mdx b/docs/universal-gateway/what-are-endpoint-urls.mdx index adec00e1e0..8a4a99b0e8 100644 --- a/docs/universal-gateway/what-are-endpoint-urls.mdx +++ b/docs/universal-gateway/what-are-endpoint-urls.mdx @@ -54,7 +54,7 @@ Invalid: - The hostname and port must match the address of a [TCP Address](/universal-gateway/tcp-addresses/what-are-tcp-addresses/) in your account. -### Examples +#### Examples Valid: @@ -83,3 +83,37 @@ Invalid: - `tls://example.internal` - `tls://example.internal:12345` - `tcp://example.internal:12345` + +## Kubernetes Endpoints + +Kubernetes endpoint URL hostnames must be in the following format: + +- `[http|tcp]://name.namespace[:port]` + +The following restrictions are enforced: + +- **Scheme** - Must be `http` or `tcp`. `https` and `tls` are not supported. +- **Hostname** - Hostnames must always be two parts separated by a single dot, + e.g. `foo.bar`. Wildcard hostnames are not allowed. +- **Port** - All port numbers [1-65535] are valid. Port must be specified for + `tcp` endpoints. +- **Namespacing** - Kubernetes endpoints are namespaced on a per-account basis. + Two accounts may have kubernetes endpoints with the same URL (e.g. + http://api.internal). Those endpoints will not conflict or + [pool](/universal-gateway/endpoint-pooling). + +#### Examples + +Valid: + +- `http://app.example` +- `http://app.example:12345` +- `tcp://app.example:443` +- `tcp://app.example:12345` + +Invalid: + +- `https://app.example` - invalid scheme `https` +- `tls://app.example:12345` - invalid scheme `tls` +- `http://app.foo.bar` - invalid hostname, must have only two parts +- `tcp://app.example` - tcp endpoint must specify port number diff --git a/sidebars.js b/sidebars.js index 90a56ae965..d11f63a853 100644 --- a/sidebars.js +++ b/sidebars.js @@ -87,24 +87,38 @@ const sidebars = { "universal-gateway/bindings", "universal-gateway/public-endpoints/index", "universal-gateway/what-are-endpoint-urls", - "universal-gateway/internal-endpoints/index", - "universal-gateway/kubernetes-endpoints", { - label: "What are Cloud Endpoints?", + label: "What are Internal Endpoints?", type: "category", - link: { type: "doc", id: "universal-gateway/cloud-endpoints/index" }, + link: { + type: "doc", + id: "universal-gateway/internal-endpoints/index", + }, + items: ["universal-gateway/internal-endpoints/quickstart"], + }, + { + label: "What are Kubernetes Endpoints?", + type: "category", + link: { + type: "doc", + id: "universal-gateway/kubernetes-endpoints", + }, items: [ - { - id: "universal-gateway/cloud-endpoints/quickstart", - type: "doc", - label: "How Do I Create a Cloud Endpoint?", - }, + "universal-gateway/kubernetes-endpoints/quickstart", + "universal-gateway/kubernetes-endpoints/services", + "universal-gateway/kubernetes-endpoints/selector", ], }, { + label: "What are Cloud Endpoints?", + type: "category", + link: { type: "doc", id: "universal-gateway/cloud-endpoints/index" }, + items: ["universal-gateway/cloud-endpoints/quickstart"], + }, + { + label: "How Do I Accept Traffic from Another Endpoint?", id: "universal-gateway/cloud-endpoints/quickstart", type: "doc", - label: "How Do I Accept Traffic from Another Endpoint?", }, { label: "Endpoints", From 0fb0f43dbdbb309e514ad2c57cce3fe91865afe6 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Mon, 24 Mar 2025 15:59:59 -0400 Subject: [PATCH 039/137] Adding other items --- docs/universal-gateway/chain-endpoints.mdx | 3 +++ docs/universal-gateway/forward-traffic.mdx | 3 +++ docs/universal-gateway/mock-api.mdx | 3 +++ sidebars.js | 8 +++----- 4 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 docs/universal-gateway/chain-endpoints.mdx create mode 100644 docs/universal-gateway/forward-traffic.mdx create mode 100644 docs/universal-gateway/mock-api.mdx diff --git a/docs/universal-gateway/chain-endpoints.mdx b/docs/universal-gateway/chain-endpoints.mdx new file mode 100644 index 0000000000..c331a2550b --- /dev/null +++ b/docs/universal-gateway/chain-endpoints.mdx @@ -0,0 +1,3 @@ +--- +title: How Do I Chain Endpoints? +--- diff --git a/docs/universal-gateway/forward-traffic.mdx b/docs/universal-gateway/forward-traffic.mdx new file mode 100644 index 0000000000..bd97cec623 --- /dev/null +++ b/docs/universal-gateway/forward-traffic.mdx @@ -0,0 +1,3 @@ +--- +title: How do I Accept Traffic From Another Endpoint? +--- diff --git a/docs/universal-gateway/mock-api.mdx b/docs/universal-gateway/mock-api.mdx new file mode 100644 index 0000000000..5e0930301a --- /dev/null +++ b/docs/universal-gateway/mock-api.mdx @@ -0,0 +1,3 @@ +--- +title: How Do I Mock API Endpoints? +--- diff --git a/sidebars.js b/sidebars.js index d11f63a853..53918674b5 100644 --- a/sidebars.js +++ b/sidebars.js @@ -115,11 +115,9 @@ const sidebars = { link: { type: "doc", id: "universal-gateway/cloud-endpoints/index" }, items: ["universal-gateway/cloud-endpoints/quickstart"], }, - { - label: "How Do I Accept Traffic from Another Endpoint?", - id: "universal-gateway/cloud-endpoints/quickstart", - type: "doc", - }, + "universal-gateway/forward-traffic", + "universal-gateway/mock-api", + "universal-gateway/chain-endpoints", { label: "Endpoints", type: "category", From 653554b0b9790d94981069fb5d8e3ab64066e206 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 25 Mar 2025 09:08:48 -0400 Subject: [PATCH 040/137] More changes --- docs/universal-gateway/migrate-from-tunnels.mdx | 3 +++ sidebars.js | 1 + 2 files changed, 4 insertions(+) create mode 100644 docs/universal-gateway/migrate-from-tunnels.mdx diff --git a/docs/universal-gateway/migrate-from-tunnels.mdx b/docs/universal-gateway/migrate-from-tunnels.mdx new file mode 100644 index 0000000000..a69a053c1d --- /dev/null +++ b/docs/universal-gateway/migrate-from-tunnels.mdx @@ -0,0 +1,3 @@ +--- +title: How Do I Migrate from Tunnels to Endpoints? +--- diff --git a/sidebars.js b/sidebars.js index 53918674b5..fe8b07b5ba 100644 --- a/sidebars.js +++ b/sidebars.js @@ -118,6 +118,7 @@ const sidebars = { "universal-gateway/forward-traffic", "universal-gateway/mock-api", "universal-gateway/chain-endpoints", + "universal-gateway/migrate-from-tunnels", { label: "Endpoints", type: "category", From 05421032f4ba15b4641a02cb10f9d30e455ed6c3 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 25 Mar 2025 15:51:24 -0400 Subject: [PATCH 041/137] Fixing sidebar --- sidebars.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sidebars.js b/sidebars.js index fe8b07b5ba..30dae04ad0 100644 --- a/sidebars.js +++ b/sidebars.js @@ -101,7 +101,7 @@ const sidebars = { type: "category", link: { type: "doc", - id: "universal-gateway/kubernetes-endpoints", + id: "universal-gateway/kubernetes-endpoints/index", }, items: [ "universal-gateway/kubernetes-endpoints/quickstart", @@ -173,17 +173,17 @@ const sidebars = { link: { type: "doc", id: "universal-gateway/bindings" }, items: [ { - id: "universal-gateway/public-endpoints", + id: "universal-gateway/public-endpoints/index", type: "doc", label: "Public", }, { - id: "universal-gateway/internal-endpoints", + id: "universal-gateway/internal-endpoints/index", type: "doc", label: "Internal", }, { - id: "universal-gateway/kubernetes-endpoints", + id: "universal-gateway/kubernetes-endpoints/index", type: "doc", label: "Kubernetes", }, From d948b256ea8102f71c3f85a9427c7136f88df513 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 25 Mar 2025 16:44:25 -0400 Subject: [PATCH 042/137] Add how to mock api guide --- docs/universal-gateway/mock-api.mdx | 110 ++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/docs/universal-gateway/mock-api.mdx b/docs/universal-gateway/mock-api.mdx index 5e0930301a..e59fac3f0f 100644 --- a/docs/universal-gateway/mock-api.mdx +++ b/docs/universal-gateway/mock-api.mdx @@ -1,3 +1,113 @@ --- title: How Do I Mock API Endpoints? --- + +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; +import ConfigExample from "/src/components/ConfigExample.tsx"; + +You can mock API responses using ngrok Endpoints. This enables you to test your application's functionality without having to stand up a full backend service or make requests to real APIs. + +The following steps will walk you through using [Traffic Policy](/traffic-policy/) to mock API responses. + +## 1. Create a Traffic Policy + +When requests are made to an Endpoint with a Traffic Policy, the policy can execute certain actions before returning a response or forwarding the traffic to downstream services. Using [request variables](/docs/traffic-policy/variables/req/), you can check many aspects of a request before sending a response, such as the value of its headers, the scheme, the user agent, and more. + +The following example Traffic Policy checks the URL path of all incoming requests, then returns a custom response if the path matches `/api/example`: + + + +## 2. Apply the Traffic Policy to an Endpoint + +There are multiple ways to apply the Traffic Policy from the previous section to your Endpoints. How you should do so depends on the type of Endpoint you're using. + +### Agent Endpoints + + + + +Run the following terminal command to create an Agent Endpoint with a Traffic Policy file: + +```bash + ngrok http 8080 --traffic-policy "policy-file-here.yml" +``` + +See [the guide on using Traffic Policy with CLI flags](/docs/traffic-policy/getting-started/agent-endpoints/cli/) for more information. + + + + +Use the following terminal command to edit your ngrok config file: + +```bash +ngrok config edit +``` + +See [the guide on using Traffic Policy with a config file](/docs/traffic-policy/getting-started/agent-endpoints/config-file/) for more information. + + + + +### Cloud Endpoints + + + + + 1. Navigate to the [Endpoints](https://dashboard.ngrok.com/endpoints/) page. + 1. Select the Cloud Endpoint you want to use. You'll be taken to a page where you can edit the Traffic Policy directly. + + + + With the ngrok CLI `api` command, you can add a Traffic Policy file to your Cloud Endpoint with the following command options: + ```bash + ngrok api endpoints create \ + --url https:// \ + --traffic-policy "policy-file-here.yml" + ``` + See [the guide on using Traffic Policy with Cloud Endpoints](/docs/traffic-policy/getting-started/cloud-endpoints/api/) for more information. + + + +## 3. Test the Traffic Policy + +To test the Traffic Policy defined in this guide, you could send a `curl` request like this: + +```shell +$ curl https://example.ngrok.app/api/example +``` + +The response should look like this: + +```http +HTTP/2 200 OK +content-type: application/json + +{ + "hello": "world" +} +``` From aaac9c73028bc207627c4777372e1c9265cd9ed2 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Wed, 26 Mar 2025 09:38:46 -0400 Subject: [PATCH 043/137] Small change --- docs/universal-gateway/mock-api.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/universal-gateway/mock-api.mdx b/docs/universal-gateway/mock-api.mdx index e59fac3f0f..c7430acc6a 100644 --- a/docs/universal-gateway/mock-api.mdx +++ b/docs/universal-gateway/mock-api.mdx @@ -95,7 +95,7 @@ See [the guide on using Traffic Policy with a config file](/docs/traffic-policy/ ## 3. Test the Traffic Policy -To test the Traffic Policy defined in this guide, you could send a `curl` request like this: +To test the Traffic Policy defined in this guide, send a request to your endpoint like this: ```shell $ curl https://example.ngrok.app/api/example From 97ba7c2730fea13332b869f049eee7a080a790f1 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 28 Mar 2025 09:56:39 -0400 Subject: [PATCH 044/137] starting on chaining --- docs/universal-gateway/chain-endpoints.mdx | 4 ++++ sidebars.js | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/universal-gateway/chain-endpoints.mdx b/docs/universal-gateway/chain-endpoints.mdx index c331a2550b..bcb1ad491f 100644 --- a/docs/universal-gateway/chain-endpoints.mdx +++ b/docs/universal-gateway/chain-endpoints.mdx @@ -1,3 +1,7 @@ --- title: How Do I Chain Endpoints? --- + +You can chain ngrok Endpoints together to route traffic to from one endpoint to multiple other endpoints based on the request. + +## Example diff --git a/sidebars.js b/sidebars.js index 30dae04ad0..fafbe21c29 100644 --- a/sidebars.js +++ b/sidebars.js @@ -116,8 +116,8 @@ const sidebars = { items: ["universal-gateway/cloud-endpoints/quickstart"], }, "universal-gateway/forward-traffic", - "universal-gateway/mock-api", "universal-gateway/chain-endpoints", + "universal-gateway/mock-api", "universal-gateway/migrate-from-tunnels", { label: "Endpoints", From 0c8ac140cee39632f884b0c1501179d59b82b8e5 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 28 Mar 2025 12:30:38 -0400 Subject: [PATCH 045/137] rough draft of chaining endpoints --- docs/universal-gateway/chain-endpoints.mdx | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/docs/universal-gateway/chain-endpoints.mdx b/docs/universal-gateway/chain-endpoints.mdx index bcb1ad491f..32faf87ac6 100644 --- a/docs/universal-gateway/chain-endpoints.mdx +++ b/docs/universal-gateway/chain-endpoints.mdx @@ -2,6 +2,25 @@ title: How Do I Chain Endpoints? --- -You can chain ngrok Endpoints together to route traffic to from one endpoint to multiple other endpoints based on the request. +You can chain ngrok Endpoints together to route traffic from one endpoint to multiple other endpoints based on request attributes, such as URL, hostname, path, cookies, or headers. + +See the [Traffic Policy Action request variables documentation](/docs/traffic-policy/variables/req/) for a full list of request attributes you can use. ## Example + +This rule forwards requests containing a `X-Endpoint-Value: {ENDPOINT}` header to `https://{ENDPOINT}.internal`. + + From e17935226e3bc29add8bf622aa9738b31053cf0d Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 28 Mar 2025 14:52:49 -0400 Subject: [PATCH 046/137] Finish chain endpoints; fix sidebar --- docs/universal-gateway/chain-endpoints.mdx | 6 ++++-- docs/universal-gateway/forward-traffic.mdx | 3 --- sidebars.js | 1 - 3 files changed, 4 insertions(+), 6 deletions(-) delete mode 100644 docs/universal-gateway/forward-traffic.mdx diff --git a/docs/universal-gateway/chain-endpoints.mdx b/docs/universal-gateway/chain-endpoints.mdx index 32faf87ac6..69df8f228d 100644 --- a/docs/universal-gateway/chain-endpoints.mdx +++ b/docs/universal-gateway/chain-endpoints.mdx @@ -2,13 +2,15 @@ title: How Do I Chain Endpoints? --- +import ConfigExample from "/src/components/ConfigExample.tsx"; + You can chain ngrok Endpoints together to route traffic from one endpoint to multiple other endpoints based on request attributes, such as URL, hostname, path, cookies, or headers. See the [Traffic Policy Action request variables documentation](/docs/traffic-policy/variables/req/) for a full list of request attributes you can use. ## Example -This rule forwards requests containing a `X-Endpoint-Value: {ENDPOINT}` header to `https://{ENDPOINT}.internal`. +This rule forwards requests containing a `X-Endpoint-Name: {ENDPOINT}` header to `https://{ENDPOINT}.internal`. Date: Fri, 28 Mar 2025 14:59:27 -0400 Subject: [PATCH 047/137] Cleared out all of Endpoint Types. Moving on to Protocols --- docs/universal-gateway/agent-endpoints.mdx | 2 +- .../cloud-endpoints/index.mdx | 4 +- docs/universal-gateway/types.mdx | 45 ------------------- sidebars.js | 26 +++-------- 4 files changed, 9 insertions(+), 68 deletions(-) delete mode 100644 docs/universal-gateway/types.mdx diff --git a/docs/universal-gateway/agent-endpoints.mdx b/docs/universal-gateway/agent-endpoints.mdx index 8468cdebb1..eb35ffdb55 100644 --- a/docs/universal-gateway/agent-endpoints.mdx +++ b/docs/universal-gateway/agent-endpoints.mdx @@ -1,5 +1,5 @@ --- -title: Agent Endpoints +title: What are Agent Endpoints? description: Learn about creating endpoints managed by Secure Tunnel agents. --- diff --git a/docs/universal-gateway/cloud-endpoints/index.mdx b/docs/universal-gateway/cloud-endpoints/index.mdx index 3b9a5c464f..f753deb639 100644 --- a/docs/universal-gateway/cloud-endpoints/index.mdx +++ b/docs/universal-gateway/cloud-endpoints/index.mdx @@ -1,4 +1,6 @@ -# Cloud Endpoints +--- +title: What are Cloud Endpoints? +--- ## Overview diff --git a/docs/universal-gateway/types.mdx b/docs/universal-gateway/types.mdx deleted file mode 100644 index e1f1cc16bc..0000000000 --- a/docs/universal-gateway/types.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Endpoint Types -description: Learn about ngrok'sCloud and Agent endpoints. ---- - -Endpoints have a **type**, which can be either `agent` or `cloud`. - -## Cloud Endpoints vs Agent Endpoints - -In general, Cloud Endpoints are the most flexible option, but which endpoint type you should choose depends on your use-case. The following table outlines the differences between Cloud and Agent endpoints. - -| | **[Cloud Endpoints](/universal-gateway/cloud-endpoints/)** | **[Agent Endpoints](/universal-gateway/agent-endpoints/)** | -| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------- | -| **Lifetime** | Always-on. Must be manually terminated. | Live as long as the [agent](/agent) process that started them. | -| **Connection Handling** | Can be configured with [Traffic Policy](/traffic-policy/). | Can be configured with [Traffic Policy](/traffic-policy/). | -| **Configuration** | Can be managed at any time via the [API](/api/) or [dashboard](https://dashboard.ngrok.com/endpoints). | Managed by the agent that initiates them. | -| **Dashboard accessibility** | Can be created and configured from the dashboard. | Read-only in the dashboard. | -| **Can use ephemeral domains?** | **No**. Must be provided a fully qualified URL on creation. | **Yes**. Ngrok can generate a URL for you on creation. | -| **Traffic Policy required?** | **Yes**. | **No**, but you can provide one if you'd like. | -| **Globally available** | **Yes**. | **Yes**. | -| **Can be managed with [the API](/api/)?** | **Yes**. | Yes, with the agent api. | -| **[Pricing options](https://ngrok.com/pricing?ref=docs)** | Available on paid plans. | Available on all plans. | - -Learn more in the [Endpoints](/universal-gateway/endpoints) documentation. - -### Protocols, Binding and Pooling - -Both Agent and Cloud Endpoints support: - -- All [Endpoint Protocols](/universal-gateway/protocols/) - - `http/https` - - `tcp` - - `tls` -- All [Endpoint Bindings](/universal-gateway/bindings/) - - - `public` - - `internal` - - `kubernetes` - -- [Endpoint Pooling](/universal-gateway/endpoint-pooling/). You can also pool Agent Endpoints with Cloud Endpoints. - -## Get started - -- See the [Cloud Endpoints Quickstart](/universal-gateway/cloud-endpoints/quickstart). -- See the ngrok [Getting Started guide](/getting-started/) to set up an Agent Endpoint. diff --git a/sidebars.js b/sidebars.js index fb124fb411..663faabe03 100644 --- a/sidebars.js +++ b/sidebars.js @@ -115,6 +115,11 @@ const sidebars = { link: { type: "doc", id: "universal-gateway/cloud-endpoints/index" }, items: ["universal-gateway/cloud-endpoints/quickstart"], }, + { + label: "What are Agent Endpoints?", + id: "universal-gateway/agent-endpoints", + type: "doc", + }, "universal-gateway/chain-endpoints", "universal-gateway/mock-api", "universal-gateway/migrate-from-tunnels", @@ -123,27 +128,6 @@ const sidebars = { type: "category", link: { type: "doc", id: "universal-gateway/endpoints" }, items: [ - { - label: "Types", - type: "category", - link: { type: "doc", id: "universal-gateway/types" }, - items: [ - { - label: "Cloud Endpoints", - type: "category", - link: { - type: "doc", - id: "universal-gateway/cloud-endpoints/index", - }, - items: ["universal-gateway/cloud-endpoints/quickstart"], - }, - { - id: "universal-gateway/agent-endpoints", - type: "doc", - label: "Agent Endpoints", - }, - ], - }, { label: "Protocols", type: "category", From d533900c98ae93ebe7d23ea574fb7f9596a47ce9 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 28 Mar 2025 15:17:21 -0400 Subject: [PATCH 048/137] Working on http/s --- docs/universal-gateway/http-s/index.mdx | 936 ++++++++++++++++++++++++ sidebars.js | 1 + 2 files changed, 937 insertions(+) create mode 100644 docs/universal-gateway/http-s/index.mdx diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx new file mode 100644 index 0000000000..cd0c4f5b21 --- /dev/null +++ b/docs/universal-gateway/http-s/index.mdx @@ -0,0 +1,936 @@ +--- +title: How do I handle HTTP/S traffic? +--- + +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; + +import TlsLimits from "../_tls_limits.mdx"; + +import RandomAgentCliExample from "/examples/agent-cli/http-random.mdx"; +import RandomAgentConfigExample from "/examples/agent-config/http-random.mdx"; +import RandomGoSdkExample from "/examples/go-sdk/http-random.mdx"; +import RandomJavascriptSdkExample from "/examples/javascript-sdk/http-random.mdx"; +import RandomPythonSdkExample from "/examples/python-sdk/http-random.mdx"; +import RandomRustSdkExample from "/examples/rust-sdk/http-random.mdx"; +import RandomSshExample from "/examples/ssh/http-random.mdx"; + +import StaticDomainAgentCliExample from "/examples/agent-cli/http-static-domain.mdx"; +import StaticDomainAgentConfigExample from "/examples/agent-config/http-static-domain.mdx"; +import StaticDomainGoSdkExample from "/examples/go-sdk/http-static-domain.mdx"; +import StaticDomainJavascriptSdkExample from "/examples/javascript-sdk/http-static-domain.mdx"; +import StaticDomainKubernetesExample from "/examples/k8s/http-static-domain.mdx"; +import StaticDomainPythonSdkExample from "/examples/python-sdk/http-static-domain.mdx"; +import StaticDomainRustSdkExample from "/examples/rust-sdk/http-static-domain.mdx"; +import StaticDomainSshExample from "/examples/ssh/http-static-domain.mdx"; + +import BrandedDomainAgentCliExample from "/examples/agent-cli/http-branded-domain.mdx"; +import BrandedDomainAgentConfigExample from "/examples/agent-config/http-branded-domain.mdx"; +import BrandedDomainGoSdkExample from "/examples/go-sdk/http-branded-domain.mdx"; +import BrandedDomainJavascriptSdkExample from "/examples/javascript-sdk/http-branded-domain.mdx"; +import BrandedDomainKubernetesExample from "/examples/k8s/http-branded-domain.mdx"; +import BrandedDomainPythonSdkExample from "/examples/python-sdk/http-branded-domain.mdx"; +import BrandedDomainRustSdkExample from "/examples/rust-sdk/http-branded-domain.mdx"; +import BrandedDomainSshExample from "/examples/ssh/http-branded-domain.mdx"; + +import BasicAuthAgentCliExample from "/examples/agent-cli/http-basic-auth.mdx"; +import BasicAuthAgentConfigExample from "/examples/agent-config/http-basic-auth.mdx"; +import BasicAuthGoSdkExample from "/examples/go-sdk/http-basic-auth.mdx"; +import BasicAuthJavascriptSdkExample from "/examples/javascript-sdk/http-basic-auth.mdx"; +import BasicAuthKubernetesExample from "/examples/k8s/http-basic-auth.mdx"; +import BasicAuthPythonSdkExample from "/examples/python-sdk/http-basic-auth.mdx"; +import BasicAuthRustSdkExample from "/examples/rust-sdk/http-basic-auth.mdx"; +import BasicAuthSshExample from "/examples/ssh/http-basic-auth.mdx"; + +import OAuthAgentCliExample from "/examples/agent-cli/http-oauth-authn.mdx"; +import OAuthAgentConfigExample from "/examples/agent-config/http-oauth-authn.mdx"; +import OAuthGoSdkExample from "/examples/go-sdk/http-oauth-authn.mdx"; +import OAuthJavascriptSdkExample from "/examples/javascript-sdk/http-oauth-authn.mdx"; +import OAuthKubernetesExample from "/examples/k8s/http-oauth-authn.mdx"; +import OAuthPythonSdkExample from "/examples/python-sdk/http-oauth-authn.mdx"; +import OAuthRustSdkExample from "/examples/rust-sdk/http-oauth-authn.mdx"; +import OAuthSshExample from "/examples/ssh/http-oauth-authn.mdx"; + +import ForwardHttpsAgentCliExample from "/examples/agent-cli/http-forward-https.mdx"; +import ForwardHttpsAgentConfigExample from "/examples/agent-config/http-forward-https.mdx"; +import ForwardHttpsGoSdkExample from "/examples/go-sdk/http-forward-https.mdx"; +import ForwardHttpsJavascriptSdkExample from "/examples/javascript-sdk/http-forward-https.mdx"; +import ForwardHttpsKubernetesExample from "/examples/k8s/http-forward-https.mdx"; +import ForwardHttpsPythonSdkExample from "/examples/python-sdk/http-forward-https.mdx"; +import ForwardHttpsRustSdkExample from "/examples/rust-sdk/http-forward-https.mdx"; +import ForwardHttpsSshExample from "/examples/ssh/http-forward-https.mdx"; + +import HostHeaderAgentCliExample from "/examples/agent-cli/http-rewrite-host-header.mdx"; +import HostHeaderAgentConfigExample from "/examples/agent-config/http-rewrite-host-header.mdx"; +import HostHeaderGoSdkExample from "/examples/go-sdk/http-rewrite-host-header.mdx"; +import HostHeaderJavascriptSdkExample from "/examples/javascript-sdk/http-rewrite-host-header.mdx"; +import HostHeaderKubernetesExample from "/examples/k8s/http-rewrite-host-header.mdx"; +import HostHeaderPythonSdkExample from "/examples/python-sdk/http-rewrite-host-header.mdx"; +import HostHeaderRustSdkExample from "/examples/rust-sdk/http-rewrite-host-header.mdx"; +import HostHeaderSshExample from "/examples/ssh/http-rewrite-host-header.mdx"; + +import WildcardAgentCliExample from "/examples/agent-cli/http-wildcard-domain.mdx"; +import WildcardAgentConfigExample from "/examples/agent-config/http-wildcard-domain.mdx"; +import WildcardGoSdkExample from "/examples/go-sdk/http-wildcard-domain.mdx"; +import WildcardJavascriptSdkExample from "/examples/javascript-sdk/http-wildcard-domain.mdx"; +import WildcardKubernetesExample from "/examples/k8s/http-wildcard-domain.mdx"; +import WildcardPythonSdkExample from "/examples/python-sdk/http-wildcard-domain.mdx"; +import WildcardRustSdkExample from "/examples/rust-sdk/http-wildcard-domain.mdx"; +import WildcardSshExample from "/examples/ssh/http-wildcard-domain.mdx"; + +import NonLocalAgentCliExample from "/examples/agent-cli/http-nonlocal.mdx"; +import NonLocalAgentConfigExample from "/examples/agent-config/http-nonlocal.mdx"; +import NonLocalGoSdkExample from "/examples/go-sdk/http-nonlocal.mdx"; +import NonLocalJavascriptSdkExample from "/examples/javascript-sdk/http-nonlocal.mdx"; +import NonLocalKubernetesExample from "/examples/k8s/http-nonlocal.mdx"; +import NonLocalPythonSdkExample from "/examples/python-sdk/http-nonlocal.mdx"; +import NonLocalRustSdkExample from "/examples/rust-sdk/http-nonlocal.mdx"; +import NonLocalSshExample from "/examples/ssh/http-nonlocal.mdx"; + +import AbsPathFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-abs-path.mdx"; +import AbsPathFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-abs-path.mdx"; +import AbsPathFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-abs-path.mdx"; +import AbsPathFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-abs-path.mdx"; +import AbsPathFileserverKubernetesExample from "/examples/k8s/http-fileserver-abs-path.mdx"; +import AbsPathFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-abs-path.mdx"; +import AbsPathFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-abs-path.mdx"; +import AbsPathFileserverSshExample from "/examples/ssh/http-fileserver-abs-path.mdx"; + +import WorkingDirFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverKubernetesExample from "/examples/k8s/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverSshExample from "/examples/ssh/http-fileserver-working-dir.mdx"; + +import WindowsFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-windows.mdx"; +import WindowsFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-windows.mdx"; +import WindowsFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-windows.mdx"; +import WindowsFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-windows.mdx"; +import WindowsFileserverKubernetesExample from "/examples/k8s/http-fileserver-windows.mdx"; +import WindowsFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-windows.mdx"; +import WindowsFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-windows.mdx"; +import WindowsFileserverSshExample from "/examples/ssh/http-fileserver-windows.mdx"; + +You can create HTTP/S endpoints to serve web services like REST APIs, web applications, websites and websocket servers. Serving a web application is as +simple as `ngrok http 80`. + +## Quickstart + +### Agent Endpoint + +Agent Endpoints are the easiest way to get started with ngrok. An [agent +endpoint](/universal-gateway/cloud-endpoints/) is started by a +[Secure Tunnels](/agent/) agent. The endpoint lives for the lifetime of the +process and forwards traffic to a port or URL of your choosing. + +Create the endpoint `https://example.ngrok.app` and forward its traffic to a +local port. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +### Cloud Endpoint + +[Cloud endpoints](/universal-gateway/cloud-endpoints/) are created via the +ngrok Dashboard or [API](/api/). They are persistent and live until they are +deleted. [Traffic Policy](/traffic-policy/) controls how a cloud endpoint +handles traffic. + +[Create an HTTPS cloud endpoint](https://dashboard.ngrok.com/endpoints/new) +which returns a `Hello world!` 200 OK response. + + + + +```sh title="Command line" +ngrok api endpoints create \ + --url https://example.ngrok.app \ + --traffic-policy "$( + + + +## URL + +URLs are validated differently depending on their [binding](/universal-gateway/bindings). To learn more about valid URLs for HTTP/S endpoints, see [the Endpoint URLs documentation](/docs/universal-gateway/what-are-endpoint-urls/). + +#### Public + +###### HTTP + +- The hostname must be a domain with a valid [public suffix](https://publicsuffix.org/). +- The port must be `80`. If you do not specify a port, the default `80` will be used for you. + +**Examples** + +- `http://example.ngrok.app` +- `http://example.ngrok.app:80` +- `http://example.party` +- `http://example.ngrok.app:81` - invalid port: port number must be `80`, not `81` +- `http://example.doesnotexist` - invalid hostname: `.doesnotexist` is not a public suffix domain +- `http://example.internal` - invalid hostname: `.internal` is not a public suffix domain + +###### HTTPS + +- The hostname must be a domain with a valid [public suffix](https://publicsuffix.org/). +- The port must be `443`. If you do not specify a port, the default `443` will be used for you. + +#### Internal + +#### Kubernetes + +##### Valid URLs + +- https://example.ngrok.app +- https://example.ngrok.app:443 +- https://example.party + +##### Invalid URLs + +- https://example.ngrok.app:8443 +- https://example.nosuchtld +- https://example.internal + +### Validation + +When you create an agent endpoint, if you do not specify a complete URL, +following defaults are used to construct an endpoint URL. When you create a +cloud endpoint, you must always specify both a scheme and hostname. + +| URL Part | Default | +| -------- | --------------------------------------------------------- | +| Scheme | `https` | +| Hostname | randomly selected | +| Port | `443` if scheme is `https`
`80` if scheme is `http` | + +Consult the following table of examples of URL defaulting: + +| Value | Endpoint URL | +| ------------------------------- | -------------------------------------------------------- | +| `https://example.ngrok.app` | `https://example.ngrok.app` | +| `http://example.ngrok.app` | `http://example.ngrok.app` | +| `example.ngrok.app` | `https://example.ngrok.app` | +| `app.example.com` | `https://app.example.com` | +| `https://example.internal` | `https://example.internal` | +| `https://example.internal:1234` | `https://example.internal:1234` | +| `http://example.internal` | `http://example.internal` | +| `foo.internal` | `https://foo.internal` | +| `{empty}` | `https://1eb2-181-80-12-3.ngrok.app` (randomly selected) | + +If you would like to listen for both http and https traffic, create two endpoints. + +#### Domains + +When you create a public endpoint, it must match a +[Domain](/universal-gateway/domains/what-are-domains) on your account. Domains help you set up +branded domains and manage TLS certificates. You may create endpoints with +wildcard domains as well. + +Endpoints with randomly-assigned hostnames are an exception and won't match an +existing Domain object. + +### Bring your own domain {#bring-your-own-domain} + +If you want to bring your own domain, first [create a Domain record and set up +a DNS CNAME record](/universal-gateway/how-do-i-use-my-own-domain). Then +create an endpoint on that domain by specifying a URL with a matching hostname. + +For example, to create an HTTPS endpoint on `https://app.example.com`, [create +a Domain](https://dashboard.ngrok.com/domains) and follow the instructions to +set up a CNAME record. Then use the following example to start an endpoint on +your domain: + + + + + + + + + + + + + + + + + + + + + + + + + + + + +### Wildcard endpoints + +You can create an endpoint which will receive traffic for all of the subdomains +matching a given wildcard domain like `*.example.com`. You must create a +[wildcard domain](/universal-gateway/domains/what-are-domains/#wildcard-domains) to create a +public wildcard endpoint. + +For example, if you create the wildcard endpoint `https://*.example.com`, it +will receive traffic for `https://foo.example.com` and +`https://bar.example.com`. + +- Connections to URLs which match an online wildcard endpoint will be routed to + it. For example, if you have created a wildcard endpoint + `https://*.example.com`, connections to `https://foo.bar.baz.example.com` will + route to it. +- Connections are routed to the most specific online endpoint. For example, if + the endpoints `https://*.example.com` and `https://app.example.com` are both + online, a connection to `https://app.example.com` will not be routed to the + wildcard endpoint. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +### Use multiple endpoints with wildcard subdomains + +With the [Agent CLI](/agent/cli), you can create separate public endpoints for subdomains of a wildcard domain no matter where the upstream services are running. See [the Domains docs](/docs/universal-gateway/domains/#wildcard-domains) for more information. + +For example, if you reserve `*.example.com` and want to route requests to `api1.example.com` and `api2.example.com`, you can specify subdomains via the CLI. ngrok will handle routing requests to the correct endpoint, even if they're on different ports. + +The first one might be at port `80`: + +```bash +ngrok http 80 --url https://api1.example.com +``` + +While the second is at port `81`: + +```bash +ngrok http 81 --url https://api2.example.com +``` + +:::tip +This is only necessary for creating _public_ endpoints to subdomains. Internal endpoints don't require a domain. +::: + +### Randomly assigned hostnames + +If you run create a public endpoint without specifying a hostname, ngrok will +automatically assign a random one for you.by selecting a random subdomain of one of our [ngrok-managed +Domains](/universal-gateway/domains#ngrok-managed-domains) to your endpoint. +For example, the command `ngrok http 80` may create an endpoint like +`https://1eb2-181-80-12-3.ngrok.app`. + +The following example create an HTTPS endpoint on a randomly assigned hostname +that forwards to port 8080. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## Traffic Policy + +Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate and transform the traffic through the endpoint. + +### Authentication + +Public endpoints are accessible to the public internet unless you secure them +with authentication. That's desirable if you're hosting a public website but +most often you want to add authentication. You can secure your endpoints with +[Traffic Policy](/traffic-policy) with any of the following actions: + +- [Basic Auth](/traffic-policy/actions/basic-auth) +- [OAuth](/traffic-policy/actions/oauth) +- [IP Restriction](/traffic-policy/actions/restrict-ips/) +- [Webhook Verification](/traffic-policy/actions/verify-webhook/) +- [JWT](/traffic-policy/actions/jwt-validation/) +- [Mutual TLS](/traffic-policy/actions/terminate-tls/) +- [OpenID Connect](/traffic-policy/actions/oidc/) +- [SAML](/traffic-policy/actions/saml/) + +#### Basic Auth Example + +Adds a username and password with the [Basic +Auth](/traffic-policy/actions/basic-auth) Traffic Policy action. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +#### Google OAuth Example + +The following example enforces a browser-based OAuth redirect flow in front of +your endpoint using Google as the identity provider by using the +[OAuth](/traffic-policy/actions/oauth) Traffic Policy action. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#### Rewriting the `host` header {#rewrite-host-header} + +Some application servers expect the `host` header to match a specific value +when they receive requests and some use the `host` header to determine which of +many sites to display. ngrok can rewrite the `host` header of incoming requests +so that your application behaves correctly. + +When you rewrite the `host` header, ngrok also rewrites the `location` header of +HTTP responses automatically to match the hostname of your Endpoint URL. + +The following example rewrites the `host` header to the value `localhost` using +the [`add-headers`](/traffic-policy/actions/add-headers) Traffic Policy action. +Adding the `Host` header [is a special +case](/traffic-policy/actions/add-headers/#special-cases) that replaces the existing +`Host` header instead of appending a second value. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## Agent Forwarding + +The [ngrok agent](/agent/) and [Agent +SDKs](/agent-sdks/) forward traffic that your endpoints receive +to upstream services. You specify a URL or port number to instruct the ngrok +agent where and how to forward traffic. + +### HTTPS forwarding + +The scheme in your upstream URL is used to determine whether to forward HTTP or +HTTPS traffic to the upstream service. If you do not specify a scheme, the +default `http` scheme is chosen _unless_ you forward to port `443`, in which +case ngrok will use `https`. Consult the following table of examples. + +| Upstream URL | Normalized Value | +| ------------------------ | ------------------------ | +| `http://localhost:1234` | `http://localhost:1234` | +| `https://localhost:1234` | `https://localhost:1234` | +| `localhost:1234` | `http://localhost:1234` | +| `1234` | `http://localhost:1234` | +| `localhost:443` | `https://localhost:443` | +| `443` | `https://localhost:443` | + +ngrok assumes that the network you run the agent on is private and it does not +verify the TLS certificate presented by the upstream service. You may change +this behavior with the [flags `--upstream-tls-verify` and +`upstream-tls-verify-cas`](/agent/cli/#ngrok-http). + + + + + + + + + + + + + + + + + + + + + + + + + + + + +### Non-local forwarding + +Agents don't just forward to ports on your localhost. You can forward traffic +to any address or URL reachable from the agent. For example, if you want to +forward traffic to a HTTP server running on your network at `192.168.1.2:80`: + + + + + + + + + + + + + + + + + + + + + + + + + + + + +### HTTP/2 forwarding + +When agents forward to upstream http/2 services, connections use HTTP/1.1 by +default. + +You can configure the agent, SDKs and Kubernetes Operator to instead use HTTP/2 +when forwarding to your upstream service. + +| Forwarder | Option | Docs | +| ------------------- | --------------------------------- | ----------------------------------------- | +| Agent | `--upstream-protocol` | [Agent CLI flags](/agent/cli/#ngrok-http) | +| Agent SDKs | language-dependent | [Agent SDKs](/agent-sdks) | +| Kubernetes Operator | `appProtocol` on the `Tunnel` CRD | [Kubernetes Operator](/k8s) | + +When http2 forwarding is enabled, all requests to your upstream service will be +transmitted over HTTP/2 Cleartext since TLS was already terminated at the ngrok +cloud service. We cannot use +[TLS-ALPN](https://httpwg.org/specs/rfc7540.html#TLS-ALPN) at this time. We +rely on [HTTP/2 with Prior +Knowledge](https://httpwg.org/specs/rfc7540.html#known-http) currently. + +### Serving file directories + +The ngrok agent supports the `file://` scheme in a forwarding URL. When you use +the `file://` scheme, the ngrok agent serves local file system directories by +using its own built-in file server, no separate server needed. It works just +like `python3 -m http.server` but it is built directly into the ngrok agent. + +Paths in `file://` URLs must be specified as absolute paths. + +#### Serve files in `/var/log` + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +#### Serve files on Windows + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +#### Serve files in your current working directory + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## Traffic Observability + +### Traffic Inspector + +[Traffic Inspector](/obs/traffic-inspection/) gives you a real-time view in the +ngrok dashboard of the HTTP traffic flowing through your HTTP/S endpoints. You +can choose whether Traffic Inspector captures only request metadata or full +request and response bodies. + +### Log Export Events + +You can export logs of traffic to HTTP/S endpoints with [ngrok's events +system](/obs/). The following events are published for log exporting: + +| Event | When | +| ------------------------------------------------------------------------ | ----------------------------------------------------------------- | +| [http_request_complete.v0](/obs/events/reference/#http-request-complete) | Published when an HTTP request to an HTTP/S endpoints completes. | +| [tcp_connection_closed.v0](/obs/events/reference/#tcp-connection-closed) | Published when a TCP connection to an HTTP/S endpoints completes. | + +## Advanced + +HTTP/S endpoints are standards-compliant HTTP reverse proxies. + +### Versions + +- HTTP/S endpoints support HTTP/1.1. +- HTTPS endpoints support HTTP/1.1 and HTTP/2. +- HTTP/1.0, HTTP/3 and QUIC are **not** supported. + +### HTTP/2 + +HTTPS endpoints will automatically use HTTP/2 for all connections if the client +supports it. Client support is determined via standard ALPN negotiation. + +HTTP/2 is used between the client and your endpoint even even if your upstream +service does not support HTTP/2. + +The section on [HTTP/2 agent forwarding](#http2-forwarding) has details on how to +configure the use of HTTP/2 when sending traffic to an upstream service. + +### Websockets + +Websocket connections are supported out-of-the-box. No configuration is required. + +### Hop by hop headers + +ngrok does not forward any [hop-by-hop +headers](https://datatracker.ietf.org/doc/html/rfc2616#section-13.5.1) to the +upstream service. As an exception, `Connection: upgrade` headers are forwarded +to support [websockets](#websockets). + +For information on headers added automatically by ngrok, see +[Upstream Headers](#upstream-headers). + +### Persistent connections + +When a connection is made to HTTP/S ngrok endpoints with HTTP/1.1, ngrok may +choose to use persistent connections (aka HTTP keep-alive) to improve the +performance of future requests from the same client if the client supports it. + +This behavior is not guaranteed and it is not configurable. + +See [RFC 7230](https://datatracker.ietf.org/doc/html/rfc7230#section-6.3) for +additional details. + +### Well Known URIs + +#### `/.well-known/acme-challenge` + +ngrok takes over handling of this path of any HTTP endpoint matching a +[Domain](/universal-gateway/domains/what-are-domains) with automated certificate management +enabled. You may disable this behavior by uploading your own certificate on the +matching Domain. + +## TLS + +ngrok automatically handles TLS (SSL) certificate management and termination for you. +There is nothing to setup, configure or manage. + +TLS connections to `https` endpoints are terminated at ngrok's cloud service. +If you wish to terminate TLS traffic at the ngrok agent or in your upstream +application, use a [TLS Endpoint](/universal-gateway/tls) instead. + +Consult the following documentation for additional details on how ngrok handles +TLS termination and certificiate management: + +- [TLS Certificates](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls) +- [TLS Termination](/universal-gateway/tls-termination) + +## Upstream Headers + +ngrok adds headers to each HTTP request with information about the original +client IP, request scheme and request `host` header value. + +| Header | Description | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| `x-forwarded-for` | The IP address of the client who initiated the request. If this header exists on the original request, ngrok will append a new value. | +| `x-forwarded-proto` | The scheme of the original request, either `http` or `https`. If this header exists on the original request, ngrok will append a new value. | +| `x-forwarded-host` | The header from the client's request if it existed, otherwise is set to the request's `Host` header value. | + +Because ngrok appends values to `x-forwarded-for` and `x-forwarded-proto`, be +sure to use the last value of the header in your application code to read the +values injected by ngrok. + +You may remove these headers with the [Remove +Headers](/traffic-policy/actions/remove-headers/) Traffic Policy action. + +## Limits & Timeouts + +[Contact us](mailto:support@ngrok.com) if you need to configure limits and +timeouts on connections to HTTP endpoints. + +#### Connection + +| Limit | Name | Notes | +| --------- | ------------------- | ------------------------------------------------------------ | +| 5 minutes | Client Idle Timeout | Time since data was last transmitted by the upstream service | +| 5 minutes | Server Idle Timeout | Time since data was last transmitted by the upstream service | +| No limit | Data transmitted | Data transmitted by the client or upstream service | + +#### TLS + + + +#### HTTP + +| Limit | Name | Notes | +| ---------- | ------------------ | --------------------------------------------- | +| No timeout | Round Trip Timeout | Time for the entire HTTP request and response | + +#### HTTP Request + +| Limit | Name | Notes | +| ---------- | ---------------------- | ---------------------------------------------------- | +| 1 MB | Request Header Size | Includes method, URI and headers | +| 1 MB | Request URI Length | Limited by the size of the request header | +| No timeout | Request Timeout | Time to read the entire HTTP request from the client | +| No timeout | Request Header Timeout | Time to read the HTTP request header from the client | +| No limit | Request Body Size | | + +#### HTTP Response + +| Limit | Name | Notes | +| ---------- | ----------------------- | ----------------------------------------------------- | +| 1 MB | Response Header Size | Includes method, URI and headers | +| No timeout | Response Timeout | Time to read the entire HTTP response from the server | +| No timeout | Response Header Timeout | Time to read the HTTP response header from the server | +| No limit | Response Body Size | | + +## Errors + +If ngrok fails to handle an HTTP request it will set the `ngrok-error-code` +header in the HTTP response with a [unique ngrok Error Code](/errors/) +describing the failure. + +ngrok guarantees that the upstream service may never set the `ngrok-error-code` +HTTP response header so you know reliably that it was set by ngrok. + +ngrok may return an error under the following conditions: + +- Your upstream service timed out or rejected the connection +- Your upstream service returned a response that was not valid HTTP +- A [Traffic Policy](/traffic-policy) action rejected the request. +- [Traffic Policy](/traffic-policy) execution encountered a runtime error. +- ngrok encountered an internal error + +## API + +HTTP/S Endpoints can be created programatically. Consult the documentation on +[Endpoint APIs](/api/resources/endpoints/). + +## Pricing + +HTTP/S endpoints are available on all plans. Consult the [Endpoints +Pricing](/universal-gateway/endpoints/#pricing) documentation for +billing details. + +See [Domains pricing](/universal-gateway/domains/#pricing) for details on +pricing for custom domains, wildcard domains and more. diff --git a/sidebars.js b/sidebars.js index 663faabe03..737af74583 100644 --- a/sidebars.js +++ b/sidebars.js @@ -123,6 +123,7 @@ const sidebars = { "universal-gateway/chain-endpoints", "universal-gateway/mock-api", "universal-gateway/migrate-from-tunnels", + "universal-gateway/http-s/index", { label: "Endpoints", type: "category", From 24ea832beb3fc0de2df62ee184f96c141e4eba68 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Mon, 31 Mar 2025 14:49:27 -0400 Subject: [PATCH 049/137] add note --- docs/universal-gateway/domains/what-are-domains.mdx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/universal-gateway/domains/what-are-domains.mdx b/docs/universal-gateway/domains/what-are-domains.mdx index dc63c5bd15..0a40afc07d 100644 --- a/docs/universal-gateway/domains/what-are-domains.mdx +++ b/docs/universal-gateway/domains/what-are-domains.mdx @@ -26,6 +26,10 @@ You can manage Domains on your [ngrok Dashboard](https://dashboard.ngrok.com/dom ## Wildcard domains +:::note +Reserving subdomains of a wildcard domain within the ngrok dashboard count towards the number of reserved domains in your account. For example, if you reserve `foo.example.com` and `*.example.com`, you have reserved two domains. +::: + You may create a Domain with a wildcard name, e.g. `*.example.com`. A wildcard domain enables you to: - Create an endpoint which receives traffic for all of its subdomains, e.g. `https://*.example.com`. See [Wildcard Endpoints](/universal-gateway/http/#wildcard-endpoints) to understand the rules for matching and precedence. From d215257f9008fbd7b17fea0bca00c0b8ba27118a Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 1 Apr 2025 09:21:43 -0400 Subject: [PATCH 050/137] Checkpoint; working on https page --- docs/universal-gateway/http.mdx | 41 ++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/docs/universal-gateway/http.mdx b/docs/universal-gateway/http.mdx index ff338a1d29..73fb04a3a5 100644 --- a/docs/universal-gateway/http.mdx +++ b/docs/universal-gateway/http.mdx @@ -1,5 +1,5 @@ --- -title: HTTP/S Endpoints +title: How Do I Handle HTTP/S Traffic? --- import TabItem from "@theme/TabItem"; @@ -105,6 +105,7 @@ import WorkingDirFileserverPythonSdkExample from "/examples/python-sdk/http-file import WorkingDirFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-working-dir.mdx"; import WorkingDirFileserverSshExample from "/examples/ssh/http-fileserver-working-dir.mdx"; +import { LangSwitcher } from "@site/src/components/LangSwitcher"; import WindowsFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-windows.mdx"; import WindowsFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-windows.mdx"; import WindowsFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-windows.mdx"; @@ -115,16 +116,40 @@ import WindowsFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver- import WindowsFileserverSshExample from "/examples/ssh/http-fileserver-windows.mdx"; HTTP/S endpoints enable you to serve web services like REST APIs, web -applications, websites and websocket servers. Serving a web application is as -simple as `ngrok http 80`. +applications, websites, and websocket servers. -Once your endpoint is running, check out: +You can create HTTP/S endpoints locally with the [Agent CLI](/agent/cli) or as [Cloud Endpoints](/universal-gateway/cloud-endpoints/) via the ngrok Dashboard. -- [Traffic Policy](/traffic-policy/) - Add routing, authentication and traffic transformation -- [Traffic Inspector](https://dashboard.ngrok.com/traffic-inspection/) - Real-time observability with request/response introspection -- [Endpoint Pooling](/universal-gateway/endpoint-pooling/) - Load balancing + + -## Quickstart + + + + + + + + + + + + + + + + + + + + + + + + + + + ### Agent Endpoint From 285e1bf9c2708266650f0d1016939572908ed053 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 1 Apr 2025 09:50:46 -0400 Subject: [PATCH 051/137] Working on wildcard domains pages --- docs/pricing-limits/index.mdx | 4 +- docs/universal-gateway/domains.mdx | 215 ------------------ .../domains/how-do-i-use-my-own-domain.mdx | 2 +- .../domains/what-are-domains.mdx | 17 -- .../domains/wildcard-domains.mdx | 121 ++++++++++ docs/universal-gateway/endpoint-pooling.mdx | 7 +- docs/universal-gateway/http-s/index.mdx | 70 +----- docs/universal-gateway/http.mdx | 57 ----- .../kubernetes-endpoints.mdx | 176 -------------- .../kubernetes-endpoints/index.mdx | 6 +- .../kubernetes-endpoints/selector.mdx | 11 + .../how-does-ngrok-handle-tls.mdx | 16 +- 12 files changed, 144 insertions(+), 558 deletions(-) delete mode 100644 docs/universal-gateway/domains.mdx create mode 100644 docs/universal-gateway/domains/wildcard-domains.mdx delete mode 100644 docs/universal-gateway/kubernetes-endpoints.mdx diff --git a/docs/pricing-limits/index.mdx b/docs/pricing-limits/index.mdx index 475352a332..92c9d670bf 100644 --- a/docs/pricing-limits/index.mdx +++ b/docs/pricing-limits/index.mdx @@ -73,9 +73,7 @@ This limit does not refresh at the end of each calendar month. ## Wildcard and Subdomain Usage -When reserving a wildcard domain on the paid plans, subdomains are counted towards your usage. For example, if you reserve `*.example.com`, `sub1.example.com` and `sub2.example.com` are counted as two subdomains. -You will be charged for each subdomain you use. -You may need to enable overages in order to do this on your paid plan. +Reserving subdomains of a wildcard domain within the ngrok dashboard count towards the number of reserved domains in your account. For example, if you reserve `foo.example.com` and `*.example.com`, you have reserved two domains.. You will be charged for each subdomain you use. You may need to enable overages in order to do this on your paid plan. ## Free vs paid plans diff --git a/docs/universal-gateway/domains.mdx b/docs/universal-gateway/domains.mdx deleted file mode 100644 index 04769e4c50..0000000000 --- a/docs/universal-gateway/domains.mdx +++ /dev/null @@ -1,215 +0,0 @@ ---- -title: Domains ---- - -# Domains - -## Overview - -Domains enable you to create public endpoints with hostnames matching the -domain. For example, after you create the domain `your-name.ngrok.app`, you may -create the Endpoint `https://your-name.ngrok.app` - -Domain names may be a subdomain of an [ngrok-managed -domain](#ngrok-managed-domains) like `foo.ngrok.app` or you can [bring your own -domain](#branded-domains) like `example.your-domain.com` by creating a CNAME -DNS record with your domain's DNS provider. - -Domains also enable you configure other domain-level behaviors including: - -- [**Global Load Balancer configuration**](#global-load-balancer) - Choose which points of presence handle traffic to a Domain's matching endpoints. -- [**TLS Certificate management**](#tls-certificates) - Configure automatic certificate provisioning or select a certificate you uploaded yourself. -- [**Dedicated IP address configuration**](#dedicated-ips) - Attach static, dedicated IPs for a Domain's matching endpoints receive traffic on. - -You can manage Domains on your [ngrok Dashboard](https://dashboard.ngrok.com/domains) -or via the [ngrok API](#api). - -## Public endpoints - -A Domain's primary responsibility is to enable you to create [public -endpoints](/universal-gateway/public-endpoints/) with a hostname matching the -domain. These are called "matching endpoints". For example, after you create -the Domain `app.example.com`, you can create the Endpoint -`https://app.example.com`. - -When you create a Domain, you may create matching public endpoints with the -following constraints: - -| Endpoint Protocol | Allowed Endpoints | -| ----------------- | ------------------------------------------------------------------------------------------------ | -| `http` | Matching endpoints on port `80` of the Domain. | -| `https` | Matching endpoints on port `443` of the Domain. | -| `tls` | Matching endpoints on port `443` of the Domain. | -| `tcp` | Not allowed. Public TCP endpoints must match a [TCP Address](/universal-gateway/tcp-addresses/). | - -If you configure your Domain to use [dedicated IPs](#dedicated-ips), these -restrictions are removed and you may create matching endpoints on any ports. - -### Wildcard Domains - -You may create a Domain with a wildcard name, e.g. `*.example.com`. A wildcard -domain enables you to: - -- Create an endpoint which receives traffic for all of its subdomains, e.g. - `https://*.example.com`. Consult the documentation for [wildcard - endpoints](/universal-gateway/http/#wildcard-endpoints) to understand - the rules for matching and precedence. - -- Create an endpoint on any subdomain which matches the wildcard, e.g. - `https://foo.example.com` or `https://foo.bar.baz.example.com` - -The wildcard `*` character may only be used as the first part of a -domain, you may not create domains like `app.*.example.com` or -`*-app.example.com`. - -:::note -Wildcard domains are available on our Enterprise plan self service. They are also available on Pay-as-You-Go plans if you contact support@ngrok.com. For Pay-as-You-Go when you create a wildcard domain and run endpoints domain `*.foo.com`, endpoints `https://a.foo.com` and `https://b.foo.com`, we bill you for each individual endpoint, which is why we ask that you request the feature. -::: - -:::note -Reserving subdomains of a wildcard domain within the ngrok dashboard count towards the number of reserved domains in your account. For example, if you reserve `foo.example.com` and `*.example.com`, you have reserved two domains. -::: - -### Ownership - -Your account exclusively owns its Domains and all of their nested subdomains -within ngrok. That means: - -- No account may create a Domain with a name that is a subdomain of your Domains. -- No other account may create endpoints with a hostname matching your Domain or - any of its nested subdomains. - -For example, if you create a Domain with the name `foo.ngrok.app`: - -- No other account create the Domains `foo.ngrok.app` or `bar.foo.ngrok.app`. -- No other account may create the endpoints `https://foo.ngrok.app` or `https://bar.foo.ngrok.app`. - -## Bring your own domain {#branded-domains} - -You can use any domain name that you already own with ngrok, e.g. -`app.your-domain.com`. To do so, you will create a CNAME record for that domain -to point traffic from the domain to ngrok's cloud service. When you create a -Domain, you will be presented with a target value for the CNAME record you need -to create. If you [create the Domain via -API](/api/resources/reserved-domains/), this value is the `cname_target` field. - -If you bring your own [wildcard domain](#wildcard-domains), you will need to -create a second DNS CNAME record for [wildcard TLS Certificate -provisioning](/universal-gateway/tls-certificates/#wildcard-domains). - -ngrok is not a domain registrar; you must already own a domain name to use it -with ngrok. - -### Apex domains - -If you want to use an apex domain (e.g. `example.com`) with ngrok, you must use -a DNS provider that supports an ALIAS record or CNAME flattening because the -DNS RFC does not permit CNAME records for apex domains. Because of how -ALIAS/CNAME flattening is implemented, apex domains will not take advantage of -the [Global Load Balancer](#global-load-balancer). If you are trying to create -your apex domain because you need to create endpoints for multiple subdomains, -use a [wildcard domain](#wildcard-domains) instead. - -## Global Load Balancer - -The [Global Load Balancer](/universal-gateway/global-load-balancer) -uses latency-aware DNS records to direct clients to the IPs of the nearest -[points of presence](/universal-gateway/points-of-presence/). - -Domains allow you to configure which points of presence the Global Load -Balancer may resolve clients to. This allows you to select which points of -presence will receive traffic for the Domain's matching endpoints. To disable -the Global Load Balancer, you may configure a domain to only resolve a single -point of presence. - -:::info Coming Soon - -Per-region global load balancer configuration is coming soon, [request access -to the developer preview](https://dashboard.ngrok.com/developer-preview). - -::: - -## TLS Certificates - -Domains manage the [TLS Certificate](/universal-gateway/tls-certificates/) used -to terminate TLS connections to the Domain's matching endpoints. When you -create a Domain, you may choose to allow ngrok to automatically provision TLS -certificates for you or to upload your own TLS certificate. - -Consult the documentation on [TLS -Certificates](/universal-gateway/tls-certificates/) for additional details on -certificate provisioning and management. - -## Dedicated IPs - -By default, a Domain's matching Endpoints receive traffic on a set of -multi-tenant [IP addresses](/universal-gateway/ip-addresses) that are -shared among all ngrok accounts. You may instead configure a Domain's matching -endpoints to receive traffic on IP addresses that are dedicated to your -account. - -If your Domain uses dedicated IPs, you may create public endpoints on _any_ -port numbers, not just 80 and 443. - -:::info Coming Soon - -Dedicated, static IPs for your domains are coming soon, [request access to the -developer preview](https://dashboard.ngrok.com/developer-preview). - -::: - -## ngrok Managed Domains - -If you don't own a domain that you want to use with ngrok, you can create a -Domain that is a subdomain of an ngrok-managed base domain. The ngrok-managed -base domains are: - -| Domain | Availability | HSTS Global Preload | -| ------------------ | ------------------------------------------------- | ------------------- | -| `ngrok.app` | Available to paying accounts | Yes | -| `ngrok.dev` | Available to paying accounts | Yes | -| `ngrok.pizza` | Available to paying accounts | No | -| `ngrok-free.app` | Used by free accounts | Yes | -| `ngrok-free.dev` | Used by free accounts | Yes | -| `ngrok-free.pizza` | Used by free accounts (coming soon) | No | -| `ngrok.io` | Discontinued and only available to older accounts | No | - -### Public Suffix List - -The ngrok-managed base domains are on the [Public Suffix -List](https://publicsuffix.org/). Browsers use the Public Suffix List to -guarantee that cookies from one subdomain cannot be accessed by other -subdomains. - -### HSTS Preload - -Some of the ngrok-managed base domains are on the global -[HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) preload -list. If the domain of the URL is on the [global HSTS preload -list](https://hstspreload.org/), modern browsers automatically convert requests -with an `http` scheme to `https`. - -If you need to create unencrypted `http` endpoints, you should create them with -hostnames that are not on the HSTS Global Preload like `ngrok.io` and -`ngrok.pizza`. - -ngrok does not prohibit you from creating `http` endpoints with hostnames whose -base domain is on the global HSTS preload list because non-browser clients -(like `curl`) can still be used to make unencrypted HTTP requests to them. - -## API - -Domains are programatically managed via: - -- [`/reserved_domains` API Resource](/api/resources/reserved-domains/) - -## Pricing - -Domains are available on all plans. Some Domain features require upgrades. See -the [Pricing page](https://ngrok.com/pricing) for details. - -| Feature | Plans | -| ---------------------- | --------------------------------------------------------------------------------- | -| Domains | All plans. The Domain name is assigned on Free, you may choose it on other plans. | -| Bring-your-own domains | Personal, Pro, Enterprise, Pay-as-you-go | -| Wildcard Domains | Enterprise | diff --git a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx index 0f4aab7b95..a04027aad9 100644 --- a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx +++ b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx @@ -26,7 +26,7 @@ with ngrok. ## Wildcard domains -If you bring your own [wildcard domain](/universal-gateway/what-are-public-endpoints#wildcard-domains), e.g. `*.example.com`, you will need to create a second `CNAME` record with your domain host for [wildcard TLS Certificate provisioning](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/#wildcard-domains). +If you bring your own [wildcard domain](/universal-gateway/wildcard-domains), e.g. `*.example.com`, you will need to create a second `CNAME` record with your domain host for [wildcard TLS Certificate provisioning](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/#wildcard-domains). ## Apex domains diff --git a/docs/universal-gateway/domains/what-are-domains.mdx b/docs/universal-gateway/domains/what-are-domains.mdx index 0a40afc07d..d5f92dbc04 100644 --- a/docs/universal-gateway/domains/what-are-domains.mdx +++ b/docs/universal-gateway/domains/what-are-domains.mdx @@ -24,23 +24,6 @@ Domains also enable you to configure other domain-level behaviors, including: You can manage Domains on your [ngrok Dashboard](https://dashboard.ngrok.com/domains) or via the [ngrok API](#api). -## Wildcard domains - -:::note -Reserving subdomains of a wildcard domain within the ngrok dashboard count towards the number of reserved domains in your account. For example, if you reserve `foo.example.com` and `*.example.com`, you have reserved two domains. -::: - -You may create a Domain with a wildcard name, e.g. `*.example.com`. A wildcard domain enables you to: - -- Create an endpoint which receives traffic for all of its subdomains, e.g. `https://*.example.com`. See [Wildcard Endpoints](/universal-gateway/http/#wildcard-endpoints) to understand the rules for matching and precedence. -- Create an endpoint on any subdomain which matches the wildcard, e.g. `https://foo.example.com` or `https://foo.bar.baz.example.com` - -:::note -The wildcard `*` character may only be used as the first part of a -domain, you may not create domains like `app.*.example.com` or -`*-app.example.com`. -::: - ## Ownership Your account exclusively owns its Domains and all of their nested subdomains diff --git a/docs/universal-gateway/domains/wildcard-domains.mdx b/docs/universal-gateway/domains/wildcard-domains.mdx new file mode 100644 index 0000000000..b3dbbcbc96 --- /dev/null +++ b/docs/universal-gateway/domains/wildcard-domains.mdx @@ -0,0 +1,121 @@ +--- +title: How Do I Use Wildcard Domains? +--- + +import WildcardAgentCliExample from "/examples/agent-cli/http-wildcard-domain.mdx"; +import WildcardAgentConfigExample from "/examples/agent-config/http-wildcard-domain.mdx"; +import WildcardGoSdkExample from "/examples/go-sdk/http-wildcard-domain.mdx"; +import WildcardJavascriptSdkExample from "/examples/javascript-sdk/http-wildcard-domain.mdx"; +import WildcardKubernetesExample from "/examples/k8s/http-wildcard-domain.mdx"; +import WildcardPythonSdkExample from "/examples/python-sdk/http-wildcard-domain.mdx"; +import WildcardRustSdkExample from "/examples/rust-sdk/http-wildcard-domain.mdx"; +import WildcardSshExample from "/examples/ssh/http-wildcard-domain.mdx"; + +You may create a Domain with a wildcard name, e.g. `*.example.com`. A wildcard domain enables you to: + +- Create an endpoint which receives traffic for all of its subdomains, e.g. `https://*.example.com`. See [Wildcard Endpoints](/universal-gateway/http/#wildcard-endpoints) to understand the rules for matching and precedence. +- Create an endpoint on any subdomain which matches the wildcard, e.g. `https://foo.example.com` or `https://foo.bar.baz.example.com` + +:::note +The wildcard `*` character may only be used as the first part of a +domain, you may not create domains like `app.*.example.com` or +`*-app.example.com`. +::: + +### Wildcard endpoints + +You can create an endpoint which will receive traffic for all of the subdomains +matching a given wildcard domain like `*.example.com`. You must create a +[wildcard domain](/universal-gateway/domains/what-are-domains/#wildcard-domains) to create a +public wildcard endpoint. + +For example, if you create the wildcard endpoint `https://*.example.com`, it +will receive traffic for `https://foo.example.com` and +`https://bar.example.com`. + +- Connections to URLs which match an online wildcard endpoint will be routed to + it. For example, if you have created a wildcard endpoint + `https://*.example.com`, connections to `https://foo.bar.baz.example.com` will + route to it. +- Connections are routed to the most specific online endpoint. For example, if + the endpoints `https://*.example.com` and `https://app.example.com` are both + online, a connection to `https://app.example.com` will not be routed to the + wildcard endpoint. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[Wildcard endpoints](/universal-gateway/wildcard-domains/#wildcard-endpoints) do not pool with non-wildcard URLs. For example, if you have +two endpoints online, `https://foo.example.com` and `https://*.example.com`, +they will not pool together and traffic to `https://foo.example.com` will not +be load balanced. Consult the documentation for [wildcard +endpoints](/universal-gateway/http/#wildcard-endpoints) to understand +the rules for matching and precedence. + +### Use multiple endpoints with wildcard subdomains + +With the [Agent CLI](/agent/cli), you can create separate public endpoints for subdomains of a wildcard domain no matter where the upstream services are running. See [the Domains docs](/docs/universal-gateway/domains/#wildcard-domains) for more information. + +For example, if you reserve `*.example.com` and want to route requests to `api1.example.com` and `api2.example.com`, you can specify subdomains via the CLI. ngrok will handle routing requests to the correct endpoint, even if they're on different ports. + +The first one might be at port `80`: + +```bash +ngrok http 80 --url https://api1.example.com +``` + +While the second is at port `81`: + +```bash +ngrok http 81 --url https://api2.example.com +``` + +:::tip +This is only necessary for creating _public_ endpoints to subdomains. Internal endpoints don't require a domain. +::: + +### TLS provisioning + +When you bring your own wildcard domain (e.g. `*.app.example.com`), ngrok uses +a DNS01 challenge for TLS certificate provisioning which means that you must +create two CNAME records when creating branded wildcard domains instead of just +one. + +For example, If your domain is `*.app.example.com` you will be required to create the +following two CNAME records: + +- `*.app.example.com` +- `_acme-challenge.app.example.com` + +Certificate provisioning will not begin until you have created both DNS +records. + +## Pricing + +Wildcard domains are available on our Enterprise plan self service. They are also available on Pay-as-You-Go plans if you contact support@ngrok.com. For Pay-as-You-Go when you create a wildcard domain and run endpoints domain `*.foo.com`, endpoints `https://a.foo.com` and `https://b.foo.com`, we bill you for each individual endpoint, which is why we ask that you request the feature. + +Reserving subdomains of a wildcard domain within the ngrok dashboard count towards the number of reserved domains in your account. For example, if you reserve `foo.example.com` and `*.example.com`, you have reserved two domains.. You will be charged for each subdomain you use. You may need to enable overages in order to do this on your paid plan. diff --git a/docs/universal-gateway/endpoint-pooling.mdx b/docs/universal-gateway/endpoint-pooling.mdx index 684b4b045f..d965c98467 100644 --- a/docs/universal-gateway/endpoint-pooling.mdx +++ b/docs/universal-gateway/endpoint-pooling.mdx @@ -225,12 +225,7 @@ endpoint in the pool. ## Wildcard Endpoints -Wildcard endpoints do not pool with non-wildcard URLs. For example, if you have -two endpoints online, `https://foo.example.com` and `https://*.example.com`, -they will not pool together and traffic to `https://foo.example.com` will not -be load balanced. Consult the documentation for [wildcard -endpoints](/universal-gateway/http/#wildcard-endpoints) to understand -the rules for matching and precedence. +TODO: Link to wildcard docs ## Protocol, Binding and Type diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx index cd0c4f5b21..25220d8c5e 100644 --- a/docs/universal-gateway/http-s/index.mdx +++ b/docs/universal-gateway/http-s/index.mdx @@ -5,6 +5,7 @@ title: How do I handle HTTP/S traffic? import TabItem from "@theme/TabItem"; import Tabs from "@theme/Tabs"; +import { LangSwitcher } from "@site/src/components/LangSwitcher"; import TlsLimits from "../_tls_limits.mdx"; import RandomAgentCliExample from "/examples/agent-cli/http-random.mdx"; @@ -309,74 +310,9 @@ your domain: -### Wildcard endpoints +### Wildcard Endpoints -You can create an endpoint which will receive traffic for all of the subdomains -matching a given wildcard domain like `*.example.com`. You must create a -[wildcard domain](/universal-gateway/domains/what-are-domains/#wildcard-domains) to create a -public wildcard endpoint. - -For example, if you create the wildcard endpoint `https://*.example.com`, it -will receive traffic for `https://foo.example.com` and -`https://bar.example.com`. - -- Connections to URLs which match an online wildcard endpoint will be routed to - it. For example, if you have created a wildcard endpoint - `https://*.example.com`, connections to `https://foo.bar.baz.example.com` will - route to it. -- Connections are routed to the most specific online endpoint. For example, if - the endpoints `https://*.example.com` and `https://app.example.com` are both - online, a connection to `https://app.example.com` will not be routed to the - wildcard endpoint. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -### Use multiple endpoints with wildcard subdomains - -With the [Agent CLI](/agent/cli), you can create separate public endpoints for subdomains of a wildcard domain no matter where the upstream services are running. See [the Domains docs](/docs/universal-gateway/domains/#wildcard-domains) for more information. - -For example, if you reserve `*.example.com` and want to route requests to `api1.example.com` and `api2.example.com`, you can specify subdomains via the CLI. ngrok will handle routing requests to the correct endpoint, even if they're on different ports. - -The first one might be at port `80`: - -```bash -ngrok http 80 --url https://api1.example.com -``` - -While the second is at port `81`: - -```bash -ngrok http 81 --url https://api2.example.com -``` - -:::tip -This is only necessary for creating _public_ endpoints to subdomains. Internal endpoints don't require a domain. -::: +TODO: Link to wildcard domains docs ### Randomly assigned hostnames diff --git a/docs/universal-gateway/http.mdx b/docs/universal-gateway/http.mdx index 73fb04a3a5..a485866229 100644 --- a/docs/universal-gateway/http.mdx +++ b/docs/universal-gateway/http.mdx @@ -69,15 +69,6 @@ import HostHeaderPythonSdkExample from "/examples/python-sdk/http-rewrite-host-h import HostHeaderRustSdkExample from "/examples/rust-sdk/http-rewrite-host-header.mdx"; import HostHeaderSshExample from "/examples/ssh/http-rewrite-host-header.mdx"; -import WildcardAgentCliExample from "/examples/agent-cli/http-wildcard-domain.mdx"; -import WildcardAgentConfigExample from "/examples/agent-config/http-wildcard-domain.mdx"; -import WildcardGoSdkExample from "/examples/go-sdk/http-wildcard-domain.mdx"; -import WildcardJavascriptSdkExample from "/examples/javascript-sdk/http-wildcard-domain.mdx"; -import WildcardKubernetesExample from "/examples/k8s/http-wildcard-domain.mdx"; -import WildcardPythonSdkExample from "/examples/python-sdk/http-wildcard-domain.mdx"; -import WildcardRustSdkExample from "/examples/rust-sdk/http-wildcard-domain.mdx"; -import WildcardSshExample from "/examples/ssh/http-wildcard-domain.mdx"; - import NonLocalAgentCliExample from "/examples/agent-cli/http-nonlocal.mdx"; import NonLocalAgentConfigExample from "/examples/agent-config/http-nonlocal.mdx"; import NonLocalGoSdkExample from "/examples/go-sdk/http-nonlocal.mdx"; @@ -105,7 +96,6 @@ import WorkingDirFileserverPythonSdkExample from "/examples/python-sdk/http-file import WorkingDirFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-working-dir.mdx"; import WorkingDirFileserverSshExample from "/examples/ssh/http-fileserver-working-dir.mdx"; -import { LangSwitcher } from "@site/src/components/LangSwitcher"; import WindowsFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-windows.mdx"; import WindowsFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-windows.mdx"; import WindowsFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-windows.mdx"; @@ -347,53 +337,6 @@ your domain: -### Wildcard endpoints - -You can create an endpoint which will receive traffic for all of the subdomains -matching a given wildcard domain like `*.example.com`. You must create a -[wildcard domain](/universal-gateway/domains/what-are-domains/#wildcard-domains) to create a -public wildcard endpoint. - -For example, if you create the wildcard endpoint `https://*.example.com`, it -will receive traffic for `https://foo.example.com` and -`https://bar.example.com`. - -- Connections to URLs which match an online wildcard endpoint will be routed to - it. For example, if you have created a wildcard endpoint - `https://*.example.com`, connections to `https://foo.bar.baz.example.com` will - route to it. -- Connections are routed to the most specific online endpoint. For example, if - the endpoints `https://*.example.com` and `https://app.example.com` are both - online, a connection to `https://app.example.com` will not be routed to the - wildcard endpoint. - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Use multiple endpoints with wildcard subdomains With the [Agent CLI](/agent/cli), you can create separate public endpoints for subdomains of a wildcard domain no matter where the upstream services are running. See [the Domains docs](/docs/universal-gateway/domains/#wildcard-domains) for more information. diff --git a/docs/universal-gateway/kubernetes-endpoints.mdx b/docs/universal-gateway/kubernetes-endpoints.mdx deleted file mode 100644 index fdc51e0cf4..0000000000 --- a/docs/universal-gateway/kubernetes-endpoints.mdx +++ /dev/null @@ -1,176 +0,0 @@ -# Kubernetes Endpoints - -:::info Coming Soon - -Kubernetes endpoints are not available yet, [request access to the developer -preview](https://dashboard.ngrok.com/developer-preview) for early access. - -::: - -## Overview - -Kubernetes endpoints are secure, private endpoints that are only addressable -inside of Kubernetes clusters where you install the [Kubernetes -operator](/k8s/). They enable you to connect to ngrok endpoints without making -them publicly addressable. - -Kubernetes endpoints have a -[binding](/universal-gateway/bindings) of `kubernetes`. - -## Quickstart - -Create a Kubernetes endpoint by specifying binding of `kubernetes` when you -create an endpoint. - -#### Step 1: Install the ngrok Kubernetes Operator - -```bash -helm install ngrok-operator ngrok/ngrok-operator \ - --namespace ngrok-operator \ - --create-namespace \ - --set description="example operator" \ - --set bindings.enabled=true \ - --set credentials.apiKey=$NGROK_API_KEY \ - --set credentials.authtoken=$NGROK_AUTHTOKEN -``` - -#### Step 2: Create a new namespace - -```bash -kubectl create ns prod -``` - -#### Step 3: Create an ngrok endpoint - -Run the following command in the same ngrok account to create the kubernetes -bound endpoint. After the command completes, the ngrok operator will [create -`Service` objects](#service-creation) in the kubernetes cluster matching the -endpoint's URL. - -```bash -ngrok http 80 --url http://customer-2.prod --binding kubernetes -``` - -#### Step 4: Connect to the endpoint - -Other pods in the Kubernetes cluster where the ngrok operator is running can -connect to the bound endpoint. - -```bash -$ kubectl run -i --tty --rm debug --restart=Never --image=appropriate/curl -- /bin/sh -# curl http://customer-2.prod -``` - -Congraulations, you just connected to your application via a private kubernetes -endpoint! - -## URLs - -Kubernetes endpoint URL hostnames must be in the following format: - -- `[http|tcp]://name.namespace[:port]` - -The following restrictions are enforced: - -- **Scheme** - Must be `http` or `tcp`. `https` and `tls` are not supported. -- **Hostname** - Hostnames must always be two parts separated by a single dot, - e.g. `foo.bar`. Wildcard hostnames are not allowed. -- **Port** - All port numbers [1-65535] are valid. Port must be specified for - `tcp` endpoints. -- **Namespacing** - Kubernetes endpoints are namespaced on a per-account basis. - Two accounts may have kubernetes endpoints with the same URL (e.g. - http://api.internal). Those endpoints will not conflict or - [pool](/universal-gateway/endpoint-pooling). - -#### Examples - -- `http://app.example` -- `http://app.example:12345` -- `tcp://app.example:443` -- `tcp://app.example:12345` -- `https://app.example` - invalid scheme `https` -- `tls://app.example:12345` - invalid scheme `tls` -- `http://app.foo.bar` - invalid hostname, must have only two parts -- `tcp://app.example` - tcp endpoint must specify port number - -## Type and Pooling - -- Kubernetes endpoints support all [Endpoint - Types](/universal-gateway/types) (`agent` and `cloud`). -- Kubernetes endpoints support [Endpoint - Pooling](/universal-gateway/endpoint-pooling). - -## `Service` Creation - -After a kubernetes-bound endpoint is created, the ngrok cloud service notifies -Kubernetes Operators that a new kubernetes-bound endpoint exists. Kubernetes -Operators create `v1.Service` objects in their Kubernetes clusters which -forward traffic they receive to the operators' pods. - -#### `ClusterIP` Service - -A Cluster IP service is created in the operator's namespace. - -```yaml -apiVersion: v1 -kind: Service -metadata: - name: # the endpoint's ID - namespace: ngrok-operator -spec: - selector: - app.kubernetes.io/name: ngrok-operator-forwarder - ports: - - protocol: TCP - port: 80 # the endpoint url's port - targetPort: # assigned by operator to target the ngrok-operator-forwarder container -``` - -#### `ExternalName` Service - -An ExternalName service is created in the namespace targeted by the second part -of the URL's hostname. - -```yaml -apiVersion: v1 -kind: Service -metadata: - name: customer-2 # first part of the URL's hostname - namespace: prod ## second part of the URL's hostname -spec: - # Point service at the Operator Forwarder - type: ExternalName - externalName: .ngrok-operator.svc.cluster.local -``` - -## How do I update endpoint selectors? - -If you don't want all kubernetes endpoints in your account to appear inside of -a cluster, you may specify an Endpoint Selector which filters which Kubernetes -endpoints are projected into the cluster it runs in. Endpoint Selectors are a -CEL expression which is evaluated against each Kubernetes Endpoint in your -account. The operator will only projects endpoints that the selector returns -`true` for. - -See [the docs on enabling bindings](/docs/k8s/guides/bindings/#enable-bindings-for-the-operator) to learn more. - -## How do I enable or disable Kubernetes endpoints on an existing installation? - -By default, if you don't change the default endpoint selector, all endpoints with a Kubernetes binding will be bound to the cluster the Operator is installed on. Changing the binding allows you to restrict which endpoints that operator will handle. - -See [the docs on enabling bindings](/docs/k8s/guides/bindings/#enable-bindings-for-the-operator) to learn more. - -## Coming Soon - -This feature is in developer preview, more documentation is coming soon. - -## API - -Kubernetes endpoints can be created programatically. Consult the documentation -on [Endpoint APIs](/api/resources/endpoints/). - -## Pricing - -Kubernetes endpoints are available on the Pay-as-you-go plan. Consult the -[Endpoints Pricing](/universal-gateway/endpoints/#pricing) -documentation for billing details. diff --git a/docs/universal-gateway/kubernetes-endpoints/index.mdx b/docs/universal-gateway/kubernetes-endpoints/index.mdx index 30010d17fa..9f72a05b0c 100644 --- a/docs/universal-gateway/kubernetes-endpoints/index.mdx +++ b/docs/universal-gateway/kubernetes-endpoints/index.mdx @@ -22,9 +22,11 @@ Kubernetes endpoints have a [binding](/universal-gateway/bindings) of `kubernete - Kubernetes endpoints support [Endpoint Pooling](/universal-gateway/endpoint-pooling). -## Coming Soon +## How do I enable or disable Kubernetes endpoints on an existing installation? -This feature is in developer preview, more documentation is coming soon. +By default, if you don't change the default endpoint selector, all endpoints with a Kubernetes binding will be bound to the cluster the Operator is installed on. Changing the binding allows you to restrict which endpoints that operator will handle. + +See [the docs on enabling bindings](/docs/k8s/guides/bindings/#enable-bindings-for-the-operator) to learn more. ## API diff --git a/docs/universal-gateway/kubernetes-endpoints/selector.mdx b/docs/universal-gateway/kubernetes-endpoints/selector.mdx index c7b1ac4d6c..b225103726 100644 --- a/docs/universal-gateway/kubernetes-endpoints/selector.mdx +++ b/docs/universal-gateway/kubernetes-endpoints/selector.mdx @@ -15,3 +15,14 @@ add the following flag when installing the Kubernetes Operator: ```bash --set binding.endpointSelector="ep.hostname.endsWith('.billing')" \ ``` + +## How do I update endpoint selectors? + +If you don't want all kubernetes endpoints in your account to appear inside of +a cluster, you may specify an Endpoint Selector which filters which Kubernetes +endpoints are projected into the cluster it runs in. Endpoint Selectors are a +CEL expression which is evaluated against each Kubernetes Endpoint in your +account. The operator will only projects endpoints that the selector returns +`true` for. + +See [the docs on enabling bindings](/docs/k8s/guides/bindings/#enable-bindings-for-the-operator) to learn more. diff --git a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx index 3ef6d46af1..1150a332f4 100644 --- a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx +++ b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx @@ -20,21 +20,9 @@ TLS certificates are composed of a private key and a certificate. These are pres TLS certificates are attached to [domains](/universal-gateway/domains/what-are-domains/) for [termination of TLS connections to endpoints](/universal-gateway/tls-termination/) whose URLs match that domain. -## Wildcard Domains +## Wildcard domains -When you bring your own wildcard domain (e.g. `*.app.example.com`), ngrok uses -a DNS01 challenge for TLS certificate provisioning which means that you must -create two CNAME records when creating branded wildcard domains instead of just -one. - -For example, If your domain is `*.app.example.com` you will be required to create the -following two CNAME records: - -- `*.app.example.com` -- `_acme-challenge.app.example.com` - -Certificate provisioning will not begin until you have created both DNS -records. +TODO: Link to wildcard domains ## API From 12918d4f399ba0e8236bc442ee84febaa6636edc Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 1 Apr 2025 10:27:51 -0400 Subject: [PATCH 052/137] Wildcard domains docs done --- docs/universal-gateway/endpoint-pooling.mdx | 4 +- docs/universal-gateway/http-s/index.mdx | 2 +- .../how-does-ngrok-handle-tls.mdx | 2 +- .../wildcard-domains/index.mdx | 36 +++++++++++++ .../wildcard-endpoints.mdx} | 53 +++---------------- 5 files changed, 46 insertions(+), 51 deletions(-) create mode 100644 docs/universal-gateway/wildcard-domains/index.mdx rename docs/universal-gateway/{domains/wildcard-domains.mdx => wildcard-domains/wildcard-endpoints.mdx} (52%) diff --git a/docs/universal-gateway/endpoint-pooling.mdx b/docs/universal-gateway/endpoint-pooling.mdx index d965c98467..774d87f121 100644 --- a/docs/universal-gateway/endpoint-pooling.mdx +++ b/docs/universal-gateway/endpoint-pooling.mdx @@ -223,9 +223,9 @@ When a connection or request is balanced to an endpoint in a pool, if that connection or request fails, it is not retried by sending it to another endpoint in the pool. -## Wildcard Endpoints +## Wildcard endpoints -TODO: Link to wildcard docs +[Wildcard endpoints](/universal-gateway/wildcard-domains/wildcard-endpoints) do not pool with non-wildcard URLs. See [the docs on Wildcard Endpoints](/universal-gateway/wildcard-domains/wildcard-endpoints/#wildcard-endpoint-pooling) for more information. ## Protocol, Binding and Type diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx index 25220d8c5e..bdb411e1a3 100644 --- a/docs/universal-gateway/http-s/index.mdx +++ b/docs/universal-gateway/http-s/index.mdx @@ -312,7 +312,7 @@ your domain: ### Wildcard Endpoints -TODO: Link to wildcard domains docs +You can create an endpoint which will receive traffic for all of the subdomains matching a given wildcard domain. See [the wildcard domain docs](/universal-gateway/wildcard-domains/) for more information. ### Randomly assigned hostnames diff --git a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx index 1150a332f4..a54aaf1b8a 100644 --- a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx +++ b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx @@ -22,7 +22,7 @@ TLS certificates are attached to [domains](/universal-gateway/domains/what-are-d ## Wildcard domains -TODO: Link to wildcard domains +See the [wildcard domains](/universal-gateway/wildcard-domains/#tls-provisioning) docs for more information about how TLS certificates are managed for wildcard domains. ## API diff --git a/docs/universal-gateway/wildcard-domains/index.mdx b/docs/universal-gateway/wildcard-domains/index.mdx new file mode 100644 index 0000000000..cfee3f347c --- /dev/null +++ b/docs/universal-gateway/wildcard-domains/index.mdx @@ -0,0 +1,36 @@ +--- +title: How Do I Use Wildcard Domains? +--- + +You may create a Domain with a wildcard name, e.g. `*.example.com`. A wildcard domain enables you to: + +- Create an endpoint which receives traffic for all of its subdomains, e.g. `https://*.example.com`. See [Wildcard Endpoints](/universal-gateway/http/#wildcard-endpoints) to understand the rules for matching and precedence. +- Create an endpoint on any subdomain which matches the wildcard, e.g. `https://foo.example.com` or `https://foo.bar.baz.example.com` + +:::note +The wildcard `*` character may only be used as the first part of a +domain, you may not create domains like `app.*.example.com` or +`*-app.example.com`. +::: + +## TLS provisioning + +When you bring your own wildcard domain (e.g. `*.app.example.com`), ngrok uses +a DNS01 challenge for TLS certificate provisioning which means that you must +create two CNAME records when creating branded wildcard domains instead of just +one. + +For example, If your domain is `*.app.example.com` you will be required to create the +following two CNAME records: + +- `*.app.example.com` +- `_acme-challenge.app.example.com` + +Certificate provisioning will not begin until you have created both DNS +records. + +## Pricing + +Wildcard domains are available on our Enterprise plan self service. They are also available on Pay-as-You-Go plans if you contact support@ngrok.com. For Pay-as-You-Go when you create a wildcard domain and run endpoints domain `*.foo.com`, endpoints `https://a.foo.com` and `https://b.foo.com`, we bill you for each individual endpoint, which is why we ask that you request the feature. + +Reserving subdomains of a wildcard domain within the ngrok dashboard count towards the number of reserved domains in your account. For example, if you reserve `foo.example.com` and `*.example.com`, you have reserved two domains.. You will be charged for each subdomain you use. You may need to enable overages in order to do this on your paid plan. diff --git a/docs/universal-gateway/domains/wildcard-domains.mdx b/docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx similarity index 52% rename from docs/universal-gateway/domains/wildcard-domains.mdx rename to docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx index b3dbbcbc96..f8881fd78c 100644 --- a/docs/universal-gateway/domains/wildcard-domains.mdx +++ b/docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx @@ -1,5 +1,5 @@ --- -title: How Do I Use Wildcard Domains? +title: How Do I Use Wildcard Endpoints? --- import WildcardAgentCliExample from "/examples/agent-cli/http-wildcard-domain.mdx"; @@ -11,23 +11,7 @@ import WildcardPythonSdkExample from "/examples/python-sdk/http-wildcard-domain. import WildcardRustSdkExample from "/examples/rust-sdk/http-wildcard-domain.mdx"; import WildcardSshExample from "/examples/ssh/http-wildcard-domain.mdx"; -You may create a Domain with a wildcard name, e.g. `*.example.com`. A wildcard domain enables you to: - -- Create an endpoint which receives traffic for all of its subdomains, e.g. `https://*.example.com`. See [Wildcard Endpoints](/universal-gateway/http/#wildcard-endpoints) to understand the rules for matching and precedence. -- Create an endpoint on any subdomain which matches the wildcard, e.g. `https://foo.example.com` or `https://foo.bar.baz.example.com` - -:::note -The wildcard `*` character may only be used as the first part of a -domain, you may not create domains like `app.*.example.com` or -`*-app.example.com`. -::: - -### Wildcard endpoints - -You can create an endpoint which will receive traffic for all of the subdomains -matching a given wildcard domain like `*.example.com`. You must create a -[wildcard domain](/universal-gateway/domains/what-are-domains/#wildcard-domains) to create a -public wildcard endpoint. +You can create an endpoint which will receive traffic for all of the subdomains matching a given wildcard domain like `*.example.com`. You must create a [wildcard domain](/universal-gateway/domains/what-are-domains/#wildcard-domains) to create a public wildcard endpoint. For example, if you create the wildcard endpoint `https://*.example.com`, it will receive traffic for `https://foo.example.com` and @@ -69,14 +53,11 @@ will receive traffic for `https://foo.example.com` and -[Wildcard endpoints](/universal-gateway/wildcard-domains/#wildcard-endpoints) do not pool with non-wildcard URLs. For example, if you have -two endpoints online, `https://foo.example.com` and `https://*.example.com`, -they will not pool together and traffic to `https://foo.example.com` will not -be load balanced. Consult the documentation for [wildcard -endpoints](/universal-gateway/http/#wildcard-endpoints) to understand -the rules for matching and precedence. +## Wildcard endpoint pooling + +Wildcard endpoints do not pool with non-wildcard URLs. For example, if you have two endpoints online, `https://foo.example.com` and `https://*.example.com`, they will not pool together and traffic to `https://foo.example.com` will not be load balanced. -### Use multiple endpoints with wildcard subdomains +### How do I use multiple endpoints with wildcard subdomains? With the [Agent CLI](/agent/cli), you can create separate public endpoints for subdomains of a wildcard domain no matter where the upstream services are running. See [the Domains docs](/docs/universal-gateway/domains/#wildcard-domains) for more information. @@ -97,25 +78,3 @@ ngrok http 81 --url https://api2.example.com :::tip This is only necessary for creating _public_ endpoints to subdomains. Internal endpoints don't require a domain. ::: - -### TLS provisioning - -When you bring your own wildcard domain (e.g. `*.app.example.com`), ngrok uses -a DNS01 challenge for TLS certificate provisioning which means that you must -create two CNAME records when creating branded wildcard domains instead of just -one. - -For example, If your domain is `*.app.example.com` you will be required to create the -following two CNAME records: - -- `*.app.example.com` -- `_acme-challenge.app.example.com` - -Certificate provisioning will not begin until you have created both DNS -records. - -## Pricing - -Wildcard domains are available on our Enterprise plan self service. They are also available on Pay-as-You-Go plans if you contact support@ngrok.com. For Pay-as-You-Go when you create a wildcard domain and run endpoints domain `*.foo.com`, endpoints `https://a.foo.com` and `https://b.foo.com`, we bill you for each individual endpoint, which is why we ask that you request the feature. - -Reserving subdomains of a wildcard domain within the ngrok dashboard count towards the number of reserved domains in your account. For example, if you reserve `foo.example.com` and `*.example.com`, you have reserved two domains.. You will be charged for each subdomain you use. You may need to enable overages in order to do this on your paid plan. From 147ca081640e40841da3785b6c9e79ce66ccad9f Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 1 Apr 2025 12:41:02 -0400 Subject: [PATCH 053/137] Adding content switcher --- docs/universal-gateway/http-s/index.mdx | 148 ++++++++++++++---- sidebars.js | 2 + .../LangSwitcher/ContentSwitcher.tsx | 26 +++ src/components/LangSwitcher/index.tsx | 5 +- 4 files changed, 151 insertions(+), 30 deletions(-) create mode 100644 src/components/LangSwitcher/ContentSwitcher.tsx diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx index bdb411e1a3..2047213003 100644 --- a/docs/universal-gateway/http-s/index.mdx +++ b/docs/universal-gateway/http-s/index.mdx @@ -115,10 +115,129 @@ import WindowsFileserverPythonSdkExample from "/examples/python-sdk/http-fileser import WindowsFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-windows.mdx"; import WindowsFileserverSshExample from "/examples/ssh/http-fileserver-windows.mdx"; +import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitcher"; + You can create HTTP/S endpoints to serve web services like REST APIs, web applications, websites and websocket servers. Serving a web application is as simple as `ngrok http 80`. -## Quickstart + + + Agent Endpoints are the easiest way to create an HTTP/S endpoint. An [agent +endpoint](/universal-gateway/cloud-endpoints/) is started by a +[Secure Tunnels](/agent/) agent. The endpoint lives for the lifetime of the +process and forwards traffic to a port or URL of your choosing. + +Create the endpoint `https://example.ngrok.app` and forward its traffic to a +local port. + + + ```bash title="Agent CLI" + ngrok http 8080 --url https://example.ngrok.app + ``` + ```go + import ( + "context" + "net" + + "golang.ngrok.com/ngrok" + "golang.ngrok.com/ngrok/config" + + ) + + func ngrokListener(ctx context.Context) (net.Listener, error) { + upstreamURL, \_ := url.Parse("http://localhost:8080") + return ngrok.ListenAndForward(ctx, + upstreamURL, + config.HTTPEndpoint( + config.WithURL("https://example.ngrok.app"), + ), + ngrok.WithAuthtokenFromEnv(), + ) + } + + ``` + ```jsx + const ngrok = require("@ngrok/ngrok"); + + (async function () { + const listener = await ngrok.forward({ + addr: 8080, + authtoken_from_env: true, + domain: "example.ngrok.app", + }); + + console.log(`Ingress established at: ${listener.url()}`); + })(); + ```` + + ```python + import ngrok + + listener = ngrok.forward("localhost:8080", authtoken_from_env=True, + domain="example.ngrok.app") + + print(f"Ingress established at: {listener.url()}"); + ``` + + ```rust + use ngrok::prelude::*; + + async fn listen_ngrok() -> anyhow::Result { + let sess = ngrok::Session::builder() + .authtoken_from_env() + .connect() + .await?; + + let tun = sess + .http_endpoint() + .domain("example.ngrok.app") + .listen() + .await?; + + println!("Listening on URL: {:?}", tun.url()); + + Ok(tun) + } + ``` + + + + + + TODO: You can do SSH: + + + TODO: You can also use Agent Config + + + + + + + + ```yaml title="Kubernetes Example" + apiVersion: networking.k8s.io/v1 + kind: Ingress + metadata: + name: example-ingress + spec: + ingressClassName: ngrok + rules: + - host: example.ngrok.app + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: example-service + port: + number: 80 + ``` + + + + ### Agent Endpoint @@ -130,33 +249,6 @@ process and forwards traffic to a port or URL of your choosing. Create the endpoint `https://example.ngrok.app` and forward its traffic to a local port. - - - - - - - - - - - - - - - - - - - - - - - - - - -
### Cloud Endpoint diff --git a/sidebars.js b/sidebars.js index 00b0332370..ea762eb927 100644 --- a/sidebars.js +++ b/sidebars.js @@ -54,6 +54,8 @@ const sidebars = { items: [ "universal-gateway/domains/how-do-i-use-my-own-domain", "universal-gateway/domains/what-are-managed-domains", + "universal-gateway/wildcard-domains/index", + "universal-gateway/wildcard-domains/wildcard-endpoints", ], }, "universal-gateway/what-are-matching-endpoints", diff --git a/src/components/LangSwitcher/ContentSwitcher.tsx b/src/components/LangSwitcher/ContentSwitcher.tsx new file mode 100644 index 0000000000..3652f99cb6 --- /dev/null +++ b/src/components/LangSwitcher/ContentSwitcher.tsx @@ -0,0 +1,26 @@ +import { useContext } from "react"; +import type { LangSwitcherContextType } from "./LangSwitcherContext"; +import LangSwitcherContext from "./LangSwitcherContext"; + +/** + * Renders its children only if the specified language matches the + * currently selected language for the component. + * This is useful for conditionally rendering content based on the + * selected language. + */ +export function ContentSwitcher({ + children, + language, +}: { + children: React.ReactNode; + language: string; + className?: string; +}) { + const { tabLanguage } = + useContext(LangSwitcherContext); + if (!language) + throw new Error("Must specify a language for the ContentSwitcher"); + + if (language !== tabLanguage) return null; + return children; +} diff --git a/src/components/LangSwitcher/index.tsx b/src/components/LangSwitcher/index.tsx index 5631551323..52d421f1b5 100644 --- a/src/components/LangSwitcher/index.tsx +++ b/src/components/LangSwitcher/index.tsx @@ -21,6 +21,7 @@ import { getCodeBlocks } from "./utils"; export function LangSwitcher({ children, className, ...props }: any) { const { defaultLanguage, tabLanguage, updateTab } = useContext(LangSwitcherContext); + const codeBlocks = getCodeBlocks(children); if (!updateTab) return "Error loading code block"; @@ -72,8 +73,8 @@ export function LangSwitcher({ children, className, ...props }: any) { {meta.title && ( - - {meta.title} + + {meta.title} )} {!meta.disableCopy && } From 15db7cdae08d2392e42922a7f9a2796509d191e2 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 1 Apr 2025 14:17:15 -0400 Subject: [PATCH 054/137] Checkpoint updating content --- .../domains/what-are-managed-domains.mdx | 60 +++++ .../http-s/endpoint-url-defaults.mdx | 28 ++ docs/universal-gateway/http-s/index.mdx | 251 +++--------------- docs/universal-gateway/http.mdx | 3 - sidebars.js | 8 +- .../LangSwitcher/ContentSwitcher.tsx | 2 +- 6 files changed, 126 insertions(+), 226 deletions(-) create mode 100644 docs/universal-gateway/http-s/endpoint-url-defaults.mdx diff --git a/docs/universal-gateway/domains/what-are-managed-domains.mdx b/docs/universal-gateway/domains/what-are-managed-domains.mdx index 94a998dd4f..b904e9f1d0 100644 --- a/docs/universal-gateway/domains/what-are-managed-domains.mdx +++ b/docs/universal-gateway/domains/what-are-managed-domains.mdx @@ -3,6 +3,9 @@ title: What Are Managed Domains? description: Learn about the free and paid domains that ngrok provides. --- +import { LangSwitcher } from "@site/src/components/LangSwitcher"; +import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitcher"; + If you don't [already own a Domain](/universal-gateway/how-do-i-use-my-own-domain) that you want to use with ngrok, you can create a domain that is a subdomain of an ngrok-managed base domain. | Domain | Availability | HSTS Global Preload | @@ -29,3 +32,60 @@ If you need to create unencrypted `http` endpoints, you should create them with :::tip ngrok does not prohibit you from creating `http` endpoints with hostnames whose base domain is on the global HSTS preload list. Non-browser clients (like `curl`) can still be used to make unencrypted HTTP requests to them. ::: + +### Randomly assigned hostnames + +If you create a public endpoint without specifying a hostname, ngrok will automatically assign a random one for you.by selecting a random subdomain of one of ngrok's managed Domains to your endpoint. + +The following example creates an HTTPS endpoint on a randomly assigned hostname that forwards to port 8080. + + + +```bash title="Agent CLI" +ngrok http 8080 +``` + +```sh title="SSH example" +ssh -R 443:localhost:80 v2@connect.ngrok-agent.com http +``` + + + + + + :::note + If your Agent Config doesn't have hostname specified, and you create an endpoint, the hostname will also be randomly assigned. For example, if your Agent Config looks like this: + + ```yaml + version: 3 + endpoints: + - name: example + url: https:// + upstream: + url: 8080 + ``` + + ::: + + +{/* + + + + + + + + + + + + + + + + + + + + */} diff --git a/docs/universal-gateway/http-s/endpoint-url-defaults.mdx b/docs/universal-gateway/http-s/endpoint-url-defaults.mdx new file mode 100644 index 0000000000..6339c2902e --- /dev/null +++ b/docs/universal-gateway/http-s/endpoint-url-defaults.mdx @@ -0,0 +1,28 @@ +--- +title: How are Endpoint URLs Constructed? +description: Learn what default values ngrok uses to construct endpoint URLs. +--- + +When you create an agent endpoint, if you do not specify a complete URL, the following defaults are used to construct an endpoint URL. When you create a cloud endpoint, you must always specify both a scheme and hostname. + +| URL Part | Default | +| -------- | --------------------------------------------------------- | +| Scheme | `https` | +| Hostname | randomly selected | +| Port | `443` if scheme is `https`
`80` if scheme is `http` | + +Consult the following table of examples of URL defaulting: + +| Value | Endpoint URL | +| ------------------------------- | -------------------------------------------------------- | +| `https://example.ngrok.app` | `https://example.ngrok.app` | +| `http://example.ngrok.app` | `http://example.ngrok.app` | +| `example.ngrok.app` | `https://example.ngrok.app` | +| `app.example.com` | `https://app.example.com` | +| `https://example.internal` | `https://example.internal` | +| `https://example.internal:1234` | `https://example.internal:1234` | +| `http://example.internal` | `http://example.internal` | +| `foo.internal` | `https://foo.internal` | +| `{empty}` | `https://1eb2-181-80-12-3.ngrok.app` (randomly selected) | + +If you would like to listen for both http and https traffic, create two endpoints. diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx index 2047213003..eb9d9d7f1b 100644 --- a/docs/universal-gateway/http-s/index.mdx +++ b/docs/universal-gateway/http-s/index.mdx @@ -1,5 +1,6 @@ --- -title: How do I handle HTTP/S traffic? +title: How Do I Handle HTTP/S traffic? +description: Learn how to create HTTP/S endpoints with ngrok. --- import TabItem from "@theme/TabItem"; @@ -70,15 +71,6 @@ import HostHeaderPythonSdkExample from "/examples/python-sdk/http-rewrite-host-h import HostHeaderRustSdkExample from "/examples/rust-sdk/http-rewrite-host-header.mdx"; import HostHeaderSshExample from "/examples/ssh/http-rewrite-host-header.mdx"; -import WildcardAgentCliExample from "/examples/agent-cli/http-wildcard-domain.mdx"; -import WildcardAgentConfigExample from "/examples/agent-config/http-wildcard-domain.mdx"; -import WildcardGoSdkExample from "/examples/go-sdk/http-wildcard-domain.mdx"; -import WildcardJavascriptSdkExample from "/examples/javascript-sdk/http-wildcard-domain.mdx"; -import WildcardKubernetesExample from "/examples/k8s/http-wildcard-domain.mdx"; -import WildcardPythonSdkExample from "/examples/python-sdk/http-wildcard-domain.mdx"; -import WildcardRustSdkExample from "/examples/rust-sdk/http-wildcard-domain.mdx"; -import WildcardSshExample from "/examples/ssh/http-wildcard-domain.mdx"; - import NonLocalAgentCliExample from "/examples/agent-cli/http-nonlocal.mdx"; import NonLocalAgentConfigExample from "/examples/agent-config/http-nonlocal.mdx"; import NonLocalGoSdkExample from "/examples/go-sdk/http-nonlocal.mdx"; @@ -115,20 +107,13 @@ import WindowsFileserverPythonSdkExample from "/examples/python-sdk/http-fileser import WindowsFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-windows.mdx"; import WindowsFileserverSshExample from "/examples/ssh/http-fileserver-windows.mdx"; -import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitcher"; - -You can create HTTP/S endpoints to serve web services like REST APIs, web applications, websites and websocket servers. Serving a web application is as -simple as `ngrok http 80`. +You can create HTTP/S endpoints to serve web services like REST APIs, web applications, websites and websocket servers. You can serve an HTTP/S endpoint in one of the following ways. - Agent Endpoints are the easiest way to create an HTTP/S endpoint. An [agent -endpoint](/universal-gateway/cloud-endpoints/) is started by a -[Secure Tunnels](/agent/) agent. The endpoint lives for the lifetime of the -process and forwards traffic to a port or URL of your choosing. + [Agent Endpoints](/agent/) are the easiest way to create an HTTP/S endpoint. You can start agent endpoints on your local machine. The endpoint wil llive for the lifetime of the process and forward traffic to a port or URL of your choosing. -Create the endpoint `https://example.ngrok.app` and forward its traffic to a -local port. + The following example creates the endpoint `https://example.ngrok.app` and forwards its traffic to a local port. ```bash title="Agent CLI" @@ -168,7 +153,7 @@ local port. console.log(`Ingress established at: ${listener.url()}`); })(); - ```` + ``` ```python import ngrok @@ -212,65 +197,13 @@ local port. - - - - ```yaml title="Kubernetes Example" - apiVersion: networking.k8s.io/v1 - kind: Ingress - metadata: - name: example-ingress - spec: - ingressClassName: ngrok - rules: - - host: example.ngrok.app - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: example-service - port: - number: 80 - ``` - - - - - -### Agent Endpoint + -Agent Endpoints are the easiest way to get started with ngrok. An [agent -endpoint](/universal-gateway/cloud-endpoints/) is started by a -[Secure Tunnels](/agent/) agent. The endpoint lives for the lifetime of the -process and forwards traffic to a port or URL of your choosing. +[Cloud endpoints](/universal-gateway/cloud-endpoints/) are created via [the ngrok Dashboard](https://dashboard.ngrok.com/endpoints/new) or [API](/api/). They are persistent and live until they are deleted. [Traffic Policy](/traffic-policy/) controls how a cloud endpoint handles traffic. -Create the endpoint `https://example.ngrok.app` and forward its traffic to a -local port. +To create an HTTPS cloud endpoint which returns a `Hello world!` `200 OK` response, you can add the following to your Cloud Endpoint's Traffic Policy in the ngrok Dashboard: -
- -### Cloud Endpoint - -[Cloud endpoints](/universal-gateway/cloud-endpoints/) are created via the -ngrok Dashboard or [API](/api/). They are persistent and live until they are -deleted. [Traffic Policy](/traffic-policy/) controls how a cloud endpoint -handles traffic. - -[Create an HTTPS cloud endpoint](https://dashboard.ngrok.com/endpoints/new) -which returns a `Hello world!` 200 OK response. - - - - -```sh title="Command line" -ngrok api endpoints create \ - --url https://example.ngrok.app \ - --traffic-policy "$( - - - -## URL - -URLs are validated differently depending on their [binding](/universal-gateway/bindings). To learn more about valid URLs for HTTP/S endpoints, see [the Endpoint URLs documentation](/docs/universal-gateway/what-are-endpoint-urls/). - -#### Public - -###### HTTP - -- The hostname must be a domain with a valid [public suffix](https://publicsuffix.org/). -- The port must be `80`. If you do not specify a port, the default `80` will be used for you. - -**Examples** - -- `http://example.ngrok.app` -- `http://example.ngrok.app:80` -- `http://example.party` -- `http://example.ngrok.app:81` - invalid port: port number must be `80`, not `81` -- `http://example.doesnotexist` - invalid hostname: `.doesnotexist` is not a public suffix domain -- `http://example.internal` - invalid hostname: `.internal` is not a public suffix domain +If you want to add it with the API instead, you can save that policy to a local file, then run the following command in your terminal, referencing the file you created: -###### HTTPS - -- The hostname must be a domain with a valid [public suffix](https://publicsuffix.org/). -- The port must be `443`. If you do not specify a port, the default `443` will be used for you. - -#### Internal - -#### Kubernetes - -##### Valid URLs +```sh title="Command line" +ngrok api endpoints create \ + --url https://example.ngrok.app \ + --traffic-policy "$( + -##### Invalid URLs + Follow the [ngrok Kubernetes Controller documentation](https://ngrok.com/docs/k8s/guides/quickstart/) to get started using ngrok with Kubernetes. You can use the following service definition to create an HTTP endpoint: -- https://example.ngrok.app:8443 -- https://example.nosuchtld -- https://example.internal + -### Validation -When you create an agent endpoint, if you do not specify a complete URL, -following defaults are used to construct an endpoint URL. When you create a -cloud endpoint, you must always specify both a scheme and hostname. + -| URL Part | Default | -| -------- | --------------------------------------------------------- | -| Scheme | `https` | -| Hostname | randomly selected | -| Port | `443` if scheme is `https`
`80` if scheme is `http` | + -Consult the following table of examples of URL defaulting: +## URLs -| Value | Endpoint URL | -| ------------------------------- | -------------------------------------------------------- | -| `https://example.ngrok.app` | `https://example.ngrok.app` | -| `http://example.ngrok.app` | `http://example.ngrok.app` | -| `example.ngrok.app` | `https://example.ngrok.app` | -| `app.example.com` | `https://app.example.com` | -| `https://example.internal` | `https://example.internal` | -| `https://example.internal:1234` | `https://example.internal:1234` | -| `http://example.internal` | `http://example.internal` | -| `foo.internal` | `https://foo.internal` | -| `{empty}` | `https://1eb2-181-80-12-3.ngrok.app` (randomly selected) | +URLs are validated differently depending on their [binding](/universal-gateway/bindings). To learn more about valid URLs for HTTP/S endpoints, see [the Endpoint URLs documentation](/docs/universal-gateway/what-are-endpoint-urls/#http). -If you would like to listen for both http and https traffic, create two endpoints. +To listen for both http and https traffic, create two endpoints. -#### Domains +## Domains When you create a public endpoint, it must match a -[Domain](/universal-gateway/domains/what-are-domains) on your account. Domains help you set up -branded domains and manage TLS certificates. You may create endpoints with -wildcard domains as well. - -Endpoints with randomly-assigned hostnames are an exception and won't match an -existing Domain object. +Domain on your account. See [the Domains documentation](/universal-gateway/domains/what-are-domains/) for more information. ### Bring your own domain {#bring-your-own-domain} -If you want to bring your own domain, first [create a Domain record and set up -a DNS CNAME record](/universal-gateway/how-do-i-use-my-own-domain). Then -create an endpoint on that domain by specifying a URL with a matching hostname. - -For example, to create an HTTPS endpoint on `https://app.example.com`, [create -a Domain](https://dashboard.ngrok.com/domains) and follow the instructions to -set up a CNAME record. Then use the following example to start an endpoint on -your domain: - - - - - - - - - - - - - - - - - - - - - - - - - - - +To bring your own domain, see [the guide on the subject](/universal-gateway/how-do-i-use-my-own-domain). -### Wildcard Endpoints +## Wildcard HTTP Endpoints -You can create an endpoint which will receive traffic for all of the subdomains matching a given wildcard domain. See [the wildcard domain docs](/universal-gateway/wildcard-domains/) for more information. - -### Randomly assigned hostnames - -If you run create a public endpoint without specifying a hostname, ngrok will -automatically assign a random one for you.by selecting a random subdomain of one of our [ngrok-managed -Domains](/universal-gateway/domains#ngrok-managed-domains) to your endpoint. -For example, the command `ngrok http 80` may create an endpoint like -`https://1eb2-181-80-12-3.ngrok.app`. - -The following example create an HTTPS endpoint on a randomly assigned hostname -that forwards to port 8080. - - - - - - - - - - - - - - - - - - - - - - - - - - - +You can create an HTTP/S endpoint which will receive traffic for all of the subdomains matching a given wildcard domain. See [the wildcard domain docs](/universal-gateway/wildcard-domains/) for more information. ## Traffic Policy diff --git a/docs/universal-gateway/http.mdx b/docs/universal-gateway/http.mdx index a485866229..e25ff2172d 100644 --- a/docs/universal-gateway/http.mdx +++ b/docs/universal-gateway/http.mdx @@ -111,9 +111,6 @@ applications, websites, and websocket servers. You can create HTTP/S endpoints locally with the [Agent CLI](/agent/cli) or as [Cloud Endpoints](/universal-gateway/cloud-endpoints/) via the ngrok Dashboard. - - - diff --git a/sidebars.js b/sidebars.js index ea762eb927..cd7cc5e285 100644 --- a/sidebars.js +++ b/sidebars.js @@ -125,7 +125,13 @@ const sidebars = { "universal-gateway/chain-endpoints", "universal-gateway/mock-api", "universal-gateway/migrate-from-tunnels", - "universal-gateway/http-s/index", + + { + label: "How Do I Handle HTTP/S Traffic?", + type: "category", + link: { type: "doc", id: "universal-gateway/http-s/index" }, + items: ["universal-gateway/http-s/endpoint-url-defaults"], + }, { label: "Endpoints", type: "category", diff --git a/src/components/LangSwitcher/ContentSwitcher.tsx b/src/components/LangSwitcher/ContentSwitcher.tsx index 3652f99cb6..a83e2478f4 100644 --- a/src/components/LangSwitcher/ContentSwitcher.tsx +++ b/src/components/LangSwitcher/ContentSwitcher.tsx @@ -4,7 +4,7 @@ import LangSwitcherContext from "./LangSwitcherContext"; /** * Renders its children only if the specified language matches the - * currently selected language for the component. + * currently selected language for the LangSwithcher component. * This is useful for conditionally rendering content based on the * selected language. */ From fb38f0a18551daa2fedf1ef6ce905c4bfeb38849 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 1 Apr 2025 14:36:49 -0400 Subject: [PATCH 055/137] Fix missing tab imports --- docs/universal-gateway/domains/what-are-managed-domains.mdx | 4 +++- .../universal-gateway/wildcard-domains/wildcard-endpoints.mdx | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/universal-gateway/domains/what-are-managed-domains.mdx b/docs/universal-gateway/domains/what-are-managed-domains.mdx index b904e9f1d0..b48fd40e88 100644 --- a/docs/universal-gateway/domains/what-are-managed-domains.mdx +++ b/docs/universal-gateway/domains/what-are-managed-domains.mdx @@ -5,6 +5,8 @@ description: Learn about the free and paid domains that ngrok provides. import { LangSwitcher } from "@site/src/components/LangSwitcher"; import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitcher"; +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; If you don't [already own a Domain](/universal-gateway/how-do-i-use-my-own-domain) that you want to use with ngrok, you can create a domain that is a subdomain of an ngrok-managed base domain. @@ -54,7 +56,7 @@ ssh -R 443:localhost:80 v2@connect.ngrok-agent.com http :::note - If your Agent Config doesn't have hostname specified, and you create an endpoint, the hostname will also be randomly assigned. For example, if your Agent Config looks like this: + If your [Agent Config file](/docs/traffic-policy/getting-started/agent-endpoints/config-file) doesn't have hostname specified, and you create an endpoint, the hostname will also be randomly assigned. For example, if your Agent Config file looks like this: ```yaml version: 3 diff --git a/docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx b/docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx index f8881fd78c..57804eed7c 100644 --- a/docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx +++ b/docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx @@ -2,6 +2,8 @@ title: How Do I Use Wildcard Endpoints? --- +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; import WildcardAgentCliExample from "/examples/agent-cli/http-wildcard-domain.mdx"; import WildcardAgentConfigExample from "/examples/agent-config/http-wildcard-domain.mdx"; import WildcardGoSdkExample from "/examples/go-sdk/http-wildcard-domain.mdx"; From 0fb9e18d449acf09f60413608e1a0d6487c5466f Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 1 Apr 2025 14:54:04 -0400 Subject: [PATCH 056/137] Finish the intro to http/s page --- docs/universal-gateway/http-s/index.mdx | 32 +++++++++++++++++-------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx index eb9d9d7f1b..40760f44a5 100644 --- a/docs/universal-gateway/http-s/index.mdx +++ b/docs/universal-gateway/http-s/index.mdx @@ -119,6 +119,9 @@ You can create HTTP/S endpoints to serve web services like REST APIs, web applic ```bash title="Agent CLI" ngrok http 8080 --url https://example.ngrok.app ``` + ```sh + ssh -R example.ngrok.app:443:localhost:8080 v2@connect.ngrok-agent.com http + ``` ```go import ( "context" @@ -187,15 +190,6 @@ You can create HTTP/S endpoints to serve web services like REST APIs, web applic - - - TODO: You can do SSH: - - - TODO: You can also use Agent Config - - -
@@ -223,7 +217,7 @@ ngrok api endpoints create \ ``` - + Follow the [ngrok Kubernetes Controller documentation](https://ngrok.com/docs/k8s/guides/quickstart/) to get started using ngrok with Kubernetes. You can use the following service definition to create an HTTP endpoint: @@ -231,6 +225,24 @@ ngrok api endpoints create \ + + + You can also create an HTTP/S endpoint using the [ngrok agent configuration file](/docs/traffic-policy/getting-started/agent-endpoints/config-file). You can edit the file with the following terminal command: + + ```bash + ngrok config edit + ``` + + Specify the endpoint URL in your configuration as shown in the following example: + + + + Then, start the agent with the following command: + + ```bash + ngrok http 8080 + ``` + From 99102d1752e9f0260694843ecdd18915f7986e01 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Wed, 2 Apr 2025 09:46:28 -0400 Subject: [PATCH 057/137] Splitting off the agent-forwarding-doc --- docs/universal-gateway/agent-forwarding.mdx | 541 ++++++++++++++++++++ docs/universal-gateway/http-s/index.mdx | 376 +------------- docs/universal-gateway/tcp.mdx | 78 --- docs/universal-gateway/tls.mdx | 73 --- 4 files changed, 557 insertions(+), 511 deletions(-) create mode 100644 docs/universal-gateway/agent-forwarding.mdx diff --git a/docs/universal-gateway/agent-forwarding.mdx b/docs/universal-gateway/agent-forwarding.mdx new file mode 100644 index 0000000000..5800c75029 --- /dev/null +++ b/docs/universal-gateway/agent-forwarding.mdx @@ -0,0 +1,541 @@ +--- +title: How does Agent Forwarding Work? +--- + +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; + +import { LangSwitcher } from "@site/src/components/LangSwitcher"; +import TlsLimits from "../_tls_limits.mdx"; + +import RandomAgentCliExample from "/examples/agent-cli/http-random.mdx"; +import RandomAgentConfigExample from "/examples/agent-config/http-random.mdx"; +import RandomGoSdkExample from "/examples/go-sdk/http-random.mdx"; +import RandomJavascriptSdkExample from "/examples/javascript-sdk/http-random.mdx"; +import RandomPythonSdkExample from "/examples/python-sdk/http-random.mdx"; +import RandomRustSdkExample from "/examples/rust-sdk/http-random.mdx"; +import RandomSshExample from "/examples/ssh/http-random.mdx"; + +import StaticDomainAgentCliExample from "/examples/agent-cli/http-static-domain.mdx"; +import StaticDomainAgentConfigExample from "/examples/agent-config/http-static-domain.mdx"; +import StaticDomainGoSdkExample from "/examples/go-sdk/http-static-domain.mdx"; +import StaticDomainJavascriptSdkExample from "/examples/javascript-sdk/http-static-domain.mdx"; +import StaticDomainKubernetesExample from "/examples/k8s/http-static-domain.mdx"; +import StaticDomainPythonSdkExample from "/examples/python-sdk/http-static-domain.mdx"; +import StaticDomainRustSdkExample from "/examples/rust-sdk/http-static-domain.mdx"; +import StaticDomainSshExample from "/examples/ssh/http-static-domain.mdx"; + +import BrandedDomainAgentCliExample from "/examples/agent-cli/http-branded-domain.mdx"; +import BrandedDomainAgentConfigExample from "/examples/agent-config/http-branded-domain.mdx"; +import BrandedDomainGoSdkExample from "/examples/go-sdk/http-branded-domain.mdx"; +import BrandedDomainJavascriptSdkExample from "/examples/javascript-sdk/http-branded-domain.mdx"; +import BrandedDomainKubernetesExample from "/examples/k8s/http-branded-domain.mdx"; +import BrandedDomainPythonSdkExample from "/examples/python-sdk/http-branded-domain.mdx"; +import BrandedDomainRustSdkExample from "/examples/rust-sdk/http-branded-domain.mdx"; +import BrandedDomainSshExample from "/examples/ssh/http-branded-domain.mdx"; + +import BasicAuthAgentCliExample from "/examples/agent-cli/http-basic-auth.mdx"; +import BasicAuthAgentConfigExample from "/examples/agent-config/http-basic-auth.mdx"; +import BasicAuthGoSdkExample from "/examples/go-sdk/http-basic-auth.mdx"; +import BasicAuthJavascriptSdkExample from "/examples/javascript-sdk/http-basic-auth.mdx"; +import BasicAuthKubernetesExample from "/examples/k8s/http-basic-auth.mdx"; +import BasicAuthPythonSdkExample from "/examples/python-sdk/http-basic-auth.mdx"; +import BasicAuthRustSdkExample from "/examples/rust-sdk/http-basic-auth.mdx"; +import BasicAuthSshExample from "/examples/ssh/http-basic-auth.mdx"; + +import OAuthAgentCliExample from "/examples/agent-cli/http-oauth-authn.mdx"; +import OAuthAgentConfigExample from "/examples/agent-config/http-oauth-authn.mdx"; +import OAuthGoSdkExample from "/examples/go-sdk/http-oauth-authn.mdx"; +import OAuthJavascriptSdkExample from "/examples/javascript-sdk/http-oauth-authn.mdx"; +import OAuthKubernetesExample from "/examples/k8s/http-oauth-authn.mdx"; +import OAuthPythonSdkExample from "/examples/python-sdk/http-oauth-authn.mdx"; +import OAuthRustSdkExample from "/examples/rust-sdk/http-oauth-authn.mdx"; +import OAuthSshExample from "/examples/ssh/http-oauth-authn.mdx"; + +import ForwardHttpsAgentCliExample from "/examples/agent-cli/http-forward-https.mdx"; +import ForwardHttpsAgentConfigExample from "/examples/agent-config/http-forward-https.mdx"; +import ForwardHttpsGoSdkExample from "/examples/go-sdk/http-forward-https.mdx"; +import ForwardHttpsJavascriptSdkExample from "/examples/javascript-sdk/http-forward-https.mdx"; +import ForwardHttpsKubernetesExample from "/examples/k8s/http-forward-https.mdx"; +import ForwardHttpsPythonSdkExample from "/examples/python-sdk/http-forward-https.mdx"; +import ForwardHttpsRustSdkExample from "/examples/rust-sdk/http-forward-https.mdx"; +import ForwardHttpsSshExample from "/examples/ssh/http-forward-https.mdx"; + +import HostHeaderAgentCliExample from "/examples/agent-cli/http-rewrite-host-header.mdx"; +import HostHeaderAgentConfigExample from "/examples/agent-config/http-rewrite-host-header.mdx"; +import HostHeaderGoSdkExample from "/examples/go-sdk/http-rewrite-host-header.mdx"; +import HostHeaderJavascriptSdkExample from "/examples/javascript-sdk/http-rewrite-host-header.mdx"; +import HostHeaderKubernetesExample from "/examples/k8s/http-rewrite-host-header.mdx"; +import HostHeaderPythonSdkExample from "/examples/python-sdk/http-rewrite-host-header.mdx"; +import HostHeaderRustSdkExample from "/examples/rust-sdk/http-rewrite-host-header.mdx"; +import HostHeaderSshExample from "/examples/ssh/http-rewrite-host-header.mdx"; + +import NonLocalAgentCliExample from "/examples/agent-cli/http-nonlocal.mdx"; +import NonLocalAgentConfigExample from "/examples/agent-config/http-nonlocal.mdx"; +import NonLocalGoSdkExample from "/examples/go-sdk/http-nonlocal.mdx"; +import NonLocalJavascriptSdkExample from "/examples/javascript-sdk/http-nonlocal.mdx"; +import NonLocalKubernetesExample from "/examples/k8s/http-nonlocal.mdx"; +import NonLocalPythonSdkExample from "/examples/python-sdk/http-nonlocal.mdx"; +import NonLocalRustSdkExample from "/examples/rust-sdk/http-nonlocal.mdx"; +import NonLocalSshExample from "/examples/ssh/http-nonlocal.mdx"; + +import AbsPathFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-abs-path.mdx"; +import AbsPathFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-abs-path.mdx"; +import AbsPathFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-abs-path.mdx"; +import AbsPathFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-abs-path.mdx"; +import AbsPathFileserverKubernetesExample from "/examples/k8s/http-fileserver-abs-path.mdx"; +import AbsPathFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-abs-path.mdx"; +import AbsPathFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-abs-path.mdx"; +import AbsPathFileserverSshExample from "/examples/ssh/http-fileserver-abs-path.mdx"; + +import WorkingDirFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverKubernetesExample from "/examples/k8s/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverSshExample from "/examples/ssh/http-fileserver-working-dir.mdx"; + +import WindowsFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-windows.mdx"; +import WindowsFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-windows.mdx"; +import WindowsFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-windows.mdx"; +import WindowsFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-windows.mdx"; +import WindowsFileserverKubernetesExample from "/examples/k8s/http-fileserver-windows.mdx"; +import WindowsFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-windows.mdx"; +import WindowsFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-windows.mdx"; +import WindowsFileserverSshExample from "/examples/ssh/http-fileserver-windows.mdx"; + +import RandomAgentCliExample from "/examples/agent-cli/tcp-random.mdx"; +import RandomAgentConfigExample from "/examples/agent-config/tcp-random.mdx"; +import RandomGoSdkExample from "/examples/go-sdk/tcp-random.mdx"; +import RandomJavascriptSdkExample from "/examples/javascript-sdk/tcp-random.mdx"; +import RandomKubernetesExample from "/examples/k8s/tcp-random.mdx"; +import RandomPythonSdkExample from "/examples/python-sdk/tcp-random.mdx"; +import RandomRustSdkExample from "/examples/rust-sdk/tcp-random.mdx"; +import RandomSshExample from "/examples/ssh/tcp-random.mdx"; + +import FixedAgentCliExample from "/examples/agent-cli/tcp-fixed.mdx"; +import FixedAgentConfigExample from "/examples/agent-config/tcp-fixed.mdx"; +import FixedGoSdkExample from "/examples/go-sdk/tcp-fixed.mdx"; +import FixedJavascriptSdkExample from "/examples/javascript-sdk/tcp-fixed.mdx"; +import FixedKubernetesExample from "/examples/k8s/tcp-fixed.mdx"; +import FixedPythonSdkExample from "/examples/python-sdk/tcp-fixed.mdx"; +import FixedRustSdkExample from "/examples/rust-sdk/tcp-fixed.mdx"; +import FixedSshExample from "/examples/ssh/tcp-fixed.mdx"; + +import NonLocalAgentCliExample from "/examples/agent-cli/tcp-nonlocal.mdx"; +import NonLocalAgentConfigExample from "/examples/agent-config/tcp-nonlocal.mdx"; +import NonLocalGoSdkExample from "/examples/go-sdk/tcp-nonlocal.mdx"; +import NonLocalJavascriptSdkExample from "/examples/javascript-sdk/tcp-nonlocal.mdx"; +import NonLocalKubernetesExample from "/examples/k8s/tcp-nonlocal.mdx"; +import NonLocalPythonSdkExample from "/examples/python-sdk/tcp-nonlocal.mdx"; +import NonLocalRustSdkExample from "/examples/rust-sdk/tcp-nonlocal.mdx"; +import NonLocalSshExample from "/examples/ssh/tcp-nonlocal.mdx"; + +import ProxyProtoAgentCliExample from "/examples/agent-cli/tcp-proxyproto.mdx"; +import ProxyProtoAgentConfigExample from "/examples/agent-config/tcp-proxyproto.mdx"; +import ProxyProtoGoSdkExample from "/examples/go-sdk/tcp-proxyproto.mdx"; +import ProxyProtoJavascriptSdkExample from "/examples/javascript-sdk/tcp-proxyproto.mdx"; +import ProxyProtoKubernetesExample from "/examples/k8s/tcp-proxyproto.mdx"; +import ProxyProtoPythonSdkExample from "/examples/python-sdk/tcp-proxyproto.mdx"; +import ProxyProtoRustSdkExample from "/examples/rust-sdk/tcp-proxyproto.mdx"; +import ProxyProtoSshExample from "/examples/ssh/tcp-proxyproto.mdx"; + +import AtAgentAgentCliExample from "/examples/agent-cli/tls-terminate-at-agent.mdx"; +import AtAgentAgentConfigExample from "/examples/agent-config/tls-terminate-at-agent.mdx"; +import AtAgentGoSdkExample from "/examples/go-sdk/tls-terminate-at-agent.mdx"; +import AtAgentJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-agent.mdx"; +import AtAgentKubernetesExample from "/examples/k8s/tls-terminate-at-agent.mdx"; +import AtAgentPythonSdkExample from "/examples/python-sdk/tls-terminate-at-agent.mdx"; +import AtAgentRustSdkExample from "/examples/rust-sdk/tls-terminate-at-agent.mdx"; +import AtAgentSshExample from "/examples/ssh/tls-terminate-at-agent.mdx"; + +import AtUpstreamAgentCliExample from "/examples/agent-cli/tls-terminate-at-upstream.mdx"; +import AtUpstreamAgentConfigExample from "/examples/agent-config/tls-terminate-at-upstream.mdx"; +import AtUpstreamGoSdkExample from "/examples/go-sdk/tls-terminate-at-upstream.mdx"; +import AtUpstreamJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-upstream.mdx"; +import AtUpstreamKubernetesExample from "/examples/k8s/tls-terminate-at-upstream.mdx"; +import AtUpstreamPythonSdkExample from "/examples/python-sdk/tls-terminate-at-upstream.mdx"; +import AtUpstreamRustSdkExample from "/examples/rust-sdk/tls-terminate-at-upstream.mdx"; +import AtUpstreamSshExample from "/examples/ssh/tls-terminate-at-upstream.mdx"; + +import CustomDomainAgentCliExample from "/examples/agent-cli/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainAgentConfigExample from "/examples/agent-config/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainGoSdkExample from "/examples/go-sdk/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainKubernetesExample from "/examples/k8s/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainPythonSdkExample from "/examples/python-sdk/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainRustSdkExample from "/examples/rust-sdk/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainSshExample from "/examples/ssh/tls-terminate-at-edge-custom-domain.mdx"; + +import ReencryptUpstreamAgentCliExample from "/examples/agent-cli/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamAgentConfigExample from "/examples/agent-config/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamGoSdkExample from "/examples/go-sdk/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamJavascriptSdkExample from "/examples/javascript-sdk/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamKubernetesExample from "/examples/k8s/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamPythonSdkExample from "/examples/python-sdk/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamRustSdkExample from "/examples/rust-sdk/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamSshExample from "/examples/ssh/tls-reencrypt-upstream.mdx"; + +import ProxyProtoAgentCliExample from "/examples/agent-cli/tls-proxyproto.mdx"; +import ProxyProtoAgentConfigExample from "/examples/agent-config/tls-proxyproto.mdx"; +import ProxyProtoGoSdkExample from "/examples/go-sdk/tls-proxyproto.mdx"; +import ProxyProtoJavascriptSdkExample from "/examples/javascript-sdk/tls-proxyproto.mdx"; +import ProxyProtoKubernetesExample from "/examples/k8s/tls-proxyproto.mdx"; +import ProxyProtoPythonSdkExample from "/examples/python-sdk/tls-proxyproto.mdx"; +import ProxyProtoRustSdkExample from "/examples/rust-sdk/tls-proxyproto.mdx"; +import ProxyProtoSshExample from "/examples/ssh/tls-proxyproto.mdx"; + +The [ngrok agent](/agent/) and [Agent +SDKs](/agent-sdks/) forward traffic that your endpoints receive +to upstream services. You specify a URL or port number to instruct the ngrok +agent where and how to forward traffic. + +### HTTPS forwarding + +The scheme in your upstream URL is used to determine whether to forward HTTP or +HTTPS traffic to the upstream service. If you do not specify a scheme, the +default `http` scheme is chosen _unless_ you forward to port `443`, in which +case ngrok will use `https`. Consult the following table of examples. + +| Upstream URL | Normalized Value | +| ------------------------ | ------------------------ | +| `http://localhost:1234` | `http://localhost:1234` | +| `https://localhost:1234` | `https://localhost:1234` | +| `localhost:1234` | `http://localhost:1234` | +| `1234` | `http://localhost:1234` | +| `localhost:443` | `https://localhost:443` | +| `443` | `https://localhost:443` | + +ngrok assumes that the network you run the agent on is private and it does not +verify the TLS certificate presented by the upstream service. You may change +this behavior with the [flags `--upstream-tls-verify` and +`upstream-tls-verify-cas`](/agent/cli/#ngrok-http). + + + + + + + + + + + + + + + + + + + + + + + + + + + + +### Non-local forwarding + +Agents don't just forward to ports on your localhost. You can forward traffic +to any address or URL reachable from the agent. For example, if you want to +forward traffic to a HTTP server running on your network at `192.168.1.2:80`: + + + + + + + + + + + + + + + + + + + + + + + + + + + + +### HTTP/2 forwarding + +When agents forward to upstream http/2 services, connections use HTTP/1.1 by +default. + +You can configure the agent, SDKs and Kubernetes Operator to instead use HTTP/2 +when forwarding to your upstream service. + +| Forwarder | Option | Docs | +| ------------------- | --------------------------------- | ----------------------------------------- | +| Agent | `--upstream-protocol` | [Agent CLI flags](/agent/cli/#ngrok-http) | +| Agent SDKs | language-dependent | [Agent SDKs](/agent-sdks) | +| Kubernetes Operator | `appProtocol` on the `Tunnel` CRD | [Kubernetes Operator](/k8s) | + +When http2 forwarding is enabled, all requests to your upstream service will be +transmitted over HTTP/2 Cleartext since TLS was already terminated at the ngrok +cloud service. We cannot use +[TLS-ALPN](https://httpwg.org/specs/rfc7540.html#TLS-ALPN) at this time. We +rely on [HTTP/2 with Prior +Knowledge](https://httpwg.org/specs/rfc7540.html#known-http) currently. + +### Serving file directories + +The ngrok agent supports the `file://` scheme in a forwarding URL. When you use +the `file://` scheme, the ngrok agent serves local file system directories by +using its own built-in file server, no separate server needed. It works just +like `python3 -m http.server` but it is built directly into the ngrok agent. + +Paths in `file://` URLs must be specified as absolute paths. + +#### Serve files in `/var/log` + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +#### Serve files on Windows + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +#### Serve files in your current working directory + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## TCP + +### Forward to non-local service + +Agents don't just forward to ports on your localhost. You can forward traffic +to any address or URL reachable from the agent. For example, if you want to +forward traffic to a Postgres server running on your network at +`192.168.1.2:5432`: + + + + + + + + + + + + + + + + + + + + + + + + + + + + +### PROXY Protocol + +When you forward traffic to an upstream TCP service, becuase traffic is coming +from the ngrok agent, it won't know the client's original IP address. You can +add the [PROXY +protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) header +on connections to your upstream service to send connection information like the +original client IP address to your upstream service. You will need to configure +your upstream service to handle the PROXY protocol header. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## TLS + +### Re-encrypt to Upstream + +If you terminate TLS at the ngrok cloud service or ngrok agent, you may want to +re-encrypt the connection from the agent to your upstream service. The ngrok +agent supports this behavior by using the non-standard `tls://` scheme syntax. + + + + +```bash +ngrok tls tls://localhost:443 --terminate-at=edge +``` + + + + + + + + + + + + + + + + + + + + + + + + + +### PROXY Protocol + +Add a [PROXY +protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) header +on connection to your upstream service. This sends connection information like +the original client IP address to your upstream service. + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx index 40760f44a5..9e044f42dc 100644 --- a/docs/universal-gateway/http-s/index.mdx +++ b/docs/universal-gateway/http-s/index.mdx @@ -107,7 +107,9 @@ import WindowsFileserverPythonSdkExample from "/examples/python-sdk/http-fileser import WindowsFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-windows.mdx"; import WindowsFileserverSshExample from "/examples/ssh/http-fileserver-windows.mdx"; -You can create HTTP/S endpoints to serve web services like REST APIs, web applications, websites and websocket servers. You can serve an HTTP/S endpoint in one of the following ways. +You can create HTTP/S endpoints to serve web services like REST APIs, web applications, websites and websocket servers. + +## Quickstart @@ -116,7 +118,7 @@ You can create HTTP/S endpoints to serve web services like REST APIs, web applic The following example creates the endpoint `https://example.ngrok.app` and forwards its traffic to a local port. - ```bash title="Agent CLI" + ```bash title="Agent CLI" titleLink="/docs/agent/" ngrok http 8080 --url https://example.ngrok.app ``` ```sh @@ -227,7 +229,7 @@ ngrok api endpoints create \ - You can also create an HTTP/S endpoint using the [ngrok agent configuration file](/docs/traffic-policy/getting-started/agent-endpoints/config-file). You can edit the file with the following terminal command: + You can create an HTTP/S endpoint using the [ngrok agent configuration file](/docs/traffic-policy/getting-started/agent-endpoints/config-file). You can edit the file with the following terminal command: ```bash ngrok config edit @@ -246,363 +248,17 @@ ngrok api endpoints create \ -## URLs - -URLs are validated differently depending on their [binding](/universal-gateway/bindings). To learn more about valid URLs for HTTP/S endpoints, see [the Endpoint URLs documentation](/docs/universal-gateway/what-are-endpoint-urls/#http). - -To listen for both http and https traffic, create two endpoints. - -## Domains - -When you create a public endpoint, it must match a -Domain on your account. See [the Domains documentation](/universal-gateway/domains/what-are-domains/) for more information. - -### Bring your own domain {#bring-your-own-domain} - -To bring your own domain, see [the guide on the subject](/universal-gateway/how-do-i-use-my-own-domain). - -## Wildcard HTTP Endpoints - -You can create an HTTP/S endpoint which will receive traffic for all of the subdomains matching a given wildcard domain. See [the wildcard domain docs](/universal-gateway/wildcard-domains/) for more information. - -## Traffic Policy - -Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate and transform the traffic through the endpoint. - -### Authentication - -Public endpoints are accessible to the public internet unless you secure them -with authentication. That's desirable if you're hosting a public website but -most often you want to add authentication. You can secure your endpoints with -[Traffic Policy](/traffic-policy) with any of the following actions: - -- [Basic Auth](/traffic-policy/actions/basic-auth) -- [OAuth](/traffic-policy/actions/oauth) -- [IP Restriction](/traffic-policy/actions/restrict-ips/) -- [Webhook Verification](/traffic-policy/actions/verify-webhook/) -- [JWT](/traffic-policy/actions/jwt-validation/) -- [Mutual TLS](/traffic-policy/actions/terminate-tls/) -- [OpenID Connect](/traffic-policy/actions/oidc/) -- [SAML](/traffic-policy/actions/saml/) - -#### Basic Auth Example - -Adds a username and password with the [Basic -Auth](/traffic-policy/actions/basic-auth) Traffic Policy action. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -#### Google OAuth Example - -The following example enforces a browser-based OAuth redirect flow in front of -your endpoint using Google as the identity provider by using the -[OAuth](/traffic-policy/actions/oauth) Traffic Policy action. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#### Rewriting the `host` header {#rewrite-host-header} - -Some application servers expect the `host` header to match a specific value -when they receive requests and some use the `host` header to determine which of -many sites to display. ngrok can rewrite the `host` header of incoming requests -so that your application behaves correctly. - -When you rewrite the `host` header, ngrok also rewrites the `location` header of -HTTP responses automatically to match the hostname of your Endpoint URL. - -The following example rewrites the `host` header to the value `localhost` using -the [`add-headers`](/traffic-policy/actions/add-headers) Traffic Policy action. -Adding the `Host` header [is a special -case](/traffic-policy/actions/add-headers/#special-cases) that replaces the existing -`Host` header instead of appending a second value. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -## Agent Forwarding - -The [ngrok agent](/agent/) and [Agent -SDKs](/agent-sdks/) forward traffic that your endpoints receive -to upstream services. You specify a URL or port number to instruct the ngrok -agent where and how to forward traffic. - -### HTTPS forwarding - -The scheme in your upstream URL is used to determine whether to forward HTTP or -HTTPS traffic to the upstream service. If you do not specify a scheme, the -default `http` scheme is chosen _unless_ you forward to port `443`, in which -case ngrok will use `https`. Consult the following table of examples. - -| Upstream URL | Normalized Value | -| ------------------------ | ------------------------ | -| `http://localhost:1234` | `http://localhost:1234` | -| `https://localhost:1234` | `https://localhost:1234` | -| `localhost:1234` | `http://localhost:1234` | -| `1234` | `http://localhost:1234` | -| `localhost:443` | `https://localhost:443` | -| `443` | `https://localhost:443` | - -ngrok assumes that the network you run the agent on is private and it does not -verify the TLS certificate presented by the upstream service. You may change -this behavior with the [flags `--upstream-tls-verify` and -`upstream-tls-verify-cas`](/agent/cli/#ngrok-http). - - - - - - - - - - - - - - - - - - - - - - - - - - - - -### Non-local forwarding - -Agents don't just forward to ports on your localhost. You can forward traffic -to any address or URL reachable from the agent. For example, if you want to -forward traffic to a HTTP server running on your network at `192.168.1.2:80`: - - - - - - - - - - - - - - - - - - - - - - - - - - - - -### HTTP/2 forwarding - -When agents forward to upstream http/2 services, connections use HTTP/1.1 by -default. - -You can configure the agent, SDKs and Kubernetes Operator to instead use HTTP/2 -when forwarding to your upstream service. - -| Forwarder | Option | Docs | -| ------------------- | --------------------------------- | ----------------------------------------- | -| Agent | `--upstream-protocol` | [Agent CLI flags](/agent/cli/#ngrok-http) | -| Agent SDKs | language-dependent | [Agent SDKs](/agent-sdks) | -| Kubernetes Operator | `appProtocol` on the `Tunnel` CRD | [Kubernetes Operator](/k8s) | - -When http2 forwarding is enabled, all requests to your upstream service will be -transmitted over HTTP/2 Cleartext since TLS was already terminated at the ngrok -cloud service. We cannot use -[TLS-ALPN](https://httpwg.org/specs/rfc7540.html#TLS-ALPN) at this time. We -rely on [HTTP/2 with Prior -Knowledge](https://httpwg.org/specs/rfc7540.html#known-http) currently. - -### Serving file directories - -The ngrok agent supports the `file://` scheme in a forwarding URL. When you use -the `file://` scheme, the ngrok agent serves local file system directories by -using its own built-in file server, no separate server needed. It works just -like `python3 -m http.server` but it is built directly into the ngrok agent. - -Paths in `file://` URLs must be specified as absolute paths. - -#### Serve files in `/var/log` - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -#### Serve files on Windows - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -#### Serve files in your current working directory - - - - - - - - - - - - - - - - - - - - - - - - - - - +## Learn more + +- **URLS** — URLs are validated differently depending on their [binding](/universal-gateway/bindings). To learn more about valid URLs for HTTP/S endpoints, see [the Endpoint URLs documentation](/docs/universal-gateway/what-are-endpoint-urls/#http). +- **Domains** — Public HTTP/S endpoints must match a domain on your account. See [the domains documentation](/universal-gateway/domains/what-are-domains/) for more information. +- **Bring your own domain** — To use your own domain with HTTP/S endpoints, see [the guide on the subject](/universal-gateway/how-do-i-use-my-own-domain). +- **Wildcard Endpoints** — You can create HTTP/S endpoints that receive traffic from all of the subdomains matching a given wildcard domain. See [the wildcard domain docs](/universal-gateway/wildcard-domains/) for more information. +- **Traffic Policy** — Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate and transform the traffic through the endpoint. +- **Agent Forwarding** — The [ngrok agent](/agent/) and [Agent SDKs](/agent-sdks/) forward traffic that your endpoints receive to upstream services. See [the agent forwarding documentation](/universal-gateway/agent-forwarding/) for more information. +- **URLS** — +- **URLS** — +- **URLS** — ## Traffic Observability diff --git a/docs/universal-gateway/tcp.mdx b/docs/universal-gateway/tcp.mdx index a68f7eaf9c..6ce3cf4c68 100644 --- a/docs/universal-gateway/tcp.mdx +++ b/docs/universal-gateway/tcp.mdx @@ -188,84 +188,6 @@ to authenticate TCP traffic because the TCP protocol is low-level. - [IP Restriction](/traffic-policy/actions/restrict-ips/) - [Mutual TLS](/traffic-policy/actions/terminate-tls/) -## Agent Forwarding - -The [ngrok agent](/agent/) and [Agent -SDKs](/agent-sdks/) forward traffic that your endpoints receive -to upstream services. You specify a URL or port number to instruct the ngrok -agent where and how to forward traffic. - -### Forward to non-local service - -Agents don't just forward to ports on your localhost. You can forward traffic -to any address or URL reachable from the agent. For example, if you want to -forward traffic to a Postgres server running on your network at -`192.168.1.2:5432`: - - - - - - - - - - - - - - - - - - - - - - - - - - - - -### PROXY Protocol - -When you forward traffic to an upstream TCP service, becuase traffic is coming -from the ngrok agent, it won't know the client's original IP address. You can -add the [PROXY -protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) header -on connections to your upstream service to send connection information like the -original client IP address to your upstream service. You will need to configure -your upstream service to handle the PROXY protocol header. - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## Observability ### Traffic Inspector diff --git a/docs/universal-gateway/tls.mdx b/docs/universal-gateway/tls.mdx index 285df1693d..9aa2425a37 100644 --- a/docs/universal-gateway/tls.mdx +++ b/docs/universal-gateway/tls.mdx @@ -255,79 +255,6 @@ Consult the documentation on [TLS Certificates](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) for details about certificate selection, provisioning and management. -## Agent Forwarding - -### Re-encrypt to Upstream - -If you terminate TLS at the ngrok cloud service or ngrok agent, you may want to -re-encrypt the connection from the agent to your upstream service. The ngrok -agent supports this behavior by using the non-standard `tls://` scheme syntax. - - - - -```bash -ngrok tls tls://localhost:443 --terminate-at=edge -``` - - - - - - - - - - - - - - - - - - - - - - - - - -### PROXY Protocol - -Add a [PROXY -protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) header -on connection to your upstream service. This sends connection information like -the original client IP address to your upstream service. - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## Compatible Clients ### SNI From dab530fbdf0347eb14f0b1007830bf2f987f4c6e Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Wed, 2 Apr 2025 10:35:49 -0400 Subject: [PATCH 058/137] clear agent-forwarding file so we can test langswitcher --- docs/universal-gateway/agent-forwarding.mdx | 538 -------------------- sidebars.js | 1 + 2 files changed, 1 insertion(+), 538 deletions(-) diff --git a/docs/universal-gateway/agent-forwarding.mdx b/docs/universal-gateway/agent-forwarding.mdx index 5800c75029..1f7bc3c365 100644 --- a/docs/universal-gateway/agent-forwarding.mdx +++ b/docs/universal-gateway/agent-forwarding.mdx @@ -1,541 +1,3 @@ --- title: How does Agent Forwarding Work? --- - -import TabItem from "@theme/TabItem"; -import Tabs from "@theme/Tabs"; - -import { LangSwitcher } from "@site/src/components/LangSwitcher"; -import TlsLimits from "../_tls_limits.mdx"; - -import RandomAgentCliExample from "/examples/agent-cli/http-random.mdx"; -import RandomAgentConfigExample from "/examples/agent-config/http-random.mdx"; -import RandomGoSdkExample from "/examples/go-sdk/http-random.mdx"; -import RandomJavascriptSdkExample from "/examples/javascript-sdk/http-random.mdx"; -import RandomPythonSdkExample from "/examples/python-sdk/http-random.mdx"; -import RandomRustSdkExample from "/examples/rust-sdk/http-random.mdx"; -import RandomSshExample from "/examples/ssh/http-random.mdx"; - -import StaticDomainAgentCliExample from "/examples/agent-cli/http-static-domain.mdx"; -import StaticDomainAgentConfigExample from "/examples/agent-config/http-static-domain.mdx"; -import StaticDomainGoSdkExample from "/examples/go-sdk/http-static-domain.mdx"; -import StaticDomainJavascriptSdkExample from "/examples/javascript-sdk/http-static-domain.mdx"; -import StaticDomainKubernetesExample from "/examples/k8s/http-static-domain.mdx"; -import StaticDomainPythonSdkExample from "/examples/python-sdk/http-static-domain.mdx"; -import StaticDomainRustSdkExample from "/examples/rust-sdk/http-static-domain.mdx"; -import StaticDomainSshExample from "/examples/ssh/http-static-domain.mdx"; - -import BrandedDomainAgentCliExample from "/examples/agent-cli/http-branded-domain.mdx"; -import BrandedDomainAgentConfigExample from "/examples/agent-config/http-branded-domain.mdx"; -import BrandedDomainGoSdkExample from "/examples/go-sdk/http-branded-domain.mdx"; -import BrandedDomainJavascriptSdkExample from "/examples/javascript-sdk/http-branded-domain.mdx"; -import BrandedDomainKubernetesExample from "/examples/k8s/http-branded-domain.mdx"; -import BrandedDomainPythonSdkExample from "/examples/python-sdk/http-branded-domain.mdx"; -import BrandedDomainRustSdkExample from "/examples/rust-sdk/http-branded-domain.mdx"; -import BrandedDomainSshExample from "/examples/ssh/http-branded-domain.mdx"; - -import BasicAuthAgentCliExample from "/examples/agent-cli/http-basic-auth.mdx"; -import BasicAuthAgentConfigExample from "/examples/agent-config/http-basic-auth.mdx"; -import BasicAuthGoSdkExample from "/examples/go-sdk/http-basic-auth.mdx"; -import BasicAuthJavascriptSdkExample from "/examples/javascript-sdk/http-basic-auth.mdx"; -import BasicAuthKubernetesExample from "/examples/k8s/http-basic-auth.mdx"; -import BasicAuthPythonSdkExample from "/examples/python-sdk/http-basic-auth.mdx"; -import BasicAuthRustSdkExample from "/examples/rust-sdk/http-basic-auth.mdx"; -import BasicAuthSshExample from "/examples/ssh/http-basic-auth.mdx"; - -import OAuthAgentCliExample from "/examples/agent-cli/http-oauth-authn.mdx"; -import OAuthAgentConfigExample from "/examples/agent-config/http-oauth-authn.mdx"; -import OAuthGoSdkExample from "/examples/go-sdk/http-oauth-authn.mdx"; -import OAuthJavascriptSdkExample from "/examples/javascript-sdk/http-oauth-authn.mdx"; -import OAuthKubernetesExample from "/examples/k8s/http-oauth-authn.mdx"; -import OAuthPythonSdkExample from "/examples/python-sdk/http-oauth-authn.mdx"; -import OAuthRustSdkExample from "/examples/rust-sdk/http-oauth-authn.mdx"; -import OAuthSshExample from "/examples/ssh/http-oauth-authn.mdx"; - -import ForwardHttpsAgentCliExample from "/examples/agent-cli/http-forward-https.mdx"; -import ForwardHttpsAgentConfigExample from "/examples/agent-config/http-forward-https.mdx"; -import ForwardHttpsGoSdkExample from "/examples/go-sdk/http-forward-https.mdx"; -import ForwardHttpsJavascriptSdkExample from "/examples/javascript-sdk/http-forward-https.mdx"; -import ForwardHttpsKubernetesExample from "/examples/k8s/http-forward-https.mdx"; -import ForwardHttpsPythonSdkExample from "/examples/python-sdk/http-forward-https.mdx"; -import ForwardHttpsRustSdkExample from "/examples/rust-sdk/http-forward-https.mdx"; -import ForwardHttpsSshExample from "/examples/ssh/http-forward-https.mdx"; - -import HostHeaderAgentCliExample from "/examples/agent-cli/http-rewrite-host-header.mdx"; -import HostHeaderAgentConfigExample from "/examples/agent-config/http-rewrite-host-header.mdx"; -import HostHeaderGoSdkExample from "/examples/go-sdk/http-rewrite-host-header.mdx"; -import HostHeaderJavascriptSdkExample from "/examples/javascript-sdk/http-rewrite-host-header.mdx"; -import HostHeaderKubernetesExample from "/examples/k8s/http-rewrite-host-header.mdx"; -import HostHeaderPythonSdkExample from "/examples/python-sdk/http-rewrite-host-header.mdx"; -import HostHeaderRustSdkExample from "/examples/rust-sdk/http-rewrite-host-header.mdx"; -import HostHeaderSshExample from "/examples/ssh/http-rewrite-host-header.mdx"; - -import NonLocalAgentCliExample from "/examples/agent-cli/http-nonlocal.mdx"; -import NonLocalAgentConfigExample from "/examples/agent-config/http-nonlocal.mdx"; -import NonLocalGoSdkExample from "/examples/go-sdk/http-nonlocal.mdx"; -import NonLocalJavascriptSdkExample from "/examples/javascript-sdk/http-nonlocal.mdx"; -import NonLocalKubernetesExample from "/examples/k8s/http-nonlocal.mdx"; -import NonLocalPythonSdkExample from "/examples/python-sdk/http-nonlocal.mdx"; -import NonLocalRustSdkExample from "/examples/rust-sdk/http-nonlocal.mdx"; -import NonLocalSshExample from "/examples/ssh/http-nonlocal.mdx"; - -import AbsPathFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-abs-path.mdx"; -import AbsPathFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-abs-path.mdx"; -import AbsPathFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverKubernetesExample from "/examples/k8s/http-fileserver-abs-path.mdx"; -import AbsPathFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverSshExample from "/examples/ssh/http-fileserver-abs-path.mdx"; - -import WorkingDirFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverKubernetesExample from "/examples/k8s/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverSshExample from "/examples/ssh/http-fileserver-working-dir.mdx"; - -import WindowsFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-windows.mdx"; -import WindowsFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-windows.mdx"; -import WindowsFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverKubernetesExample from "/examples/k8s/http-fileserver-windows.mdx"; -import WindowsFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverSshExample from "/examples/ssh/http-fileserver-windows.mdx"; - -import RandomAgentCliExample from "/examples/agent-cli/tcp-random.mdx"; -import RandomAgentConfigExample from "/examples/agent-config/tcp-random.mdx"; -import RandomGoSdkExample from "/examples/go-sdk/tcp-random.mdx"; -import RandomJavascriptSdkExample from "/examples/javascript-sdk/tcp-random.mdx"; -import RandomKubernetesExample from "/examples/k8s/tcp-random.mdx"; -import RandomPythonSdkExample from "/examples/python-sdk/tcp-random.mdx"; -import RandomRustSdkExample from "/examples/rust-sdk/tcp-random.mdx"; -import RandomSshExample from "/examples/ssh/tcp-random.mdx"; - -import FixedAgentCliExample from "/examples/agent-cli/tcp-fixed.mdx"; -import FixedAgentConfigExample from "/examples/agent-config/tcp-fixed.mdx"; -import FixedGoSdkExample from "/examples/go-sdk/tcp-fixed.mdx"; -import FixedJavascriptSdkExample from "/examples/javascript-sdk/tcp-fixed.mdx"; -import FixedKubernetesExample from "/examples/k8s/tcp-fixed.mdx"; -import FixedPythonSdkExample from "/examples/python-sdk/tcp-fixed.mdx"; -import FixedRustSdkExample from "/examples/rust-sdk/tcp-fixed.mdx"; -import FixedSshExample from "/examples/ssh/tcp-fixed.mdx"; - -import NonLocalAgentCliExample from "/examples/agent-cli/tcp-nonlocal.mdx"; -import NonLocalAgentConfigExample from "/examples/agent-config/tcp-nonlocal.mdx"; -import NonLocalGoSdkExample from "/examples/go-sdk/tcp-nonlocal.mdx"; -import NonLocalJavascriptSdkExample from "/examples/javascript-sdk/tcp-nonlocal.mdx"; -import NonLocalKubernetesExample from "/examples/k8s/tcp-nonlocal.mdx"; -import NonLocalPythonSdkExample from "/examples/python-sdk/tcp-nonlocal.mdx"; -import NonLocalRustSdkExample from "/examples/rust-sdk/tcp-nonlocal.mdx"; -import NonLocalSshExample from "/examples/ssh/tcp-nonlocal.mdx"; - -import ProxyProtoAgentCliExample from "/examples/agent-cli/tcp-proxyproto.mdx"; -import ProxyProtoAgentConfigExample from "/examples/agent-config/tcp-proxyproto.mdx"; -import ProxyProtoGoSdkExample from "/examples/go-sdk/tcp-proxyproto.mdx"; -import ProxyProtoJavascriptSdkExample from "/examples/javascript-sdk/tcp-proxyproto.mdx"; -import ProxyProtoKubernetesExample from "/examples/k8s/tcp-proxyproto.mdx"; -import ProxyProtoPythonSdkExample from "/examples/python-sdk/tcp-proxyproto.mdx"; -import ProxyProtoRustSdkExample from "/examples/rust-sdk/tcp-proxyproto.mdx"; -import ProxyProtoSshExample from "/examples/ssh/tcp-proxyproto.mdx"; - -import AtAgentAgentCliExample from "/examples/agent-cli/tls-terminate-at-agent.mdx"; -import AtAgentAgentConfigExample from "/examples/agent-config/tls-terminate-at-agent.mdx"; -import AtAgentGoSdkExample from "/examples/go-sdk/tls-terminate-at-agent.mdx"; -import AtAgentJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-agent.mdx"; -import AtAgentKubernetesExample from "/examples/k8s/tls-terminate-at-agent.mdx"; -import AtAgentPythonSdkExample from "/examples/python-sdk/tls-terminate-at-agent.mdx"; -import AtAgentRustSdkExample from "/examples/rust-sdk/tls-terminate-at-agent.mdx"; -import AtAgentSshExample from "/examples/ssh/tls-terminate-at-agent.mdx"; - -import AtUpstreamAgentCliExample from "/examples/agent-cli/tls-terminate-at-upstream.mdx"; -import AtUpstreamAgentConfigExample from "/examples/agent-config/tls-terminate-at-upstream.mdx"; -import AtUpstreamGoSdkExample from "/examples/go-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamKubernetesExample from "/examples/k8s/tls-terminate-at-upstream.mdx"; -import AtUpstreamPythonSdkExample from "/examples/python-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamRustSdkExample from "/examples/rust-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamSshExample from "/examples/ssh/tls-terminate-at-upstream.mdx"; - -import CustomDomainAgentCliExample from "/examples/agent-cli/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainAgentConfigExample from "/examples/agent-config/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainGoSdkExample from "/examples/go-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainKubernetesExample from "/examples/k8s/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainPythonSdkExample from "/examples/python-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainRustSdkExample from "/examples/rust-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainSshExample from "/examples/ssh/tls-terminate-at-edge-custom-domain.mdx"; - -import ReencryptUpstreamAgentCliExample from "/examples/agent-cli/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamAgentConfigExample from "/examples/agent-config/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamGoSdkExample from "/examples/go-sdk/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamJavascriptSdkExample from "/examples/javascript-sdk/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamKubernetesExample from "/examples/k8s/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamPythonSdkExample from "/examples/python-sdk/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamRustSdkExample from "/examples/rust-sdk/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamSshExample from "/examples/ssh/tls-reencrypt-upstream.mdx"; - -import ProxyProtoAgentCliExample from "/examples/agent-cli/tls-proxyproto.mdx"; -import ProxyProtoAgentConfigExample from "/examples/agent-config/tls-proxyproto.mdx"; -import ProxyProtoGoSdkExample from "/examples/go-sdk/tls-proxyproto.mdx"; -import ProxyProtoJavascriptSdkExample from "/examples/javascript-sdk/tls-proxyproto.mdx"; -import ProxyProtoKubernetesExample from "/examples/k8s/tls-proxyproto.mdx"; -import ProxyProtoPythonSdkExample from "/examples/python-sdk/tls-proxyproto.mdx"; -import ProxyProtoRustSdkExample from "/examples/rust-sdk/tls-proxyproto.mdx"; -import ProxyProtoSshExample from "/examples/ssh/tls-proxyproto.mdx"; - -The [ngrok agent](/agent/) and [Agent -SDKs](/agent-sdks/) forward traffic that your endpoints receive -to upstream services. You specify a URL or port number to instruct the ngrok -agent where and how to forward traffic. - -### HTTPS forwarding - -The scheme in your upstream URL is used to determine whether to forward HTTP or -HTTPS traffic to the upstream service. If you do not specify a scheme, the -default `http` scheme is chosen _unless_ you forward to port `443`, in which -case ngrok will use `https`. Consult the following table of examples. - -| Upstream URL | Normalized Value | -| ------------------------ | ------------------------ | -| `http://localhost:1234` | `http://localhost:1234` | -| `https://localhost:1234` | `https://localhost:1234` | -| `localhost:1234` | `http://localhost:1234` | -| `1234` | `http://localhost:1234` | -| `localhost:443` | `https://localhost:443` | -| `443` | `https://localhost:443` | - -ngrok assumes that the network you run the agent on is private and it does not -verify the TLS certificate presented by the upstream service. You may change -this behavior with the [flags `--upstream-tls-verify` and -`upstream-tls-verify-cas`](/agent/cli/#ngrok-http). - - - - - - - - - - - - - - - - - - - - - - - - - - - - -### Non-local forwarding - -Agents don't just forward to ports on your localhost. You can forward traffic -to any address or URL reachable from the agent. For example, if you want to -forward traffic to a HTTP server running on your network at `192.168.1.2:80`: - - - - - - - - - - - - - - - - - - - - - - - - - - - - -### HTTP/2 forwarding - -When agents forward to upstream http/2 services, connections use HTTP/1.1 by -default. - -You can configure the agent, SDKs and Kubernetes Operator to instead use HTTP/2 -when forwarding to your upstream service. - -| Forwarder | Option | Docs | -| ------------------- | --------------------------------- | ----------------------------------------- | -| Agent | `--upstream-protocol` | [Agent CLI flags](/agent/cli/#ngrok-http) | -| Agent SDKs | language-dependent | [Agent SDKs](/agent-sdks) | -| Kubernetes Operator | `appProtocol` on the `Tunnel` CRD | [Kubernetes Operator](/k8s) | - -When http2 forwarding is enabled, all requests to your upstream service will be -transmitted over HTTP/2 Cleartext since TLS was already terminated at the ngrok -cloud service. We cannot use -[TLS-ALPN](https://httpwg.org/specs/rfc7540.html#TLS-ALPN) at this time. We -rely on [HTTP/2 with Prior -Knowledge](https://httpwg.org/specs/rfc7540.html#known-http) currently. - -### Serving file directories - -The ngrok agent supports the `file://` scheme in a forwarding URL. When you use -the `file://` scheme, the ngrok agent serves local file system directories by -using its own built-in file server, no separate server needed. It works just -like `python3 -m http.server` but it is built directly into the ngrok agent. - -Paths in `file://` URLs must be specified as absolute paths. - -#### Serve files in `/var/log` - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -#### Serve files on Windows - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -#### Serve files in your current working directory - - - - - - - - - - - - - - - - - - - - - - - - - - - - -## TCP - -### Forward to non-local service - -Agents don't just forward to ports on your localhost. You can forward traffic -to any address or URL reachable from the agent. For example, if you want to -forward traffic to a Postgres server running on your network at -`192.168.1.2:5432`: - - - - - - - - - - - - - - - - - - - - - - - - - - - - -### PROXY Protocol - -When you forward traffic to an upstream TCP service, becuase traffic is coming -from the ngrok agent, it won't know the client's original IP address. You can -add the [PROXY -protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) header -on connections to your upstream service to send connection information like the -original client IP address to your upstream service. You will need to configure -your upstream service to handle the PROXY protocol header. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -## TLS - -### Re-encrypt to Upstream - -If you terminate TLS at the ngrok cloud service or ngrok agent, you may want to -re-encrypt the connection from the agent to your upstream service. The ngrok -agent supports this behavior by using the non-standard `tls://` scheme syntax. - - - - -```bash -ngrok tls tls://localhost:443 --terminate-at=edge -``` - - - - - - - - - - - - - - - - - - - - - - - - - -### PROXY Protocol - -Add a [PROXY -protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) header -on connection to your upstream service. This sends connection information like -the original client IP address to your upstream service. - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sidebars.js b/sidebars.js index cd7cc5e285..ba6bdd601c 100644 --- a/sidebars.js +++ b/sidebars.js @@ -125,6 +125,7 @@ const sidebars = { "universal-gateway/chain-endpoints", "universal-gateway/mock-api", "universal-gateway/migrate-from-tunnels", + "universal-gateway/agent-forwarding", { label: "How Do I Handle HTTP/S Traffic?", From 0ad57e2c03fdba2749410ac66e67e831b6225ba5 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Wed, 2 Apr 2025 12:08:20 -0400 Subject: [PATCH 059/137] Intro to agent forwarding fixed --- docs/universal-gateway/agent-forwarding.mdx | 595 ++++++++++++++++++ .../domains/what-are-managed-domains.mdx | 2 +- .../LangSwitcher/ContentSwitcher.tsx | 14 +- 3 files changed, 605 insertions(+), 6 deletions(-) diff --git a/docs/universal-gateway/agent-forwarding.mdx b/docs/universal-gateway/agent-forwarding.mdx index 1f7bc3c365..920956d704 100644 --- a/docs/universal-gateway/agent-forwarding.mdx +++ b/docs/universal-gateway/agent-forwarding.mdx @@ -1,3 +1,598 @@ --- title: How does Agent Forwarding Work? --- + +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; + +import { LangSwitcher } from "@site/src/components/LangSwitcher"; +import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitcher"; + +import RandomAgentCliExample from "/examples/agent-cli/http-random.mdx"; +import RandomAgentConfigExample from "/examples/agent-config/http-random.mdx"; +import RandomGoSdkExample from "/examples/go-sdk/http-random.mdx"; +import RandomJavascriptSdkExample from "/examples/javascript-sdk/http-random.mdx"; +import RandomPythonSdkExample from "/examples/python-sdk/http-random.mdx"; +import RandomRustSdkExample from "/examples/rust-sdk/http-random.mdx"; +import RandomSshExample from "/examples/ssh/http-random.mdx"; + +import StaticDomainAgentCliExample from "/examples/agent-cli/http-static-domain.mdx"; +import StaticDomainAgentConfigExample from "/examples/agent-config/http-static-domain.mdx"; +import StaticDomainGoSdkExample from "/examples/go-sdk/http-static-domain.mdx"; +import StaticDomainJavascriptSdkExample from "/examples/javascript-sdk/http-static-domain.mdx"; +import StaticDomainKubernetesExample from "/examples/k8s/http-static-domain.mdx"; +import StaticDomainPythonSdkExample from "/examples/python-sdk/http-static-domain.mdx"; +import StaticDomainRustSdkExample from "/examples/rust-sdk/http-static-domain.mdx"; +import StaticDomainSshExample from "/examples/ssh/http-static-domain.mdx"; + +import BrandedDomainAgentCliExample from "/examples/agent-cli/http-branded-domain.mdx"; +import BrandedDomainAgentConfigExample from "/examples/agent-config/http-branded-domain.mdx"; +import BrandedDomainGoSdkExample from "/examples/go-sdk/http-branded-domain.mdx"; +import BrandedDomainJavascriptSdkExample from "/examples/javascript-sdk/http-branded-domain.mdx"; +import BrandedDomainKubernetesExample from "/examples/k8s/http-branded-domain.mdx"; +import BrandedDomainPythonSdkExample from "/examples/python-sdk/http-branded-domain.mdx"; +import BrandedDomainRustSdkExample from "/examples/rust-sdk/http-branded-domain.mdx"; +import BrandedDomainSshExample from "/examples/ssh/http-branded-domain.mdx"; + +import BasicAuthAgentCliExample from "/examples/agent-cli/http-basic-auth.mdx"; +import BasicAuthAgentConfigExample from "/examples/agent-config/http-basic-auth.mdx"; +import BasicAuthGoSdkExample from "/examples/go-sdk/http-basic-auth.mdx"; +import BasicAuthJavascriptSdkExample from "/examples/javascript-sdk/http-basic-auth.mdx"; +import BasicAuthKubernetesExample from "/examples/k8s/http-basic-auth.mdx"; +import BasicAuthPythonSdkExample from "/examples/python-sdk/http-basic-auth.mdx"; +import BasicAuthRustSdkExample from "/examples/rust-sdk/http-basic-auth.mdx"; +import BasicAuthSshExample from "/examples/ssh/http-basic-auth.mdx"; + +import OAuthAgentCliExample from "/examples/agent-cli/http-oauth-authn.mdx"; +import OAuthAgentConfigExample from "/examples/agent-config/http-oauth-authn.mdx"; +import OAuthGoSdkExample from "/examples/go-sdk/http-oauth-authn.mdx"; +import OAuthJavascriptSdkExample from "/examples/javascript-sdk/http-oauth-authn.mdx"; +import OAuthKubernetesExample from "/examples/k8s/http-oauth-authn.mdx"; +import OAuthPythonSdkExample from "/examples/python-sdk/http-oauth-authn.mdx"; +import OAuthRustSdkExample from "/examples/rust-sdk/http-oauth-authn.mdx"; +import OAuthSshExample from "/examples/ssh/http-oauth-authn.mdx"; + +import ForwardHttpsAgentConfigExample from "/examples/agent-config/http-forward-https.mdx"; +import ForwardHttpsKubernetesExample from "/examples/k8s/http-forward-https.mdx"; + +import HostHeaderAgentCliExample from "/examples/agent-cli/http-rewrite-host-header.mdx"; +import HostHeaderAgentConfigExample from "/examples/agent-config/http-rewrite-host-header.mdx"; +import HostHeaderGoSdkExample from "/examples/go-sdk/http-rewrite-host-header.mdx"; +import HostHeaderJavascriptSdkExample from "/examples/javascript-sdk/http-rewrite-host-header.mdx"; +import HostHeaderKubernetesExample from "/examples/k8s/http-rewrite-host-header.mdx"; +import HostHeaderPythonSdkExample from "/examples/python-sdk/http-rewrite-host-header.mdx"; +import HostHeaderRustSdkExample from "/examples/rust-sdk/http-rewrite-host-header.mdx"; +import HostHeaderSshExample from "/examples/ssh/http-rewrite-host-header.mdx"; + +import NonLocalAgentCliExample from "/examples/agent-cli/http-nonlocal.mdx"; +import NonLocalAgentConfigExample from "/examples/agent-config/http-nonlocal.mdx"; +import NonLocalGoSdkExample from "/examples/go-sdk/http-nonlocal.mdx"; +import NonLocalJavascriptSdkExample from "/examples/javascript-sdk/http-nonlocal.mdx"; +import NonLocalKubernetesExample from "/examples/k8s/http-nonlocal.mdx"; +import NonLocalPythonSdkExample from "/examples/python-sdk/http-nonlocal.mdx"; +import NonLocalRustSdkExample from "/examples/rust-sdk/http-nonlocal.mdx"; +import NonLocalSshExample from "/examples/ssh/http-nonlocal.mdx"; + +import AbsPathFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-abs-path.mdx"; +import AbsPathFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-abs-path.mdx"; +import AbsPathFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-abs-path.mdx"; +import AbsPathFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-abs-path.mdx"; +import AbsPathFileserverKubernetesExample from "/examples/k8s/http-fileserver-abs-path.mdx"; +import AbsPathFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-abs-path.mdx"; +import AbsPathFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-abs-path.mdx"; +import AbsPathFileserverSshExample from "/examples/ssh/http-fileserver-abs-path.mdx"; + +import WorkingDirFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverKubernetesExample from "/examples/k8s/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverSshExample from "/examples/ssh/http-fileserver-working-dir.mdx"; + +import WindowsFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-windows.mdx"; +import WindowsFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-windows.mdx"; +import WindowsFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-windows.mdx"; +import WindowsFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-windows.mdx"; +import WindowsFileserverKubernetesExample from "/examples/k8s/http-fileserver-windows.mdx"; +import WindowsFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-windows.mdx"; +import WindowsFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-windows.mdx"; +import WindowsFileserverSshExample from "/examples/ssh/http-fileserver-windows.mdx"; + +import RandomAgentCliExampleTCP from "/examples/agent-cli/tcp-random.mdx"; +import RandomAgentConfigExampleTCP from "/examples/agent-config/tcp-random.mdx"; +import RandomGoSdkExampleTCP from "/examples/go-sdk/tcp-random.mdx"; +import RandomJavascriptSdkExampleTCP from "/examples/javascript-sdk/tcp-random.mdx"; +import RandomKubernetesExampleTCP from "/examples/k8s/tcp-random.mdx"; +import RandomPythonSdkExampleTCP from "/examples/python-sdk/tcp-random.mdx"; +import RandomRustSdkExampleTCP from "/examples/rust-sdk/tcp-random.mdx"; +import RandomSshExampleTCP from "/examples/ssh/tcp-random.mdx"; + +import FixedAgentCliExampleTCP from "/examples/agent-cli/tcp-fixed.mdx"; +import FixedAgentConfigExampleTCP from "/examples/agent-config/tcp-fixed.mdx"; +import FixedGoSdkExampleTCP from "/examples/go-sdk/tcp-fixed.mdx"; +import FixedJavascriptSdkExampleTCP from "/examples/javascript-sdk/tcp-fixed.mdx"; +import FixedKubernetesExampleTCP from "/examples/k8s/tcp-fixed.mdx"; +import FixedPythonSdkExampleTCP from "/examples/python-sdk/tcp-fixed.mdx"; +import FixedRustSdkExampleTCP from "/examples/rust-sdk/tcp-fixed.mdx"; +import FixedSshExampleTCP from "/examples/ssh/tcp-fixed.mdx"; + +import NonLocalAgentCliExampleTCP from "/examples/agent-cli/tcp-nonlocal.mdx"; +import NonLocalAgentConfigExampleTCP from "/examples/agent-config/tcp-nonlocal.mdx"; +import NonLocalGoSdkExampleTCP from "/examples/go-sdk/tcp-nonlocal.mdx"; +import NonLocalJavascriptSdkExampleTCP from "/examples/javascript-sdk/tcp-nonlocal.mdx"; +import NonLocalKubernetesExampleTCP from "/examples/k8s/tcp-nonlocal.mdx"; +import NonLocalPythonSdkExampleTCP from "/examples/python-sdk/tcp-nonlocal.mdx"; +import NonLocalRustSdkExampleTCP from "/examples/rust-sdk/tcp-nonlocal.mdx"; +import NonLocalSshExampleTCP from "/examples/ssh/tcp-nonlocal.mdx"; + +import ProxyProtoAgentCliExample from "/examples/agent-cli/tcp-proxyproto.mdx"; +import ProxyProtoAgentConfigExample from "/examples/agent-config/tcp-proxyproto.mdx"; +import ProxyProtoGoSdkExample from "/examples/go-sdk/tcp-proxyproto.mdx"; +import ProxyProtoJavascriptSdkExample from "/examples/javascript-sdk/tcp-proxyproto.mdx"; +import ProxyProtoKubernetesExample from "/examples/k8s/tcp-proxyproto.mdx"; +import ProxyProtoPythonSdkExample from "/examples/python-sdk/tcp-proxyproto.mdx"; +import ProxyProtoRustSdkExample from "/examples/rust-sdk/tcp-proxyproto.mdx"; +import ProxyProtoSshExample from "/examples/ssh/tcp-proxyproto.mdx"; + +import AtAgentAgentCliExample from "/examples/agent-cli/tls-terminate-at-agent.mdx"; +import AtAgentAgentConfigExample from "/examples/agent-config/tls-terminate-at-agent.mdx"; +import AtAgentGoSdkExample from "/examples/go-sdk/tls-terminate-at-agent.mdx"; +import AtAgentJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-agent.mdx"; +import AtAgentKubernetesExample from "/examples/k8s/tls-terminate-at-agent.mdx"; +import AtAgentPythonSdkExample from "/examples/python-sdk/tls-terminate-at-agent.mdx"; +import AtAgentRustSdkExample from "/examples/rust-sdk/tls-terminate-at-agent.mdx"; +import AtAgentSshExample from "/examples/ssh/tls-terminate-at-agent.mdx"; + +import AtUpstreamAgentCliExample from "/examples/agent-cli/tls-terminate-at-upstream.mdx"; +import AtUpstreamAgentConfigExample from "/examples/agent-config/tls-terminate-at-upstream.mdx"; +import AtUpstreamGoSdkExample from "/examples/go-sdk/tls-terminate-at-upstream.mdx"; +import AtUpstreamJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-upstream.mdx"; +import AtUpstreamKubernetesExample from "/examples/k8s/tls-terminate-at-upstream.mdx"; +import AtUpstreamPythonSdkExample from "/examples/python-sdk/tls-terminate-at-upstream.mdx"; +import AtUpstreamRustSdkExample from "/examples/rust-sdk/tls-terminate-at-upstream.mdx"; +import AtUpstreamSshExample from "/examples/ssh/tls-terminate-at-upstream.mdx"; + +import CustomDomainAgentCliExample from "/examples/agent-cli/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainAgentConfigExample from "/examples/agent-config/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainGoSdkExample from "/examples/go-sdk/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainKubernetesExample from "/examples/k8s/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainPythonSdkExample from "/examples/python-sdk/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainRustSdkExample from "/examples/rust-sdk/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainSshExample from "/examples/ssh/tls-terminate-at-edge-custom-domain.mdx"; + +import ReencryptUpstreamAgentCliExample from "/examples/agent-cli/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamAgentConfigExample from "/examples/agent-config/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamGoSdkExample from "/examples/go-sdk/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamJavascriptSdkExample from "/examples/javascript-sdk/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamKubernetesExample from "/examples/k8s/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamPythonSdkExample from "/examples/python-sdk/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamRustSdkExample from "/examples/rust-sdk/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamSshExample from "/examples/ssh/tls-reencrypt-upstream.mdx"; + +import ProxyProtoAgentCliExampleTLS from "/examples/agent-cli/tls-proxyproto.mdx"; +import ProxyProtoAgentConfigExampleTLS from "/examples/agent-config/tls-proxyproto.mdx"; +import ProxyProtoGoSdkExampleTLS from "/examples/go-sdk/tls-proxyproto.mdx"; +import ProxyProtoJavascriptSdkExampleTLS from "/examples/javascript-sdk/tls-proxyproto.mdx"; +import ProxyProtoKubernetesExampleTLS from "/examples/k8s/tls-proxyproto.mdx"; +import ProxyProtoPythonSdkExampleTLS from "/examples/python-sdk/tls-proxyproto.mdx"; +import ProxyProtoRustSdkExampleTLS from "/examples/rust-sdk/tls-proxyproto.mdx"; +import ProxyProtoSshExampleTLS from "/examples/ssh/tls-proxyproto.mdx"; + +The [ngrok agent](/agent/) and [Agent SDKs](/agent-sdks/) forward traffic that your endpoints receive to upstream services. You specify a URL or port number to instruct the ngrok agent where and how to forward traffic. + +## HTTPS forwarding + +The scheme in your upstream URL is used to determine whether to forward HTTP or HTTPS traffic to the upstream service. If you do not specify a scheme, the default `http` scheme is chosen _unless_ you forward to port `443`, in which case ngrok will use `https`. Consult the following table of examples. + +| Upstream URL | Normalized Value | +| ------------------------ | ------------------------ | +| `http://localhost:1234` | `http://localhost:1234` | +| `https://localhost:1234` | `https://localhost:1234` | +| `localhost:1234` | `http://localhost:1234` | +| `1234` | `http://localhost:1234` | +| `localhost:443` | `https://localhost:443` | +| `443` | `https://localhost:443` | + +ngrok assumes that the network you run the agent on is private and it does not verify the TLS certificate presented by the upstream service. You may change this behavior with the [flags `--upstream-tls-verify` and `upstream-tls-verify-cas`](/agent/cli/#ngrok-http). + + + + +```bash +ngrok http https://localhost:8443 +``` + +```go +import ( + "context" + "net/url" + + "golang.ngrok.com/ngrok" + "golang.ngrok.com/ngrok/config" + +) + +func ngrokForwarder(ctx context.Context) (ngrok.Forwarder, error) { +backendUrl, err := url.Parse("https://localhost:8443") +if err != nil { +return nil, err +} + + return ngrok.ListenAndForward(ctx, + backendUrl, + config.HTTPEndpoint(), + ngrok.WithAuthtokenFromEnv(), + ) + +} +``` + +```jsx +const ngrok = require("@ngrok/ngrok"); + +(async function () { + const listener = await ngrok.forward({ + addr: "https://localhost:8443", + authtoken_from_env: true, + }); + + console.log(`Ingress established at: ${listener.url()}`); +})(); +``` + +```python +import ngrok + +listener = ngrok.forward("https://localhost:8443", authtoken_from_env=True) + +print(f"Ingress established at: {listener.url()}"); +``` + +```rust +use ngrok::prelude::*; +use ngrok::tunnel; +use ngrok::forwarder::Forwarder; +use url::Url; + +async fn forward_ngrok() -> Result, Error> { + let sess = ngrok::Session::builder() + .authtoken_from_env() + .connect() + .await?; + sess + .http_endpoint() + .listen_and_forward(Url::parse("https://localhost:8443")?) + .await + .map_err(Into::into) +} +``` + + + + + + + + + + + + + + + + + For HTTP/2 Use: `config.HTTPEndpoint(config.WithAppProtocol("http2"))` + + + + + +:::info +Forwarding to an upstream HTTPS service is not supported via SSH. +::: + + + +### Non-local forwarding + +Agents don't just forward to ports on your localhost. You can forward traffic +to any address or URL reachable from the agent. For example, if you want to +forward traffic to a HTTP server running on your network at `192.168.1.2:80`: + + + + + + + + + + + + + + + + + + + + + + + + + + + + +### HTTP/2 forwarding + +When agents forward to upstream http/2 services, connections use HTTP/1.1 by +default. + +You can configure the agent, SDKs and Kubernetes Operator to instead use HTTP/2 +when forwarding to your upstream service. + +| Forwarder | Option | Docs | +| ------------------- | --------------------------------- | ----------------------------------------- | +| Agent | `--upstream-protocol` | [Agent CLI flags](/agent/cli/#ngrok-http) | +| Agent SDKs | language-dependent | [Agent SDKs](/agent-sdks) | +| Kubernetes Operator | `appProtocol` on the `Tunnel` CRD | [Kubernetes Operator](/k8s) | + +When http2 forwarding is enabled, all requests to your upstream service will be +transmitted over HTTP/2 Cleartext since TLS was already terminated at the ngrok +cloud service. We cannot use +[TLS-ALPN](https://httpwg.org/specs/rfc7540.html#TLS-ALPN) at this time. We +rely on [HTTP/2 with Prior +Knowledge](https://httpwg.org/specs/rfc7540.html#known-http) currently. + +### Serving file directories + +The ngrok agent supports the `file://` scheme in a forwarding URL. When you use +the `file://` scheme, the ngrok agent serves local file system directories by +using its own built-in file server, no separate server needed. It works just +like `python3 -m http.server` but it is built directly into the ngrok agent. + +Paths in `file://` URLs must be specified as absolute paths. + +#### Serve files in `/var/log` + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +#### Serve files on Windows + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +#### Serve files in your current working directory + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## TCP + +### Forward to non-local service + +Agents don't just forward to ports on your localhost. You can forward traffic +to any address or URL reachable from the agent. For example, if you want to +forward traffic to a Postgres server running on your network at +`192.168.1.2:5432`: + + + + + + + + + + + + + + + + + + + + + + + + + + + + +### PROXY Protocol + +When you forward traffic to an upstream TCP service, becuase traffic is coming +from the ngrok agent, it won't know the client's original IP address. You can +add the [PROXY +protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) header +on connections to your upstream service to send connection information like the +original client IP address to your upstream service. You will need to configure +your upstream service to handle the PROXY protocol header. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## TLS + +### Re-encrypt to Upstream + +If you terminate TLS at the ngrok cloud service or ngrok agent, you may want to +re-encrypt the connection from the agent to your upstream service. The ngrok +agent supports this behavior by using the non-standard `tls://` scheme syntax. + + + + +```bash +ngrok tls tls://localhost:443 --terminate-at=edge +``` + + + + + + + + + + + + + + + + + + + + + + + + + +### PROXY Protocol + +Add a [PROXY +protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) header +on connection to your upstream service. This sends connection information like +the original client IP address to your upstream service. + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/universal-gateway/domains/what-are-managed-domains.mdx b/docs/universal-gateway/domains/what-are-managed-domains.mdx index b48fd40e88..b16086c1b3 100644 --- a/docs/universal-gateway/domains/what-are-managed-domains.mdx +++ b/docs/universal-gateway/domains/what-are-managed-domains.mdx @@ -53,7 +53,7 @@ ssh -R 443:localhost:80 v2@connect.ngrok-agent.com http - + :::note If your [Agent Config file](/docs/traffic-policy/getting-started/agent-endpoints/config-file) doesn't have hostname specified, and you create an endpoint, the hostname will also be randomly assigned. For example, if your Agent Config file looks like this: diff --git a/src/components/LangSwitcher/ContentSwitcher.tsx b/src/components/LangSwitcher/ContentSwitcher.tsx index a83e2478f4..b0bdf11509 100644 --- a/src/components/LangSwitcher/ContentSwitcher.tsx +++ b/src/components/LangSwitcher/ContentSwitcher.tsx @@ -10,17 +10,21 @@ import LangSwitcherContext from "./LangSwitcherContext"; */ export function ContentSwitcher({ children, - language, + languages, }: { children: React.ReactNode; - language: string; + languages: string[]; className?: string; }) { const { tabLanguage } = useContext(LangSwitcherContext); - if (!language) + if (!languages?.length) throw new Error("Must specify a language for the ContentSwitcher"); - if (language !== tabLanguage) return null; - return children; + for (const lang of languages) { + if (lang === tabLanguage) { + return children; + } + } + return null; } From 5fbd348ae1d64494d1a145cfed03f7fbc3a63b70 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Wed, 2 Apr 2025 14:35:21 -0400 Subject: [PATCH 060/137] non-local forwarding done; LangSwitcher updated --- .../index.mdx} | 204 +----------------- .../agent-forwarding/non-local-forwarding.mdx | 199 +++++++++++++++++ .../serving-file-directories.mdx | 131 +++++++++++ examples/java-sdk/http-basic-auth.mdx | 2 +- examples/java-sdk/http-branded-domain.mdx | 2 +- examples/java-sdk/http-ip-restrictions.mdx | 2 +- examples/java-sdk/http-oauth-byo-app.mdx | 2 +- .../java-sdk/http-oauth-customize-scopes.mdx | 2 +- examples/java-sdk/http-random.mdx | 2 +- examples/java-sdk/http-schemes.mdx | 2 +- examples/java-sdk/http-static-domain.mdx | 2 +- .../java-sdk/http-webhook-verification.mdx | 2 +- .../java-sdk/http-websocket-tcp-converter.mdx | 2 +- examples/java-sdk/http-wildcard-domain.mdx | 2 +- sidebars.js | 11 +- src/components/LangSwitcher/LanguageData.tsx | 29 +++ src/components/LangSwitcher/data.ts | 43 ++++ src/components/LangSwitcher/index.tsx | 79 ++++--- src/components/LangSwitcher/utils.ts | 9 + src/components/code-block.tsx | 33 +-- 20 files changed, 500 insertions(+), 260 deletions(-) rename docs/universal-gateway/{agent-forwarding.mdx => agent-forwarding/index.mdx} (70%) create mode 100644 docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx create mode 100644 docs/universal-gateway/agent-forwarding/serving-file-directories.mdx create mode 100644 src/components/LangSwitcher/LanguageData.tsx create mode 100644 src/components/LangSwitcher/data.ts diff --git a/docs/universal-gateway/agent-forwarding.mdx b/docs/universal-gateway/agent-forwarding/index.mdx similarity index 70% rename from docs/universal-gateway/agent-forwarding.mdx rename to docs/universal-gateway/agent-forwarding/index.mdx index 920956d704..159befcc35 100644 --- a/docs/universal-gateway/agent-forwarding.mdx +++ b/docs/universal-gateway/agent-forwarding/index.mdx @@ -1,5 +1,5 @@ --- -title: How does Agent Forwarding Work? +title: How Does Agent Forwarding Work? --- import TabItem from "@theme/TabItem"; @@ -65,41 +65,12 @@ import HostHeaderRustSdkExample from "/examples/rust-sdk/http-rewrite-host-heade import HostHeaderSshExample from "/examples/ssh/http-rewrite-host-header.mdx"; import NonLocalAgentCliExample from "/examples/agent-cli/http-nonlocal.mdx"; -import NonLocalAgentConfigExample from "/examples/agent-config/http-nonlocal.mdx"; import NonLocalGoSdkExample from "/examples/go-sdk/http-nonlocal.mdx"; import NonLocalJavascriptSdkExample from "/examples/javascript-sdk/http-nonlocal.mdx"; -import NonLocalKubernetesExample from "/examples/k8s/http-nonlocal.mdx"; import NonLocalPythonSdkExample from "/examples/python-sdk/http-nonlocal.mdx"; import NonLocalRustSdkExample from "/examples/rust-sdk/http-nonlocal.mdx"; import NonLocalSshExample from "/examples/ssh/http-nonlocal.mdx"; -import AbsPathFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-abs-path.mdx"; -import AbsPathFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-abs-path.mdx"; -import AbsPathFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverKubernetesExample from "/examples/k8s/http-fileserver-abs-path.mdx"; -import AbsPathFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverSshExample from "/examples/ssh/http-fileserver-abs-path.mdx"; - -import WorkingDirFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverKubernetesExample from "/examples/k8s/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverSshExample from "/examples/ssh/http-fileserver-working-dir.mdx"; - -import WindowsFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-windows.mdx"; -import WindowsFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-windows.mdx"; -import WindowsFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverKubernetesExample from "/examples/k8s/http-fileserver-windows.mdx"; -import WindowsFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverSshExample from "/examples/ssh/http-fileserver-windows.mdx"; - import RandomAgentCliExampleTCP from "/examples/agent-cli/tcp-random.mdx"; import RandomAgentConfigExampleTCP from "/examples/agent-config/tcp-random.mdx"; import RandomGoSdkExampleTCP from "/examples/go-sdk/tcp-random.mdx"; @@ -183,6 +154,10 @@ import ProxyProtoSshExampleTLS from "/examples/ssh/tls-proxyproto.mdx"; The [ngrok agent](/agent/) and [Agent SDKs](/agent-sdks/) forward traffic that your endpoints receive to upstream services. You specify a URL or port number to instruct the ngrok agent where and how to forward traffic. +:::note +This page covers forwarding traffic to upstream resources. If you specifically want to forward traffic from one endpoint to another, [use Traffic Policy](/universal-gateway/chain-endpoints). +::: + ## HTTPS forwarding The scheme in your upstream URL is used to determine whether to forward HTTP or HTTPS traffic to the upstream service. If you do not specify a scheme, the default `http` scheme is chosen _unless_ you forward to port `443`, in which case ngrok will use `https`. Consult the following table of examples. @@ -285,7 +260,7 @@ async fn forward_ngrok() -> Result, Error> { - For HTTP/2 Use: `config.HTTPEndpoint(config.WithAppProtocol("http2"))` +For HTTP/2 Use: `config.HTTPEndpoint(config.WithAppProtocol("http2"))` @@ -297,39 +272,6 @@ Forwarding to an upstream HTTPS service is not supported via SSH. -### Non-local forwarding - -Agents don't just forward to ports on your localhost. You can forward traffic -to any address or URL reachable from the agent. For example, if you want to -forward traffic to a HTTP server running on your network at `192.168.1.2:80`: - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### HTTP/2 forwarding When agents forward to upstream http/2 services, connections use HTTP/1.1 by @@ -351,142 +293,8 @@ cloud service. We cannot use rely on [HTTP/2 with Prior Knowledge](https://httpwg.org/specs/rfc7540.html#known-http) currently. -### Serving file directories - -The ngrok agent supports the `file://` scheme in a forwarding URL. When you use -the `file://` scheme, the ngrok agent serves local file system directories by -using its own built-in file server, no separate server needed. It works just -like `python3 -m http.server` but it is built directly into the ngrok agent. - -Paths in `file://` URLs must be specified as absolute paths. - -#### Serve files in `/var/log` - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -#### Serve files on Windows - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -#### Serve files in your current working directory - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## TCP -### Forward to non-local service - -Agents don't just forward to ports on your localhost. You can forward traffic -to any address or URL reachable from the agent. For example, if you want to -forward traffic to a Postgres server running on your network at -`192.168.1.2:5432`: - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### PROXY Protocol When you forward traffic to an upstream TCP service, becuase traffic is coming diff --git a/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx b/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx new file mode 100644 index 0000000000..464e2a0e52 --- /dev/null +++ b/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx @@ -0,0 +1,199 @@ +--- +title: How Does Non-Local Forwarding Work? +--- + +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; + +import { LangSwitcher } from "@site/src/components/LangSwitcher"; +import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitcher"; + +import NonLocalAgentConfigExample from "/examples/agent-config/http-nonlocal.mdx"; +import NonLocalAgentConfigExampleTCP from "/examples/agent-config/tcp-nonlocal.mdx"; +import NonLocalKubernetesExample from "/examples/k8s/http-nonlocal.mdx"; +import NonLocalKubernetesExampleTCP from "/examples/k8s/tcp-nonlocal.mdx"; + +Aside from ports on your localhost, ngrok Agents can [forward traffic](/universal-gateway/agent-forwarding/) to any address or URL reachable from the agent. + +## HTTP non-local forwarding + +The following example demonstrates how to forward traffic to an HTTP server running on your network at `192.168.1.2:80`: + + + + + ```bash + ngrok http 192.168.1.2:80 + ``` + + ```sh + ssh -R 0:192.168.1.2:80 v2@connect.ngrok-agent.com http + ``` + + ```go + import ( + "context" + "net/url" + + "golang.ngrok.com/ngrok" + "golang.ngrok.com/ngrok/config" + ) + + func ngrokForwarder(ctx context.Context) (ngrok.Forwarder, error) { + backendUrl, err := url.Parse("http://192.168.1.2:80") + if err != nil { + return nil, err + } + + return ngrok.ListenAndForward(ctx, + backendUrl, + config.HTTPEndpoint(), + ngrok.WithAuthtokenFromEnv(), + ) + } + + ``` + + ```jsx + const ngrok = require("@ngrok/ngrok"); + + (async function () { + const listener = await ngrok.forward({ + addr: "192.168.1.2:80", + authtoken_from_env: true, + }); + + console.log(`Ingress established at: ${listener.url()}`); + })(); + ``` + + ```python + import ngrok + + listener = ngrok.forward("192.168.1.2:80", authtoken_from_env=True) + + print(f"Ingress established at: {listener.url()}"); + ``` + + ```rust + use ngrok::prelude::*; + use ngrok::tunnel; + use ngrok::forwarder::Forwarder; + use url::Url; + + async fn forward_ngrok() -> Result, Error> { + let sess = ngrok::Session::builder() + .authtoken_from_env() + .connect() + .await?; + sess + .http_endpoint() + .listen_and_forward(Url::parse("http://192.168.1.2:80")?) + .await + .map_err(Into::into) + } + ``` + + + + + + + + + + + + +## TCP non-local forwarding + +The following example demonstrates how to forward traffic to a Postgres server running on your network at `192.168.1.2:5432`: + + + + + +```bash +ngrok tcp 192.168.1.2:5432 +``` + +```sh +ssh -R 0:192.168.1.2:5432 v2@connect.ngrok-agent.com tcp +``` + +```go +import ( + "context" + "net/url" + + "golang.ngrok.com/ngrok" + "golang.ngrok.com/ngrok/config" +) + +func ngrokForwarder(ctx context.Context) (ngrok.Forwarder, error) { + backendUrl, err := url.Parse("tcp://192.168.1.2:80") + if err != nil { + return nil, err + } + + return ngrok.ListenAndForward(ctx, + backendUrl, + config.TCPEndpoint(), + ngrok.WithAuthtokenFromEnv(), + ) +} +``` + +```jsx +const ngrok = require("@ngrok/ngrok"); + +(async function () { + const listener = await ngrok.forward({ + addr: "192.168.1.2:5432", + authtoken_from_env: true, + proto: "tcp", + }); + + console.log(`Ingress established at: ${listener.url()}`); +})(); +``` + +```python +import ngrok + +listener = ngrok.forward("192.168.1.2:5432", authtoken_from_env=True, + proto="tcp") + +print(f"Ingress established at: {listener.url()}"); +``` + +```rust +use ngrok::prelude::*; +use ngrok::tunnel; +use ngrok::forwarder::Forwarder; +use url::Url; + +async fn forward_ngrok() -> Result, Error> { + let sess = ngrok::Session::builder() + .authtoken_from_env() + .connect() + .await?; + sess + .tcp_endpoint() + .listen_and_forward(Url::parse("tcp://127.0.0.1:8090")?) + .await + .map_err(Into::into) +} +``` + + + + + + + + + + + + diff --git a/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx b/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx new file mode 100644 index 0000000000..aa9cbbf283 --- /dev/null +++ b/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx @@ -0,0 +1,131 @@ +--- +title: How Do I Serve File Directories? +--- + +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; + +import { LangSwitcher } from "@site/src/components/LangSwitcher"; +import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitcher"; + +import AbsPathFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-abs-path.mdx"; +import AbsPathFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-abs-path.mdx"; +import AbsPathFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-abs-path.mdx"; +import AbsPathFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-abs-path.mdx"; +import AbsPathFileserverKubernetesExample from "/examples/k8s/http-fileserver-abs-path.mdx"; +import AbsPathFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-abs-path.mdx"; +import AbsPathFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-abs-path.mdx"; +import AbsPathFileserverSshExample from "/examples/ssh/http-fileserver-abs-path.mdx"; + +import WorkingDirFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverKubernetesExample from "/examples/k8s/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-working-dir.mdx"; +import WorkingDirFileserverSshExample from "/examples/ssh/http-fileserver-working-dir.mdx"; + +import WindowsFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-windows.mdx"; +import WindowsFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-windows.mdx"; +import WindowsFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-windows.mdx"; +import WindowsFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-windows.mdx"; +import WindowsFileserverKubernetesExample from "/examples/k8s/http-fileserver-windows.mdx"; +import WindowsFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-windows.mdx"; +import WindowsFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-windows.mdx"; +import WindowsFileserverSshExample from "/examples/ssh/http-fileserver-windows.mdx"; + +The ngrok agent supports the `file://` scheme in [a forwarding URL](/universal-gateway/agent-forwarding/). When you use the `file://` scheme, the ngrok agent serves local file system directories by using its own built-in file server, no separate server needed. It works just like `python3 -m http.server` but it is built directly into the ngrok agent. + +Paths in `file://` URLs must be specified as absolute paths. + +#### Serve files in `/var/log` + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +#### Serve files on Windows + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +#### Serve files in your current working directory + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/java-sdk/http-basic-auth.mdx b/examples/java-sdk/http-basic-auth.mdx index 40653da781..4473e0dd3c 100644 --- a/examples/java-sdk/http-basic-auth.mdx +++ b/examples/java-sdk/http-basic-auth.mdx @@ -28,4 +28,4 @@ public class Quickstart { ``` -Java SDK Docs: +Java SDK Docs: https://github.com/ngrok/ngrok-java diff --git a/examples/java-sdk/http-branded-domain.mdx b/examples/java-sdk/http-branded-domain.mdx index 3a80bd0fb4..d7162a769d 100644 --- a/examples/java-sdk/http-branded-domain.mdx +++ b/examples/java-sdk/http-branded-domain.mdx @@ -21,4 +21,4 @@ public class Quickstart { ``` -Java SDK Docs: +Java SDK Docs: https://github.com/ngrok/ngrok-java diff --git a/examples/java-sdk/http-ip-restrictions.mdx b/examples/java-sdk/http-ip-restrictions.mdx index 05f4ab17cc..45272a2339 100644 --- a/examples/java-sdk/http-ip-restrictions.mdx +++ b/examples/java-sdk/http-ip-restrictions.mdx @@ -39,4 +39,4 @@ public class Quickstart { ``` -Java SDK Docs: +Java SDK Docs: https://github.com/ngrok/ngrok-java diff --git a/examples/java-sdk/http-oauth-byo-app.mdx b/examples/java-sdk/http-oauth-byo-app.mdx index 80381e1047..52d9e6312d 100644 --- a/examples/java-sdk/http-oauth-byo-app.mdx +++ b/examples/java-sdk/http-oauth-byo-app.mdx @@ -40,4 +40,4 @@ public class Quickstart { ``` -Java SDK Docs: +Java SDK Docs: https://github.com/ngrok/ngrok-java diff --git a/examples/java-sdk/http-oauth-customize-scopes.mdx b/examples/java-sdk/http-oauth-customize-scopes.mdx index e1284ef442..fa9e638739 100644 --- a/examples/java-sdk/http-oauth-customize-scopes.mdx +++ b/examples/java-sdk/http-oauth-customize-scopes.mdx @@ -24,4 +24,4 @@ public class Quickstart { ``` -Java SDK Docs: +Java SDK Docs: https://github.com/ngrok/ngrok-java diff --git a/examples/java-sdk/http-random.mdx b/examples/java-sdk/http-random.mdx index 0df30a12c5..ad95e0bf10 100644 --- a/examples/java-sdk/http-random.mdx +++ b/examples/java-sdk/http-random.mdx @@ -20,4 +20,4 @@ public class Quickstart { ``` -Java SDK Docs: +Java SDK Docs: https://github.com/ngrok/ngrok-java diff --git a/examples/java-sdk/http-schemes.mdx b/examples/java-sdk/http-schemes.mdx index 63168f90db..b72c3719e3 100644 --- a/examples/java-sdk/http-schemes.mdx +++ b/examples/java-sdk/http-schemes.mdx @@ -20,4 +20,4 @@ public class Quickstart { ``` -Java SDK Docs: +Java SDK Docs: https://github.com/ngrok/ngrok-java diff --git a/examples/java-sdk/http-static-domain.mdx b/examples/java-sdk/http-static-domain.mdx index 3a80bd0fb4..d7162a769d 100644 --- a/examples/java-sdk/http-static-domain.mdx +++ b/examples/java-sdk/http-static-domain.mdx @@ -21,4 +21,4 @@ public class Quickstart { ``` -Java SDK Docs: +Java SDK Docs: https://github.com/ngrok/ngrok-java diff --git a/examples/java-sdk/http-webhook-verification.mdx b/examples/java-sdk/http-webhook-verification.mdx index 2c307143fa..6611ee0ec4 100644 --- a/examples/java-sdk/http-webhook-verification.mdx +++ b/examples/java-sdk/http-webhook-verification.mdx @@ -38,4 +38,4 @@ public class Quickstart { ``` -Java SDK Docs: +Java SDK Docs: https://github.com/ngrok/ngrok-java diff --git a/examples/java-sdk/http-websocket-tcp-converter.mdx b/examples/java-sdk/http-websocket-tcp-converter.mdx index 84e68a7df4..08d643bd03 100644 --- a/examples/java-sdk/http-websocket-tcp-converter.mdx +++ b/examples/java-sdk/http-websocket-tcp-converter.mdx @@ -34,4 +34,4 @@ public class Quickstart { ``` -Java SDK Docs: +Java SDK Docs: https://github.com/ngrok/ngrok-java diff --git a/examples/java-sdk/http-wildcard-domain.mdx b/examples/java-sdk/http-wildcard-domain.mdx index c5c2d8463e..edf7a55577 100644 --- a/examples/java-sdk/http-wildcard-domain.mdx +++ b/examples/java-sdk/http-wildcard-domain.mdx @@ -21,4 +21,4 @@ public class Quickstart { ``` -Java SDK Docs: +Java SDK Docs: https://github.com/ngrok/ngrok-java diff --git a/sidebars.js b/sidebars.js index ba6bdd601c..ccce9ca23b 100644 --- a/sidebars.js +++ b/sidebars.js @@ -125,8 +125,15 @@ const sidebars = { "universal-gateway/chain-endpoints", "universal-gateway/mock-api", "universal-gateway/migrate-from-tunnels", - "universal-gateway/agent-forwarding", - + { + label: "How Does Agent Fowarding Work?", + type: "category", + link: { type: "doc", id: "universal-gateway/agent-forwarding/index" }, + items: [ + "universal-gateway/agent-forwarding/non-local-forwarding", + "universal-gateway/agent-forwarding/serving-file-directories", + ], + }, { label: "How Do I Handle HTTP/S Traffic?", type: "category", diff --git a/src/components/LangSwitcher/LanguageData.tsx b/src/components/LangSwitcher/LanguageData.tsx new file mode 100644 index 0000000000..6c0ba23627 --- /dev/null +++ b/src/components/LangSwitcher/LanguageData.tsx @@ -0,0 +1,29 @@ +import type { LanguageData } from "./data"; + +export function LanguageData({ data }: { data: LanguageData }) { + let anchoredLinks = data.links.map((link) => { + return ( + + here + + ); + }); + + const linkText = anchoredLinks.reduce((prev, curr, index): any => { + if (index === 0) { + return [prev, curr]; + } else if (index === data.links.length - 1) { + return [prev, ", and ", curr]; + } else { + return [prev, ", ", curr]; + } + }); + + return ( +
+
+ See the ngrok {data.displayName} package docs {linkText}. +
+
+ ); +} diff --git a/src/components/LangSwitcher/data.ts b/src/components/LangSwitcher/data.ts new file mode 100644 index 0000000000..83d1f853cb --- /dev/null +++ b/src/components/LangSwitcher/data.ts @@ -0,0 +1,43 @@ +export type LanguageData = { + name: string; + altNames?: string[]; + displayName: string; + links: string[]; +}; + +export const languageData: LanguageData[] = [ + { + name: "go", + displayName: "Go", + links: ["https://pkg.go.dev/golang.ngrok.com/ngrok#ListenAndForward"], + }, + { + name: "rust", + displayName: "Rust", + links: [ + "https://docs.rs/ngrok/0.14.0-pre.13/ngrok/config/struct.TcpTunnelBuilder.html#method.listen_and_forward", + ], + }, + { + name: "python", + displayName: "Python", + links: [ + "https://ngrok.github.io/ngrok-python/tcp_listener_builder.html#ngrok.TcpListenerBuilder.remote_addr", + "https://ngrok.github.io/ngrok-python/index.html#full-configuration", + ], + }, + { + name: "java", + displayName: "Java", + links: ["https://github.com/ngrok/ngrok-java"], + }, + { + name: "javascript", + displayName: "JavaScript", + links: [ + "https://ngrok.github.io/ngrok-javascript/interfaces/Config.html#addr", + "https://ngrok.github.io/ngrok-javascript/classes/TcpListenerBuilder.html#listenAndForward", + ], + altNames: ["typescript", "ts", "js", "jsx", "tsx"], + }, +]; diff --git a/src/components/LangSwitcher/index.tsx b/src/components/LangSwitcher/index.tsx index 52d421f1b5..fa2fad68f4 100644 --- a/src/components/LangSwitcher/index.tsx +++ b/src/components/LangSwitcher/index.tsx @@ -11,11 +11,13 @@ import { fmtCode, } from "@ngrok/mantle/code-block"; import clsx from "clsx"; +import convertToSpaces from "convert-to-spaces"; import { useContext } from "react"; import { CodeBlockFallback } from "../code-block"; import LangSwitcherContext, { type LangSwitcherContextType, } from "./LangSwitcherContext"; +import { LanguageData } from "./LanguageData"; import { getCodeBlocks } from "./utils"; export function LangSwitcher({ children, className, ...props }: any) { @@ -40,10 +42,14 @@ export function LangSwitcher({ children, className, ...props }: any) { codeBlocks.find((child: any) => child.language === tabLanguage) || codeBlocks[0]; // This also needs to be updated to use the right codeblock data, not [0] - const { meta } = matchingBlock; + const { meta, info } = matchingBlock; const collapsible = meta.collapsible && matchingBlock.content.split("\n").length > 10; + const codeblockContent = convertToSpaces( + fmtCode`${matchingBlock.content.toString()}`, + ); + return ( {() => ( - - -
- {codeBlocks.map((child: any) => ( - - ))} -
-
- - {meta.title && ( - - {meta.title} - - )} - {!meta.disableCopy && } - - {collapsible && } - -
+
+ + +
+ {codeBlocks.map((child: any) => ( + + ))} +
+
+ + {meta.title && ( + + {meta.title} + + )} + {!meta.disableCopy && } + + {collapsible && } + +
+ {info && } +
)}
); diff --git a/src/components/LangSwitcher/utils.ts b/src/components/LangSwitcher/utils.ts index 2eac1fdfeb..b6906722ed 100644 --- a/src/components/LangSwitcher/utils.ts +++ b/src/components/LangSwitcher/utils.ts @@ -1,4 +1,5 @@ import { parseLanguage, parseMetastring } from "@ngrok/mantle/code-block"; +import { languageData } from "./data"; export const getCodeBlocks = (children: any) => { return children.map((child: any, index: number) => { @@ -17,10 +18,18 @@ export const getCodeBlocks = (children: any) => { }, title, childIndex: index, + info: getLanguageInfo(parsedLanguage), }; }); }; +export const getLanguageInfo = (language: string) => { + return languageData.find( + (item) => + item.name === language || item?.altNames?.some((alt) => alt === language), + ); +}; + // The name of the query param or localstorage item to search for // to get the default tab value export const paramName = "defaultTabLang"; diff --git a/src/components/code-block.tsx b/src/components/code-block.tsx index c53c6456ec..855df011d6 100644 --- a/src/components/code-block.tsx +++ b/src/components/code-block.tsx @@ -15,6 +15,8 @@ import { import type { WithStyleProps } from "@ngrok/mantle/types"; import convertToSpaces from "convert-to-spaces"; import type { ComponentProps, ReactNode } from "react"; +import { LanguageData } from "./LangSwitcher/LanguageData"; +import { getLanguageInfo } from "./LangSwitcher/utils"; type Props = WithStyleProps & { /** @@ -74,21 +76,24 @@ function DocsCodeBlock({ const collapsible = meta.collapsible && children.split("\n").length > 20; const codeblockContent = convertToSpaces(fmtCode`${children}`); - + const info = getLanguageInfo(language); return ( - - {hasHeader && ( - - {mode ? : _icon} - {title && {title}} - - )} - - {!meta.disableCopy && } - - {collapsible && } - - +
+ + {hasHeader && ( + + {mode ? : _icon} + {title && {title}} + + )} + + {!meta.disableCopy && } + + {collapsible && } + + + {info && } +
); } From 4b55637998e71ba4a3c2a7259b6757d53dfabd1a Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Wed, 2 Apr 2025 14:58:27 -0400 Subject: [PATCH 061/137] Serving file directories done --- .../serving-file-directories.mdx | 230 ++++++++++-------- 1 file changed, 125 insertions(+), 105 deletions(-) diff --git a/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx b/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx index aa9cbbf283..7a239b0bc4 100644 --- a/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx +++ b/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx @@ -6,126 +6,146 @@ import TabItem from "@theme/TabItem"; import Tabs from "@theme/Tabs"; import { LangSwitcher } from "@site/src/components/LangSwitcher"; -import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitcher"; - -import AbsPathFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-abs-path.mdx"; -import AbsPathFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-abs-path.mdx"; -import AbsPathFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverKubernetesExample from "/examples/k8s/http-fileserver-abs-path.mdx"; -import AbsPathFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverSshExample from "/examples/ssh/http-fileserver-abs-path.mdx"; - -import WorkingDirFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverKubernetesExample from "/examples/k8s/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverSshExample from "/examples/ssh/http-fileserver-working-dir.mdx"; - -import WindowsFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-windows.mdx"; -import WindowsFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-windows.mdx"; -import WindowsFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverKubernetesExample from "/examples/k8s/http-fileserver-windows.mdx"; -import WindowsFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverSshExample from "/examples/ssh/http-fileserver-windows.mdx"; The ngrok agent supports the `file://` scheme in [a forwarding URL](/universal-gateway/agent-forwarding/). When you use the `file://` scheme, the ngrok agent serves local file system directories by using its own built-in file server, no separate server needed. It works just like `python3 -m http.server` but it is built directly into the ngrok agent. Paths in `file://` URLs must be specified as absolute paths. +:::info + +Serving directory files is not supported with: + +- SSH +- JavaScript +- Python +- Rust +- Kubernetes Operator + ::: + #### Serve files in `/var/log` - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + ```bash + ngrok http "file:///var/log" + ``` -
+ ```go + import ( + "context" + "net" + + "golang.ngrok.com/ngrok" + "golang.ngrok.com/ngrok/config" + ) + + func serveFiles(ctx context.Context) error { + l, _ := ngrok.Listen(ctx, + config.HTTPEndpoint(), + ngrok.WithAuthtokenFromEnv(), + ) + http.Serve(l, http.FileServer(http.Dir("/var/log"))) + } + ``` + +
+ +
+ + +```yaml +version: 3 +endpoints: + - name: example + url: "https://example.ngrok.app" + upstream: + url: "file:///var/log" +``` + + + +
#### Serve files on Windows - - - - - - - - - - - - - - - - - - - - - - - - - + + + + +```bash +ngrok http "file://C:\Users\alan\Directory Name" +``` + +```go +import ( + "context" + "net" + + "golang.ngrok.com/ngrok" + "golang.ngrok.com/ngrok/config" +) + +func serveFiles(ctx context.Context) error { + l, _ := ngrok.Listen(ctx, + config.HTTPEndpoint(), + ngrok.WithAuthtokenFromEnv(), + ) + http.Serve(l, http.FileServer(http.Dir("C:\Users\alan\Directory Name"))) +} +``` + + + + + + +```yaml +version: 3 +endpoints: + - name: example + url: "https://example.ngrok.app" + upstream: + url: "file://C:\Users\alan\Directory Name" +``` + + +
#### Serve files in your current working directory - - - - - - - - - - - - - - - - - - - - - - - - - + + + +```bash +ngrok http file://`pwd` +``` + +```go +import ( + "context" + "net" + + "golang.ngrok.com/ngrok" + "golang.ngrok.com/ngrok/config" +) + +func serveFiles(ctx context.Context) error { + l, _ := ngrok.Listen(ctx, + config.HTTPEndpoint(), + ngrok.WithAuthtokenFromEnv(), + ) + http.Serve(l, http.FileServer(http.Dir("."))) +} +``` + + + + + Serving the current working directory is not supported via the agent configuration file. + + From ad44627643042d4f5f011ebf165d2856abb5689f Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 3 Apr 2025 11:15:51 -0400 Subject: [PATCH 062/137] Swizzle tabs --- .../forward-original-connection-data.mdx | 74 +++++++++ .../agent-forwarding/index.mdx | 136 +++++---------- src/theme/Tabs/index.tsx | 157 ++++++++++++++++++ src/theme/Tabs/styles.module.css | 7 + 4 files changed, 279 insertions(+), 95 deletions(-) create mode 100644 docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx create mode 100644 src/theme/Tabs/index.tsx create mode 100644 src/theme/Tabs/styles.module.css diff --git a/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx b/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx new file mode 100644 index 0000000000..aab5a49c74 --- /dev/null +++ b/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx @@ -0,0 +1,74 @@ +--- +title: How Do I Forward Original Connection Data? +--- + +### TCP + +When you forward traffic to an upstream TCP service, becuase traffic is coming +from the ngrok agent, it won't know the client's original IP address. You can +add the [PROXY +protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) header +on connections to your upstream service to send connection information like the +original client IP address to your upstream service. You will need to configure +your upstream service to handle the PROXY protocol header. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +### TLS + +Add a [PROXY +protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) header +on connection to your upstream service. This sends connection information like +the original client IP address to your upstream service. + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/universal-gateway/agent-forwarding/index.mdx b/docs/universal-gateway/agent-forwarding/index.mdx index 159befcc35..44ea29e2ae 100644 --- a/docs/universal-gateway/agent-forwarding/index.mdx +++ b/docs/universal-gateway/agent-forwarding/index.mdx @@ -173,6 +173,10 @@ The scheme in your upstream URL is used to determine whether to forward HTTP or ngrok assumes that the network you run the agent on is private and it does not verify the TLS certificate presented by the upstream service. You may change this behavior with the [flags `--upstream-tls-verify` and `upstream-tls-verify-cas`](/agent/cli/#ngrok-http). +:::info +Forwarding to an upstream HTTPS service is not supported via SSH. +::: + @@ -260,14 +264,8 @@ async fn forward_ngrok() -> Result, Error> { +:::note For HTTP/2 Use: `config.HTTPEndpoint(config.WithAppProtocol("http2"))` - - - - - -:::info -Forwarding to an upstream HTTPS service is not supported via SSH. ::: @@ -293,69 +291,41 @@ cloud service. We cannot use rely on [HTTP/2 with Prior Knowledge](https://httpwg.org/specs/rfc7540.html#known-http) currently. -## TCP - -### PROXY Protocol - -When you forward traffic to an upstream TCP service, becuase traffic is coming -from the ngrok agent, it won't know the client's original IP address. You can -add the [PROXY -protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) header -on connections to your upstream service to send connection information like the -original client IP address to your upstream service. You will need to configure -your upstream service to handle the PROXY protocol header. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -## TLS - -### Re-encrypt to Upstream +### How do I encrypt traffic forwarded to upstream services? If you terminate TLS at the ngrok cloud service or ngrok agent, you may want to re-encrypt the connection from the agent to your upstream service. The ngrok agent supports this behavior by using the non-standard `tls://` scheme syntax. - - + + + ```bash ngrok tls tls://localhost:443 --terminate-at=edge ``` - - - - - - - - - +```python +import ngrok + +listener = ngrok.forward("tls://localhost:443", authtoken_from_env=True, + proto="tls" + crt=bytearray(), + key=bytearray()) + +print(f"Ingress established at: {listener.url()}"); +``` + + + + + An empty certificate and key will default to the ngrok edge's automatically + provisioned keypair. The upstream certificate of `localhost:443` will be + validated by a filepath specified in the `SSL_CERT_FILE` environment variable + (e.g. `SSL_CERT_FILE=/path/to/ca.crt`), or falling back to the host OS + installed trusted certificate authorities. + + @@ -363,44 +333,20 @@ ngrok tls tls://localhost:443 --terminate-at=edge - - + + -### PROXY Protocol - -Add a [PROXY -protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) header -on connection to your upstream service. This sends connection information like -the original client IP address to your upstream service. - - - - - - - - - - - - - - - - - - - - - - - - - - - +:::info + +Re-encrypting the connection to your upstream service with TLS is not supported for: + +- SSH +- Go +- Rust + +::: diff --git a/src/theme/Tabs/index.tsx b/src/theme/Tabs/index.tsx new file mode 100644 index 0000000000..d1663745bc --- /dev/null +++ b/src/theme/Tabs/index.tsx @@ -0,0 +1,157 @@ +import React, {cloneElement, type ReactElement, type ReactNode} from 'react'; +import clsx from 'clsx'; +import { + useScrollPositionBlocker, + useTabs, + sanitizeTabsChildren, + type TabItemProps, +} from '@docusaurus/theme-common/internal'; +import useIsBrowser from '@docusaurus/useIsBrowser'; +import type {Props} from '@theme/Tabs'; +import styles from './styles.module.css'; + +function TabList({ + className, + block, + selectedValue, + selectValue, + tabValues, +}: Props & ReturnType) { + const tabRefs: (HTMLLIElement | null)[] = []; + const {blockElementScrollPositionUntilNextRender} = + useScrollPositionBlocker(); + + const handleTabChange = ( + event: + | React.FocusEvent + | React.MouseEvent + | React.KeyboardEvent, + ) => { + const newTab = event.currentTarget; + const newTabIndex = tabRefs.indexOf(newTab); + const newTabValue = tabValues[newTabIndex]!.value; + + if (newTabValue !== selectedValue) { + blockElementScrollPositionUntilNextRender(newTab); + selectValue(newTabValue); + } + }; + + const handleKeydown = (event: React.KeyboardEvent) => { + let focusElement: HTMLLIElement | null = null; + + switch (event.key) { + case 'Enter': { + handleTabChange(event); + break; + } + case 'ArrowRight': { + const nextTab = tabRefs.indexOf(event.currentTarget) + 1; + focusElement = tabRefs[nextTab] ?? tabRefs[0]!; + break; + } + case 'ArrowLeft': { + const prevTab = tabRefs.indexOf(event.currentTarget) - 1; + focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1]!; + break; + } + default: + break; + } + + focusElement?.focus(); + }; + + return ( +
    + {tabValues.map(({value, label, attributes}) => ( +
  • { + tabRefs.push(tabControl); + }} + onKeyDown={handleKeydown} + onClick={handleTabChange} + {...attributes} + className={clsx( + 'tabs__item', + styles.tabItem, + attributes?.className as string, + { + 'tabs__item--active': selectedValue === value, + }, + )}> + {label ?? value} +
  • + ))} +
+ ); +} + +function TabContent({ + lazy, + children, + selectedValue, +}: Props & ReturnType) { + const childTabs = (Array.isArray(children) ? children : [children]).filter( + Boolean, + ) as ReactElement[]; + if (lazy) { + const selectedTabItem = childTabs.find( + (tabItem) => tabItem.props.value === selectedValue, + ); + if (!selectedTabItem) { + // fail-safe or fail-fast? not sure what's best here + return null; + } + return cloneElement(selectedTabItem, { + className: clsx('margin-top--md', selectedTabItem.props.className), + }); + } + return ( +
+ {childTabs.map((tabItem, i) => + cloneElement(tabItem, { + key: i, + hidden: tabItem.props.value !== selectedValue, + }), + )} +
+ ); +} + +function TabsComponent(props: Props): ReactNode { + const tabs = useTabs(props); + return ( +
+ + +
+ ); +} + +export default function Tabs(props: Props): ReactNode { + const isBrowser = useIsBrowser(); + return ( + + {sanitizeTabsChildren(props.children)} + + ); +} diff --git a/src/theme/Tabs/styles.module.css b/src/theme/Tabs/styles.module.css new file mode 100644 index 0000000000..0c79270e70 --- /dev/null +++ b/src/theme/Tabs/styles.module.css @@ -0,0 +1,7 @@ +.tabList { + margin-bottom: var(--ifm-leading); +} + +.tabItem { + margin-top: 0 !important; +} From 180731c0709752e075354b29c4d00090c2c941db Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 3 Apr 2025 15:16:44 +0000 Subject: [PATCH 063/137] ci: apply automated fixes --- src/theme/Tabs/index.tsx | 275 ++++++++++++++++--------------- src/theme/Tabs/styles.module.css | 4 +- 2 files changed, 141 insertions(+), 138 deletions(-) diff --git a/src/theme/Tabs/index.tsx b/src/theme/Tabs/index.tsx index d1663745bc..e07ec4470c 100644 --- a/src/theme/Tabs/index.tsx +++ b/src/theme/Tabs/index.tsx @@ -1,157 +1,160 @@ -import React, {cloneElement, type ReactElement, type ReactNode} from 'react'; -import clsx from 'clsx'; import { - useScrollPositionBlocker, - useTabs, - sanitizeTabsChildren, - type TabItemProps, -} from '@docusaurus/theme-common/internal'; -import useIsBrowser from '@docusaurus/useIsBrowser'; -import type {Props} from '@theme/Tabs'; -import styles from './styles.module.css'; + sanitizeTabsChildren, + useScrollPositionBlocker, + useTabs, + type TabItemProps, +} from "@docusaurus/theme-common/internal"; +import useIsBrowser from "@docusaurus/useIsBrowser"; +import type { Props } from "@theme/Tabs"; +import clsx from "clsx"; +import React, { cloneElement, type ReactElement, type ReactNode } from "react"; +import styles from "./styles.module.css"; function TabList({ - className, - block, - selectedValue, - selectValue, - tabValues, + className, + block, + selectedValue, + selectValue, + tabValues, }: Props & ReturnType) { - const tabRefs: (HTMLLIElement | null)[] = []; - const {blockElementScrollPositionUntilNextRender} = - useScrollPositionBlocker(); + const tabRefs: (HTMLLIElement | null)[] = []; + const { blockElementScrollPositionUntilNextRender } = + useScrollPositionBlocker(); - const handleTabChange = ( - event: - | React.FocusEvent - | React.MouseEvent - | React.KeyboardEvent, - ) => { - const newTab = event.currentTarget; - const newTabIndex = tabRefs.indexOf(newTab); - const newTabValue = tabValues[newTabIndex]!.value; + const handleTabChange = ( + event: + | React.FocusEvent + | React.MouseEvent + | React.KeyboardEvent, + ) => { + const newTab = event.currentTarget; + const newTabIndex = tabRefs.indexOf(newTab); + const newTabValue = tabValues[newTabIndex]!.value; - if (newTabValue !== selectedValue) { - blockElementScrollPositionUntilNextRender(newTab); - selectValue(newTabValue); - } - }; + if (newTabValue !== selectedValue) { + blockElementScrollPositionUntilNextRender(newTab); + selectValue(newTabValue); + } + }; - const handleKeydown = (event: React.KeyboardEvent) => { - let focusElement: HTMLLIElement | null = null; + const handleKeydown = (event: React.KeyboardEvent) => { + let focusElement: HTMLLIElement | null = null; - switch (event.key) { - case 'Enter': { - handleTabChange(event); - break; - } - case 'ArrowRight': { - const nextTab = tabRefs.indexOf(event.currentTarget) + 1; - focusElement = tabRefs[nextTab] ?? tabRefs[0]!; - break; - } - case 'ArrowLeft': { - const prevTab = tabRefs.indexOf(event.currentTarget) - 1; - focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1]!; - break; - } - default: - break; - } + switch (event.key) { + case "Enter": { + handleTabChange(event); + break; + } + case "ArrowRight": { + const nextTab = tabRefs.indexOf(event.currentTarget) + 1; + focusElement = tabRefs[nextTab] ?? tabRefs[0]!; + break; + } + case "ArrowLeft": { + const prevTab = tabRefs.indexOf(event.currentTarget) - 1; + focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1]!; + break; + } + default: + break; + } - focusElement?.focus(); - }; + focusElement?.focus(); + }; - return ( -
    - {tabValues.map(({value, label, attributes}) => ( -
  • { - tabRefs.push(tabControl); - }} - onKeyDown={handleKeydown} - onClick={handleTabChange} - {...attributes} - className={clsx( - 'tabs__item', - styles.tabItem, - attributes?.className as string, - { - 'tabs__item--active': selectedValue === value, - }, - )}> - {label ?? value} -
  • - ))} -
- ); + return ( +
    + {tabValues.map(({ value, label, attributes }) => ( +
  • { + tabRefs.push(tabControl); + }} + onKeyDown={handleKeydown} + onClick={handleTabChange} + {...attributes} + className={clsx( + "tabs__item", + styles.tabItem, + attributes?.className as string, + { + "tabs__item--active": selectedValue === value, + }, + )} + > + {label ?? value} +
  • + ))} +
+ ); } function TabContent({ - lazy, - children, - selectedValue, + lazy, + children, + selectedValue, }: Props & ReturnType) { - const childTabs = (Array.isArray(children) ? children : [children]).filter( - Boolean, - ) as ReactElement[]; - if (lazy) { - const selectedTabItem = childTabs.find( - (tabItem) => tabItem.props.value === selectedValue, - ); - if (!selectedTabItem) { - // fail-safe or fail-fast? not sure what's best here - return null; - } - return cloneElement(selectedTabItem, { - className: clsx('margin-top--md', selectedTabItem.props.className), - }); - } - return ( -
- {childTabs.map((tabItem, i) => - cloneElement(tabItem, { - key: i, - hidden: tabItem.props.value !== selectedValue, - }), - )} -
- ); + const childTabs = (Array.isArray(children) ? children : [children]).filter( + Boolean, + ) as ReactElement[]; + if (lazy) { + const selectedTabItem = childTabs.find( + (tabItem) => tabItem.props.value === selectedValue, + ); + if (!selectedTabItem) { + // fail-safe or fail-fast? not sure what's best here + return null; + } + return cloneElement(selectedTabItem, { + className: clsx("margin-top--md", selectedTabItem.props.className), + }); + } + return ( +
+ {childTabs.map((tabItem, i) => + cloneElement(tabItem, { + key: i, + hidden: tabItem.props.value !== selectedValue, + }), + )} +
+ ); } function TabsComponent(props: Props): ReactNode { - const tabs = useTabs(props); - return ( -
- - -
- ); + const tabs = useTabs(props); + return ( +
+ + +
+ ); } export default function Tabs(props: Props): ReactNode { - const isBrowser = useIsBrowser(); - return ( - - {sanitizeTabsChildren(props.children)} - - ); + const isBrowser = useIsBrowser(); + return ( + + {sanitizeTabsChildren(props.children)} + + ); } diff --git a/src/theme/Tabs/styles.module.css b/src/theme/Tabs/styles.module.css index 0c79270e70..6619bf14e3 100644 --- a/src/theme/Tabs/styles.module.css +++ b/src/theme/Tabs/styles.module.css @@ -1,7 +1,7 @@ .tabList { - margin-bottom: var(--ifm-leading); + margin-bottom: var(--ifm-leading); } .tabItem { - margin-top: 0 !important; + margin-top: 0 !important; } From d221958b4cbc57f9012ae3208edfddb22a80119d Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 3 Apr 2025 13:17:10 -0400 Subject: [PATCH 064/137] Synced tab switchers work in a basic way; needs cleanup --- .../LangSwitcher/ContentSwitcher.tsx | 4 +- .../LangSwitcher/LangSwitcherContext.tsx | 10 +- src/components/LangSwitcher/index.tsx | 12 +- src/components/LangSwitcher/utils.ts | 23 +- src/theme/DocItem/Content/index.tsx | 41 ++- src/theme/Tabs/TabListContext.tsx | 11 + src/theme/Tabs/index.tsx | 273 +++++++++--------- 7 files changed, 206 insertions(+), 168 deletions(-) create mode 100644 src/theme/Tabs/TabListContext.tsx diff --git a/src/components/LangSwitcher/ContentSwitcher.tsx b/src/components/LangSwitcher/ContentSwitcher.tsx index b0bdf11509..b2ffe71f9d 100644 --- a/src/components/LangSwitcher/ContentSwitcher.tsx +++ b/src/components/LangSwitcher/ContentSwitcher.tsx @@ -16,13 +16,13 @@ export function ContentSwitcher({ languages: string[]; className?: string; }) { - const { tabLanguage } = + const { selectedLanguage } = useContext(LangSwitcherContext); if (!languages?.length) throw new Error("Must specify a language for the ContentSwitcher"); for (const lang of languages) { - if (lang === tabLanguage) { + if (lang === selectedLanguage) { return children; } } diff --git a/src/components/LangSwitcher/LangSwitcherContext.tsx b/src/components/LangSwitcher/LangSwitcherContext.tsx index 03d524c722..02196f3c6e 100644 --- a/src/components/LangSwitcher/LangSwitcherContext.tsx +++ b/src/components/LangSwitcher/LangSwitcherContext.tsx @@ -2,14 +2,16 @@ import type { SupportedLanguage } from "@ngrok/mantle/code-block"; import { createContext } from "react"; export type LangSwitcherContextType = { - tabLanguage: string | SupportedLanguage | null; + selectedLanguage: string | SupportedLanguage | null; defaultLanguage: string | null; - updateTab: null | ((newLang: string | SupportedLanguage) => void); + updateSelectedLanguage: + | null + | ((newLang: string | SupportedLanguage) => void); }; const LangSwitcherContext = createContext({ - tabLanguage: "", - updateTab: null, + selectedLanguage: "", + updateSelectedLanguage: null, defaultLanguage: null, }); diff --git a/src/components/LangSwitcher/index.tsx b/src/components/LangSwitcher/index.tsx index fa2fad68f4..5e532a72c9 100644 --- a/src/components/LangSwitcher/index.tsx +++ b/src/components/LangSwitcher/index.tsx @@ -21,25 +21,25 @@ import { LanguageData } from "./LanguageData"; import { getCodeBlocks } from "./utils"; export function LangSwitcher({ children, className, ...props }: any) { - const { defaultLanguage, tabLanguage, updateTab } = + const { defaultLanguage, selectedLanguage, updateSelectedLanguage } = useContext(LangSwitcherContext); const codeBlocks = getCodeBlocks(children); - if (!updateTab) return "Error loading code block"; + if (!updateSelectedLanguage) return "Error loading code block"; // if no language tab is set yet - if (tabLanguage === null) { + if (selectedLanguage === null) { // Check if the user has specified a default language const startingLanguage = codeBlocks.find((child: any) => child.language === defaultLanguage) || codeBlocks[0]; - updateTab(startingLanguage.language); + updateSelectedLanguage(startingLanguage.language); // if no default language is set, set the first tab as the selected tab } const matchingBlock = - codeBlocks.find((child: any) => child.language === tabLanguage) || + codeBlocks.find((child: any) => child.language === selectedLanguage) || codeBlocks[0]; // This also needs to be updated to use the right codeblock data, not [0] const { meta, info } = matchingBlock; @@ -64,7 +64,7 @@ export function LangSwitcher({ children, className, ...props }: any) { {codeBlocks.map((child: any) => ( + {/* {title && {title}} */} + + {meta.title && ( +
+ <> + {meta.mode ? ( + + ) : ( + + )} + + {meta.title} + + +
+ )} {!meta.disableCopy && } {collapsible && } diff --git a/src/theme/Tabs/index.tsx b/src/theme/Tabs/index.tsx index 41f70130d4..24268233bf 100644 --- a/src/theme/Tabs/index.tsx +++ b/src/theme/Tabs/index.tsx @@ -14,12 +14,7 @@ import { } from "@ngrok/mantle/tabs"; import type { Props } from "@theme/Tabs"; import clsx from "clsx"; -import React, { - cloneElement, - useContext, - type ReactElement, - type ReactNode, -} from "react"; +import React, { useContext, type ReactElement, type ReactNode } from "react"; import styles from "./styles.module.css"; import TabListContext from "./TabListContext"; From 6c6f1987eaae1613918782ff81ea7190cd5a10fa Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 4 Apr 2025 12:50:35 -0400 Subject: [PATCH 070/137] Add ability to add custom tab names to switcher --- .../agent-forwarding/non-local-forwarding.mdx | 2 +- src/components/LangSwitcher/data.ts | 14 +++++++ src/components/LangSwitcher/index.tsx | 2 +- src/components/LangSwitcher/utils.ts | 42 ++++++++++++++++--- src/components/code-block.tsx | 3 -- 5 files changed, 52 insertions(+), 11 deletions(-) diff --git a/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx b/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx index 464e2a0e52..12e7f29290 100644 --- a/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx +++ b/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx @@ -167,7 +167,7 @@ listener = ngrok.forward("192.168.1.2:5432", authtoken_from_env=True, print(f"Ingress established at: {listener.url()}"); ``` -```rust +```rust title="go" tabName="Agent Cli" use ngrok::prelude::*; use ngrok::tunnel; use ngrok::forwarder::Forwarder; diff --git a/src/components/LangSwitcher/data.ts b/src/components/LangSwitcher/data.ts index 83d1f853cb..c9f65b6621 100644 --- a/src/components/LangSwitcher/data.ts +++ b/src/components/LangSwitcher/data.ts @@ -41,3 +41,17 @@ export const languageData: LanguageData[] = [ altNames: ["typescript", "ts", "js", "jsx", "tsx"], }, ]; + +export type CustomLanguage = { + name: string; + // The language whose syntax should be used. + // For example, a "ssh" language could use "bash" syntax. + syntaxLanguage: string; +}; + +export const customLanguages: CustomLanguage[] = [ + { + name: "ssh", + syntaxLanguage: "bash", + }, +]; diff --git a/src/components/LangSwitcher/index.tsx b/src/components/LangSwitcher/index.tsx index 1bbb8d2575..a99a78987b 100644 --- a/src/components/LangSwitcher/index.tsx +++ b/src/components/LangSwitcher/index.tsx @@ -74,7 +74,7 @@ export function LangSwitcher({ children, className, ...props }: any) { : "outlined" } > - {child.language.toUpperCase()} + {child.meta.tabName || child.language.toUpperCase()} ))} diff --git a/src/components/LangSwitcher/utils.ts b/src/components/LangSwitcher/utils.ts index ab732bf033..dac5dd3abc 100644 --- a/src/components/LangSwitcher/utils.ts +++ b/src/components/LangSwitcher/utils.ts @@ -1,13 +1,42 @@ -import { parseLanguage, parseMetastring } from "@ngrok/mantle/code-block"; +import { parseLanguage } from "@ngrok/mantle/code-block"; import { languageData } from "./data"; +function getTabNameData(metastring: string) { + if (!metastring.includes("tabName=")) return ""; + // Get the substring starting with tabName= and ending with + // a closing quote and a space + const tabNameSubstring = metastring.split("tabName=")[1] ?? ""; + const lastQuoteIndex = tabNameSubstring.indexOf(`" `); + const tabNameValueEnd = + lastQuoteIndex > 0 ? lastQuoteIndex : tabNameSubstring.length - 1; + return tabNameSubstring.substring(1, tabNameValueEnd); +} + +function getMetaData(metastring: string | undefined) { + if (!metastring) { + return {}; + } + const meta = metastring.split(/\s+/); + const metaData: Record = {}; + meta.forEach((item) => { + const [key, value] = item.split("="); + if (key && value) { + metaData[key] = value.replace(/['"]/g, ""); // Remove " characters + } + }); + // Add the tabName to the metaData object + metaData["tabName"] = getTabNameData(metastring); // Remove " characters + return metaData; +} + export const getCodeBlocks = (children: any) => { - return children.map((child: any, index: number) => { + return children.map((child: any) => { const { className, metastring, children, language } = child.props.children.props ?? child.props; + const parsedLanguage = language || parseLanguage(className); - const meta = parseMetastring(metastring); - const title = meta.title ?? child.props.title; + const meta = getMetaData(metastring); + const title = meta.title || child.props.title; return { language: parsedLanguage, content: children, @@ -15,9 +44,10 @@ export const getCodeBlocks = (children: any) => { ...meta, // Make it collapsible by default collapsible: true, + // If no title found yet, check for a tabName. + // If a tabName exists, use the parsedLanguage as the title + title: title ? title : meta.tabName ? parsedLanguage : null, }, - title, - childIndex: index, info: getLanguageInfo(parsedLanguage), }; }); diff --git a/src/components/code-block.tsx b/src/components/code-block.tsx index d5654ad2b2..7058830cb4 100644 --- a/src/components/code-block.tsx +++ b/src/components/code-block.tsx @@ -70,9 +70,6 @@ function DocsCodeBlock({ }: Props) { const language = _language ?? parseLanguage(className); const meta = parseMetastring(metastring); - const title = _title || meta.title; - const mode = _mode || meta.mode; - const hasHeader = title || mode || _icon; const collapsible = meta.collapsible && children.split("\n").length > 20; From 6ae830e9fd4f0a520ba159ab33ffa8cadbf798d9 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 4 Apr 2025 13:54:26 -0400 Subject: [PATCH 071/137] Fix imports --- .../forward-original-connection-data.mdx | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx b/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx index aab5a49c74..c67c39aa0f 100644 --- a/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx +++ b/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx @@ -2,6 +2,156 @@ title: How Do I Forward Original Connection Data? --- +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; + +import { LangSwitcher } from "@site/src/components/LangSwitcher"; +import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitcher"; + +import RandomAgentCliExample from "/examples/agent-cli/http-random.mdx"; +import RandomAgentConfigExample from "/examples/agent-config/http-random.mdx"; +import RandomGoSdkExample from "/examples/go-sdk/http-random.mdx"; +import RandomJavascriptSdkExample from "/examples/javascript-sdk/http-random.mdx"; +import RandomPythonSdkExample from "/examples/python-sdk/http-random.mdx"; +import RandomRustSdkExample from "/examples/rust-sdk/http-random.mdx"; +import RandomSshExample from "/examples/ssh/http-random.mdx"; + +import StaticDomainAgentCliExample from "/examples/agent-cli/http-static-domain.mdx"; +import StaticDomainAgentConfigExample from "/examples/agent-config/http-static-domain.mdx"; +import StaticDomainGoSdkExample from "/examples/go-sdk/http-static-domain.mdx"; +import StaticDomainJavascriptSdkExample from "/examples/javascript-sdk/http-static-domain.mdx"; +import StaticDomainKubernetesExample from "/examples/k8s/http-static-domain.mdx"; +import StaticDomainPythonSdkExample from "/examples/python-sdk/http-static-domain.mdx"; +import StaticDomainRustSdkExample from "/examples/rust-sdk/http-static-domain.mdx"; +import StaticDomainSshExample from "/examples/ssh/http-static-domain.mdx"; + +import BrandedDomainAgentCliExample from "/examples/agent-cli/http-branded-domain.mdx"; +import BrandedDomainAgentConfigExample from "/examples/agent-config/http-branded-domain.mdx"; +import BrandedDomainGoSdkExample from "/examples/go-sdk/http-branded-domain.mdx"; +import BrandedDomainJavascriptSdkExample from "/examples/javascript-sdk/http-branded-domain.mdx"; +import BrandedDomainKubernetesExample from "/examples/k8s/http-branded-domain.mdx"; +import BrandedDomainPythonSdkExample from "/examples/python-sdk/http-branded-domain.mdx"; +import BrandedDomainRustSdkExample from "/examples/rust-sdk/http-branded-domain.mdx"; +import BrandedDomainSshExample from "/examples/ssh/http-branded-domain.mdx"; + +import BasicAuthAgentCliExample from "/examples/agent-cli/http-basic-auth.mdx"; +import BasicAuthAgentConfigExample from "/examples/agent-config/http-basic-auth.mdx"; +import BasicAuthGoSdkExample from "/examples/go-sdk/http-basic-auth.mdx"; +import BasicAuthJavascriptSdkExample from "/examples/javascript-sdk/http-basic-auth.mdx"; +import BasicAuthKubernetesExample from "/examples/k8s/http-basic-auth.mdx"; +import BasicAuthPythonSdkExample from "/examples/python-sdk/http-basic-auth.mdx"; +import BasicAuthRustSdkExample from "/examples/rust-sdk/http-basic-auth.mdx"; +import BasicAuthSshExample from "/examples/ssh/http-basic-auth.mdx"; + +import OAuthAgentCliExample from "/examples/agent-cli/http-oauth-authn.mdx"; +import OAuthAgentConfigExample from "/examples/agent-config/http-oauth-authn.mdx"; +import OAuthGoSdkExample from "/examples/go-sdk/http-oauth-authn.mdx"; +import OAuthJavascriptSdkExample from "/examples/javascript-sdk/http-oauth-authn.mdx"; +import OAuthKubernetesExample from "/examples/k8s/http-oauth-authn.mdx"; +import OAuthPythonSdkExample from "/examples/python-sdk/http-oauth-authn.mdx"; +import OAuthRustSdkExample from "/examples/rust-sdk/http-oauth-authn.mdx"; +import OAuthSshExample from "/examples/ssh/http-oauth-authn.mdx"; + +import ForwardHttpsAgentConfigExample from "/examples/agent-config/http-forward-https.mdx"; +import ForwardHttpsKubernetesExample from "/examples/k8s/http-forward-https.mdx"; + +import HostHeaderAgentCliExample from "/examples/agent-cli/http-rewrite-host-header.mdx"; +import HostHeaderAgentConfigExample from "/examples/agent-config/http-rewrite-host-header.mdx"; +import HostHeaderGoSdkExample from "/examples/go-sdk/http-rewrite-host-header.mdx"; +import HostHeaderJavascriptSdkExample from "/examples/javascript-sdk/http-rewrite-host-header.mdx"; +import HostHeaderKubernetesExample from "/examples/k8s/http-rewrite-host-header.mdx"; +import HostHeaderPythonSdkExample from "/examples/python-sdk/http-rewrite-host-header.mdx"; +import HostHeaderRustSdkExample from "/examples/rust-sdk/http-rewrite-host-header.mdx"; +import HostHeaderSshExample from "/examples/ssh/http-rewrite-host-header.mdx"; + +import NonLocalAgentCliExample from "/examples/agent-cli/http-nonlocal.mdx"; +import NonLocalGoSdkExample from "/examples/go-sdk/http-nonlocal.mdx"; +import NonLocalJavascriptSdkExample from "/examples/javascript-sdk/http-nonlocal.mdx"; +import NonLocalPythonSdkExample from "/examples/python-sdk/http-nonlocal.mdx"; +import NonLocalRustSdkExample from "/examples/rust-sdk/http-nonlocal.mdx"; +import NonLocalSshExample from "/examples/ssh/http-nonlocal.mdx"; + +import RandomAgentCliExampleTCP from "/examples/agent-cli/tcp-random.mdx"; +import RandomAgentConfigExampleTCP from "/examples/agent-config/tcp-random.mdx"; +import RandomGoSdkExampleTCP from "/examples/go-sdk/tcp-random.mdx"; +import RandomJavascriptSdkExampleTCP from "/examples/javascript-sdk/tcp-random.mdx"; +import RandomKubernetesExampleTCP from "/examples/k8s/tcp-random.mdx"; +import RandomPythonSdkExampleTCP from "/examples/python-sdk/tcp-random.mdx"; +import RandomRustSdkExampleTCP from "/examples/rust-sdk/tcp-random.mdx"; +import RandomSshExampleTCP from "/examples/ssh/tcp-random.mdx"; + +import FixedAgentCliExampleTCP from "/examples/agent-cli/tcp-fixed.mdx"; +import FixedAgentConfigExampleTCP from "/examples/agent-config/tcp-fixed.mdx"; +import FixedGoSdkExampleTCP from "/examples/go-sdk/tcp-fixed.mdx"; +import FixedJavascriptSdkExampleTCP from "/examples/javascript-sdk/tcp-fixed.mdx"; +import FixedKubernetesExampleTCP from "/examples/k8s/tcp-fixed.mdx"; +import FixedPythonSdkExampleTCP from "/examples/python-sdk/tcp-fixed.mdx"; +import FixedRustSdkExampleTCP from "/examples/rust-sdk/tcp-fixed.mdx"; +import FixedSshExampleTCP from "/examples/ssh/tcp-fixed.mdx"; + +import NonLocalAgentCliExampleTCP from "/examples/agent-cli/tcp-nonlocal.mdx"; +import NonLocalAgentConfigExampleTCP from "/examples/agent-config/tcp-nonlocal.mdx"; +import NonLocalGoSdkExampleTCP from "/examples/go-sdk/tcp-nonlocal.mdx"; +import NonLocalJavascriptSdkExampleTCP from "/examples/javascript-sdk/tcp-nonlocal.mdx"; +import NonLocalKubernetesExampleTCP from "/examples/k8s/tcp-nonlocal.mdx"; +import NonLocalPythonSdkExampleTCP from "/examples/python-sdk/tcp-nonlocal.mdx"; +import NonLocalRustSdkExampleTCP from "/examples/rust-sdk/tcp-nonlocal.mdx"; +import NonLocalSshExampleTCP from "/examples/ssh/tcp-nonlocal.mdx"; + +import ProxyProtoAgentCliExample from "/examples/agent-cli/tcp-proxyproto.mdx"; +import ProxyProtoAgentConfigExample from "/examples/agent-config/tcp-proxyproto.mdx"; +import ProxyProtoGoSdkExample from "/examples/go-sdk/tcp-proxyproto.mdx"; +import ProxyProtoJavascriptSdkExample from "/examples/javascript-sdk/tcp-proxyproto.mdx"; +import ProxyProtoKubernetesExample from "/examples/k8s/tcp-proxyproto.mdx"; +import ProxyProtoPythonSdkExample from "/examples/python-sdk/tcp-proxyproto.mdx"; +import ProxyProtoRustSdkExample from "/examples/rust-sdk/tcp-proxyproto.mdx"; +import ProxyProtoSshExample from "/examples/ssh/tcp-proxyproto.mdx"; + +import AtAgentAgentCliExample from "/examples/agent-cli/tls-terminate-at-agent.mdx"; +import AtAgentAgentConfigExample from "/examples/agent-config/tls-terminate-at-agent.mdx"; +import AtAgentGoSdkExample from "/examples/go-sdk/tls-terminate-at-agent.mdx"; +import AtAgentJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-agent.mdx"; +import AtAgentKubernetesExample from "/examples/k8s/tls-terminate-at-agent.mdx"; +import AtAgentPythonSdkExample from "/examples/python-sdk/tls-terminate-at-agent.mdx"; +import AtAgentRustSdkExample from "/examples/rust-sdk/tls-terminate-at-agent.mdx"; +import AtAgentSshExample from "/examples/ssh/tls-terminate-at-agent.mdx"; + +import AtUpstreamAgentCliExample from "/examples/agent-cli/tls-terminate-at-upstream.mdx"; +import AtUpstreamAgentConfigExample from "/examples/agent-config/tls-terminate-at-upstream.mdx"; +import AtUpstreamGoSdkExample from "/examples/go-sdk/tls-terminate-at-upstream.mdx"; +import AtUpstreamJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-upstream.mdx"; +import AtUpstreamKubernetesExample from "/examples/k8s/tls-terminate-at-upstream.mdx"; +import AtUpstreamPythonSdkExample from "/examples/python-sdk/tls-terminate-at-upstream.mdx"; +import AtUpstreamRustSdkExample from "/examples/rust-sdk/tls-terminate-at-upstream.mdx"; +import AtUpstreamSshExample from "/examples/ssh/tls-terminate-at-upstream.mdx"; + +import CustomDomainAgentCliExample from "/examples/agent-cli/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainAgentConfigExample from "/examples/agent-config/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainGoSdkExample from "/examples/go-sdk/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainKubernetesExample from "/examples/k8s/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainPythonSdkExample from "/examples/python-sdk/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainRustSdkExample from "/examples/rust-sdk/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainSshExample from "/examples/ssh/tls-terminate-at-edge-custom-domain.mdx"; + +import ReencryptUpstreamAgentCliExample from "/examples/agent-cli/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamAgentConfigExample from "/examples/agent-config/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamGoSdkExample from "/examples/go-sdk/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamJavascriptSdkExample from "/examples/javascript-sdk/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamKubernetesExample from "/examples/k8s/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamPythonSdkExample from "/examples/python-sdk/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamRustSdkExample from "/examples/rust-sdk/tls-reencrypt-upstream.mdx"; +import ReencryptUpstreamSshExample from "/examples/ssh/tls-reencrypt-upstream.mdx"; + +import ProxyProtoAgentCliExampleTLS from "/examples/agent-cli/tls-proxyproto.mdx"; +import ProxyProtoAgentConfigExampleTLS from "/examples/agent-config/tls-proxyproto.mdx"; +import ProxyProtoGoSdkExampleTLS from "/examples/go-sdk/tls-proxyproto.mdx"; +import ProxyProtoJavascriptSdkExampleTLS from "/examples/javascript-sdk/tls-proxyproto.mdx"; +import ProxyProtoKubernetesExampleTLS from "/examples/k8s/tls-proxyproto.mdx"; +import ProxyProtoPythonSdkExampleTLS from "/examples/python-sdk/tls-proxyproto.mdx"; +import ProxyProtoRustSdkExampleTLS from "/examples/rust-sdk/tls-proxyproto.mdx"; +import ProxyProtoSshExampleTLS from "/examples/ssh/tls-proxyproto.mdx"; + ### TCP When you forward traffic to an upstream TCP service, becuase traffic is coming From 1b77e7f7bdf9a99992037b70a4e4bfbcb0d1227f Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 4 Apr 2025 14:04:22 -0400 Subject: [PATCH 072/137] Add tabname --- .../agent-forwarding/non-local-forwarding.mdx | 6 +++--- docs/universal-gateway/http-s/index.mdx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx b/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx index 12e7f29290..ca741715c5 100644 --- a/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx +++ b/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx @@ -26,7 +26,7 @@ The following example demonstrates how to forward traffic to an HTTP server runn ngrok http 192.168.1.2:80 ``` - ```sh + ```sh tabName="SSH" ssh -R 0:192.168.1.2:80 v2@connect.ngrok-agent.com http ``` @@ -117,7 +117,7 @@ The following example demonstrates how to forward traffic to a Postgres server r ngrok tcp 192.168.1.2:5432 ``` -```sh +```sh tabName="SSH" ssh -R 0:192.168.1.2:5432 v2@connect.ngrok-agent.com tcp ``` @@ -167,7 +167,7 @@ listener = ngrok.forward("192.168.1.2:5432", authtoken_from_env=True, print(f"Ingress established at: {listener.url()}"); ``` -```rust title="go" tabName="Agent Cli" +```rust use ngrok::prelude::*; use ngrok::tunnel; use ngrok::forwarder::Forwarder; diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx index 9e044f42dc..b7290f0152 100644 --- a/docs/universal-gateway/http-s/index.mdx +++ b/docs/universal-gateway/http-s/index.mdx @@ -121,7 +121,7 @@ You can create HTTP/S endpoints to serve web services like REST APIs, web applic ```bash title="Agent CLI" titleLink="/docs/agent/" ngrok http 8080 --url https://example.ngrok.app ``` - ```sh + ```sh tabName="SSH" ssh -R example.ngrok.app:443:localhost:8080 v2@connect.ngrok-agent.com http ``` ```go From c378742f9f8bbcebcb665626dd1044cf635f0735 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 4 Apr 2025 14:39:56 -0400 Subject: [PATCH 073/137] Fix tab labels in single code blocks --- .../agent-forwarding/non-local-forwarding.mdx | 11 ++++++----- examples/agent-config/http-nonlocal.mdx | 2 +- src/components/LangSwitcher/index.tsx | 9 ++++++++- src/components/LangSwitcher/utils.ts | 4 ++-- src/components/code-block.tsx | 17 ++++++++--------- src/theme/CodeBlock/index.tsx | 1 + 6 files changed, 26 insertions(+), 18 deletions(-) diff --git a/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx b/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx index ca741715c5..144a39828a 100644 --- a/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx +++ b/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx @@ -97,11 +97,12 @@ The following example demonstrates how to forward traffic to an HTTP server runn
- - - - - + + + + + + diff --git a/examples/agent-config/http-nonlocal.mdx b/examples/agent-config/http-nonlocal.mdx index d9ed77f3dd..869e97515d 100644 --- a/examples/agent-config/http-nonlocal.mdx +++ b/examples/agent-config/http-nonlocal.mdx @@ -1,4 +1,4 @@ -```yaml title="hello" mode=traffic-policy +```yaml mode=traffic-policy version: 3 endpoints: - name: example diff --git a/src/components/LangSwitcher/index.tsx b/src/components/LangSwitcher/index.tsx index a99a78987b..07ecea46c0 100644 --- a/src/components/LangSwitcher/index.tsx +++ b/src/components/LangSwitcher/index.tsx @@ -1,4 +1,5 @@ import BrowserOnly from "@docusaurus/BrowserOnly"; +import { useScrollPositionBlocker } from "@docusaurus/theme-common/internal"; import { Button } from "@ngrok/mantle/button"; import { CodeBlock, @@ -24,6 +25,8 @@ import { getCodeBlocks } from "./utils"; export function LangSwitcher({ children, className, ...props }: any) { const { defaultLanguage, selectedLanguage, updateSelectedLanguage } = useContext(LangSwitcherContext); + const { blockElementScrollPositionUntilNextRender } = + useScrollPositionBlocker(); const codeBlocks = getCodeBlocks(children); @@ -65,7 +68,11 @@ export function LangSwitcher({ children, className, ...props }: any) { {codeBlocks.map((child: any) => ( - ))} - - - - {meta.title && ( -
- <> - {meta.mode ? ( - - ) : ( - - )} - - {meta.title} - - -
- )} - {!meta.disableCopy && } - - {collapsible && } -
- - {info && } - + + {codeBlocks.map((child: any) => ( + + ))} + + } + info={matchingBlock.info} + codeBlockProps={props} + /> + //
+ // + // + //
+ // {codeBlocks.map((child: any) => ( + // + // ))} + //
+ //
+ // + // {meta.title && ( + //
+ // <> + // {meta.mode ? ( + // + // ) : ( + // + // )} + // + // {meta.title} + // + // + //
+ // )} + // {!meta.disableCopy && } + // + // {collapsible && } + //
+ //
+ // {info && } + //
)} ); diff --git a/src/components/LangSwitcher/utils.ts b/src/components/LangSwitcher/utils.ts index e10b257291..fa6e7b926c 100644 --- a/src/components/LangSwitcher/utils.ts +++ b/src/components/LangSwitcher/utils.ts @@ -1,5 +1,5 @@ import { parseLanguage } from "@ngrok/mantle/code-block"; -import { languageData } from "./data"; +import { languageInfo } from "./data"; export function getTabNameData(metastring: string) { if (!metastring.includes("tabName=")) return ""; @@ -54,7 +54,7 @@ export const getCodeBlocks = (children: any) => { }; export const getLanguageInfo = (language: string) => { - return languageData.find( + return languageInfo.find( (item) => item.name === language || item?.altNames?.some((alt) => alt === language), ); diff --git a/src/components/code-block.tsx b/src/components/code-block.tsx index dceb0e0e1a..84887750b7 100644 --- a/src/components/code-block.tsx +++ b/src/components/code-block.tsx @@ -1,21 +1,9 @@ import { Button } from "@ngrok/mantle/button"; import type { Mode, SupportedLanguage } from "@ngrok/mantle/code-block"; -import { - CodeBlock, - CodeBlockBody, - CodeBlockCode, - CodeBlockCopyButton, - CodeBlockExpanderButton, - CodeBlockHeader, - CodeBlockIcon, - CodeBlockTitle, - fmtCode, - parseLanguage, -} from "@ngrok/mantle/code-block"; +import { CodeBlock, parseLanguage } from "@ngrok/mantle/code-block"; import type { WithStyleProps } from "@ngrok/mantle/types"; -import convertToSpaces from "convert-to-spaces"; import type { ComponentProps, ReactNode } from "react"; -import { LanguageData } from "./LangSwitcher/LanguageData"; +import { CodeBlockWithInfo } from "./CodeBlockWithInfo"; import { getLanguageInfo, getMetaData } from "./LangSwitcher/utils"; type Props = WithStyleProps & { @@ -66,50 +54,61 @@ function DocsCodeBlock({ const langInClassName = langMatchesInClassName ? langMatchesInClassName[0]?.split("-")[1] : ""; - const language = _language ?? parseLanguage(langInClassName); - console.log(props, className, language); - const meta = getMetaData(metastring); - - const collapsible = meta.collapsible && children.split("\n").length > 20; - - const codeblockContent = convertToSpaces(fmtCode`${children}`); - const info = getLanguageInfo(language); + const language = _language || parseLanguage(langInClassName); return ( -
- - - - {/* {title && {title}} */} - - - {meta.title && ( -
- <> - {meta.mode ? ( - - ) : ( - - )} - - {meta.title} - - -
- )} - {!meta.disableCopy && } - - {collapsible && } -
-
- {info && } -
+ + {language.toUpperCase()} + + } + info={getLanguageInfo(language)} + codeBlockProps={props} + /> + //
+ // + // + // + // + // + // {meta.title && ( + //
+ // <> + // {meta.mode ? ( + // + // ) : ( + // + // )} + // + // {meta.title} + // + // + //
+ // )} + // {!meta.disableCopy && } + // + // {collapsible && } + //
+ //
+ // {info && } + //
); } diff --git a/src/theme/CodeBlock/index.tsx b/src/theme/CodeBlock/index.tsx index c3b6fd1b8d..afece5ba9b 100644 --- a/src/theme/CodeBlock/index.tsx +++ b/src/theme/CodeBlock/index.tsx @@ -6,7 +6,6 @@ import DocsCodeBlock, { CodeBlockFallback } from "../../components/code-block"; type Props = ComponentProps; export default function CodeBlock({ className, ...props }: Props) { - console.log("CodeBlock", props, className); return ( Date: Mon, 7 Apr 2025 13:25:28 -0400 Subject: [PATCH 077/137] Update behavior of code block --- .../agent-forwarding/index.mdx | 165 ++---------------- docs/universal-gateway/http-s/index.mdx | 2 +- examples/k8s/http-forward-https.mdx | 2 +- sidebars.js | 76 ++++---- src/components/CodeBlockWithInfo/index.tsx | 9 +- src/components/LangSwitcher/LanguageData.tsx | 2 +- src/components/LangSwitcher/data.ts | 13 +- src/components/LangSwitcher/index.tsx | 9 +- src/components/LangSwitcher/utils.ts | 39 ++++- src/theme/Tabs/index.tsx | 4 +- static/scripts/fix-redirect.js | 2 +- .../redirects/question-answer-redirects.js | 2 +- 12 files changed, 126 insertions(+), 199 deletions(-) diff --git a/docs/universal-gateway/agent-forwarding/index.mdx b/docs/universal-gateway/agent-forwarding/index.mdx index 44ea29e2ae..645791265c 100644 --- a/docs/universal-gateway/agent-forwarding/index.mdx +++ b/docs/universal-gateway/agent-forwarding/index.mdx @@ -8,149 +8,10 @@ import Tabs from "@theme/Tabs"; import { LangSwitcher } from "@site/src/components/LangSwitcher"; import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitcher"; -import RandomAgentCliExample from "/examples/agent-cli/http-random.mdx"; -import RandomAgentConfigExample from "/examples/agent-config/http-random.mdx"; -import RandomGoSdkExample from "/examples/go-sdk/http-random.mdx"; -import RandomJavascriptSdkExample from "/examples/javascript-sdk/http-random.mdx"; -import RandomPythonSdkExample from "/examples/python-sdk/http-random.mdx"; -import RandomRustSdkExample from "/examples/rust-sdk/http-random.mdx"; -import RandomSshExample from "/examples/ssh/http-random.mdx"; - -import StaticDomainAgentCliExample from "/examples/agent-cli/http-static-domain.mdx"; -import StaticDomainAgentConfigExample from "/examples/agent-config/http-static-domain.mdx"; -import StaticDomainGoSdkExample from "/examples/go-sdk/http-static-domain.mdx"; -import StaticDomainJavascriptSdkExample from "/examples/javascript-sdk/http-static-domain.mdx"; -import StaticDomainKubernetesExample from "/examples/k8s/http-static-domain.mdx"; -import StaticDomainPythonSdkExample from "/examples/python-sdk/http-static-domain.mdx"; -import StaticDomainRustSdkExample from "/examples/rust-sdk/http-static-domain.mdx"; -import StaticDomainSshExample from "/examples/ssh/http-static-domain.mdx"; - -import BrandedDomainAgentCliExample from "/examples/agent-cli/http-branded-domain.mdx"; -import BrandedDomainAgentConfigExample from "/examples/agent-config/http-branded-domain.mdx"; -import BrandedDomainGoSdkExample from "/examples/go-sdk/http-branded-domain.mdx"; -import BrandedDomainJavascriptSdkExample from "/examples/javascript-sdk/http-branded-domain.mdx"; -import BrandedDomainKubernetesExample from "/examples/k8s/http-branded-domain.mdx"; -import BrandedDomainPythonSdkExample from "/examples/python-sdk/http-branded-domain.mdx"; -import BrandedDomainRustSdkExample from "/examples/rust-sdk/http-branded-domain.mdx"; -import BrandedDomainSshExample from "/examples/ssh/http-branded-domain.mdx"; - -import BasicAuthAgentCliExample from "/examples/agent-cli/http-basic-auth.mdx"; -import BasicAuthAgentConfigExample from "/examples/agent-config/http-basic-auth.mdx"; -import BasicAuthGoSdkExample from "/examples/go-sdk/http-basic-auth.mdx"; -import BasicAuthJavascriptSdkExample from "/examples/javascript-sdk/http-basic-auth.mdx"; -import BasicAuthKubernetesExample from "/examples/k8s/http-basic-auth.mdx"; -import BasicAuthPythonSdkExample from "/examples/python-sdk/http-basic-auth.mdx"; -import BasicAuthRustSdkExample from "/examples/rust-sdk/http-basic-auth.mdx"; -import BasicAuthSshExample from "/examples/ssh/http-basic-auth.mdx"; - -import OAuthAgentCliExample from "/examples/agent-cli/http-oauth-authn.mdx"; -import OAuthAgentConfigExample from "/examples/agent-config/http-oauth-authn.mdx"; -import OAuthGoSdkExample from "/examples/go-sdk/http-oauth-authn.mdx"; -import OAuthJavascriptSdkExample from "/examples/javascript-sdk/http-oauth-authn.mdx"; -import OAuthKubernetesExample from "/examples/k8s/http-oauth-authn.mdx"; -import OAuthPythonSdkExample from "/examples/python-sdk/http-oauth-authn.mdx"; -import OAuthRustSdkExample from "/examples/rust-sdk/http-oauth-authn.mdx"; -import OAuthSshExample from "/examples/ssh/http-oauth-authn.mdx"; - import ForwardHttpsAgentConfigExample from "/examples/agent-config/http-forward-https.mdx"; import ForwardHttpsKubernetesExample from "/examples/k8s/http-forward-https.mdx"; -import HostHeaderAgentCliExample from "/examples/agent-cli/http-rewrite-host-header.mdx"; -import HostHeaderAgentConfigExample from "/examples/agent-config/http-rewrite-host-header.mdx"; -import HostHeaderGoSdkExample from "/examples/go-sdk/http-rewrite-host-header.mdx"; -import HostHeaderJavascriptSdkExample from "/examples/javascript-sdk/http-rewrite-host-header.mdx"; -import HostHeaderKubernetesExample from "/examples/k8s/http-rewrite-host-header.mdx"; -import HostHeaderPythonSdkExample from "/examples/python-sdk/http-rewrite-host-header.mdx"; -import HostHeaderRustSdkExample from "/examples/rust-sdk/http-rewrite-host-header.mdx"; -import HostHeaderSshExample from "/examples/ssh/http-rewrite-host-header.mdx"; - -import NonLocalAgentCliExample from "/examples/agent-cli/http-nonlocal.mdx"; -import NonLocalGoSdkExample from "/examples/go-sdk/http-nonlocal.mdx"; -import NonLocalJavascriptSdkExample from "/examples/javascript-sdk/http-nonlocal.mdx"; -import NonLocalPythonSdkExample from "/examples/python-sdk/http-nonlocal.mdx"; -import NonLocalRustSdkExample from "/examples/rust-sdk/http-nonlocal.mdx"; -import NonLocalSshExample from "/examples/ssh/http-nonlocal.mdx"; - -import RandomAgentCliExampleTCP from "/examples/agent-cli/tcp-random.mdx"; -import RandomAgentConfigExampleTCP from "/examples/agent-config/tcp-random.mdx"; -import RandomGoSdkExampleTCP from "/examples/go-sdk/tcp-random.mdx"; -import RandomJavascriptSdkExampleTCP from "/examples/javascript-sdk/tcp-random.mdx"; -import RandomKubernetesExampleTCP from "/examples/k8s/tcp-random.mdx"; -import RandomPythonSdkExampleTCP from "/examples/python-sdk/tcp-random.mdx"; -import RandomRustSdkExampleTCP from "/examples/rust-sdk/tcp-random.mdx"; -import RandomSshExampleTCP from "/examples/ssh/tcp-random.mdx"; - -import FixedAgentCliExampleTCP from "/examples/agent-cli/tcp-fixed.mdx"; -import FixedAgentConfigExampleTCP from "/examples/agent-config/tcp-fixed.mdx"; -import FixedGoSdkExampleTCP from "/examples/go-sdk/tcp-fixed.mdx"; -import FixedJavascriptSdkExampleTCP from "/examples/javascript-sdk/tcp-fixed.mdx"; -import FixedKubernetesExampleTCP from "/examples/k8s/tcp-fixed.mdx"; -import FixedPythonSdkExampleTCP from "/examples/python-sdk/tcp-fixed.mdx"; -import FixedRustSdkExampleTCP from "/examples/rust-sdk/tcp-fixed.mdx"; -import FixedSshExampleTCP from "/examples/ssh/tcp-fixed.mdx"; - -import NonLocalAgentCliExampleTCP from "/examples/agent-cli/tcp-nonlocal.mdx"; -import NonLocalAgentConfigExampleTCP from "/examples/agent-config/tcp-nonlocal.mdx"; -import NonLocalGoSdkExampleTCP from "/examples/go-sdk/tcp-nonlocal.mdx"; -import NonLocalJavascriptSdkExampleTCP from "/examples/javascript-sdk/tcp-nonlocal.mdx"; -import NonLocalKubernetesExampleTCP from "/examples/k8s/tcp-nonlocal.mdx"; -import NonLocalPythonSdkExampleTCP from "/examples/python-sdk/tcp-nonlocal.mdx"; -import NonLocalRustSdkExampleTCP from "/examples/rust-sdk/tcp-nonlocal.mdx"; -import NonLocalSshExampleTCP from "/examples/ssh/tcp-nonlocal.mdx"; - -import ProxyProtoAgentCliExample from "/examples/agent-cli/tcp-proxyproto.mdx"; -import ProxyProtoAgentConfigExample from "/examples/agent-config/tcp-proxyproto.mdx"; -import ProxyProtoGoSdkExample from "/examples/go-sdk/tcp-proxyproto.mdx"; -import ProxyProtoJavascriptSdkExample from "/examples/javascript-sdk/tcp-proxyproto.mdx"; -import ProxyProtoKubernetesExample from "/examples/k8s/tcp-proxyproto.mdx"; -import ProxyProtoPythonSdkExample from "/examples/python-sdk/tcp-proxyproto.mdx"; -import ProxyProtoRustSdkExample from "/examples/rust-sdk/tcp-proxyproto.mdx"; -import ProxyProtoSshExample from "/examples/ssh/tcp-proxyproto.mdx"; - -import AtAgentAgentCliExample from "/examples/agent-cli/tls-terminate-at-agent.mdx"; -import AtAgentAgentConfigExample from "/examples/agent-config/tls-terminate-at-agent.mdx"; -import AtAgentGoSdkExample from "/examples/go-sdk/tls-terminate-at-agent.mdx"; -import AtAgentJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-agent.mdx"; -import AtAgentKubernetesExample from "/examples/k8s/tls-terminate-at-agent.mdx"; -import AtAgentPythonSdkExample from "/examples/python-sdk/tls-terminate-at-agent.mdx"; -import AtAgentRustSdkExample from "/examples/rust-sdk/tls-terminate-at-agent.mdx"; -import AtAgentSshExample from "/examples/ssh/tls-terminate-at-agent.mdx"; - -import AtUpstreamAgentCliExample from "/examples/agent-cli/tls-terminate-at-upstream.mdx"; -import AtUpstreamAgentConfigExample from "/examples/agent-config/tls-terminate-at-upstream.mdx"; -import AtUpstreamGoSdkExample from "/examples/go-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamKubernetesExample from "/examples/k8s/tls-terminate-at-upstream.mdx"; -import AtUpstreamPythonSdkExample from "/examples/python-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamRustSdkExample from "/examples/rust-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamSshExample from "/examples/ssh/tls-terminate-at-upstream.mdx"; - -import CustomDomainAgentCliExample from "/examples/agent-cli/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainAgentConfigExample from "/examples/agent-config/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainGoSdkExample from "/examples/go-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainKubernetesExample from "/examples/k8s/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainPythonSdkExample from "/examples/python-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainRustSdkExample from "/examples/rust-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainSshExample from "/examples/ssh/tls-terminate-at-edge-custom-domain.mdx"; - -import ReencryptUpstreamAgentCliExample from "/examples/agent-cli/tls-reencrypt-upstream.mdx"; import ReencryptUpstreamAgentConfigExample from "/examples/agent-config/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamGoSdkExample from "/examples/go-sdk/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamJavascriptSdkExample from "/examples/javascript-sdk/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamKubernetesExample from "/examples/k8s/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamPythonSdkExample from "/examples/python-sdk/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamRustSdkExample from "/examples/rust-sdk/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamSshExample from "/examples/ssh/tls-reencrypt-upstream.mdx"; - -import ProxyProtoAgentCliExampleTLS from "/examples/agent-cli/tls-proxyproto.mdx"; -import ProxyProtoAgentConfigExampleTLS from "/examples/agent-config/tls-proxyproto.mdx"; -import ProxyProtoGoSdkExampleTLS from "/examples/go-sdk/tls-proxyproto.mdx"; -import ProxyProtoJavascriptSdkExampleTLS from "/examples/javascript-sdk/tls-proxyproto.mdx"; -import ProxyProtoKubernetesExampleTLS from "/examples/k8s/tls-proxyproto.mdx"; -import ProxyProtoPythonSdkExampleTLS from "/examples/python-sdk/tls-proxyproto.mdx"; -import ProxyProtoRustSdkExampleTLS from "/examples/rust-sdk/tls-proxyproto.mdx"; -import ProxyProtoSshExampleTLS from "/examples/ssh/tls-proxyproto.mdx"; The [ngrok agent](/agent/) and [Agent SDKs](/agent-sdks/) forward traffic that your endpoints receive to upstream services. You specify a URL or port number to instruct the ngrok agent where and how to forward traffic. @@ -316,9 +177,25 @@ listener = ngrok.forward("tls://localhost:443", authtoken_from_env=True, print(f"Ingress established at: {listener.url()}"); ``` +```jsx +const ngrok = require("@ngrok/ngrok"); + +(async function () { + const listener = await ngrok.forward({ + addr: "tls://localhost:443", + authtoken_from_env: true, + proto: "tls", + crt: "", + key: "", + }); + + console.log(`Ingress established at: ${listener.url()}`); +})(); +``` + - + An empty certificate and key will default to the ngrok edge's automatically provisioned keypair. The upstream certificate of `localhost:443` will be validated by a filepath specified in the `SSL_CERT_FILE` environment variable @@ -326,18 +203,12 @@ print(f"Ingress established at: {listener.url()}"); installed trusted certificate authorities. - - - - - - - +TLS endpoints are not supported by the ngrok Kubernetes Operator diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx index b7290f0152..f65374c1fb 100644 --- a/docs/universal-gateway/http-s/index.mdx +++ b/docs/universal-gateway/http-s/index.mdx @@ -118,7 +118,7 @@ You can create HTTP/S endpoints to serve web services like REST APIs, web applic The following example creates the endpoint `https://example.ngrok.app` and forwards its traffic to a local port. - ```bash title="Agent CLI" titleLink="/docs/agent/" + ```bash ngrok http 8080 --url https://example.ngrok.app ``` ```sh tabName="SSH" diff --git a/examples/k8s/http-forward-https.mdx b/examples/k8s/http-forward-https.mdx index 42d6f5f231..7d1990ada6 100644 --- a/examples/k8s/http-forward-https.mdx +++ b/examples/k8s/http-forward-https.mdx @@ -2,7 +2,7 @@ Add the `k8s.ngrok.com/app-protocols` label to the **Service** definition targeted by your ingress backend to instruct the Operator to use `https` when forwarding connections. -```yaml +```yaml tabsToSpaces=true apiVersion: v1 kind: Service metadata: diff --git a/sidebars.js b/sidebars.js index ccce9ca23b..18e0b8ae25 100644 --- a/sidebars.js +++ b/sidebars.js @@ -85,46 +85,58 @@ const sidebars = { "universal-gateway/tls-certificates/what-are-private-tls-keys", ], }, - "universal-gateway/endpoints", - "universal-gateway/bindings", - "universal-gateway/public-endpoints/index", - "universal-gateway/what-are-endpoint-urls", { - label: "What are Internal Endpoints?", + label: "What are Endpoints?", type: "category", link: { type: "doc", - id: "universal-gateway/internal-endpoints/index", - }, - items: ["universal-gateway/internal-endpoints/quickstart"], - }, - { - label: "What are Kubernetes Endpoints?", - type: "category", - link: { - type: "doc", - id: "universal-gateway/kubernetes-endpoints/index", + id: "universal-gateway/endpoints", }, items: [ - "universal-gateway/kubernetes-endpoints/quickstart", - "universal-gateway/kubernetes-endpoints/services", - "universal-gateway/kubernetes-endpoints/selector", + "universal-gateway/bindings", + "universal-gateway/public-endpoints/index", + "universal-gateway/what-are-endpoint-urls", + { + label: "What are Internal Endpoints?", + type: "category", + link: { + type: "doc", + id: "universal-gateway/internal-endpoints/index", + }, + items: ["universal-gateway/internal-endpoints/quickstart"], + }, + { + label: "What are Kubernetes Endpoints?", + type: "category", + link: { + type: "doc", + id: "universal-gateway/kubernetes-endpoints/index", + }, + items: [ + "universal-gateway/kubernetes-endpoints/quickstart", + "universal-gateway/kubernetes-endpoints/services", + "universal-gateway/kubernetes-endpoints/selector", + ], + }, + { + label: "What are Cloud Endpoints?", + type: "category", + link: { + type: "doc", + id: "universal-gateway/cloud-endpoints/index", + }, + items: ["universal-gateway/cloud-endpoints/quickstart"], + }, + { + label: "What are Agent Endpoints?", + id: "universal-gateway/agent-endpoints", + type: "doc", + }, + "universal-gateway/chain-endpoints", + "universal-gateway/mock-api", + "universal-gateway/migrate-from-tunnels", ], }, - { - label: "What are Cloud Endpoints?", - type: "category", - link: { type: "doc", id: "universal-gateway/cloud-endpoints/index" }, - items: ["universal-gateway/cloud-endpoints/quickstart"], - }, - { - label: "What are Agent Endpoints?", - id: "universal-gateway/agent-endpoints", - type: "doc", - }, - "universal-gateway/chain-endpoints", - "universal-gateway/mock-api", - "universal-gateway/migrate-from-tunnels", { label: "How Does Agent Fowarding Work?", type: "category", diff --git a/src/components/CodeBlockWithInfo/index.tsx b/src/components/CodeBlockWithInfo/index.tsx index 9c47088bd9..abfb8b28a3 100644 --- a/src/components/CodeBlockWithInfo/index.tsx +++ b/src/components/CodeBlockWithInfo/index.tsx @@ -1,3 +1,4 @@ +import useBaseUrl from "@docusaurus/useBaseUrl"; import { CodeBlock, CodeBlockBody, @@ -60,7 +61,13 @@ export function CodeBlockWithInfo({ )} - {meta.title} + {meta.titleLink ? ( +
+ {meta.title} + + ) : ( + {meta.title} + )}
diff --git a/src/components/LangSwitcher/LanguageData.tsx b/src/components/LangSwitcher/LanguageData.tsx index db3f85e1db..89afd31bb3 100644 --- a/src/components/LangSwitcher/LanguageData.tsx +++ b/src/components/LangSwitcher/LanguageData.tsx @@ -21,7 +21,7 @@ export function LanguageData({ data }: { data: LanguageInfo }) { return (
-
+
See the ngrok {data.displayName} package docs {linkText}.
diff --git a/src/components/LangSwitcher/data.ts b/src/components/LangSwitcher/data.ts index 7a427ef269..2eee098aaa 100644 --- a/src/components/LangSwitcher/data.ts +++ b/src/components/LangSwitcher/data.ts @@ -1,6 +1,6 @@ export type LanguageInfo = { name: string; - altNames?: string[]; + allNames?: string[]; displayName: string; links: string[]; }; @@ -38,7 +38,16 @@ export const languageInfo: LanguageInfo[] = [ "https://ngrok.github.io/ngrok-javascript/interfaces/Config.html#addr", "https://ngrok.github.io/ngrok-javascript/classes/TcpListenerBuilder.html#listenAndForward", ], - altNames: ["typescript", "ts", "js", "jsx", "tsx"], + allNames: ["javascript", "typescript", "ts", "js", "jsx", "tsx"], + }, + { + name: "typescript", + displayName: "TypeScript", + links: [ + "https://ngrok.github.io/ngrok-javascript/interfaces/Config.html#addr", + "https://ngrok.github.io/ngrok-javascript/classes/TcpListenerBuilder.html#listenAndForward", + ], + allNames: ["typescript", "ts", "tsx"], }, ]; diff --git a/src/components/LangSwitcher/index.tsx b/src/components/LangSwitcher/index.tsx index 1dd15dc9e4..c9e40fda61 100644 --- a/src/components/LangSwitcher/index.tsx +++ b/src/components/LangSwitcher/index.tsx @@ -6,7 +6,7 @@ import { CodeBlockWithInfo } from "../CodeBlockWithInfo"; import LangSwitcherContext, { type LangSwitcherContextType, } from "./LangSwitcherContext"; -import { getCodeBlocks } from "./utils"; +import { getCodeBlocks, languagesAreSynonyms } from "./utils"; export function LangSwitcher({ children, className, ...props }: any) { const { defaultLanguage, selectedLanguage, updateSelectedLanguage } = @@ -27,8 +27,11 @@ export function LangSwitcher({ children, className, ...props }: any) { } const matchingBlock = - codeBlocks.find((child: any) => child.language === selectedLanguage) || - codeBlocks[0]; + codeBlocks.find( + (child: any) => + child.language === selectedLanguage || + languagesAreSynonyms(child.language, selectedLanguage), + ) || codeBlocks[0]; return ( 0 ? lastQuoteIndex : tabNameSubstring.length - 1; @@ -24,8 +30,13 @@ export function getMetaData(metastring: string | undefined) { metaData[key] = value.replace(/['"]/g, ""); // Remove " characters } }); - // Add the tabName to the metaData object - metaData["tabName"] = getTabNameData(metastring); // Remove " characters + // Add the properties that use quotes to the metaData object + ["tabName", "title"].forEach((property) => { + const quotedData = getMetaDataWithQuotes(property, metastring); + if (quotedData) { + metaData[property] = quotedData; + } + }); return metaData; } @@ -56,10 +67,24 @@ export const getCodeBlocks = (children: any) => { export const getLanguageInfo = (language: string) => { return languageInfo.find( (item) => - item.name === language || item?.altNames?.some((alt) => alt === language), + item.name === language || item?.allNames?.some((alt) => alt === language), ); }; +export function languagesAreSynonyms( + languageToCheck: string, + selectedLanguage: string | null, +) { + if (!selectedLanguage) return false; + const synonymousLanguage = languageInfo.find((lang: LanguageInfo) => + lang.allNames?.includes(selectedLanguage), + ); + return ( + synonymousLanguage?.name === languageToCheck || + synonymousLanguage?.allNames?.includes(languageToCheck) + ); +} + // The name of the query param or localstorage item to search for // to get the default tab value export const langParamName = "defaultTabLang"; diff --git a/src/theme/Tabs/index.tsx b/src/theme/Tabs/index.tsx index 24268233bf..5c46d86754 100644 --- a/src/theme/Tabs/index.tsx +++ b/src/theme/Tabs/index.tsx @@ -112,7 +112,7 @@ function TabList({ {tabValues.map(({ value, label, attributes }) => ( - {label ?? value} + {label || value} ))} diff --git a/static/scripts/fix-redirect.js b/static/scripts/fix-redirect.js index 75a4fd32d0..c699b4781b 100644 --- a/static/scripts/fix-redirect.js +++ b/static/scripts/fix-redirect.js @@ -1,4 +1,4 @@ -import questionAnswerRedirects from "./redirects/question-answer-redirects"; +questionAnswerRedirects = require("./redirects/question-answer-redirects"); export const getNormalizedPaths = (from, path) => { return { diff --git a/static/scripts/redirects/question-answer-redirects.js b/static/scripts/redirects/question-answer-redirects.js index 4d4eb88899..994977beff 100644 --- a/static/scripts/redirects/question-answer-redirects.js +++ b/static/scripts/redirects/question-answer-redirects.js @@ -1,4 +1,4 @@ -import { fromExact, fromIncludes } from "../fix-redirect" +import { fromExact } from "../fix-redirect" export default [ /** From 457b28ae6d0106dadad28ceac9986e5f6bfc0a32 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Mon, 7 Apr 2025 16:26:29 -0400 Subject: [PATCH 078/137] Alphabetizing tabs and adding common labels to all tab components --- docs/universal-gateway/http-s/index.mdx | 2 +- src/components/LangSwitcher/index.tsx | 46 ------------------------- src/components/code-block.tsx | 34 ------------------ src/theme/Tabs/index.tsx | 17 ++++++++- src/theme/Tabs/utils.tsx | 27 +++++++++++++++ 5 files changed, 44 insertions(+), 82 deletions(-) create mode 100644 src/theme/Tabs/utils.tsx diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx index f65374c1fb..66883a86bb 100644 --- a/docs/universal-gateway/http-s/index.mdx +++ b/docs/universal-gateway/http-s/index.mdx @@ -219,7 +219,7 @@ ngrok api endpoints create \ ``` - + Follow the [ngrok Kubernetes Controller documentation](https://ngrok.com/docs/k8s/guides/quickstart/) to get started using ngrok with Kubernetes. You can use the following service definition to create an HTTP endpoint: diff --git a/src/components/LangSwitcher/index.tsx b/src/components/LangSwitcher/index.tsx index c9e40fda61..cca8ea1137 100644 --- a/src/components/LangSwitcher/index.tsx +++ b/src/components/LangSwitcher/index.tsx @@ -68,52 +68,6 @@ export function LangSwitcher({ children, className, ...props }: any) { info={matchingBlock.info} codeBlockProps={props} /> - //
- // - // - //
- // {codeBlocks.map((child: any) => ( - // - // ))} - //
- //
- // - // {meta.title && ( - //
- // <> - // {meta.mode ? ( - // - // ) : ( - // - // )} - // - // {meta.title} - // - // - //
- // )} - // {!meta.disableCopy && } - // - // {collapsible && } - //
- //
- // {info && } - //
)}
); diff --git a/src/components/code-block.tsx b/src/components/code-block.tsx index 84887750b7..dfd96611dd 100644 --- a/src/components/code-block.tsx +++ b/src/components/code-block.tsx @@ -75,40 +75,6 @@ function DocsCodeBlock({ info={getLanguageInfo(language)} codeBlockProps={props} /> - //
- // - // - // - // - // - // {meta.title && ( - //
- // <> - // {meta.mode ? ( - // - // ) : ( - // - // )} - // - // {meta.title} - // - // - //
- // )} - // {!meta.disableCopy && } - // - // {collapsible && } - //
- //
- // {info && } - //
); } diff --git a/src/theme/Tabs/index.tsx b/src/theme/Tabs/index.tsx index 5c46d86754..90c0ac46af 100644 --- a/src/theme/Tabs/index.tsx +++ b/src/theme/Tabs/index.tsx @@ -17,6 +17,7 @@ import clsx from "clsx"; import React, { useContext, type ReactElement, type ReactNode } from "react"; import styles from "./styles.module.css"; import TabListContext from "./TabListContext"; +import { getCommonLabel } from "./utils"; function getValidTabToShow( tabValues: readonly TabValue[], @@ -70,6 +71,8 @@ function TabList({ const newTabValue = tabValues[newTabIndex]!.label || tabValues[newTabIndex]!.value; + console.log("Switching to", tabValues[newTabIndex]); + if (newTabValue !== selectedTabItem && updateSelectedTabItem) { blockElementScrollPositionUntilNextRender(newTab); updateSelectedTabItem(newTabValue); @@ -155,9 +158,21 @@ function TabContent({ children }: Props & ReturnType) { function TabsComponent(props: Props): ReactNode { const tabs = useTabs(props); + console.log("Tabs before sorting", tabs); + const sortedTabs = { + ...tabs, + tabValues: tabs.tabValues + .slice(0) + .map((tab) => ({ + ...tab, + label: getCommonLabel(tab.value) || tab.label, + })) + .sort((a: any, b: any) => a.label.localeCompare(b.label)), + }; + console.log("Tabs", sortedTabs); return (
- +
); } diff --git a/src/theme/Tabs/utils.tsx b/src/theme/Tabs/utils.tsx new file mode 100644 index 0000000000..fe05903bc6 --- /dev/null +++ b/src/theme/Tabs/utils.tsx @@ -0,0 +1,27 @@ +const commonLabels = [ + { searchTerm: new RegExp("kubernetes", "i"), label: "Kubernetes Controller" }, + { + searchTerm: new RegExp("kubernetes-endpoint", "i"), + label: "Kubernetes Controller", + }, + { + searchTerm: new RegExp("kubernetes-controller", "i"), + label: "Kubernetes Controller", + }, + { searchTerm: new RegExp("k8s", "i"), label: "Kubernetes Controller" }, + { + searchTerm: new RegExp("k8s-controller", "i"), + label: "Kubernetes Controller", + }, + { + searchTerm: new RegExp("k8s-endpoint", "i"), + label: "Kubernetes Controller", + }, + { searchTerm: new RegExp("agent-config", "i"), label: "Agent Config" }, + { searchTerm: new RegExp("agent-endpoint", "i"), label: "Agent Endpoint" }, + { searchTerm: new RegExp("cloud-endpoint", "i"), label: "Cloud Endpoint" }, +]; + +export function getCommonLabel(value: string) { + return commonLabels.find((item) => item.searchTerm.test(value))?.label; +} From d8dc3a7983ad8d1a3a6fd2be044521d58368277d Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Mon, 7 Apr 2025 16:26:52 -0400 Subject: [PATCH 079/137] Removing the common label for tabs functionality; can't get it to work --- src/theme/Tabs/index.tsx | 5 ----- src/theme/Tabs/utils.tsx | 27 --------------------------- 2 files changed, 32 deletions(-) delete mode 100644 src/theme/Tabs/utils.tsx diff --git a/src/theme/Tabs/index.tsx b/src/theme/Tabs/index.tsx index 90c0ac46af..48b25bfb41 100644 --- a/src/theme/Tabs/index.tsx +++ b/src/theme/Tabs/index.tsx @@ -17,7 +17,6 @@ import clsx from "clsx"; import React, { useContext, type ReactElement, type ReactNode } from "react"; import styles from "./styles.module.css"; import TabListContext from "./TabListContext"; -import { getCommonLabel } from "./utils"; function getValidTabToShow( tabValues: readonly TabValue[], @@ -163,10 +162,6 @@ function TabsComponent(props: Props): ReactNode { ...tabs, tabValues: tabs.tabValues .slice(0) - .map((tab) => ({ - ...tab, - label: getCommonLabel(tab.value) || tab.label, - })) .sort((a: any, b: any) => a.label.localeCompare(b.label)), }; console.log("Tabs", sortedTabs); diff --git a/src/theme/Tabs/utils.tsx b/src/theme/Tabs/utils.tsx deleted file mode 100644 index fe05903bc6..0000000000 --- a/src/theme/Tabs/utils.tsx +++ /dev/null @@ -1,27 +0,0 @@ -const commonLabels = [ - { searchTerm: new RegExp("kubernetes", "i"), label: "Kubernetes Controller" }, - { - searchTerm: new RegExp("kubernetes-endpoint", "i"), - label: "Kubernetes Controller", - }, - { - searchTerm: new RegExp("kubernetes-controller", "i"), - label: "Kubernetes Controller", - }, - { searchTerm: new RegExp("k8s", "i"), label: "Kubernetes Controller" }, - { - searchTerm: new RegExp("k8s-controller", "i"), - label: "Kubernetes Controller", - }, - { - searchTerm: new RegExp("k8s-endpoint", "i"), - label: "Kubernetes Controller", - }, - { searchTerm: new RegExp("agent-config", "i"), label: "Agent Config" }, - { searchTerm: new RegExp("agent-endpoint", "i"), label: "Agent Endpoint" }, - { searchTerm: new RegExp("cloud-endpoint", "i"), label: "Cloud Endpoint" }, -]; - -export function getCommonLabel(value: string) { - return commonLabels.find((item) => item.searchTerm.test(value))?.label; -} From 6cbbfcf64c6878307dbbac31880acc1a0083f12a Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 8 Apr 2025 09:29:40 -0400 Subject: [PATCH 080/137] Remove convert to spaces --- src/components/CodeBlockWithInfo/index.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/components/CodeBlockWithInfo/index.tsx b/src/components/CodeBlockWithInfo/index.tsx index abfb8b28a3..855b2c7f58 100644 --- a/src/components/CodeBlockWithInfo/index.tsx +++ b/src/components/CodeBlockWithInfo/index.tsx @@ -11,7 +11,6 @@ import { fmtCode, } from "@ngrok/mantle/code-block"; import clsx from "clsx"; -import convertToSpaces from "convert-to-spaces"; import type { ReactNode } from "react"; import type { LanguageInfo } from "../LangSwitcher/data"; import { LanguageData } from "../LangSwitcher/LanguageData"; @@ -41,10 +40,6 @@ export function CodeBlockWithInfo({ ? false : meta.collapsible && content.split("\n").length > collapseLineNumber; - const codeblockContent = !meta?.tabsToSpaces - ? content - : convertToSpaces(content); - return (
@@ -73,10 +68,7 @@ export function CodeBlockWithInfo({
)} {!meta?.disableCopy && } - + {collapsible && } From 3ecd98ca8a74ed46159dbb690146c5a4b85ade01 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 8 Apr 2025 09:38:30 -0400 Subject: [PATCH 081/137] Fix sorting code --- docs/universal-gateway/http-s/index.mdx | 2 +- sidebars.js | 54 ++++++++++++------------- src/theme/Tabs/index.tsx | 8 ++-- 3 files changed, 31 insertions(+), 33 deletions(-) diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx index 66883a86bb..f7ff9b50da 100644 --- a/docs/universal-gateway/http-s/index.mdx +++ b/docs/universal-gateway/http-s/index.mdx @@ -219,7 +219,7 @@ ngrok api endpoints create \ ``` - + Follow the [ngrok Kubernetes Controller documentation](https://ngrok.com/docs/k8s/guides/quickstart/) to get started using ngrok with Kubernetes. You can use the following service definition to create an HTTP endpoint: diff --git a/sidebars.js b/sidebars.js index 18e0b8ae25..c74232ce4e 100644 --- a/sidebars.js +++ b/sidebars.js @@ -58,33 +58,6 @@ const sidebars = { "universal-gateway/wildcard-domains/wildcard-endpoints", ], }, - "universal-gateway/what-are-matching-endpoints", - { - label: "What are TCP Addresses?", - type: "category", - link: { - type: "doc", - id: "universal-gateway/tcp-addresses/what-are-tcp-addresses", - }, - items: [ - "universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned", - ], - }, - { - label: "How Does ngrok Handle TLS?", - type: "category", - link: { - type: "doc", - id: "universal-gateway/tls-certificates/how-does-ngrok-handle-tls", - }, - items: [ - "universal-gateway/tls-certificates/what-is-automatic-certificate-management", - "universal-gateway/tls-certificates/how-are-certificates-selected", - "universal-gateway/tls-certificates/how-do-i-use-my-own-certificates", - "universal-gateway/tls-certificates/what-is-a-certificate-bundle", - "universal-gateway/tls-certificates/what-are-private-tls-keys", - ], - }, { label: "What are Endpoints?", type: "category", @@ -132,11 +105,38 @@ const sidebars = { id: "universal-gateway/agent-endpoints", type: "doc", }, + "universal-gateway/what-are-matching-endpoints", "universal-gateway/chain-endpoints", "universal-gateway/mock-api", "universal-gateway/migrate-from-tunnels", ], }, + { + label: "What are TCP Addresses?", + type: "category", + link: { + type: "doc", + id: "universal-gateway/tcp-addresses/what-are-tcp-addresses", + }, + items: [ + "universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned", + ], + }, + { + label: "How Does ngrok Handle TLS?", + type: "category", + link: { + type: "doc", + id: "universal-gateway/tls-certificates/how-does-ngrok-handle-tls", + }, + items: [ + "universal-gateway/tls-certificates/what-is-automatic-certificate-management", + "universal-gateway/tls-certificates/how-are-certificates-selected", + "universal-gateway/tls-certificates/how-do-i-use-my-own-certificates", + "universal-gateway/tls-certificates/what-is-a-certificate-bundle", + "universal-gateway/tls-certificates/what-are-private-tls-keys", + ], + }, { label: "How Does Agent Fowarding Work?", type: "category", diff --git a/src/theme/Tabs/index.tsx b/src/theme/Tabs/index.tsx index 48b25bfb41..e8c39cd9da 100644 --- a/src/theme/Tabs/index.tsx +++ b/src/theme/Tabs/index.tsx @@ -70,8 +70,6 @@ function TabList({ const newTabValue = tabValues[newTabIndex]!.label || tabValues[newTabIndex]!.value; - console.log("Switching to", tabValues[newTabIndex]); - if (newTabValue !== selectedTabItem && updateSelectedTabItem) { blockElementScrollPositionUntilNextRender(newTab); updateSelectedTabItem(newTabValue); @@ -157,14 +155,14 @@ function TabContent({ children }: Props & ReturnType) { function TabsComponent(props: Props): ReactNode { const tabs = useTabs(props); - console.log("Tabs before sorting", tabs); const sortedTabs = { ...tabs, tabValues: tabs.tabValues .slice(0) - .sort((a: any, b: any) => a.label.localeCompare(b.label)), + .sort((a: any, b: any) => + a.label ? a.label.localeCompare(b.label) : -1, + ), }; - console.log("Tabs", sortedTabs); return (
From 5dfa1e26eb5b2fc7e592ed6472afcade41640089 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 8 Apr 2025 11:15:21 -0400 Subject: [PATCH 082/137] Break out how https endpoints work --- .../http-s/http-s-endpoints.mdx | 55 +++++++++++++++++++ docs/universal-gateway/http-s/index.mdx | 55 ------------------- sidebars.js | 29 +++++----- src/theme/Tabs/index.tsx | 4 +- 4 files changed, 70 insertions(+), 73 deletions(-) create mode 100644 docs/universal-gateway/http-s/http-s-endpoints.mdx diff --git a/docs/universal-gateway/http-s/http-s-endpoints.mdx b/docs/universal-gateway/http-s/http-s-endpoints.mdx new file mode 100644 index 0000000000..d8f0f31541 --- /dev/null +++ b/docs/universal-gateway/http-s/http-s-endpoints.mdx @@ -0,0 +1,55 @@ +--- +title: How do HTTP/S Endpoints Work? +description: Learn how ngrok's HTTP/S endpoints support websockets, HTTP/2, and more. +--- + +[HTTP/S endpoints](/universal-gateway/https-s) are standards-compliant HTTP reverse proxies. + +## Supported versions + +- HTTP/S endpoints support HTTP/1.1. +- HTTPS endpoints support HTTP/1.1 and HTTP/2. +- HTTP/1.0, HTTP/3 and QUIC are **not** supported. + +## HTTP/2 support + +HTTP/2 is a newer version of HTTP that offers improved performance by enabling multiple requests and responses over a single connection, among [other benefits](https://en.wikipedia.org/wiki/HTTP/2). + +ngrok's HTTPS endpoints automatically use HTTP/2 for all connections if the client +supports it. Client support is determined via standard [ALPN](https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation). + +HTTP/2 is used between the client and your endpoint even if your upstream +service does not support HTTP/2. + +See the [HTTP/2 agent forwarding](/universal-gateway/agent-forwarding/#http2-forwarding) documentation to learn how to use HTTP/2 when sending traffic to an upstream service. + +## Websocket support + +Websocket connections are supported out-of-the-box with no configuration required. + +## Hop by hop headers + +ngrok does not forward any [hop-by-hop +headers](https://datatracker.ietf.org/doc/html/rfc2616#section-13.5.1) to upstream services other than `Connection: upgrade`, which are forwarded +to support [websockets](#websocket-support). + +For information on headers added automatically by ngrok, see +[the docs on upstream headers for HTTP/S endpoints](/universal-gateway/http-s/#upstream-headers). + +## Persistent connections + +When a connection is made to HTTP/S ngrok endpoints with HTTP/1.1, ngrok may +choose to use [persistent connections](https://en.wikipedia.org/wiki/HTTP_persistent_connection), or HTTP keep-alive, to improve the +performance of future requests from the same client (if the client supports it). + +This behavior is not guaranteed and it is not configurable. + +See [RFC 7230](https://datatracker.ietf.org/doc/html/rfc7230#section-6.3) for +additional details. + +## Well Known URIs + +ngrok handles the `/.well-known/acme-challenge` path of any HTTP endpoint matching a +[domain](/universal-gateway/domains/what-are-domains) with [automated certificate management](/universal-gateway/tls-certificates/what-is-automatic-certificate-management/) +enabled. You may disable this behavior by [uploading your own certificate](/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates/) on the +matching domain. diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx index f7ff9b50da..2932ebd99d 100644 --- a/docs/universal-gateway/http-s/index.mdx +++ b/docs/universal-gateway/http-s/index.mdx @@ -279,61 +279,6 @@ system](/obs/). The following events are published for log exporting: | [http_request_complete.v0](/obs/events/reference/#http-request-complete) | Published when an HTTP request to an HTTP/S endpoints completes. | | [tcp_connection_closed.v0](/obs/events/reference/#tcp-connection-closed) | Published when a TCP connection to an HTTP/S endpoints completes. | -## Advanced - -HTTP/S endpoints are standards-compliant HTTP reverse proxies. - -### Versions - -- HTTP/S endpoints support HTTP/1.1. -- HTTPS endpoints support HTTP/1.1 and HTTP/2. -- HTTP/1.0, HTTP/3 and QUIC are **not** supported. - -### HTTP/2 - -HTTPS endpoints will automatically use HTTP/2 for all connections if the client -supports it. Client support is determined via standard ALPN negotiation. - -HTTP/2 is used between the client and your endpoint even even if your upstream -service does not support HTTP/2. - -The section on [HTTP/2 agent forwarding](#http2-forwarding) has details on how to -configure the use of HTTP/2 when sending traffic to an upstream service. - -### Websockets - -Websocket connections are supported out-of-the-box. No configuration is required. - -### Hop by hop headers - -ngrok does not forward any [hop-by-hop -headers](https://datatracker.ietf.org/doc/html/rfc2616#section-13.5.1) to the -upstream service. As an exception, `Connection: upgrade` headers are forwarded -to support [websockets](#websockets). - -For information on headers added automatically by ngrok, see -[Upstream Headers](#upstream-headers). - -### Persistent connections - -When a connection is made to HTTP/S ngrok endpoints with HTTP/1.1, ngrok may -choose to use persistent connections (aka HTTP keep-alive) to improve the -performance of future requests from the same client if the client supports it. - -This behavior is not guaranteed and it is not configurable. - -See [RFC 7230](https://datatracker.ietf.org/doc/html/rfc7230#section-6.3) for -additional details. - -### Well Known URIs - -#### `/.well-known/acme-challenge` - -ngrok takes over handling of this path of any HTTP endpoint matching a -[Domain](/universal-gateway/domains/what-are-domains) with automated certificate management -enabled. You may disable this behavior by uploading your own certificate on the -matching Domain. - ## TLS ngrok automatically handles TLS (SSL) certificate management and termination for you. diff --git a/sidebars.js b/sidebars.js index c74232ce4e..2afb2adebd 100644 --- a/sidebars.js +++ b/sidebars.js @@ -67,8 +67,8 @@ const sidebars = { }, items: [ "universal-gateway/bindings", + "universal-gateway/agent-endpoints", "universal-gateway/public-endpoints/index", - "universal-gateway/what-are-endpoint-urls", { label: "What are Internal Endpoints?", type: "category", @@ -78,6 +78,15 @@ const sidebars = { }, items: ["universal-gateway/internal-endpoints/quickstart"], }, + { + label: "What are Cloud Endpoints?", + type: "category", + link: { + type: "doc", + id: "universal-gateway/cloud-endpoints/index", + }, + items: ["universal-gateway/cloud-endpoints/quickstart"], + }, { label: "What are Kubernetes Endpoints?", type: "category", @@ -91,20 +100,8 @@ const sidebars = { "universal-gateway/kubernetes-endpoints/selector", ], }, - { - label: "What are Cloud Endpoints?", - type: "category", - link: { - type: "doc", - id: "universal-gateway/cloud-endpoints/index", - }, - items: ["universal-gateway/cloud-endpoints/quickstart"], - }, - { - label: "What are Agent Endpoints?", - id: "universal-gateway/agent-endpoints", - type: "doc", - }, + "universal-gateway/what-are-endpoint-urls", + "universal-gateway/http-s/endpoint-url-defaults", "universal-gateway/what-are-matching-endpoints", "universal-gateway/chain-endpoints", "universal-gateway/mock-api", @@ -150,7 +147,7 @@ const sidebars = { label: "How Do I Handle HTTP/S Traffic?", type: "category", link: { type: "doc", id: "universal-gateway/http-s/index" }, - items: ["universal-gateway/http-s/endpoint-url-defaults"], + items: ["universal-gateway/http-s/http-s-endpoints"], }, { label: "Endpoints", diff --git a/src/theme/Tabs/index.tsx b/src/theme/Tabs/index.tsx index e8c39cd9da..d909e9bea3 100644 --- a/src/theme/Tabs/index.tsx +++ b/src/theme/Tabs/index.tsx @@ -155,7 +155,7 @@ function TabContent({ children }: Props & ReturnType) { function TabsComponent(props: Props): ReactNode { const tabs = useTabs(props); - const sortedTabs = { + const alphabetizedTabs = { ...tabs, tabValues: tabs.tabValues .slice(0) @@ -165,7 +165,7 @@ function TabsComponent(props: Props): ReactNode { }; return (
- +
); } From 3850e6d46db83ff721cdf87ec3b1c262212aad17 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 8 Apr 2025 13:11:51 -0400 Subject: [PATCH 083/137] Finish HTTP/S page --- docs/errors/index.md | 14 ++ docs/pricing-limits/http-s-limits.mdx | 45 ++++ docs/universal-gateway/http-s/index.mdx | 228 +----------------- .../http-s/upstream-headers.mdx | 18 ++ 4 files changed, 87 insertions(+), 218 deletions(-) create mode 100644 docs/pricing-limits/http-s-limits.mdx create mode 100644 docs/universal-gateway/http-s/upstream-headers.mdx diff --git a/docs/errors/index.md b/docs/errors/index.md index 6c8d6eacea..f2427ce726 100644 --- a/docs/errors/index.md +++ b/docs/errors/index.md @@ -60,3 +60,17 @@ complete list of all of ngrok's error codes. ## Customize Error Pages for your Traffic To access and provide feedback on a development preview of custom error pages [Fill out the form](https://ngrok.com/new-features/custom-error-pages?ref=errordoc). + +## HTTP Errors + +If ngrok fails to handle an HTTP request it will set the `ngrok-error-code` header in the HTTP response with a [unique ngrok Error Code](/errors/) describing the failure. + +ngrok guarantees that the upstream service may never set the `ngrok-error-code` HTTP response header so you know reliably that it was set by ngrok. + +ngrok may return an error under the following conditions: + +- Your upstream service timed out or rejected the connection +- Your upstream service returned a response that was not valid HTTP +- A [Traffic Policy](/traffic-policy) action rejected the request. +- [Traffic Policy](/traffic-policy) execution encountered a runtime error. +- ngrok encountered an internal error diff --git a/docs/pricing-limits/http-s-limits.mdx b/docs/pricing-limits/http-s-limits.mdx new file mode 100644 index 0000000000..060e9ad382 --- /dev/null +++ b/docs/pricing-limits/http-s-limits.mdx @@ -0,0 +1,45 @@ +--- +title: HTTP/S Endpoint Limits +description: Learn about data limits and timeouts for HTTP/S endpoints on ngrok. +--- + +import TlsLimits from "../universal-gateway/_tls_limits.mdx"; + +[Contact us](mailto:support@ngrok.com) if you need to configure limits and timeouts on connections to HTTP/S endpoints. + +## Connection + +| Limit | Name | Notes | +| --------- | ------------------- | ------------------------------------------------------------ | +| 5 minutes | Client Idle Timeout | Time since data was last transmitted by the upstream service | +| 5 minutes | Server Idle Timeout | Time since data was last transmitted by the upstream service | +| No limit | Data transmitted | Data transmitted by the client or upstream service | + +## TLS + + + +## HTTP + +| Limit | Name | Notes | +| ---------- | ------------------ | --------------------------------------------- | +| No timeout | Round Trip Timeout | Time for the entire HTTP request and response | + +## HTTP Request + +| Limit | Name | Notes | +| ---------- | ---------------------- | ---------------------------------------------------- | +| 1 MB | Request Header Size | Includes method, URI and headers | +| 1 MB | Request URI Length | Limited by the size of the request header | +| No timeout | Request Timeout | Time to read the entire HTTP request from the client | +| No timeout | Request Header Timeout | Time to read the HTTP request header from the client | +| No limit | Request Body Size | | + +## HTTP Response + +| Limit | Name | Notes | +| ---------- | ----------------------- | ----------------------------------------------------- | +| 1 MB | Response Header Size | Includes method, URI and headers | +| No timeout | Response Timeout | Time to read the entire HTTP response from the server | +| No timeout | Response Header Timeout | Time to read the HTTP response header from the server | +| No limit | Response Body Size | | diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx index 2932ebd99d..e34ca9f7ad 100644 --- a/docs/universal-gateway/http-s/index.mdx +++ b/docs/universal-gateway/http-s/index.mdx @@ -3,109 +3,13 @@ title: How Do I Handle HTTP/S traffic? description: Learn how to create HTTP/S endpoints with ngrok. --- +import StaticDomainAgentConfigExample from "/examples/agent-config/http-static-domain.mdx"; +import StaticDomainKubernetesExample from "/examples/k8s/http-static-domain.mdx"; + import TabItem from "@theme/TabItem"; import Tabs from "@theme/Tabs"; import { LangSwitcher } from "@site/src/components/LangSwitcher"; -import TlsLimits from "../_tls_limits.mdx"; - -import RandomAgentCliExample from "/examples/agent-cli/http-random.mdx"; -import RandomAgentConfigExample from "/examples/agent-config/http-random.mdx"; -import RandomGoSdkExample from "/examples/go-sdk/http-random.mdx"; -import RandomJavascriptSdkExample from "/examples/javascript-sdk/http-random.mdx"; -import RandomPythonSdkExample from "/examples/python-sdk/http-random.mdx"; -import RandomRustSdkExample from "/examples/rust-sdk/http-random.mdx"; -import RandomSshExample from "/examples/ssh/http-random.mdx"; - -import StaticDomainAgentCliExample from "/examples/agent-cli/http-static-domain.mdx"; -import StaticDomainAgentConfigExample from "/examples/agent-config/http-static-domain.mdx"; -import StaticDomainGoSdkExample from "/examples/go-sdk/http-static-domain.mdx"; -import StaticDomainJavascriptSdkExample from "/examples/javascript-sdk/http-static-domain.mdx"; -import StaticDomainKubernetesExample from "/examples/k8s/http-static-domain.mdx"; -import StaticDomainPythonSdkExample from "/examples/python-sdk/http-static-domain.mdx"; -import StaticDomainRustSdkExample from "/examples/rust-sdk/http-static-domain.mdx"; -import StaticDomainSshExample from "/examples/ssh/http-static-domain.mdx"; - -import BrandedDomainAgentCliExample from "/examples/agent-cli/http-branded-domain.mdx"; -import BrandedDomainAgentConfigExample from "/examples/agent-config/http-branded-domain.mdx"; -import BrandedDomainGoSdkExample from "/examples/go-sdk/http-branded-domain.mdx"; -import BrandedDomainJavascriptSdkExample from "/examples/javascript-sdk/http-branded-domain.mdx"; -import BrandedDomainKubernetesExample from "/examples/k8s/http-branded-domain.mdx"; -import BrandedDomainPythonSdkExample from "/examples/python-sdk/http-branded-domain.mdx"; -import BrandedDomainRustSdkExample from "/examples/rust-sdk/http-branded-domain.mdx"; -import BrandedDomainSshExample from "/examples/ssh/http-branded-domain.mdx"; - -import BasicAuthAgentCliExample from "/examples/agent-cli/http-basic-auth.mdx"; -import BasicAuthAgentConfigExample from "/examples/agent-config/http-basic-auth.mdx"; -import BasicAuthGoSdkExample from "/examples/go-sdk/http-basic-auth.mdx"; -import BasicAuthJavascriptSdkExample from "/examples/javascript-sdk/http-basic-auth.mdx"; -import BasicAuthKubernetesExample from "/examples/k8s/http-basic-auth.mdx"; -import BasicAuthPythonSdkExample from "/examples/python-sdk/http-basic-auth.mdx"; -import BasicAuthRustSdkExample from "/examples/rust-sdk/http-basic-auth.mdx"; -import BasicAuthSshExample from "/examples/ssh/http-basic-auth.mdx"; - -import OAuthAgentCliExample from "/examples/agent-cli/http-oauth-authn.mdx"; -import OAuthAgentConfigExample from "/examples/agent-config/http-oauth-authn.mdx"; -import OAuthGoSdkExample from "/examples/go-sdk/http-oauth-authn.mdx"; -import OAuthJavascriptSdkExample from "/examples/javascript-sdk/http-oauth-authn.mdx"; -import OAuthKubernetesExample from "/examples/k8s/http-oauth-authn.mdx"; -import OAuthPythonSdkExample from "/examples/python-sdk/http-oauth-authn.mdx"; -import OAuthRustSdkExample from "/examples/rust-sdk/http-oauth-authn.mdx"; -import OAuthSshExample from "/examples/ssh/http-oauth-authn.mdx"; - -import ForwardHttpsAgentCliExample from "/examples/agent-cli/http-forward-https.mdx"; -import ForwardHttpsAgentConfigExample from "/examples/agent-config/http-forward-https.mdx"; -import ForwardHttpsGoSdkExample from "/examples/go-sdk/http-forward-https.mdx"; -import ForwardHttpsJavascriptSdkExample from "/examples/javascript-sdk/http-forward-https.mdx"; -import ForwardHttpsKubernetesExample from "/examples/k8s/http-forward-https.mdx"; -import ForwardHttpsPythonSdkExample from "/examples/python-sdk/http-forward-https.mdx"; -import ForwardHttpsRustSdkExample from "/examples/rust-sdk/http-forward-https.mdx"; -import ForwardHttpsSshExample from "/examples/ssh/http-forward-https.mdx"; - -import HostHeaderAgentCliExample from "/examples/agent-cli/http-rewrite-host-header.mdx"; -import HostHeaderAgentConfigExample from "/examples/agent-config/http-rewrite-host-header.mdx"; -import HostHeaderGoSdkExample from "/examples/go-sdk/http-rewrite-host-header.mdx"; -import HostHeaderJavascriptSdkExample from "/examples/javascript-sdk/http-rewrite-host-header.mdx"; -import HostHeaderKubernetesExample from "/examples/k8s/http-rewrite-host-header.mdx"; -import HostHeaderPythonSdkExample from "/examples/python-sdk/http-rewrite-host-header.mdx"; -import HostHeaderRustSdkExample from "/examples/rust-sdk/http-rewrite-host-header.mdx"; -import HostHeaderSshExample from "/examples/ssh/http-rewrite-host-header.mdx"; - -import NonLocalAgentCliExample from "/examples/agent-cli/http-nonlocal.mdx"; -import NonLocalAgentConfigExample from "/examples/agent-config/http-nonlocal.mdx"; -import NonLocalGoSdkExample from "/examples/go-sdk/http-nonlocal.mdx"; -import NonLocalJavascriptSdkExample from "/examples/javascript-sdk/http-nonlocal.mdx"; -import NonLocalKubernetesExample from "/examples/k8s/http-nonlocal.mdx"; -import NonLocalPythonSdkExample from "/examples/python-sdk/http-nonlocal.mdx"; -import NonLocalRustSdkExample from "/examples/rust-sdk/http-nonlocal.mdx"; -import NonLocalSshExample from "/examples/ssh/http-nonlocal.mdx"; - -import AbsPathFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-abs-path.mdx"; -import AbsPathFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-abs-path.mdx"; -import AbsPathFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverKubernetesExample from "/examples/k8s/http-fileserver-abs-path.mdx"; -import AbsPathFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverSshExample from "/examples/ssh/http-fileserver-abs-path.mdx"; - -import WorkingDirFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverKubernetesExample from "/examples/k8s/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverSshExample from "/examples/ssh/http-fileserver-working-dir.mdx"; - -import WindowsFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-windows.mdx"; -import WindowsFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-windows.mdx"; -import WindowsFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverKubernetesExample from "/examples/k8s/http-fileserver-windows.mdx"; -import WindowsFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverSshExample from "/examples/ssh/http-fileserver-windows.mdx"; You can create HTTP/S endpoints to serve web services like REST APIs, web applications, websites and websocket servers. @@ -256,131 +160,19 @@ ngrok api endpoints create \ - **Wildcard Endpoints** — You can create HTTP/S endpoints that receive traffic from all of the subdomains matching a given wildcard domain. See [the wildcard domain docs](/universal-gateway/wildcard-domains/) for more information. - **Traffic Policy** — Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate and transform the traffic through the endpoint. - **Agent Forwarding** — The [ngrok agent](/agent/) and [Agent SDKs](/agent-sdks/) forward traffic that your endpoints receive to upstream services. See [the agent forwarding documentation](/universal-gateway/agent-forwarding/) for more information. -- **URLS** — -- **URLS** — -- **URLS** — - -## Traffic Observability - -### Traffic Inspector - -[Traffic Inspector](/obs/traffic-inspection/) gives you a real-time view in the -ngrok dashboard of the HTTP traffic flowing through your HTTP/S endpoints. You -can choose whether Traffic Inspector captures only request metadata or full -request and response bodies. - -### Log Export Events - -You can export logs of traffic to HTTP/S endpoints with [ngrok's events -system](/obs/). The following events are published for log exporting: - -| Event | When | -| ------------------------------------------------------------------------ | ----------------------------------------------------------------- | -| [http_request_complete.v0](/obs/events/reference/#http-request-complete) | Published when an HTTP request to an HTTP/S endpoints completes. | -| [tcp_connection_closed.v0](/obs/events/reference/#tcp-connection-closed) | Published when a TCP connection to an HTTP/S endpoints completes. | - -## TLS - -ngrok automatically handles TLS (SSL) certificate management and termination for you. -There is nothing to setup, configure or manage. - -TLS connections to `https` endpoints are terminated at ngrok's cloud service. -If you wish to terminate TLS traffic at the ngrok agent or in your upstream -application, use a [TLS Endpoint](/universal-gateway/tls) instead. - -Consult the following documentation for additional details on how ngrok handles -TLS termination and certificiate management: - -- [TLS Certificates](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls) -- [TLS Termination](/universal-gateway/tls-termination) - -## Upstream Headers - -ngrok adds headers to each HTTP request with information about the original -client IP, request scheme and request `host` header value. - -| Header | Description | -| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -| `x-forwarded-for` | The IP address of the client who initiated the request. If this header exists on the original request, ngrok will append a new value. | -| `x-forwarded-proto` | The scheme of the original request, either `http` or `https`. If this header exists on the original request, ngrok will append a new value. | -| `x-forwarded-host` | The header from the client's request if it existed, otherwise is set to the request's `Host` header value. | - -Because ngrok appends values to `x-forwarded-for` and `x-forwarded-proto`, be -sure to use the last value of the header in your application code to read the -values injected by ngrok. - -You may remove these headers with the [Remove -Headers](/traffic-policy/actions/remove-headers/) Traffic Policy action. - -## Limits & Timeouts - -[Contact us](mailto:support@ngrok.com) if you need to configure limits and -timeouts on connections to HTTP endpoints. - -#### Connection - -| Limit | Name | Notes | -| --------- | ------------------- | ------------------------------------------------------------ | -| 5 minutes | Client Idle Timeout | Time since data was last transmitted by the upstream service | -| 5 minutes | Server Idle Timeout | Time since data was last transmitted by the upstream service | -| No limit | Data transmitted | Data transmitted by the client or upstream service | - -#### TLS - - - -#### HTTP - -| Limit | Name | Notes | -| ---------- | ------------------ | --------------------------------------------- | -| No timeout | Round Trip Timeout | Time for the entire HTTP request and response | - -#### HTTP Request - -| Limit | Name | Notes | -| ---------- | ---------------------- | ---------------------------------------------------- | -| 1 MB | Request Header Size | Includes method, URI and headers | -| 1 MB | Request URI Length | Limited by the size of the request header | -| No timeout | Request Timeout | Time to read the entire HTTP request from the client | -| No timeout | Request Header Timeout | Time to read the HTTP request header from the client | -| No limit | Request Body Size | | - -#### HTTP Response - -| Limit | Name | Notes | -| ---------- | ----------------------- | ----------------------------------------------------- | -| 1 MB | Response Header Size | Includes method, URI and headers | -| No timeout | Response Timeout | Time to read the entire HTTP response from the server | -| No timeout | Response Header Timeout | Time to read the HTTP response header from the server | -| No limit | Response Body Size | | +- **Traffic Observability** — [Traffic Inspector](/obs/traffic-inspection/) gives you a real-time view in the ngrok dashboard of the HTTP traffic flowing through your HTTP/S endpoints. You can even [export traffic logs with the Traffic Events system](/docs/obs/events/reference/#traffic-events). +- **TLC** — Learn how [ngrok automatically handles TLS](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) and [TLS termination](/universal-gateway/tls-termination/) for HTTP/S endpoints for you. ## Errors -If ngrok fails to handle an HTTP request it will set the `ngrok-error-code` -header in the HTTP response with a [unique ngrok Error Code](/errors/) -describing the failure. - -ngrok guarantees that the upstream service may never set the `ngrok-error-code` -HTTP response header so you know reliably that it was set by ngrok. - -ngrok may return an error under the following conditions: - -- Your upstream service timed out or rejected the connection -- Your upstream service returned a response that was not valid HTTP -- A [Traffic Policy](/traffic-policy) action rejected the request. -- [Traffic Policy](/traffic-policy) execution encountered a runtime error. -- ngrok encountered an internal error +Learn how ngrok handles errors for HTTP/S endpoints in the [Errors documentation](/errors/#http-errors). ## API -HTTP/S Endpoints can be created programatically. Consult the documentation on -[Endpoint APIs](/api/resources/endpoints/). +HTTP/S Endpoints can be created programatically. Consult the documentation on [Endpoint APIs](/api/resources/endpoints/). -## Pricing +## Limits & Pricing -HTTP/S endpoints are available on all plans. Consult the [Endpoints -Pricing](/universal-gateway/endpoints/#pricing) documentation for -billing details. +HTTP/S endpoints are available on all plans. Consult the [pricing](/pricing-limits/) documentation for billing details. -See [Domains pricing](/universal-gateway/domains/#pricing) for details on -pricing for custom domains, wildcard domains and more. +For limits, see the [HTTP/S Limits documentation](/pricing-limits/http-s-limits/). diff --git a/docs/universal-gateway/http-s/upstream-headers.mdx b/docs/universal-gateway/http-s/upstream-headers.mdx new file mode 100644 index 0000000000..99a72e1962 --- /dev/null +++ b/docs/universal-gateway/http-s/upstream-headers.mdx @@ -0,0 +1,18 @@ +--- +title: How Do Upstream Headers Work with HTTP/S? +--- + +ngrok adds headers to each [HTTP request](/universal-gateway/http-s/) with information about the original +client IP, request scheme and request `host` header value. + +| Header | Description | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| `x-forwarded-for` | The IP address of the client who initiated the request. If this header exists on the original request, ngrok will append a new value. | +| `x-forwarded-proto` | The scheme of the original request, either `http` or `https`. If this header exists on the original request, ngrok will append a new value. | +| `x-forwarded-host` | The header from the client's request if it existed, otherwise is set to the request's `Host` header value. | + +Because ngrok appends values to `x-forwarded-for` and `x-forwarded-proto`, be +sure to use the last value of the header in your application code to read the +values injected by ngrok. + +You may remove these headers with the [Remove Headers](/traffic-policy/actions/remove-headers/) Traffic Policy action. From 47f972bf997353036da62bb2a2f4b69be5062324 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 8 Apr 2025 13:22:00 -0400 Subject: [PATCH 084/137] Add sidebar changes --- sidebars.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sidebars.js b/sidebars.js index 2afb2adebd..01425bc323 100644 --- a/sidebars.js +++ b/sidebars.js @@ -34,7 +34,10 @@ const sidebars = { label: "Pricing & Limits", type: "category", link: { type: "doc", id: "pricing-limits/index" }, - items: ["pricing-limits/free-plan-limits"], + items: [ + "pricing-limits/free-plan-limits", + "pricing-limits/http-s-limits", + ], }, { label: "Universal Gateway", @@ -132,6 +135,7 @@ const sidebars = { "universal-gateway/tls-certificates/how-do-i-use-my-own-certificates", "universal-gateway/tls-certificates/what-is-a-certificate-bundle", "universal-gateway/tls-certificates/what-are-private-tls-keys", + "universal-gateway/http-s/upstream-headers", ], }, { From 694d2841361f1cf2fa1dc80ce3556fc843c91f08 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 8 Apr 2025 13:24:20 -0400 Subject: [PATCH 085/137] Put upstream headers in its proper place --- sidebars.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sidebars.js b/sidebars.js index 01425bc323..46d4cf43f7 100644 --- a/sidebars.js +++ b/sidebars.js @@ -135,7 +135,6 @@ const sidebars = { "universal-gateway/tls-certificates/how-do-i-use-my-own-certificates", "universal-gateway/tls-certificates/what-is-a-certificate-bundle", "universal-gateway/tls-certificates/what-are-private-tls-keys", - "universal-gateway/http-s/upstream-headers", ], }, { @@ -151,7 +150,10 @@ const sidebars = { label: "How Do I Handle HTTP/S Traffic?", type: "category", link: { type: "doc", id: "universal-gateway/http-s/index" }, - items: ["universal-gateway/http-s/http-s-endpoints"], + items: [ + "universal-gateway/http-s/http-s-endpoints", + "universal-gateway/http-s/upstream-headers", + ], }, { label: "Endpoints", From b01c1d7d56fd0effa6757409984fdac8e2a9e698 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 8 Apr 2025 13:27:28 -0400 Subject: [PATCH 086/137] Nest certificates under TLS --- sidebars.js | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/sidebars.js b/sidebars.js index 46d4cf43f7..8880faa354 100644 --- a/sidebars.js +++ b/sidebars.js @@ -123,18 +123,28 @@ const sidebars = { ], }, { - label: "How Does ngrok Handle TLS?", + label: "How Do I Handle TLS Traffic?", type: "category", link: { type: "doc", - id: "universal-gateway/tls-certificates/how-does-ngrok-handle-tls", + id: "universal-gateway/tls", }, items: [ - "universal-gateway/tls-certificates/what-is-automatic-certificate-management", - "universal-gateway/tls-certificates/how-are-certificates-selected", - "universal-gateway/tls-certificates/how-do-i-use-my-own-certificates", - "universal-gateway/tls-certificates/what-is-a-certificate-bundle", - "universal-gateway/tls-certificates/what-are-private-tls-keys", + { + label: "How Does ngrok Handle TLS Certificates?", + type: "category", + link: { + type: "doc", + id: "universal-gateway/tls-certificates/how-does-ngrok-handle-tls", + }, + items: [ + "universal-gateway/tls-certificates/what-is-automatic-certificate-management", + "universal-gateway/tls-certificates/how-are-certificates-selected", + "universal-gateway/tls-certificates/how-do-i-use-my-own-certificates", + "universal-gateway/tls-certificates/what-is-a-certificate-bundle", + "universal-gateway/tls-certificates/what-are-private-tls-keys", + ], + }, ], }, { From ebb1c114c9811d2b7ec499ea8f63f31d8a1b9602 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 8 Apr 2025 14:43:28 -0400 Subject: [PATCH 087/137] Almost done breaking up TLS --- docs/errors/index.md | 14 ++ ...{http-s-limits.mdx => endpoint-limits.mdx} | 35 ++- docs/universal-gateway/bindings.mdx | 4 + docs/universal-gateway/http-s/index.mdx | 6 +- docs/universal-gateway/tls-termination.mdx | 3 +- docs/universal-gateway/tls.mdx | 222 ++---------------- docs/universal-gateway/tls/tls-clients.mdx | 20 ++ .../what-are-endpoint-urls.mdx | 4 + sidebars.js | 4 +- traffic-policy/actions/restrict-ips/index.mdx | 4 + .../actions/terminate-tls/index.mdx | 4 + 11 files changed, 104 insertions(+), 216 deletions(-) rename docs/pricing-limits/{http-s-limits.mdx => endpoint-limits.mdx} (65%) create mode 100644 docs/universal-gateway/tls/tls-clients.mdx diff --git a/docs/errors/index.md b/docs/errors/index.md index f2427ce726..2c6bc664e8 100644 --- a/docs/errors/index.md +++ b/docs/errors/index.md @@ -74,3 +74,17 @@ ngrok may return an error under the following conditions: - A [Traffic Policy](/traffic-policy) action rejected the request. - [Traffic Policy](/traffic-policy) execution encountered a runtime error. - ngrok encountered an internal error + +## TLS Errors + +If a TLS handshake fails, an appropriate TLS abort code will be sent to the +client. + +In all other cases, if an error is encountered while handling TLS connections +to your endpoints (e.g. no available backends or internal server error), the +connection will be closed. The TLS protocol and its implementations are not +sufficiently flexible enough to deliver additional rich error information when +failures are encountered. + +Use the [observability](#observability) features to understand connection +handling errors. diff --git a/docs/pricing-limits/http-s-limits.mdx b/docs/pricing-limits/endpoint-limits.mdx similarity index 65% rename from docs/pricing-limits/http-s-limits.mdx rename to docs/pricing-limits/endpoint-limits.mdx index 060e9ad382..774a718608 100644 --- a/docs/pricing-limits/http-s-limits.mdx +++ b/docs/pricing-limits/endpoint-limits.mdx @@ -1,13 +1,18 @@ --- -title: HTTP/S Endpoint Limits -description: Learn about data limits and timeouts for HTTP/S endpoints on ngrok. +title: Endpoint Limits +description: Learn about data limits and timeouts for endpoints on ngrok. --- +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; import TlsLimits from "../universal-gateway/_tls_limits.mdx"; -[Contact us](mailto:support@ngrok.com) if you need to configure limits and timeouts on connections to HTTP/S endpoints. +[Contact us](mailto:support@ngrok.com) if you need to configure limits and timeouts on connections to endpoints. -## Connection +## Connection limits + + + | Limit | Name | Notes | | --------- | ------------------- | ------------------------------------------------------------ | @@ -15,17 +20,31 @@ import TlsLimits from "../universal-gateway/_tls_limits.mdx"; | 5 minutes | Server Idle Timeout | Time since data was last transmitted by the upstream service | | No limit | Data transmitted | Data transmitted by the client or upstream service | -## TLS + + + +| Limit | Name | Notes | +| --------- | ------------------- | -------------------------------------------------------------- | +| 3 seconds | ClientHello Timeout | Time between connection establishment and ClientHello received | +| 5 minutes | Client Idle Timeout | Time since data was last transmitted by the upstream service | +| 5 minutes | Server Idle Timeout | Time since data was last transmitted by the upstream service | +| No limit | Data transmitted | Data transmitted by the client or upstream service | + + + + + +## TLS certificate limits -## HTTP +## HTTP timeout limits | Limit | Name | Notes | | ---------- | ------------------ | --------------------------------------------- | | No timeout | Round Trip Timeout | Time for the entire HTTP request and response | -## HTTP Request +## HTTP Request limits | Limit | Name | Notes | | ---------- | ---------------------- | ---------------------------------------------------- | @@ -35,7 +54,7 @@ import TlsLimits from "../universal-gateway/_tls_limits.mdx"; | No timeout | Request Header Timeout | Time to read the HTTP request header from the client | | No limit | Request Body Size | | -## HTTP Response +## HTTP Response limits | Limit | Name | Notes | | ---------- | ----------------------- | ----------------------------------------------------- | diff --git a/docs/universal-gateway/bindings.mdx b/docs/universal-gateway/bindings.mdx index b711bdf1b2..1da004651a 100644 --- a/docs/universal-gateway/bindings.mdx +++ b/docs/universal-gateway/bindings.mdx @@ -37,4 +37,8 @@ Example URLs: - `http://service.namespace` - `tcp://db.controlplane:5432` +:::note +TLS endpoints don't support the `kubernetes` binding. +::: + Learn more about [Kubernetes Endpoints](/universal-gateway/kubernetes-endpoints). diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx index e34ca9f7ad..c8d5584a9e 100644 --- a/docs/universal-gateway/http-s/index.mdx +++ b/docs/universal-gateway/http-s/index.mdx @@ -161,7 +161,7 @@ ngrok api endpoints create \ - **Traffic Policy** — Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate and transform the traffic through the endpoint. - **Agent Forwarding** — The [ngrok agent](/agent/) and [Agent SDKs](/agent-sdks/) forward traffic that your endpoints receive to upstream services. See [the agent forwarding documentation](/universal-gateway/agent-forwarding/) for more information. - **Traffic Observability** — [Traffic Inspector](/obs/traffic-inspection/) gives you a real-time view in the ngrok dashboard of the HTTP traffic flowing through your HTTP/S endpoints. You can even [export traffic logs with the Traffic Events system](/docs/obs/events/reference/#traffic-events). -- **TLC** — Learn how [ngrok automatically handles TLS](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) and [TLS termination](/universal-gateway/tls-termination/) for HTTP/S endpoints for you. +- **TLS** — Learn how [ngrok automatically handles TLS](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) and [TLS termination](/universal-gateway/tls-termination/) for HTTP/S endpoints for you. ## Errors @@ -173,6 +173,6 @@ HTTP/S Endpoints can be created programatically. Consult the documentation on [E ## Limits & Pricing -HTTP/S endpoints are available on all plans. Consult the [pricing](/pricing-limits/) documentation for billing details. +HTTP/S endpoints are available on all plans. Consult the [pricing](/pricing-limits/) documentation for general billing details. -For limits, see the [HTTP/S Limits documentation](/pricing-limits/http-s-limits/). +For HTTP/S limits, see the [endpoint Limits documentation](/pricing-limits/endpoint-limits/). diff --git a/docs/universal-gateway/tls-termination.mdx b/docs/universal-gateway/tls-termination.mdx index b515a61d2f..87603bf8fc 100644 --- a/docs/universal-gateway/tls-termination.mdx +++ b/docs/universal-gateway/tls-termination.mdx @@ -1,5 +1,6 @@ --- -title: TLS Termination +title: How Do I Handle TLS Termination? +description: Learn how to terminate TLS with ngrok. --- import TabItem from "@theme/TabItem"; diff --git a/docs/universal-gateway/tls.mdx b/docs/universal-gateway/tls.mdx index 9aa2425a37..877c4f1a74 100644 --- a/docs/universal-gateway/tls.mdx +++ b/docs/universal-gateway/tls.mdx @@ -100,176 +100,27 @@ Endpoint](/universal-gateway/http/). -## URLs +## Learn more -URLs are validated differently depending on their -[binding](/universal-gateway/bindings). Consult the -following documentation for details on valid URLs for TLS endpoints: +- **URLS** — URLs are validated differently depending on their [binding](/universal-gateway/bindings). To learn more about valid URLs for TLS endpoints, see [the Endpoint URLs documentation](/docs/universal-gateway/what-are-endpoint-urls/#http). +- **Domains** — Public TLS endpoints must match a domain on your account. See [the domains documentation](/universal-gateway/domains/what-are-domains/) for more information. +- **Authentication** — You can secure your TLS endpoints with the [IP Restriction](/traffic-policy/actions/restrict-ips/) and [Mutual TLS](/docs/guides/other-guides/how-to-terminate-traffic-with-ngrok-configs/#mutual-tls-example) Traffic Policy actions. There is a limited set of actions available to authenticate TLS traffic because the TLS protocol is low-level. +- **Bring your own domain** — To use your own domain with TLS endpoints, see [the guide on the subject](/universal-gateway/how-do-i-use-my-own-domain). +- **Wildcard Endpoints** — You can create TLS endpoints that receive traffic from all of the subdomains matching a given wildcard domain. See [the wildcard domain docs](/universal-gateway/wildcard-domains/) for more information. +- **Traffic Policy** — Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate and transform the traffic through the endpoint. +- **Agent Forwarding** — The [ngrok agent](/agent/) and [Agent SDKs](/agent-sdks/) forward traffic that your endpoints receive to upstream services. See [the agent forwarding documentation](/universal-gateway/agent-forwarding/) for more information. +- **Traffic Observability** — [Traffic Inspector](/obs/traffic-inspection/) gives you a real-time view in the ngrok dashboard of the HTTP traffic flowing through your TLS endpoints. You can even [export traffic logs with the Traffic Events system](/docs/obs/events/reference/#traffic-events). +- **TLS Certificates** — Learn how [ngrok automatically handles TLS](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) and [TLS termination](/universal-gateway/tls-termination/) for TLS endpoints for you. -- [Public Endpoint URLs](/universal-gateway/public-endpoints/#https-tls) -- [Internal Endpoint URLs](/universal-gateway/internal-endpoints/#urls) -- [Kubernetes Endpoint URLs](/universal-gateway/kubernetes-endpoints/#urls) +## TLS termination -There is no standard scheme for TLS URLs so ngrok renders them as `tls://`. +TLS Endpoints enable you to to define where [TLS termination](/universal-gateway/tls-termination/) occurs. You can configure your endpoint to terminate TLS at the ngrok cloud service. You can also achieve [end-to-end encryption](/universal-gateway/tls-termination/#end-to-end-encryption) by terminating at the agent or your upstream service. -## Bindings +:::tip +When you use end-to-end encryption, the ngrok cloud service can not see payloads that transit through your endpoints. +::: -TLS endpoints support `public` and `internal` bindings. `kubernetes` binding is -not supported. - -## Traffic Policy - -Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate -and transform the traffic through your TLS endpoints. - -### Authentication - -When you create public TLS endpoints, you often want to secure them with -authentication. You can secure your TLS endpoints with the following [Traffic -Policy](/traffic-policy/) actions. There is a limited set of actions available -to authenticate TLS traffic because the TLS protocol is low-level. - -- [IP Restriction](/traffic-policy/actions/restrict-ips/) -- [Mutual TLS](/traffic-policy/actions/terminate-tls/) - -## TLS - -### Termination - -TLS Endpoints provide you with the flexibility to define where TLS termination -occurs. You may configure your endpoint to terminate TLS at the ngrok cloud -service or you can achieve [end-to-end -encryption](/universal-gateway/tls-termination/#end-to-end-encryption) -by terminating at the agent or your upstream service. When you use end-to-end -encryption, the ngrok cloud service can not see payload that transit through -your endpoints. - -Consult the documentation on [TLS Termination -Locations](/universal-gateway/tls-termination/#termination-location) for -additional details. - -#### Cloud Service - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -#### Terminate at Agent - -See [TLS Termination at the Agent for End-to-End Encryption](/universal-gateway/tls-termination#end-to-end-encryption) for additional details. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -#### Terminate at Upstream - - - - - - - - - - - - - - - - - - - - - - - - - - - - -### Certificates - -It is very common to encounter certificate errors when working with TLS -endpoints. When terminating TLS at ngrok's cloud service, ngrok will -automatically select, provision and manage certs for you. When performing -[end-to-end -encryption](/universal-gateway/tls-termination/#end-to-end-encryption) -by terminating at the agent or upstream service, you become responsible for -provisioning, managing and distributing certificates. - -Consult the documentation on [TLS -Certificates](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) for details about -certificate selection, provisioning and management. - -## Compatible Clients - -### SNI - -TLS endpoints only work with modern TLS clients that populate the SNI -extension. See the documentation on [TLS -Termination](/universal-gateway/tls-termination/#sni) for additional -details on compatible clients. - -### STARTTLS - -Protocols that begin in plain text and upgrade to TLS via a mechanism like -STARTTLS in SMTP, IMAP, etc are not supported. If you need to support -connections which upgrade to TLS, use a [TCP -Endpoint](/universal-gateway/tcp/). +See [the TLS Termination documentation](/universal-gateway/tls-termination/#termination-location) for more information. ## Observability @@ -286,50 +137,17 @@ system](/obs/). The following events are published for log exporting: | ------------------------------------------------------------------------ | ------------------------------------------------------------ | | [tcp_connection_closed.v0](/obs/events/reference/#tcp-connection-closed) | Published when a TCP connection to a TCP endpoint completes. | -## Limits & Timeouts - -[Contact us](mailto:support@ngrok.com) if you need to configure limits and -timeouts on connections to TLS endpoints. - -#### Connections - -| Limit | Name | Notes | -| --------- | ------------------- | -------------------------------------------------------------- | -| 3 seconds | ClientHello Timeout | Time between connection establishment and ClientHello received | -| 5 minutes | Client Idle Timeout | Time since data was last transmitted by the upstream service | -| 5 minutes | Server Idle Timeout | Time since data was last transmitted by the upstream service | -| No limit | Data transmitted | Data transmitted by the client or upstream service | - -#### TLS - - - ## Errors -If a TLS handshake fails, an appropriate TLS abort code will be sent to the -client. - -In all other cases, if an error is encountered while handling TLS connections -to your endpoints (e.g. no available backends or internal server error), the -connection will be closed. The TLS protocol and its implementations are not -sufficiently flexible enough to deliver additional rich error information when -failures are encountered. - -Use the [observability](#observability) features to understand connection -handling errors. +Learn how ngrok handles errors for TLS endpoints in the [Errors documentation](/errors/#tls-errors). ## API TLS Endpoints can be created programatically. Consult the documentation on [Endpoint APIs](/api/resources/endpoints/). -## Pricing - -TLS endpoints are available on Pay-as-you-go, Pro, and Enterprise plans. Consult the [Endpoints -Pricing](/universal-gateway/endpoints/#pricing) documentation for -billing details. +## Limits & Timeouts -See [Domains pricing](/universal-gateway/domains/#pricing) for details on -pricing for custom domains, wildcard domains and more. +TLS endpoints are available on Pay-as-you-go, Pro, and Enterprise plans. Consult the [pricing](/pricing-limits/) documentation for general billing details. -Zero-knowledge TLS is available on the Enterprise plan. +For TLS limits, see the [endpoint Limits documentation](/pricing-limits/endpoint-limits/). diff --git a/docs/universal-gateway/tls/tls-clients.mdx b/docs/universal-gateway/tls/tls-clients.mdx new file mode 100644 index 0000000000..4093ef8b4e --- /dev/null +++ b/docs/universal-gateway/tls/tls-clients.mdx @@ -0,0 +1,20 @@ +--- +title: Which TLS Clients Do ngrok Support? +description: Learn about the different TLS clients available for ngrok and how to use them. +--- + +## Compatible Clients + +## SNI + +TLS endpoints only work with modern TLS clients that populate the SNI +extension. See the documentation on [TLS +Termination](/universal-gateway/tls-termination/#sni) for additional +details on compatible clients. + +## STARTTLS + +Protocols that begin in plain text and upgrade to TLS via a mechanism like +STARTTLS in SMTP, IMAP, etc are not supported. If you need to support +connections which upgrade to TLS, use a [TCP +Endpoint](/universal-gateway/tcp/). diff --git a/docs/universal-gateway/what-are-endpoint-urls.mdx b/docs/universal-gateway/what-are-endpoint-urls.mdx index 8a4a99b0e8..3f0d617ea6 100644 --- a/docs/universal-gateway/what-are-endpoint-urls.mdx +++ b/docs/universal-gateway/what-are-endpoint-urls.mdx @@ -34,6 +34,10 @@ Invalid: - The hostname must be a domain with a valid [public suffix](https://publicsuffix.org/). - The port must be `443`. If you do not specify a port, the default `443` will be used for you. +:::note +There is no standard scheme for TLS URLs so ngrok renders them as `tls://`. +::: + #### Examples Valid: diff --git a/sidebars.js b/sidebars.js index 8880faa354..5039023715 100644 --- a/sidebars.js +++ b/sidebars.js @@ -36,7 +36,7 @@ const sidebars = { link: { type: "doc", id: "pricing-limits/index" }, items: [ "pricing-limits/free-plan-limits", - "pricing-limits/http-s-limits", + "pricing-limits/endpoint-limits", ], }, { @@ -130,6 +130,7 @@ const sidebars = { id: "universal-gateway/tls", }, items: [ + "universal-gateway/tls-termination", { label: "How Does ngrok Handle TLS Certificates?", type: "category", @@ -230,7 +231,6 @@ const sidebars = { }, items: [ "universal-gateway/global-load-balancer", - "universal-gateway/tls-termination", "universal-gateway/ddos-protection", "universal-gateway/ip-addresses", "universal-gateway/points-of-presence", diff --git a/traffic-policy/actions/restrict-ips/index.mdx b/traffic-policy/actions/restrict-ips/index.mdx index f6f284071b..415857f222 100644 --- a/traffic-policy/actions/restrict-ips/index.mdx +++ b/traffic-policy/actions/restrict-ips/index.mdx @@ -3,3 +3,7 @@ The **Restrict IPs** Traffic Policy action allows you to allow or deny traffic based on the source IP address of connections to your ngrok endpoints. You can define rules using either **Allow and Deny lists**, or **Reference IDs** to existing ngrok [IP Policies](/docs/api/resources/ip-policies/). + +:::note +This Traffic Policy action is great for restricting traffic to TLS endpoints. +::: diff --git a/traffic-policy/actions/terminate-tls/index.mdx b/traffic-policy/actions/terminate-tls/index.mdx index 99afe99e66..10244a7edf 100644 --- a/traffic-policy/actions/terminate-tls/index.mdx +++ b/traffic-policy/actions/terminate-tls/index.mdx @@ -1,3 +1,7 @@ ## Overview The **Terminate TLS** Traffic Policy action allows you to control how TLS traffic is terminated by ngrok. This action is useful for when you need to specify a custom certificate, control which TLS versions are supported, or enable mutual TLS authentication. + +:::note +This Traffic Policy action is great for restricting traffic to TLS endpoints. +::: From fb634f6e3d3fba956c679dbe3db18d98b88b2d8a Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 8 Apr 2025 16:00:16 -0400 Subject: [PATCH 088/137] TLS broken out --- docs/universal-gateway/tls.mdx | 153 ------------- docs/universal-gateway/tls/index.mdx | 204 ++++++++++++++++++ docs/universal-gateway/tls/tls-clients.mdx | 2 +- sidebars.js | 3 +- .../LangSwitcher/ContentSwitcher.tsx | 2 +- 5 files changed, 208 insertions(+), 156 deletions(-) delete mode 100644 docs/universal-gateway/tls.mdx create mode 100644 docs/universal-gateway/tls/index.mdx diff --git a/docs/universal-gateway/tls.mdx b/docs/universal-gateway/tls.mdx deleted file mode 100644 index 877c4f1a74..0000000000 --- a/docs/universal-gateway/tls.mdx +++ /dev/null @@ -1,153 +0,0 @@ ---- -title: TLS Endpoints ---- - -import TabItem from "@theme/TabItem"; -import Tabs from "@theme/Tabs"; - -import TlsLimits from "./_tls_limits.mdx"; - -import AtAgentAgentCliExample from "/examples/agent-cli/tls-terminate-at-agent.mdx"; -import AtAgentAgentConfigExample from "/examples/agent-config/tls-terminate-at-agent.mdx"; -import AtAgentGoSdkExample from "/examples/go-sdk/tls-terminate-at-agent.mdx"; -import AtAgentJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-agent.mdx"; -import AtAgentKubernetesExample from "/examples/k8s/tls-terminate-at-agent.mdx"; -import AtAgentPythonSdkExample from "/examples/python-sdk/tls-terminate-at-agent.mdx"; -import AtAgentRustSdkExample from "/examples/rust-sdk/tls-terminate-at-agent.mdx"; -import AtAgentSshExample from "/examples/ssh/tls-terminate-at-agent.mdx"; - -import AtUpstreamAgentCliExample from "/examples/agent-cli/tls-terminate-at-upstream.mdx"; -import AtUpstreamAgentConfigExample from "/examples/agent-config/tls-terminate-at-upstream.mdx"; -import AtUpstreamGoSdkExample from "/examples/go-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamKubernetesExample from "/examples/k8s/tls-terminate-at-upstream.mdx"; -import AtUpstreamPythonSdkExample from "/examples/python-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamRustSdkExample from "/examples/rust-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamSshExample from "/examples/ssh/tls-terminate-at-upstream.mdx"; - -import CustomDomainAgentCliExample from "/examples/agent-cli/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainAgentConfigExample from "/examples/agent-config/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainGoSdkExample from "/examples/go-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainKubernetesExample from "/examples/k8s/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainPythonSdkExample from "/examples/python-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainRustSdkExample from "/examples/rust-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainSshExample from "/examples/ssh/tls-terminate-at-edge-custom-domain.mdx"; - -import ReencryptUpstreamAgentCliExample from "/examples/agent-cli/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamAgentConfigExample from "/examples/agent-config/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamGoSdkExample from "/examples/go-sdk/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamJavascriptSdkExample from "/examples/javascript-sdk/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamKubernetesExample from "/examples/k8s/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamPythonSdkExample from "/examples/python-sdk/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamRustSdkExample from "/examples/rust-sdk/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamSshExample from "/examples/ssh/tls-reencrypt-upstream.mdx"; - -import ProxyProtoAgentCliExample from "/examples/agent-cli/tls-proxyproto.mdx"; -import ProxyProtoAgentConfigExample from "/examples/agent-config/tls-proxyproto.mdx"; -import ProxyProtoGoSdkExample from "/examples/go-sdk/tls-proxyproto.mdx"; -import ProxyProtoJavascriptSdkExample from "/examples/javascript-sdk/tls-proxyproto.mdx"; -import ProxyProtoKubernetesExample from "/examples/k8s/tls-proxyproto.mdx"; -import ProxyProtoPythonSdkExample from "/examples/python-sdk/tls-proxyproto.mdx"; -import ProxyProtoRustSdkExample from "/examples/rust-sdk/tls-proxyproto.mdx"; -import ProxyProtoSshExample from "/examples/ssh/tls-proxyproto.mdx"; - -# TLS Endpoints - -## Overview - -TLS endpoints enable you to deliver any network service that runs over a -TLS-based protocol. TLS endpoints make no assumptions about the wrapped -protocol being transported. - -TLS endpoints inspect the [Server Name Indication (SNI)](#sni) -data on incoming TLS connections to route connections to the appropriate -endpoint. - -Because the TLS protocol describes no application-level semantics, ngrok can -only offer a [limited set of traffic policy actions](/traffic-policy/actions/) -to handle TLS traffic. - -If you are delivering an HTTPS application, prefer to create an [HTTP -Endpoint](/universal-gateway/http/). - -## Quickstart - - - - - - - - - - - - - - - - - - - - - - - - - - - - -## Learn more - -- **URLS** — URLs are validated differently depending on their [binding](/universal-gateway/bindings). To learn more about valid URLs for TLS endpoints, see [the Endpoint URLs documentation](/docs/universal-gateway/what-are-endpoint-urls/#http). -- **Domains** — Public TLS endpoints must match a domain on your account. See [the domains documentation](/universal-gateway/domains/what-are-domains/) for more information. -- **Authentication** — You can secure your TLS endpoints with the [IP Restriction](/traffic-policy/actions/restrict-ips/) and [Mutual TLS](/docs/guides/other-guides/how-to-terminate-traffic-with-ngrok-configs/#mutual-tls-example) Traffic Policy actions. There is a limited set of actions available to authenticate TLS traffic because the TLS protocol is low-level. -- **Bring your own domain** — To use your own domain with TLS endpoints, see [the guide on the subject](/universal-gateway/how-do-i-use-my-own-domain). -- **Wildcard Endpoints** — You can create TLS endpoints that receive traffic from all of the subdomains matching a given wildcard domain. See [the wildcard domain docs](/universal-gateway/wildcard-domains/) for more information. -- **Traffic Policy** — Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate and transform the traffic through the endpoint. -- **Agent Forwarding** — The [ngrok agent](/agent/) and [Agent SDKs](/agent-sdks/) forward traffic that your endpoints receive to upstream services. See [the agent forwarding documentation](/universal-gateway/agent-forwarding/) for more information. -- **Traffic Observability** — [Traffic Inspector](/obs/traffic-inspection/) gives you a real-time view in the ngrok dashboard of the HTTP traffic flowing through your TLS endpoints. You can even [export traffic logs with the Traffic Events system](/docs/obs/events/reference/#traffic-events). -- **TLS Certificates** — Learn how [ngrok automatically handles TLS](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) and [TLS termination](/universal-gateway/tls-termination/) for TLS endpoints for you. - -## TLS termination - -TLS Endpoints enable you to to define where [TLS termination](/universal-gateway/tls-termination/) occurs. You can configure your endpoint to terminate TLS at the ngrok cloud service. You can also achieve [end-to-end encryption](/universal-gateway/tls-termination/#end-to-end-encryption) by terminating at the agent or your upstream service. - -:::tip -When you use end-to-end encryption, the ngrok cloud service can not see payloads that transit through your endpoints. -::: - -See [the TLS Termination documentation](/universal-gateway/tls-termination/#termination-location) for more information. - -## Observability - -### Traffic Inspector - -[Traffic Inspector](/obs/traffic-inspection) does not support TLS endpoints. - -### Log Export Events - -You can export logs of traffic to TLS endpoints with [ngrok's events -system](/obs/). The following events are published for log exporting: - -| Event | When | -| ------------------------------------------------------------------------ | ------------------------------------------------------------ | -| [tcp_connection_closed.v0](/obs/events/reference/#tcp-connection-closed) | Published when a TCP connection to a TCP endpoint completes. | - -## Errors - -Learn how ngrok handles errors for TLS endpoints in the [Errors documentation](/errors/#tls-errors). - -## API - -TLS Endpoints can be created programatically. Consult the documentation on -[Endpoint APIs](/api/resources/endpoints/). - -## Limits & Timeouts - -TLS endpoints are available on Pay-as-you-go, Pro, and Enterprise plans. Consult the [pricing](/pricing-limits/) documentation for general billing details. - -For TLS limits, see the [endpoint Limits documentation](/pricing-limits/endpoint-limits/). diff --git a/docs/universal-gateway/tls/index.mdx b/docs/universal-gateway/tls/index.mdx new file mode 100644 index 0000000000..d48da2ead8 --- /dev/null +++ b/docs/universal-gateway/tls/index.mdx @@ -0,0 +1,204 @@ +--- +title: TLS Endpoints +--- + +import { LangSwitcher } from "@site/src/components/LangSwitcher"; +import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitcher"; +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; +import TlsLimits from "./_tls_limits.mdx"; + +# TLS Endpoints + +## Overview + +TLS endpoints enable you to deliver any network service that runs over a +TLS-based protocol. TLS endpoints make no assumptions about the wrapped +protocol being transported. + +TLS endpoints inspect the [Server Name Indication (SNI)](#sni) +data on incoming TLS connections to route connections to the appropriate +endpoint. + +Because the TLS protocol describes no application-level semantics, ngrok can +only offer a [limited set of traffic policy actions](/traffic-policy/actions/) +to handle TLS traffic. + +If you are delivering an HTTPS application, prefer to create an [HTTP +Endpoint](/universal-gateway/http/). + +## Quickstart + + + + + +```bash +ngrok tls 80 \ + --url tls://your-name.ngrok.app \ + --traffic-policy-file traffic-policy.yml +``` + +```go +import ( + "context" + "net" + + "golang.ngrok.com/ngrok" + "golang.ngrok.com/ngrok/config" +) + +func ngrokListener(ctx context.Context) (net.Listener, error) { + return ngrok.Listen(ctx, + config.TLSEndpoint( + config.WithDomain("your-name.ngrok.app"), + config.WithTLSTermination( + config.WithTLSTerminationAt(config.TLSAtEdge), + ), + ), + ngrok.WithAuthtokenFromEnv(), + ) +} +``` + +```jsx +const ngrok = require("@ngrok/ngrok"); +const fs = require("fs"); + +(async function () { + const listener = await ngrok.forward({ + addr: 8080, + authtoken_from_env: true, + proto: "tls", + domain: "app.example.com", + crt: fs.readFileSync("/path/to/app-example-com-crt.pem", "utf8"), + key: fs.readFileSync("/path/to/app-example-com-key.pem", "utf8"), + mutual_tls_cas: [fs.readFileSync("/path/to/cas.pem", "utf8")], + }); + + console.log(`Ingress established at: ${listener.url()}`); +})(); +``` + +```python +import ngrok + +def load_file(name): + with open(name, "r") as crt: + return bytearray(crt.read().encode()) + +listener = ngrok.forward("localhost:8080", authtoken_from_env=True, + proto="tls", + domain="app.example.com", + crt=load_file("/path/to/app-example-com-crt.pem"), + key=load_file("/path/to/app-example-com-key.pem"), + mutual_tls_cas=load_file("/path/to/cas.pem")) + +print(f"Ingress established at: {listener.url()}"); +``` + + + + + +For the above example, you can use the following Traffic Policy file: + +```yaml title="traffic-policy.yml" +on_tcp_connect: + - actions: + - type: terminate-tls +``` + + + + + +```yaml +version: 3 +endpoints: + - name: example + url: tls://your-name.ngrok.app + upstream: + url: 80 + traffic_policy: + on_tcp_connect: + - actions: + - type: terminate-tls +``` + + + + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: example-route + namespace: ngrok-gateway +spec: + rules: + - backendRefs: + - name: game-2048 + port: 80 + kind: Service + filters: + - type: RequestHeaderModifier + requestHeaderModifier: + remove: ["x-request-id"] + add: + - name: my-request-header-name + value: my-header-value + set: + - name: my-request-header-to-set + value: set-header-value +``` + + + + + +:::info + +TLS termination at the edge is not supported for: + +- SSH +- Rust + +::: + +## Learn more + +- **URLS** — URLs are validated differently depending on their [binding](/universal-gateway/bindings). To learn more about valid URLs for TLS endpoints, see [the Endpoint URLs documentation](/docs/universal-gateway/what-are-endpoint-urls/#http). +- **Domains** — Public TLS endpoints must match a domain on your account. See [the domains documentation](/universal-gateway/domains/what-are-domains/) for more information. +- **Authentication** — You can secure your TLS endpoints with the [IP Restriction](/traffic-policy/actions/restrict-ips/) and [Mutual TLS](/docs/guides/other-guides/how-to-terminate-traffic-with-ngrok-configs/#mutual-tls-example) Traffic Policy actions. There is a limited set of actions available to authenticate TLS traffic because the TLS protocol is low-level. +- **Bring your own domain** — To use your own domain with TLS endpoints, see [the guide on the subject](/universal-gateway/how-do-i-use-my-own-domain). +- **Wildcard Endpoints** — You can create TLS endpoints that receive traffic from all of the subdomains matching a given wildcard domain. See [the wildcard domain docs](/universal-gateway/wildcard-domains/) for more information. +- **Traffic Policy** — Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate and transform the traffic through the endpoint. +- **Agent Forwarding** — The [ngrok agent](/agent/) and [Agent SDKs](/agent-sdks/) forward traffic that your endpoints receive to upstream services. See [the agent forwarding documentation](/universal-gateway/agent-forwarding/) for more information. +- **Traffic Observability** — [Traffic Inspector](/obs/traffic-inspection/) gives you a real-time view in the ngrok dashboard of the traffic flowing through your TLS endpoints. You can even [export traffic logs with the Traffic Events system](/docs/obs/events/reference/). +- **TLS Certificates** — Learn how [ngrok automatically handles TLS](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) and [TLS termination](/universal-gateway/tls-termination/) for TLS endpoints for you. + +## TLS termination + +TLS Endpoints enable you to to define where [TLS termination](/universal-gateway/tls-termination/) occurs. You can configure your endpoint to terminate TLS at the ngrok cloud service. You can also achieve [end-to-end encryption](/universal-gateway/tls-termination/#end-to-end-encryption) by terminating at the agent or your upstream service. + +:::tip +When you use end-to-end encryption, the ngrok cloud service can not see payloads that transit through your endpoints. +::: + +See [the TLS Termination documentation](/universal-gateway/tls-termination/#termination-location) for more information. + +## Errors + +Learn how ngrok handles errors for TLS endpoints in the [Errors documentation](/errors/#tls-errors). + +## API + +TLS Endpoints can be created programatically. Consult the documentation on +[Endpoint APIs](/api/resources/endpoints/). + +## Limits & Timeouts + +TLS endpoints are available on Pay-as-you-go, Pro, and Enterprise plans. Consult the [pricing](/pricing-limits/) documentation for general billing details. + +For TLS limits, see the [endpoint Limits documentation](/pricing-limits/endpoint-limits/). diff --git a/docs/universal-gateway/tls/tls-clients.mdx b/docs/universal-gateway/tls/tls-clients.mdx index 4093ef8b4e..78bf31e220 100644 --- a/docs/universal-gateway/tls/tls-clients.mdx +++ b/docs/universal-gateway/tls/tls-clients.mdx @@ -3,7 +3,7 @@ title: Which TLS Clients Do ngrok Support? description: Learn about the different TLS clients available for ngrok and how to use them. --- -## Compatible Clients +ngrok's TLS endpoints are designed to work with TLS clients that fit the criteria described on this page. ## SNI diff --git a/sidebars.js b/sidebars.js index 5039023715..2703fdf17b 100644 --- a/sidebars.js +++ b/sidebars.js @@ -127,7 +127,7 @@ const sidebars = { type: "category", link: { type: "doc", - id: "universal-gateway/tls", + id: "universal-gateway/tls/index", }, items: [ "universal-gateway/tls-termination", @@ -146,6 +146,7 @@ const sidebars = { "universal-gateway/tls-certificates/what-are-private-tls-keys", ], }, + "universal-gateway/tls/tls-clients", ], }, { diff --git a/src/components/LangSwitcher/ContentSwitcher.tsx b/src/components/LangSwitcher/ContentSwitcher.tsx index b2ffe71f9d..be6bcfb25e 100644 --- a/src/components/LangSwitcher/ContentSwitcher.tsx +++ b/src/components/LangSwitcher/ContentSwitcher.tsx @@ -23,7 +23,7 @@ export function ContentSwitcher({ for (const lang of languages) { if (lang === selectedLanguage) { - return children; + return
{children}
; } } return null; From 2f5e104a9b2d50a2d65530ca7036b16225332e37 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 8 Apr 2025 16:03:03 -0400 Subject: [PATCH 089/137] Reorder sidebar --- sidebars.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sidebars.js b/sidebars.js index 2703fdf17b..74220daf3c 100644 --- a/sidebars.js +++ b/sidebars.js @@ -122,6 +122,15 @@ const sidebars = { "universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned", ], }, + { + label: "How Do I Handle HTTP/S Traffic?", + type: "category", + link: { type: "doc", id: "universal-gateway/http-s/index" }, + items: [ + "universal-gateway/http-s/http-s-endpoints", + "universal-gateway/http-s/upstream-headers", + ], + }, { label: "How Do I Handle TLS Traffic?", type: "category", @@ -158,15 +167,6 @@ const sidebars = { "universal-gateway/agent-forwarding/serving-file-directories", ], }, - { - label: "How Do I Handle HTTP/S Traffic?", - type: "category", - link: { type: "doc", id: "universal-gateway/http-s/index" }, - items: [ - "universal-gateway/http-s/http-s-endpoints", - "universal-gateway/http-s/upstream-headers", - ], - }, { label: "Endpoints", type: "category", From 75fb29b9ec8898ce76d5460839856aab8450a6f7 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 8 Apr 2025 16:04:58 -0400 Subject: [PATCH 090/137] Remove unused sidebar sections --- sidebars.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/sidebars.js b/sidebars.js index 74220daf3c..50c9863549 100644 --- a/sidebars.js +++ b/sidebars.js @@ -177,16 +177,6 @@ const sidebars = { type: "category", link: { type: "doc", id: "universal-gateway/protocols" }, items: [ - { - id: "universal-gateway/http", - type: "doc", - label: "HTTP/S", - }, - { - id: "universal-gateway/tls", - type: "doc", - label: "TLS", - }, { id: "universal-gateway/tcp", type: "doc", From 351fd90e9896b26967a9f22e47789c0b50f5e0a7 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Wed, 9 Apr 2025 10:18:42 -0400 Subject: [PATCH 091/137] Break up TLS termination --- docs/universal-gateway/http.mdx | 8 +- docs/universal-gateway/tcp.mdx | 6 +- docs/universal-gateway/tcp/index.mdx | 243 ++++++++++++++++++ .../how-does-ngrok-handle-tls.mdx | 9 +- docs/universal-gateway/tls-termination.mdx | 39 +-- docs/universal-gateway/tls/handshake.mdx | 37 +++ docs/universal-gateway/tls/index.mdx | 2 +- .../tls/tls-termination/index.mdx | 56 ++++ .../tls-termination/termination-location.mdx | 147 +++++++++++ .../tls-termination/termination-mechanics.mdx | 52 ++++ sidebars.js | 10 +- 11 files changed, 561 insertions(+), 48 deletions(-) create mode 100644 docs/universal-gateway/tcp/index.mdx create mode 100644 docs/universal-gateway/tls/handshake.mdx create mode 100644 docs/universal-gateway/tls/tls-termination/index.mdx create mode 100644 docs/universal-gateway/tls/tls-termination/termination-location.mdx create mode 100644 docs/universal-gateway/tls/tls-termination/termination-mechanics.mdx diff --git a/docs/universal-gateway/http.mdx b/docs/universal-gateway/http.mdx index e25ff2172d..155d0e3980 100644 --- a/docs/universal-gateway/http.mdx +++ b/docs/universal-gateway/http.mdx @@ -747,10 +747,10 @@ request and response bodies. You can export logs of traffic to HTTP/S endpoints with [ngrok's events system](/obs/). The following events are published for log exporting: -| Event | When | -| ------------------------------------------------------------------------ | ----------------------------------------------------------------- | -| [http_request_complete.v0](/obs/events/reference/#http-request-complete) | Published when an HTTP request to an HTTP/S endpoints completes. | -| [tcp_connection_closed.v0](/obs/events/reference/#tcp-connection-closed) | Published when a TCP connection to an HTTP/S endpoints completes. | +| Event | When | +| ------------------------------------------------------------------------ | ------------------------------------------------------------------ | +| [http_request_complete.v0](/obs/events/reference/#http-request-complete) | Published when an HTTP request to an HTTP/S endpoint completes. | +| [tcp_connection_closed.v0](/obs/events/reference/#tcp-connection-closed) | Published when a TCP connection to any type of endpoint completes. | ## Advanced diff --git a/docs/universal-gateway/tcp.mdx b/docs/universal-gateway/tcp.mdx index 6ce3cf4c68..8cbab47816 100644 --- a/docs/universal-gateway/tcp.mdx +++ b/docs/universal-gateway/tcp.mdx @@ -199,9 +199,9 @@ to authenticate TCP traffic because the TCP protocol is low-level. You can export logs of traffic to TCP endpoints with [ngrok's events system](/obs/events/). The following events are published for log exporting: -| Event | When | -| ------------------------------------------------------------------------ | ------------------------------------------------------------ | -| [tcp_connection_closed.v0](/obs/events/reference/#tcp-connection-closed) | Published when a TCP connection to a TCP endpoint completes. | +| Event | When | +| ------------------------------------------------------------------------ | ------------------------------------------------------------------ | +| [tcp_connection_closed.v0](/obs/events/reference/#tcp-connection-closed) | Published when a TCP connection to any type of endpoint completes. | ## Limits & Timeouts diff --git a/docs/universal-gateway/tcp/index.mdx b/docs/universal-gateway/tcp/index.mdx new file mode 100644 index 0000000000..8cbab47816 --- /dev/null +++ b/docs/universal-gateway/tcp/index.mdx @@ -0,0 +1,243 @@ +--- +title: TCP Endpoints +--- + +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; + +import RandomAgentCliExample from "/examples/agent-cli/tcp-random.mdx"; +import RandomAgentConfigExample from "/examples/agent-config/tcp-random.mdx"; +import RandomGoSdkExample from "/examples/go-sdk/tcp-random.mdx"; +import RandomJavascriptSdkExample from "/examples/javascript-sdk/tcp-random.mdx"; +import RandomKubernetesExample from "/examples/k8s/tcp-random.mdx"; +import RandomPythonSdkExample from "/examples/python-sdk/tcp-random.mdx"; +import RandomRustSdkExample from "/examples/rust-sdk/tcp-random.mdx"; +import RandomSshExample from "/examples/ssh/tcp-random.mdx"; + +import FixedAgentCliExample from "/examples/agent-cli/tcp-fixed.mdx"; +import FixedAgentConfigExample from "/examples/agent-config/tcp-fixed.mdx"; +import FixedGoSdkExample from "/examples/go-sdk/tcp-fixed.mdx"; +import FixedJavascriptSdkExample from "/examples/javascript-sdk/tcp-fixed.mdx"; +import FixedKubernetesExample from "/examples/k8s/tcp-fixed.mdx"; +import FixedPythonSdkExample from "/examples/python-sdk/tcp-fixed.mdx"; +import FixedRustSdkExample from "/examples/rust-sdk/tcp-fixed.mdx"; +import FixedSshExample from "/examples/ssh/tcp-fixed.mdx"; + +import NonLocalAgentCliExample from "/examples/agent-cli/tcp-nonlocal.mdx"; +import NonLocalAgentConfigExample from "/examples/agent-config/tcp-nonlocal.mdx"; +import NonLocalGoSdkExample from "/examples/go-sdk/tcp-nonlocal.mdx"; +import NonLocalJavascriptSdkExample from "/examples/javascript-sdk/tcp-nonlocal.mdx"; +import NonLocalKubernetesExample from "/examples/k8s/tcp-nonlocal.mdx"; +import NonLocalPythonSdkExample from "/examples/python-sdk/tcp-nonlocal.mdx"; +import NonLocalRustSdkExample from "/examples/rust-sdk/tcp-nonlocal.mdx"; +import NonLocalSshExample from "/examples/ssh/tcp-nonlocal.mdx"; + +import ProxyProtoAgentCliExample from "/examples/agent-cli/tcp-proxyproto.mdx"; +import ProxyProtoAgentConfigExample from "/examples/agent-config/tcp-proxyproto.mdx"; +import ProxyProtoGoSdkExample from "/examples/go-sdk/tcp-proxyproto.mdx"; +import ProxyProtoJavascriptSdkExample from "/examples/javascript-sdk/tcp-proxyproto.mdx"; +import ProxyProtoKubernetesExample from "/examples/k8s/tcp-proxyproto.mdx"; +import ProxyProtoPythonSdkExample from "/examples/python-sdk/tcp-proxyproto.mdx"; +import ProxyProtoRustSdkExample from "/examples/rust-sdk/tcp-proxyproto.mdx"; +import ProxyProtoSshExample from "/examples/ssh/tcp-proxyproto.mdx"; + +# TCP Endpoints + +## Overview + +TCP endpoints enable you to deliver any network service with a TCP-based +protocol. They are commonly used to create connectivity for: + +- Remote access protocols like SSH, VNC and RDP +- Databases like MySQL, Postgres, MSSQL and SQLite +- IoT protocols like MQTT +- Gaming servers like Minecraft + +If you are accepting TLS traffic, you may prefer to create a [TLS Endpoint](/universal-gateway/tls/). + +::::info Free Plan Usage +TCP endpoints are only available on a free plan after [adding a valid payment method](https://dashboard.ngrok.com/settings#id-verification) to your account. +:::: + +## Quickstart + +Agent Endpoints are the easiest way to get started with ngrok. An [agent +endpoint](/universal-gateway/cloud-endpoints/) is started by a +[Secure Tunnels](/agent/) agent. The endpoint lives for the lifetime +of the process and forwards traffic to a port or URL of your choosing. + +This example creates a TCP endpoint on a randomly-assigned URL - e.g. +`tcp://1.tcp.ngrok.io:12345` and forwards its traffic to a local port. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## URLs + +URLs are validated differently depending on their +[binding](/universal-gateway/bindings). Consult the +following documentation for details on valid URLs for TCP endpoints: + +- [Public Endpoint URLs](/universal-gateway/public-endpoints/#tcp) +- [Internal Endpoint URLs](/universal-gateway/internal-endpoints/#urls) +- [Kubernetes Endpoint URLs](/universal-gateway/kubernetes-endpoints/#urls) + +There is no standard scheme for TCP URLs so ngrok renders them as `tcp://`. + +### Static URLs + +If you would like a public TCP endpoint to have a static URL, you must first +create a [TCP Address](/universal-gateway/tcp-addresses/what-are-tcp-addresses/). When you create a TCP +address, a random hostname and port will be assigned to you, e.g. +`1.tcp.ngrok.io:12345`. + +A TCP address is only needed to make a public TCP endpoint have a static URL. +They are not needed for TCP endpoints on other bindings, like `internal` or +`kubernetes`. + +After you have created a TCP Address, specify the address (e.g. +`1.tcp.eu.ngrok.io:12345`) in the URL when you create the endpoint. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +### Custom domains + +Public TCP endpoints are assigned randomly on an ngrok-controlled hostname with +a randomly-assigned port. You may not choose the hostname and you may not +select the port. + +You may, however, simulate a customized hostname by creating a CNAME record to +the hostname of your assigned TCP address. If you do so, be aware that all +ports on that hostname, even those provisioned to other accounts will then be +available on your domain. + +For example if your TCP address is `5.tcp.ngrok.io:12345`, you could create the +following CNAME record: + +``` +CNAME tcp.mydomain.com -> 5.tcp.ngrok.io +``` + +And then you can access that TCP endpoint with + +``` +telnet tcp.mydomain.com 12345 +``` + +## Traffic Policy + +Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate +and transform the traffic through the endpoint. + +### Authentication + +When you create public TCP endpoints, you often want to secure them with +authentication. You can secure your TCP endpoints with the following [Traffic +Policy](/traffic-policy/) actions. There is a limited set of actions available +to authenticate TCP traffic because the TCP protocol is low-level. + +- [IP Restriction](/traffic-policy/actions/restrict-ips/) +- [Mutual TLS](/traffic-policy/actions/terminate-tls/) + +## Observability + +### Traffic Inspector + +[Traffic Inspector](/obs/traffic-inspection) does not support TCP endpoints. + +### Log Export Events + +You can export logs of traffic to TCP endpoints with [ngrok's events +system](/obs/events/). The following events are published for log exporting: + +| Event | When | +| ------------------------------------------------------------------------ | ------------------------------------------------------------------ | +| [tcp_connection_closed.v0](/obs/events/reference/#tcp-connection-closed) | Published when a TCP connection to any type of endpoint completes. | + +## Limits & Timeouts + +[Contact us](mailto:support@ngrok.com) if you need to configure limits and timeouts on +connections to TCP endpoints. + +| Limit | Name | Notes | +| --------- | ------------------- | ------------------------------------------------------------ | +| 5 minutes | Client Idle Timeout | Time since data was last transmitted by the upstream service | +| 5 minutes | Server Idle Timeout | Time since data was last transmitted by the upstream service | +| No limit | Data transmitted | Data transmitted by the client or upstream service | + +## Errors + +If an error is encountered while handling connections to a TCP endpoint for any +reason (e.g. traffic policy action error, internal server error), the +connection will be closed. Because of the low-level nature of the TCP protocol, +there is no mechanism used to transmit information about what error code was +encountered. + +Use the [observability](#observability) features to understand connection +handling errors. + +## API + +TCP Endpoints can be created programatically. Consult the documentation on +[Endpoint APIs](/api/resources/endpoints/). + +## Pricing + +TCP endpoints are available on all plans. Consult the [Endpoints +Pricing](/universal-gateway/endpoints/#pricing) documentation for +billing details. + +TCP endpoints are only available on a free plan after [adding a valid payment +method](https://dashboard.ngrok.com/settings#id-verification) to your account. + +See [TCP Addresses pricing](/universal-gateway/tcp-addresses/#pricing) for +details on pricing for fixed TCP Addresses. diff --git a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx index a54aaf1b8a..34a6d70ed6 100644 --- a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx +++ b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx @@ -1,5 +1,5 @@ --- -title: How Does ngrok Handle TLS? +title: How Does ngrok Handle TLS Certificates? description: Learn how ngrok handles TLS certificates. --- @@ -9,6 +9,7 @@ You can manage TLS certificates with: - [The Dashboard](https://dashboard.ngrok.com/tls-certs) - [The API](/api/resources/tls-certificates/). +- [The `terminate-tls` Traffic Policy action](/traffic-policy/actions/terminate-tls/) You can also [specify the local path to a certificate file](/agent/cli/#example-10) when starting a TLS endpoint with the Agent CLI. @@ -24,6 +25,12 @@ TLS certificates are attached to [domains](/universal-gateway/domains/what-are-d See the [wildcard domains](/universal-gateway/wildcard-domains/#tls-provisioning) docs for more information about how TLS certificates are managed for wildcard domains. +## Mutual TLS + +Mutual TLS is supported when terminating TLS at ngrok's cloud service via the `mutual_tls_certificate_authorities` field of the [`terminate-tls`](/traffic-policy/actions/terminate-tls) traffic policy action. + +You can also enable mutual TLS when terminating TLS at the agent via the `mutual_tls_certificate_authorities` property of the [`agent_tls_termination`](/agent/config/v3/#endpoint-configuration-options) section of an endpoint configuration in the [agent configuration](/agent/config/v3/) file. + ## API TLS certificates are managed programatically via: diff --git a/docs/universal-gateway/tls-termination.mdx b/docs/universal-gateway/tls-termination.mdx index 87603bf8fc..7c71e2071a 100644 --- a/docs/universal-gateway/tls-termination.mdx +++ b/docs/universal-gateway/tls-termination.mdx @@ -1,5 +1,5 @@ --- -title: How Do I Handle TLS Termination? +title: How Do I Terminate TLS? description: Learn how to terminate TLS with ngrok. --- @@ -233,43 +233,6 @@ section of an endpoint configuration](/agent/config/v3/#endpoint-configuration-options) in the agent configuration file. -## Handshake - -### TLS Version - -ngrok uses TLS 1.3 (the latest version) by default. If a client does not -support TLS 1.3, ngrok will use the highest possible version that the client -supports, down to TLS 1.1. - -You may customize the minimum and maximum supported versions of TLS with the -[`terminate-tls`](/traffic-policy/actions/terminate-tls) traffic policy action. - -### ALPN - -`https` endpoints negotiate the next protocol via ALPN with the following -default list in order of preference: - -``` -['h2', 'http/1.1'] -``` - -### SNI - -ngrok endpoints do not support legacy clients which do not set the SNI -extension. For example, the following clients (and others) will fail to work -with ngrok endpoints: - -- Microsoft Internet Explorer 6.0 -- Microsoft Internet Explorer 7 & 8 on Windows XP or earlier -- Native browser on Android 2.X -- Java <=1.6 -- [Python 2.X, 3.0, 3.1 if required modules are not installed](https://stackoverflow.com/questions/18578439/using-requests-with-tls-doesnt-give-sni-support/18579484#18579484) - -### Encrypted Client Hello - -ngrok endpoints do not yet support the draft implementation of [Encrypted -Client Hello](https://datatracker.ietf.org/doc/draft-ietf-tls-esni/). - ## FIPS Compliance ngrok does not use a FIPS-compliant TLS implementation by default, but one can diff --git a/docs/universal-gateway/tls/handshake.mdx b/docs/universal-gateway/tls/handshake.mdx new file mode 100644 index 0000000000..692d08918d --- /dev/null +++ b/docs/universal-gateway/tls/handshake.mdx @@ -0,0 +1,37 @@ +--- +title: How Does the TLS Handshake Work? +description: Learn how the TLS handshake works with ngrok. +--- + +ngrok uses TLS 1.3 (the latest version) by default. If a client does not +support TLS 1.3, ngrok will use the highest possible version that the client +supports, down to TLS 1.1. + +You may customize the minimum and maximum supported versions of TLS with the +[`terminate-tls`](/traffic-policy/actions/terminate-tls) traffic policy action. + +### ALPN + +`https` endpoints negotiate the next protocol via ALPN with the following +default list in order of preference: + +``` +['h2', 'http/1.1'] +``` + +### SNI + +ngrok endpoints do not support legacy clients which do not set the SNI +extension. For example, the following clients (and others) will fail to work +with ngrok endpoints: + +- Microsoft Internet Explorer 6.0 +- Microsoft Internet Explorer 7 & 8 on Windows XP or earlier +- Native browser on Android 2.X +- Java <=1.6 +- [Python 2.X, 3.0, 3.1 if required modules are not installed](https://stackoverflow.com/questions/18578439/using-requests-with-tls-doesnt-give-sni-support/18579484#18579484) + +### Encrypted Client Hello + +ngrok endpoints do not yet support the draft implementation of [Encrypted +Client Hello](https://datatracker.ietf.org/doc/draft-ietf-tls-esni/). diff --git a/docs/universal-gateway/tls/index.mdx b/docs/universal-gateway/tls/index.mdx index d48da2ead8..3a0c2188e5 100644 --- a/docs/universal-gateway/tls/index.mdx +++ b/docs/universal-gateway/tls/index.mdx @@ -197,7 +197,7 @@ Learn how ngrok handles errors for TLS endpoints in the [Errors documentation](/ TLS Endpoints can be created programatically. Consult the documentation on [Endpoint APIs](/api/resources/endpoints/). -## Limits & Timeouts +## Limits & Pricing TLS endpoints are available on Pay-as-you-go, Pro, and Enterprise plans. Consult the [pricing](/pricing-limits/) documentation for general billing details. diff --git a/docs/universal-gateway/tls/tls-termination/index.mdx b/docs/universal-gateway/tls/tls-termination/index.mdx new file mode 100644 index 0000000000..8ca4e89256 --- /dev/null +++ b/docs/universal-gateway/tls/tls-termination/index.mdx @@ -0,0 +1,56 @@ +--- +title: How Do I Terminate TLS? +description: Learn how to terminate TLS with ngrok. +--- + +# TLS Termination + +ngrok automatically handles TLS (SSL) termination and certificate management +for you. There is typically nothing to setup, configure or manage. + +## Overview + +ngrok's TLS termination behavior is determined by an endpoint's protocol and +traffic policy. You may customize each endpoint to choose where TLS is +terminated, how it is terminated and even whether it is terminated at all. When +ngrok's cloud service terminates TLS, it: + +- Uses latest and most secure version of TLS +- Uses the [TLS + Certificate](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) attached to the + [Domain](/universal-gateway/domains/what-are-domains/) which matches the Endpoint URL's + hostname +- Accelerates your traffic by using the global load balancer to terminate at its + closest point of presence + +ngrok supports [end-to-end encryption](#end-to-end-encryption) where the ngrok +cloud service does not terminate TLS connections and only sees enciphered +traffic. When configured this way, you are responsible for configuring TLS +termination in your upstream service or at the ngrok agent. + +## How is TLS terminated by default? + +An endpoint's protocol determines the ngrok cloud service's default TLS +termination behavior. + +| Endpoint Protocol | TLS Termination | +| --------------------------------- | --------------------------------------------------------- | +| [HTTP](/universal-gateway/http/) | None | +| [HTTPS](/universal-gateway/http/) | Always at ngrok's cloud service. | +| [TLS](/universal-gateway/tls/) | Default no termination, configurable with `terminate-tls` | +| [TCP](/universal-gateway/tcp/) | Default no termination, configurable with `terminate-tls` | + +## Learn more + +- **Using Traffic Policy** — The [`terminate-tls` Traffic Policy + Action](/traffic-policy/actions/terminate-tls) enables you to terminate TLS + connections at ngrok's cloud service for TCP and TLS endpoints. +- **Optimizations** — Learn about ngrok's [TLS termination optimizations](/universal-gateway/tls-termination/termination-mechanics/) and how they can improve the performance of your TLS endpoints. +- **Certificates** — ngrok makes managing TLS certificates simple. See [the TLS Certificates documentation](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) for more details on how they are [selected](/universal-gateway/tls-certificates/how-are-certificates-selected), managed, provisioned and renewed. +- **End-to-end encryption** — Enabling end-to-end encryption for TLS endpoints is straightforward. See the docs on [how TLS termination works](/universal-gateway/tls-termination/termination-mechanics/#end-to-end-encryption) to learn more. + +## Limits & Pricing + +TLS endpoints are available on Pay-as-you-go, Pro, and Enterprise plans. Consult the [pricing](/pricing-limits/) documentation for general billing details. + +For TLS limits, see the [endpoint Limits documentation](/pricing-limits/endpoint-limits/). diff --git a/docs/universal-gateway/tls/tls-termination/termination-location.mdx b/docs/universal-gateway/tls/tls-termination/termination-location.mdx new file mode 100644 index 0000000000..624295748b --- /dev/null +++ b/docs/universal-gateway/tls/tls-termination/termination-location.mdx @@ -0,0 +1,147 @@ +--- +title: Where Is TLS Terminated? +description: Learn about the different locations where TLS termination can occur in ngrok. +--- + +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; + +import TlsLimits from "../_tls_limits.mdx"; + +import AtAgentAgentCliExample from "/examples/agent-cli/tls-terminate-at-agent.mdx"; +import AtAgentAgentConfigExample from "/examples/agent-config/tls-terminate-at-agent.mdx"; +import AtAgentGoSdkExample from "/examples/go-sdk/tls-terminate-at-agent.mdx"; +import AtAgentJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-agent.mdx"; +import AtAgentKubernetesExample from "/examples/k8s/tls-terminate-at-agent.mdx"; +import AtAgentPythonSdkExample from "/examples/python-sdk/tls-terminate-at-agent.mdx"; +import AtAgentRustSdkExample from "/examples/rust-sdk/tls-terminate-at-agent.mdx"; +import AtAgentSshExample from "/examples/ssh/tls-terminate-at-agent.mdx"; + +import AtUpstreamAgentCliExample from "/examples/agent-cli/tls-terminate-at-upstream.mdx"; +import AtUpstreamAgentConfigExample from "/examples/agent-config/tls-terminate-at-upstream.mdx"; +import AtUpstreamGoSdkExample from "/examples/go-sdk/tls-terminate-at-upstream.mdx"; +import AtUpstreamJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-upstream.mdx"; +import AtUpstreamKubernetesExample from "/examples/k8s/tls-terminate-at-upstream.mdx"; +import AtUpstreamPythonSdkExample from "/examples/python-sdk/tls-terminate-at-upstream.mdx"; +import AtUpstreamRustSdkExample from "/examples/rust-sdk/tls-terminate-at-upstream.mdx"; +import AtUpstreamSshExample from "/examples/ssh/tls-terminate-at-upstream.mdx"; + +import CustomDomainAgentCliExample from "/examples/agent-cli/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainAgentConfigExample from "/examples/agent-config/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainGoSdkExample from "/examples/go-sdk/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainKubernetesExample from "/examples/k8s/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainPythonSdkExample from "/examples/python-sdk/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainRustSdkExample from "/examples/rust-sdk/tls-terminate-at-edge-custom-domain.mdx"; +import CustomDomainSshExample from "/examples/ssh/tls-terminate-at-edge-custom-domain.mdx"; + +[TLS connections](/universal-gateway/tls/) to your ngrok endpoints are terminated at one of three +locations. + +- **ngrok's cloud service**: This is the easiest and most common. All HTTPS + endpoints terminate TLS at ngrok's cloud service. When connections are + terminated by ngrok's cloud service, they are re-encrypted before they are + transmitted over a Secure Tunnel to an agent. +- **ngrok agent**: This is a form of [end-to-end + encryption](#end-to-end-encryption) where the ngrok cloud service does not + terminate TLS and you instead configure the ngrok agent to terminate TLS + connections for you. +- **your upstream service**: This is another form of [end-to-end + encryption](#end-to-end-encryption) where neither the cloud service nor an + agent terminates TLS connections. Instead, your upstream application service is + responsible for TLS termination. + +### Examples + +#### Cloud Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +#### Terminate at Agent + +See [Zero-Knowledge TLS at the Agent](/agent/agent-tls-termination/) for additional details. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +#### Terminate at Upstream + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/universal-gateway/tls/tls-termination/termination-mechanics.mdx b/docs/universal-gateway/tls/tls-termination/termination-mechanics.mdx new file mode 100644 index 0000000000..9542dfc973 --- /dev/null +++ b/docs/universal-gateway/tls/tls-termination/termination-mechanics.mdx @@ -0,0 +1,52 @@ +--- +title: How Does ngrok TLS Termination Work? +description: Learn how ngrok optimizes TLS termination to give your apps better performance. +--- + +The ngrok cloud service has multiple built-in optimizations for [TLS termination](/universal-gateway/tls/tls-termination/). + +## Acceleration + +The ngrok cloud service improves the performance of your endpoints by +accelerating TLS termination using ngrok's [global points +of presence](/universal-gateway/points-of-presence). + +TLS connection set-up requires multiple network round-trips. When round-trip +times (RTTs) are long, TLS connection establishment slows down. ngrok reduces +the latency of these round-trip times between the client and your endpoint by +terminating connections at the closest [point of +presence](/universal-gateway/points-of-presence/) via its [global load +balancer](/universal-gateway/global-load-balancer). + +## FIPS Compliance + +ngrok does not use a [FIPS-compliant](https://en.wikipedia.org/wiki/FIPS_140-2) TLS implementation by default, but one can +be enabled for your endpoints. + +[Contact us](mailto:support@ngrok.com) if you require a FIPS-compliant TLS +implementation. + +## End-to-end encryption + +You may choose to terminate TLS at your upstream service or at the ngrok agent +to achieve end-to-end encryption (E2EE), often referred to as Zero-knowledge TLS. When your endpoints operate in this +mode, the ngrok cloud service can not see the payloads that transfer through +your endpoints. + +Creating an endpoint with end-to-end encryption is simple: + +- Create a TLS or TCP endpoint +- **Do not** add a `terminate-tls` action to its traffic policy. + +That's it! Read the [Agent TLS Termination +Guide](/agent/agent-tls-termination/) for a step by step approach to set it up. + +To set up the agent to terminate TLS for you, consult the following table +because the configuration depends on which kind of agent you are using. + +| Agent | Documentation | +| ------------------- | ------------------------------------------------------------------------------------------------------- | +| Agent Config File | [`agent_tls_termination`](/agent/config/v3/#endpoint-configuration-options) | +| Go SDK | [WithTLSTerminationKeyPair](https://pkg.go.dev/golang.ngrok.com/ngrok/config#WithTLSTerminationKeyPair) | +| Other SDKs | not supported | +| Kubernetes Operator | not supported | diff --git a/sidebars.js b/sidebars.js index 50c9863549..3611f23637 100644 --- a/sidebars.js +++ b/sidebars.js @@ -139,7 +139,15 @@ const sidebars = { id: "universal-gateway/tls/index", }, items: [ - "universal-gateway/tls-termination", + { + label: "How Do I Terminate TLS?", + type: "category", + link: { + type: "doc", + id: "universal-gateway/tls/tls-termination/index", + }, + items: ["universal-gateway/tls/handshake"], + }, { label: "How Does ngrok Handle TLS Certificates?", type: "category", From 0eef8cf759502c90d8deece1c8438b456e6c5245 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Wed, 9 Apr 2025 11:42:58 -0400 Subject: [PATCH 092/137] Add updated TLS termination docs --- .../http-s/http-s-endpoints.mdx | 2 +- ...rtificates.mdx => custom-certificates.mdx} | 0 .../how-does-ngrok-handle-tls.mdx | 2 +- .../what-are-private-tls-keys.mdx | 2 +- .../what-is-a-certificate-bundle.mdx | 2 +- ...at-is-automatic-certificate-management.mdx | 2 +- docs/universal-gateway/tls/index.mdx | 6 +- .../tls/tls-termination/index.mdx | 75 +++++++++++++------ .../tls-termination/termination-location.mdx | 2 +- .../tls-termination/termination-mechanics.mdx | 16 +++- sidebars.js | 20 ++--- 11 files changed, 80 insertions(+), 49 deletions(-) rename docs/universal-gateway/tls-certificates/{how-do-i-use-my-own-certificates.mdx => custom-certificates.mdx} (100%) diff --git a/docs/universal-gateway/http-s/http-s-endpoints.mdx b/docs/universal-gateway/http-s/http-s-endpoints.mdx index d8f0f31541..5ebbe1d850 100644 --- a/docs/universal-gateway/http-s/http-s-endpoints.mdx +++ b/docs/universal-gateway/http-s/http-s-endpoints.mdx @@ -51,5 +51,5 @@ additional details. ngrok handles the `/.well-known/acme-challenge` path of any HTTP endpoint matching a [domain](/universal-gateway/domains/what-are-domains) with [automated certificate management](/universal-gateway/tls-certificates/what-is-automatic-certificate-management/) -enabled. You may disable this behavior by [uploading your own certificate](/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates/) on the +enabled. You may disable this behavior by [uploading your own certificate](/universal-gateway/tls-certificates/custom-certificates/) on the matching domain. diff --git a/docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx b/docs/universal-gateway/tls-certificates/custom-certificates.mdx similarity index 100% rename from docs/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates.mdx rename to docs/universal-gateway/tls-certificates/custom-certificates.mdx diff --git a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx index 34a6d70ed6..a6a24a7772 100644 --- a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx +++ b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx @@ -3,7 +3,7 @@ title: How Does ngrok Handle TLS Certificates? description: Learn how ngrok handles TLS certificates. --- -ngrok [automatically handles](/universal-gateway/tls-certificates/what-is-automatic-certificate-management) TLS (SSL) certificate management and termination for you out of the box, but you can also [customize how termination works](/traffic-policy/actions/terminate-tls/) and [use your own certificates](/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates). +ngrok [automatically handles](/universal-gateway/tls-certificates/what-is-automatic-certificate-management) TLS (SSL) certificate management and termination for you out of the box, but you can also [customize how termination works](/traffic-policy/actions/terminate-tls/) and [use your own certificates](/universal-gateway/tls-certificates/custom-certificates). You can manage TLS certificates with: diff --git a/docs/universal-gateway/tls-certificates/what-are-private-tls-keys.mdx b/docs/universal-gateway/tls-certificates/what-are-private-tls-keys.mdx index afadc89335..f218c52a15 100644 --- a/docs/universal-gateway/tls-certificates/what-are-private-tls-keys.mdx +++ b/docs/universal-gateway/tls-certificates/what-are-private-tls-keys.mdx @@ -3,7 +3,7 @@ title: What Are Private TLS Keys? description: Learn what a TLS Certificate private key is and how to upload one to ngrok. --- -When [uploading your own TLS certificates to ngrok](/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates), you must also upload a private key. +When [uploading your own TLS certificates to ngrok](/universal-gateway/tls-certificates/custom-certificates), you must also upload a private key. You can do so with the `private_key_pem` field when uploading a TLS certificate [with the API](/api/resources/tls-certificates/). diff --git a/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx b/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx index 0601c07c73..825b88dc09 100644 --- a/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx +++ b/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx @@ -3,7 +3,7 @@ title: What Is a Certificate Bundle? description: Learn what a certificate bundle is and how to upload one to ngrok. --- -When [uploading your own TLS certificates to ngrok](/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates), you must also upload a certificate bundle. +When [uploading your own TLS certificates to ngrok](/universal-gateway/tls-certificates/custom-certificates), you must also upload a certificate bundle. Certificate bundles are a combination of all TLS certificates necessary to establish a [chain of trust](https://letsencrypt.org/certificates/) to a trusted root certificate authority. They consist of a series of [PEM-encoded X.509](https://en.wikipedia.org/wiki/X.509) certificates that have been concatenated together. **The certificates must be arranged in the proper order.** diff --git a/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx b/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx index 40d2d8aace..9e8066e349 100644 --- a/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx +++ b/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx @@ -5,7 +5,7 @@ description: Learn how ngrok provisions TLS certificates. Whenever you create a [domain](/universal-gateway/domains/what-are-domains/), ngrok automatically provisions and manages your TLS certificates by default. Your TLS certificates will be automatically provisioned **and renewed** with [Let's Encrypt](https://letsencrypt.org/about/), an ACME-compliant certificate authority. Others may be supported in the future. -Alternatively, you can [bring your own TLS certificates](/universal-gateway/tls-certificates/how-do-i-use-my-own-certificates) and [use your own certificate authority](/api/resources/certificate-authorities/). +Alternatively, you can [bring your own TLS certificates](/universal-gateway/tls-certificates/custom-certificates) and [use your own certificate authority](/api/resources/certificate-authorities/). :::tip It is recommended that you choose automatic TLS certificate management unless you have special requirements. diff --git a/docs/universal-gateway/tls/index.mdx b/docs/universal-gateway/tls/index.mdx index 3a0c2188e5..583d9e83b4 100644 --- a/docs/universal-gateway/tls/index.mdx +++ b/docs/universal-gateway/tls/index.mdx @@ -1,14 +1,12 @@ --- -title: TLS Endpoints +title: How Do I Handle TLS Traffic? --- import { LangSwitcher } from "@site/src/components/LangSwitcher"; import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitcher"; import TabItem from "@theme/TabItem"; import Tabs from "@theme/Tabs"; -import TlsLimits from "./_tls_limits.mdx"; - -# TLS Endpoints +import TlsLimits from "../_tls_limits.mdx"; ## Overview diff --git a/docs/universal-gateway/tls/tls-termination/index.mdx b/docs/universal-gateway/tls/tls-termination/index.mdx index 8ca4e89256..8eea0649fa 100644 --- a/docs/universal-gateway/tls/tls-termination/index.mdx +++ b/docs/universal-gateway/tls/tls-termination/index.mdx @@ -3,30 +3,11 @@ title: How Do I Terminate TLS? description: Learn how to terminate TLS with ngrok. --- -# TLS Termination +import ConfigExample from "/src/components/ConfigExample.tsx"; -ngrok automatically handles TLS (SSL) termination and certificate management -for you. There is typically nothing to setup, configure or manage. +You can configure TLS termination for HTTPS, TCP, and TLS endpoints with ngrok. By default, ngrok automatically terminates TLS for HTTPS endpoints, but you can still customize how that termination is done using the [`terminate-tls`](/traffic-policy/actions/terminate-tls/) Traffic Policy action. -## Overview - -ngrok's TLS termination behavior is determined by an endpoint's protocol and -traffic policy. You may customize each endpoint to choose where TLS is -terminated, how it is terminated and even whether it is terminated at all. When -ngrok's cloud service terminates TLS, it: - -- Uses latest and most secure version of TLS -- Uses the [TLS - Certificate](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) attached to the - [Domain](/universal-gateway/domains/what-are-domains/) which matches the Endpoint URL's - hostname -- Accelerates your traffic by using the global load balancer to terminate at its - closest point of presence - -ngrok supports [end-to-end encryption](#end-to-end-encryption) where the ngrok -cloud service does not terminate TLS connections and only sees enciphered -traffic. When configured this way, you are responsible for configuring TLS -termination in your upstream service or at the ngrok agent. +TLS (SSL) certificate management is automatically handled for you by default for all endpoints, though you can also [bring your own TLS certificates](/universal-gateway/tls-certificates/bring-your-own-certs/). ## How is TLS terminated by default? @@ -40,12 +21,60 @@ termination behavior. | [TLS](/universal-gateway/tls/) | Default no termination, configurable with `terminate-tls` | | [TCP](/universal-gateway/tcp/) | Default no termination, configurable with `terminate-tls` | +## Example + +This example sets the minimum and maximum TLS versions that the endpoint will support for incoming connections to TLS version 1.3. Clients can then only connect to the endpoint using TLS version 1.3 and will receive a handshake error if they attempt to connect using a different version. + +### **Step 1** — Create a Traffic Policy + + + +### **Step 2** — Start an endpoint + +```shell +ngrok http 8080 --url https://terminate-tls-example.ngrok.app --traffic-policy-file /path/to/policy.yml +``` + +### **Step 3** — Make a request + +```shell +curl https://terminate-tls-example.ngrok.app +``` + +If your curl was built with a version of OpenSSL that supports TLS 1.3, the request will succeed. However, we can verify that the endpoint only supports TLS 1.3 by telling curl to use a different version of TLS: + +```shell +curl https://terminate-tls-example.ngrok.app --tlsv1.2 --tls-max 1.2 +``` + +You should receive an "alert protocol version" error indicating that the endpoint only supports TLS 1.3. + ## Learn more - **Using Traffic Policy** — The [`terminate-tls` Traffic Policy Action](/traffic-policy/actions/terminate-tls) enables you to terminate TLS connections at ngrok's cloud service for TCP and TLS endpoints. -- **Optimizations** — Learn about ngrok's [TLS termination optimizations](/universal-gateway/tls-termination/termination-mechanics/) and how they can improve the performance of your TLS endpoints. +- **Behavior** — Learn about [how ngrok's TLS termination works](/universal-gateway/tls-termination/termination-mechanics/), and how its built-in optimizatiions can improve the performance of your TLS endpoints. - **Certificates** — ngrok makes managing TLS certificates simple. See [the TLS Certificates documentation](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) for more details on how they are [selected](/universal-gateway/tls-certificates/how-are-certificates-selected), managed, provisioned and renewed. - **End-to-end encryption** — Enabling end-to-end encryption for TLS endpoints is straightforward. See the docs on [how TLS termination works](/universal-gateway/tls-termination/termination-mechanics/#end-to-end-encryption) to learn more. diff --git a/docs/universal-gateway/tls/tls-termination/termination-location.mdx b/docs/universal-gateway/tls/tls-termination/termination-location.mdx index 624295748b..c015836140 100644 --- a/docs/universal-gateway/tls/tls-termination/termination-location.mdx +++ b/docs/universal-gateway/tls/tls-termination/termination-location.mdx @@ -6,7 +6,7 @@ description: Learn about the different locations where TLS termination can occur import TabItem from "@theme/TabItem"; import Tabs from "@theme/Tabs"; -import TlsLimits from "../_tls_limits.mdx"; +import TlsLimits from "../../_tls_limits.mdx"; import AtAgentAgentCliExample from "/examples/agent-cli/tls-terminate-at-agent.mdx"; import AtAgentAgentConfigExample from "/examples/agent-config/tls-terminate-at-agent.mdx"; diff --git a/docs/universal-gateway/tls/tls-termination/termination-mechanics.mdx b/docs/universal-gateway/tls/tls-termination/termination-mechanics.mdx index 9542dfc973..0f73fd9f4e 100644 --- a/docs/universal-gateway/tls/tls-termination/termination-mechanics.mdx +++ b/docs/universal-gateway/tls/tls-termination/termination-mechanics.mdx @@ -1,9 +1,21 @@ --- title: How Does ngrok TLS Termination Work? -description: Learn how ngrok optimizes TLS termination to give your apps better performance. +description: Learn how ngrok's TLS termination works. --- -The ngrok cloud service has multiple built-in optimizations for [TLS termination](/universal-gateway/tls/tls-termination/). +ngrok's TLS termination behavior is determined by an endpoint's protocol and traffic policy. You may customize each endpoint to choose where TLS is terminated, how it is terminated and even whether it is terminated at all. When ngrok's cloud service terminates TLS, it: + +- Uses the latest and most secure version of TLS +- Uses the [TLS + Certificate](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) attached to the + [Domain](/universal-gateway/domains/what-are-domains/) which matches the Endpoint URL's + hostname +- Accelerates your traffic by using the global load balancer to terminate at its + closest point of presence + +:::info +ngrok supports end-to-end encryption, which enables you to encrypt traffic between visitors and your upstream services so the ngrok cloud service can't access it. See the docs on [how TLS termination works](#end-to-end-encryption) to learn more. +::: ## Acceleration diff --git a/sidebars.js b/sidebars.js index 3611f23637..c07d90406e 100644 --- a/sidebars.js +++ b/sidebars.js @@ -146,7 +146,11 @@ const sidebars = { type: "doc", id: "universal-gateway/tls/tls-termination/index", }, - items: ["universal-gateway/tls/handshake"], + items: [ + "universal-gateway/tls/handshake", + "universal-gateway/tls/tls-termination/termination-mechanics", + "universal-gateway/tls/tls-termination/termination-location", + ], }, { label: "How Does ngrok Handle TLS Certificates?", @@ -158,7 +162,7 @@ const sidebars = { items: [ "universal-gateway/tls-certificates/what-is-automatic-certificate-management", "universal-gateway/tls-certificates/how-are-certificates-selected", - "universal-gateway/tls-certificates/how-do-i-use-my-own-certificates", + "universal-gateway/tls-certificates/custom-certificates", "universal-gateway/tls-certificates/what-is-a-certificate-bundle", "universal-gateway/tls-certificates/what-are-private-tls-keys", ], @@ -180,18 +184,6 @@ const sidebars = { type: "category", link: { type: "doc", id: "universal-gateway/endpoints" }, items: [ - { - label: "Protocols", - type: "category", - link: { type: "doc", id: "universal-gateway/protocols" }, - items: [ - { - id: "universal-gateway/tcp", - type: "doc", - label: "TCP", - }, - ], - }, { label: "Bindings", type: "category", From 7290914d9ae736554a053ec1f9cf38618295d58e Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Wed, 9 Apr 2025 11:54:07 -0400 Subject: [PATCH 093/137] adjusting code block to new changes --- src/components/CodeBlockWithInfo/index.tsx | 7 ++++++- src/components/code-block.tsx | 7 +++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/components/CodeBlockWithInfo/index.tsx b/src/components/CodeBlockWithInfo/index.tsx index 855b2c7f58..717a89b1ec 100644 --- a/src/components/CodeBlockWithInfo/index.tsx +++ b/src/components/CodeBlockWithInfo/index.tsx @@ -39,6 +39,7 @@ export function CodeBlockWithInfo({ const collapsible = !meta ? false : meta.collapsible && content.split("\n").length > collapseLineNumber; + const indentation = meta?.indentation; return (
@@ -68,7 +69,11 @@ export function CodeBlockWithInfo({
)} {!meta?.disableCopy && } - + {collapsible && } diff --git a/src/components/code-block.tsx b/src/components/code-block.tsx index fbb00e186c..944509adf9 100644 --- a/src/components/code-block.tsx +++ b/src/components/code-block.tsx @@ -1,5 +1,9 @@ import { Button } from "@ngrok/mantle/button"; -import type { Mode, SupportedLanguage } from "@ngrok/mantle/code-block"; +import type { + CodeBlockCode, + Mode, + SupportedLanguage, +} from "@ngrok/mantle/code-block"; import { CodeBlock, parseLanguage } from "@ngrok/mantle/code-block"; import type { WithStyleProps } from "@ngrok/mantle/types"; import type { ComponentProps, ReactNode } from "react"; @@ -61,7 +65,6 @@ function DocsCodeBlock({ ? langMatchesInClassName[0]?.split("-")[1] : ""; const language = _language || parseLanguage(langInClassName); - // const indentation = _indentation ?? meta.indentation; return ( Date: Wed, 9 Apr 2025 11:59:37 -0400 Subject: [PATCH 094/137] Add indentation --- src/components/CodeBlockWithInfo/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/CodeBlockWithInfo/index.tsx b/src/components/CodeBlockWithInfo/index.tsx index 717a89b1ec..135ccca8a8 100644 --- a/src/components/CodeBlockWithInfo/index.tsx +++ b/src/components/CodeBlockWithInfo/index.tsx @@ -39,7 +39,7 @@ export function CodeBlockWithInfo({ const collapsible = !meta ? false : meta.collapsible && content.split("\n").length > collapseLineNumber; - const indentation = meta?.indentation; + const indentation = meta?.indentation === "tabs" ? "tabs" : "spaces"; return (
From 4c8d8fea7411a79cb246d140bedd2554114a87ab Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Wed, 9 Apr 2025 12:54:03 -0400 Subject: [PATCH 095/137] Extra stuff removed --- .../agent-forwarding/index.mdx | 2 +- .../public-endpoints/index.mdx | 13 +++ .../what-are-matching-endpoints.mdx | 21 ---- sidebars.js | 99 +++++++++---------- 4 files changed, 63 insertions(+), 72 deletions(-) delete mode 100644 docs/universal-gateway/what-are-matching-endpoints.mdx diff --git a/docs/universal-gateway/agent-forwarding/index.mdx b/docs/universal-gateway/agent-forwarding/index.mdx index 645791265c..26fde07d2c 100644 --- a/docs/universal-gateway/agent-forwarding/index.mdx +++ b/docs/universal-gateway/agent-forwarding/index.mdx @@ -1,5 +1,5 @@ --- -title: How Does Agent Forwarding Work? +title: How Do I Forward Traffic To My Upstream Services? --- import TabItem from "@theme/TabItem"; diff --git a/docs/universal-gateway/public-endpoints/index.mdx b/docs/universal-gateway/public-endpoints/index.mdx index 7aeea295cf..1a95d72c04 100644 --- a/docs/universal-gateway/public-endpoints/index.mdx +++ b/docs/universal-gateway/public-endpoints/index.mdx @@ -31,6 +31,19 @@ To keep such services both public and secure, you can add a Traffic Policy to yo - [IP restrictions](/docs/traffic-policy/actions/restrict-ips/) - [Mutual TLS](/docs/traffic-policy/actions/terminate-tls/#example-traffic-policy-document) +## Matching endpoints + +A matching endpoint is a public endpoint with a [hostname](https://en.wikipedia.org/wiki/Hostname.) matching a [Domain](/universal-gateway/what-are-domains) or [TCP Address](/universal-gateway/what-are-tcp-addresses) you've configured with ngrok. + +Matching endpoints are subject to the following restrictions: + +| Endpoint Protocol | Required Port | +| ----------------- | ------------- | +| `http` | `80` | +| `https` | `443` | +| `tls` | `443` | +| `tcp` | Any | + ## API Public endpoints can be created programatically. Consult the documentation on diff --git a/docs/universal-gateway/what-are-matching-endpoints.mdx b/docs/universal-gateway/what-are-matching-endpoints.mdx deleted file mode 100644 index 43c023af40..0000000000 --- a/docs/universal-gateway/what-are-matching-endpoints.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: What are Matching Endpoints? -description: Learn about endpoints that match the domain or TCP address they're created on. ---- - -A matching endpoint is a public endpoint with a [hostname](https://en.wikipedia.org/wiki/Hostname.) matching a [Domain](/universal-gateway/what-are-domains) or [TCP Address](/universal-gateway/what-are-tcp-addresses) you've configured with ngrok. - -For example, after you create the Domain `app.example.com`, you can create the [Endpoint](/universal-gateway/endpoints) `https://app.example.com`. - -Matching endpoints are subject to the following restrictions: - -| Endpoint Protocol | Required Port | -| ----------------- | ------------- | -| `http` | `80` | -| `https` | `443` | -| `tls` | `443` | -| `tcp` | Any | - -:::tip -If you configure your Domain to use [dedicated IPs](/universal-gateway/ip-addresses/#dedicated-ips), these restrictions are removed and you may create matching endpoints on any ports. -::: diff --git a/sidebars.js b/sidebars.js index c07d90406e..5d21b4012f 100644 --- a/sidebars.js +++ b/sidebars.js @@ -105,7 +105,6 @@ const sidebars = { }, "universal-gateway/what-are-endpoint-urls", "universal-gateway/http-s/endpoint-url-defaults", - "universal-gateway/what-are-matching-endpoints", "universal-gateway/chain-endpoints", "universal-gateway/mock-api", "universal-gateway/migrate-from-tunnels", @@ -171,7 +170,7 @@ const sidebars = { ], }, { - label: "How Does Agent Fowarding Work?", + label: "How Do I Forward Traffic?", type: "category", link: { type: "doc", id: "universal-gateway/agent-forwarding/index" }, items: [ @@ -179,54 +178,54 @@ const sidebars = { "universal-gateway/agent-forwarding/serving-file-directories", ], }, - { - label: "Endpoints", - type: "category", - link: { type: "doc", id: "universal-gateway/endpoints" }, - items: [ - { - label: "Bindings", - type: "category", - link: { type: "doc", id: "universal-gateway/bindings" }, - items: [ - { - id: "universal-gateway/public-endpoints/index", - type: "doc", - label: "Public", - }, - { - id: "universal-gateway/internal-endpoints/index", - type: "doc", - label: "Internal", - }, - { - id: "universal-gateway/kubernetes-endpoints/index", - type: "doc", - label: "Kubernetes", - }, - ], - }, - { - id: "universal-gateway/endpoint-pooling", - type: "doc", - label: "Pooling", - }, - ], - }, - { - label: "Network", - type: "category", - link: { - type: "doc", - id: "universal-gateway/global-load-balancer", - }, - items: [ - "universal-gateway/global-load-balancer", - "universal-gateway/ddos-protection", - "universal-gateway/ip-addresses", - "universal-gateway/points-of-presence", - ], - }, + // { + // label: "Endpoints", + // type: "category", + // link: { type: "doc", id: "universal-gateway/endpoints" }, + // items: [ + // { + // label: "Bindings", + // type: "category", + // link: { type: "doc", id: "universal-gateway/bindings" }, + // items: [ + // { + // id: "universal-gateway/public-endpoints/index", + // type: "doc", + // label: "Public", + // }, + // { + // id: "universal-gateway/internal-endpoints/index", + // type: "doc", + // label: "Internal", + // }, + // { + // id: "universal-gateway/kubernetes-endpoints/index", + // type: "doc", + // label: "Kubernetes", + // }, + // ], + // }, + // { + // id: "universal-gateway/endpoint-pooling", + // type: "doc", + // label: "Pooling", + // }, + // ], + // }, + // { + // label: "Network", + // type: "category", + // link: { + // type: "doc", + // id: "universal-gateway/global-load-balancer", + // }, + // items: [ + // "universal-gateway/global-load-balancer", + // "universal-gateway/ddos-protection", + // "universal-gateway/ip-addresses", + // "universal-gateway/points-of-presence", + // ], + // }, ], }, { From 8f5526ef63dd99902d19c01fbbd1f7f7c30f838d Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 10 Apr 2025 11:52:41 -0400 Subject: [PATCH 096/137] Update pnpm-lock.yaml --- pnpm-lock.yaml | 194 ++++++++++++++++++++++++------------------------- 1 file changed, 97 insertions(+), 97 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f5710bcf7a..57fe513d5e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -101,7 +101,7 @@ importers: version: 2.16.0(react@18.3.1) redocusaurus: specifier: 2.2.2 - version: 2.2.2(@docusaurus/theme-common@3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.3.20)(react@18.3.1))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@docusaurus/utils@3.7.0(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(core-js@3.41.0)(enzyme@3.11.0)(mobx@6.13.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.17(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(webpack@5.99.4) + version: 2.2.2(@docusaurus/theme-common@3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.3.20)(react@18.3.1))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@docusaurus/utils@3.7.0(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(core-js@3.41.0)(enzyme@3.11.0)(mobx@6.13.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.17(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(webpack@5.99.5) yaml: specifier: 2.7.1 version: 2.7.1 @@ -1485,8 +1485,8 @@ packages: resolution: {integrity: sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==} engines: {node: '>=12'} - '@polka/url@1.0.0-next.28': - resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} '@radix-ui/number@1.1.1': resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} @@ -2695,8 +2695,8 @@ packages: caniuse-api@3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} - caniuse-lite@1.0.30001712: - resolution: {integrity: sha512-MBqPpGYYdQ7/hfKiet9SCI+nmN5/hp4ZzveOJubl5DTAMa5oggjAuoi0Z4onBpKPFI2ePGnQuQIzF3VxDjDJig==} + caniuse-lite@1.0.30001713: + resolution: {integrity: sha512-wCIWIg+A4Xr7NfhTuHdX+/FKh3+Op3LBbSp2N5Pfx6T/LhdQy3GTyoTg48BReaW/MyMNZAkTadsBtai3ldWK0Q==} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -3448,8 +3448,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.134: - resolution: {integrity: sha512-zSwzrLg3jNP3bwsLqWHmS5z2nIOQ5ngMnfMZOWWtXnqqQkPVyOipxK98w+1beLw1TB+EImPNcG8wVP/cLVs2Og==} + electron-to-chromium@1.5.135: + resolution: {integrity: sha512-8gXUdEmvb+WCaYUhA0Svr08uSeRjM2w3x5uHOc1QbaEVzJXB8rgm5eptieXzyKoVEtinLvW6MtTcurA65PeS1Q==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -4063,8 +4063,8 @@ packages: http-parser-js@0.5.10: resolution: {integrity: sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==} - http-proxy-middleware@2.0.7: - resolution: {integrity: sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==} + http-proxy-middleware@2.0.9: + resolution: {integrity: sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==} engines: {node: '>=12.0.0'} peerDependencies: '@types/express': ^4.17.13 @@ -4463,8 +4463,8 @@ packages: jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - katex@0.16.21: - resolution: {integrity: sha512-XvqR7FgOHtWupfMiigNzmh+MgUVmDGU2kXZm899ZkPfcuoPuFxyHmXsgATDpFZDAXCI8tvinaVcDo8PIIJSo4A==} + katex@0.16.22: + resolution: {integrity: sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==} hasBin: true keyv@4.5.4: @@ -6978,8 +6978,8 @@ packages: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} - webpack@5.99.4: - resolution: {integrity: sha512-TkHfuepzYbQ02GMRzZABrkguDyG6p5gaw4qxFb/cuE+XjN21lecJsNATdphBMXawFxIZxUvDHJfrs8BEfyZFzg==} + webpack@5.99.5: + resolution: {integrity: sha512-q+vHBa6H9qwBLUlHL4Y7L0L1/LlyBKZtS9FHNCQmtayxjI5RKC9yD8gpvLeqGv5lCQp1Re04yi0MF40pf30Pvg==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -8370,25 +8370,25 @@ snapshots: '@docusaurus/logger': 3.7.0 '@docusaurus/types': 3.7.0(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils': 3.7.0(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - babel-loader: 9.2.1(@babel/core@7.26.10)(webpack@5.99.4) + babel-loader: 9.2.1(@babel/core@7.26.10)(webpack@5.99.5) clean-css: 5.3.3 - copy-webpack-plugin: 11.0.0(webpack@5.99.4) - css-loader: 6.11.0(webpack@5.99.4) - css-minimizer-webpack-plugin: 5.0.1(clean-css@5.3.3)(webpack@5.99.4) + copy-webpack-plugin: 11.0.0(webpack@5.99.5) + css-loader: 6.11.0(webpack@5.99.5) + css-minimizer-webpack-plugin: 5.0.1(clean-css@5.3.3)(webpack@5.99.5) cssnano: 6.1.2(postcss@8.5.3) - file-loader: 6.2.0(webpack@5.99.4) + file-loader: 6.2.0(webpack@5.99.5) html-minifier-terser: 7.2.0 - mini-css-extract-plugin: 2.9.2(webpack@5.99.4) - null-loader: 4.0.1(webpack@5.99.4) + mini-css-extract-plugin: 2.9.2(webpack@5.99.5) + null-loader: 4.0.1(webpack@5.99.5) postcss: 8.5.3 - postcss-loader: 7.3.4(postcss@8.5.3)(typescript@5.8.3)(webpack@5.99.4) + postcss-loader: 7.3.4(postcss@8.5.3)(typescript@5.8.3)(webpack@5.99.5) postcss-preset-env: 10.1.5(postcss@8.5.3) - react-dev-utils: 12.0.1(typescript@5.8.3)(webpack@5.99.4) - terser-webpack-plugin: 5.3.14(webpack@5.99.4) + react-dev-utils: 12.0.1(typescript@5.8.3)(webpack@5.99.5) + terser-webpack-plugin: 5.3.14(webpack@5.99.5) tslib: 2.8.1 - url-loader: 4.1.1(file-loader@6.2.0(webpack@5.99.4))(webpack@5.99.4) - webpack: 5.99.4 - webpackbar: 6.0.1(webpack@5.99.4) + url-loader: 4.1.1(file-loader@6.2.0(webpack@5.99.5))(webpack@5.99.5) + webpack: 5.99.5 + webpackbar: 6.0.1(webpack@5.99.5) transitivePeerDependencies: - '@parcel/css' - '@rspack/core' @@ -8431,17 +8431,17 @@ snapshots: eval: 0.1.8 fs-extra: 11.3.0 html-tags: 3.3.1 - html-webpack-plugin: 5.6.3(webpack@5.99.4) + html-webpack-plugin: 5.6.3(webpack@5.99.5) leven: 3.1.0 lodash: 4.17.21 p-map: 4.0.0 prompts: 2.4.2 react: 18.3.1 - react-dev-utils: 12.0.1(typescript@5.8.3)(webpack@5.99.4) + react-dev-utils: 12.0.1(typescript@5.8.3)(webpack@5.99.5) react-dom: 18.3.1(react@18.3.1) react-helmet-async: '@slorber/react-helmet-async@1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)' react-loadable: '@docusaurus/react-loadable@6.0.0(react@18.3.1)' - react-loadable-ssr-addon-v5-slorber: 1.0.1(@docusaurus/react-loadable@6.0.0(react@18.3.1))(webpack@5.99.4) + react-loadable-ssr-addon-v5-slorber: 1.0.1(@docusaurus/react-loadable@6.0.0(react@18.3.1))(webpack@5.99.5) react-router: 5.3.4(react@18.3.1) react-router-config: 5.1.1(react-router@5.3.4(react@18.3.1))(react@18.3.1) react-router-dom: 5.3.4(react@18.3.1) @@ -8450,9 +8450,9 @@ snapshots: shelljs: 0.8.5 tslib: 2.8.1 update-notifier: 6.0.2 - webpack: 5.99.4 + webpack: 5.99.5 webpack-bundle-analyzer: 4.10.2 - webpack-dev-server: 4.15.2(webpack@5.99.4) + webpack-dev-server: 4.15.2(webpack@5.99.5) webpack-merge: 6.0.1 transitivePeerDependencies: - '@docusaurus/faster' @@ -8495,7 +8495,7 @@ snapshots: '@slorber/remark-comment': 1.0.0 escape-html: 1.0.3 estree-util-value-to-estree: 3.3.3 - file-loader: 6.2.0(webpack@5.99.4) + file-loader: 6.2.0(webpack@5.99.5) fs-extra: 11.3.0 image-size: 1.2.1 mdast-util-mdx: 3.0.0 @@ -8511,9 +8511,9 @@ snapshots: tslib: 2.8.1 unified: 11.0.5 unist-util-visit: 5.0.0 - url-loader: 4.1.1(file-loader@6.2.0(webpack@5.99.4))(webpack@5.99.4) + url-loader: 4.1.1(file-loader@6.2.0(webpack@5.99.5))(webpack@5.99.5) vfile: 6.0.3 - webpack: 5.99.4 + webpack: 5.99.5 transitivePeerDependencies: - '@swc/core' - acorn @@ -8597,7 +8597,7 @@ snapshots: tslib: 2.8.1 unist-util-visit: 5.0.0 utility-types: 3.11.0 - webpack: 5.99.4 + webpack: 5.99.5 transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' @@ -8639,7 +8639,7 @@ snapshots: react-dom: 18.3.1(react@18.3.1) tslib: 2.8.1 utility-types: 3.11.0 - webpack: 5.99.4 + webpack: 5.99.5 transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' @@ -8672,7 +8672,7 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) tslib: 2.8.1 - webpack: 5.99.4 + webpack: 5.99.5 transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' @@ -8858,7 +8858,7 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) tslib: 2.8.1 - webpack: 5.99.4 + webpack: 5.99.5 transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' @@ -9098,7 +9098,7 @@ snapshots: react-dom: 18.3.1(react@18.3.1) react-helmet-async: '@slorber/react-helmet-async@1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)' utility-types: 3.11.0 - webpack: 5.99.4 + webpack: 5.99.5 webpack-merge: 5.10.0 transitivePeerDependencies: - '@swc/core' @@ -9148,7 +9148,7 @@ snapshots: '@docusaurus/types': 3.7.0(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils-common': 3.7.0(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) escape-string-regexp: 4.0.0 - file-loader: 6.2.0(webpack@5.99.4) + file-loader: 6.2.0(webpack@5.99.5) fs-extra: 11.3.0 github-slugger: 1.5.0 globby: 11.1.0 @@ -9161,9 +9161,9 @@ snapshots: resolve-pathname: 3.0.0 shelljs: 0.8.5 tslib: 2.8.1 - url-loader: 4.1.1(file-loader@6.2.0(webpack@5.99.4))(webpack@5.99.4) + url-loader: 4.1.1(file-loader@6.2.0(webpack@5.99.5))(webpack@5.99.5) utility-types: 3.11.0 - webpack: 5.99.4 + webpack: 5.99.5 transitivePeerDependencies: - '@swc/core' - acorn @@ -9410,7 +9410,7 @@ snapshots: '@pnpm/network.ca-file': 1.0.2 config-chain: 1.1.13 - '@polka/url@1.0.0-next.28': {} + '@polka/url@1.0.0-next.29': {} '@radix-ui/number@1.1.1': {} @@ -10616,7 +10616,7 @@ snapshots: autoprefixer@10.4.21(postcss@8.5.3): dependencies: browserslist: 4.24.4 - caniuse-lite: 1.0.30001712 + caniuse-lite: 1.0.30001713 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.1.1 @@ -10627,12 +10627,12 @@ snapshots: dependencies: possible-typed-array-names: 1.1.0 - babel-loader@9.2.1(@babel/core@7.26.10)(webpack@5.99.4): + babel-loader@9.2.1(@babel/core@7.26.10)(webpack@5.99.5): dependencies: '@babel/core': 7.26.10 find-cache-dir: 4.0.0 schema-utils: 4.3.0 - webpack: 5.99.4 + webpack: 5.99.5 babel-plugin-dynamic-import-node@2.3.3: dependencies: @@ -10747,8 +10747,8 @@ snapshots: browserslist@4.24.4: dependencies: - caniuse-lite: 1.0.30001712 - electron-to-chromium: 1.5.134 + caniuse-lite: 1.0.30001713 + electron-to-chromium: 1.5.135 node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.24.4) @@ -10807,11 +10807,11 @@ snapshots: caniuse-api@3.0.0: dependencies: browserslist: 4.24.4 - caniuse-lite: 1.0.30001712 + caniuse-lite: 1.0.30001713 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 - caniuse-lite@1.0.30001712: {} + caniuse-lite@1.0.30001713: {} ccount@2.0.1: {} @@ -11030,7 +11030,7 @@ snapshots: copy-text-to-clipboard@3.2.0: {} - copy-webpack-plugin@11.0.0(webpack@5.99.4): + copy-webpack-plugin@11.0.0(webpack@5.99.5): dependencies: fast-glob: 3.3.3 glob-parent: 6.0.2 @@ -11038,7 +11038,7 @@ snapshots: normalize-path: 3.0.0 schema-utils: 4.3.0 serialize-javascript: 6.0.2 - webpack: 5.99.4 + webpack: 5.99.5 core-js-compat@3.41.0: dependencies: @@ -11109,7 +11109,7 @@ snapshots: postcss-selector-parser: 7.1.0 postcss-value-parser: 4.2.0 - css-loader@6.11.0(webpack@5.99.4): + css-loader@6.11.0(webpack@5.99.5): dependencies: icss-utils: 5.1.0(postcss@8.5.3) postcss: 8.5.3 @@ -11120,9 +11120,9 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.7.1 optionalDependencies: - webpack: 5.99.4 + webpack: 5.99.5 - css-minimizer-webpack-plugin@5.0.1(clean-css@5.3.3)(webpack@5.99.4): + css-minimizer-webpack-plugin@5.0.1(clean-css@5.3.3)(webpack@5.99.5): dependencies: '@jridgewell/trace-mapping': 0.3.25 cssnano: 6.1.2(postcss@8.5.3) @@ -11130,7 +11130,7 @@ snapshots: postcss: 8.5.3 schema-utils: 4.3.0 serialize-javascript: 6.0.2 - webpack: 5.99.4 + webpack: 5.99.5 optionalDependencies: clean-css: 5.3.3 @@ -11562,7 +11562,7 @@ snapshots: - styled-components - supports-color - docusaurus-theme-redoc@2.2.2(@docusaurus/theme-common@3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.3.20)(react@18.3.1))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(core-js@3.41.0)(enzyme@3.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(webpack@5.99.4): + docusaurus-theme-redoc@2.2.2(@docusaurus/theme-common@3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.3.20)(react@18.3.1))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(core-js@3.41.0)(enzyme@3.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(webpack@5.99.5): dependencies: '@docusaurus/theme-common': 3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.3.20)(react@18.3.1))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@redocly/openapi-core': 1.16.0 @@ -11573,7 +11573,7 @@ snapshots: postcss-prefix-selector: 1.16.1(postcss@8.5.3) redoc: 2.1.5(core-js@3.41.0)(enzyme@3.11.0)(mobx@6.13.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.17(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) styled-components: 6.1.17(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - webpack: 5.99.4 + webpack: 5.99.5 transitivePeerDependencies: - core-js - encoding @@ -11648,7 +11648,7 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.134: {} + electron-to-chromium@1.5.135: {} emoji-regex@8.0.0: {} @@ -11988,11 +11988,11 @@ snapshots: dependencies: escape-string-regexp: 1.0.5 - file-loader@6.2.0(webpack@5.99.4): + file-loader@6.2.0(webpack@5.99.5): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.99.4 + webpack: 5.99.5 filesize@8.0.7: {} @@ -12046,7 +12046,7 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - fork-ts-checker-webpack-plugin@6.5.3(typescript@5.8.3)(webpack@5.99.4): + fork-ts-checker-webpack-plugin@6.5.3(typescript@5.8.3)(webpack@5.99.5): dependencies: '@babel/code-frame': 7.26.2 '@types/json-schema': 7.0.15 @@ -12062,7 +12062,7 @@ snapshots: semver: 7.7.1 tapable: 1.1.3 typescript: 5.8.3 - webpack: 5.99.4 + webpack: 5.99.5 form-data-encoder@2.1.4: {} @@ -12423,7 +12423,7 @@ snapshots: html-void-elements@3.0.0: {} - html-webpack-plugin@5.6.3(webpack@5.99.4): + html-webpack-plugin@5.6.3(webpack@5.99.5): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -12431,7 +12431,7 @@ snapshots: pretty-error: 4.0.0 tapable: 2.2.1 optionalDependencies: - webpack: 5.99.4 + webpack: 5.99.5 htmlparser2@6.1.0: dependencies: @@ -12475,7 +12475,7 @@ snapshots: http-parser-js@0.5.10: {} - http-proxy-middleware@2.0.7(@types/express@4.17.21): + http-proxy-middleware@2.0.9(@types/express@4.17.21): dependencies: '@types/http-proxy': 1.17.16 http-proxy: 1.18.1 @@ -12835,7 +12835,7 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 - katex@0.16.21: + katex@0.16.22: dependencies: commander: 8.3.0 @@ -13181,7 +13181,7 @@ snapshots: dagre-d3-es: 7.0.11 dayjs: 1.11.13 dompurify: 3.2.5 - katex: 0.16.21 + katex: 0.16.22 khroma: 2.1.0 lodash-es: 4.17.21 marked: 15.0.8 @@ -13516,11 +13516,11 @@ snapshots: mimic-response@4.0.0: {} - mini-css-extract-plugin@2.9.2(webpack@5.99.4): + mini-css-extract-plugin@2.9.2(webpack@5.99.5): dependencies: schema-utils: 4.3.0 tapable: 2.2.1 - webpack: 5.99.4 + webpack: 5.99.5 minimalistic-assert@1.0.1: {} @@ -13643,11 +13643,11 @@ snapshots: dependencies: boolbase: 1.0.0 - null-loader@4.0.1(webpack@5.99.4): + null-loader@4.0.1(webpack@5.99.5): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.99.4 + webpack: 5.99.5 oas-kit-common@1.0.8: dependencies: @@ -14093,13 +14093,13 @@ snapshots: optionalDependencies: postcss: 8.5.3 - postcss-loader@7.3.4(postcss@8.5.3)(typescript@5.8.3)(webpack@5.99.4): + postcss-loader@7.3.4(postcss@8.5.3)(typescript@5.8.3)(webpack@5.99.5): dependencies: cosmiconfig: 8.3.6(typescript@5.8.3) jiti: 1.21.7 postcss: 8.5.3 semver: 7.7.1 - webpack: 5.99.4 + webpack: 5.99.5 transitivePeerDependencies: - typescript @@ -14504,7 +14504,7 @@ snapshots: date-fns: 3.6.0 react: 18.3.1 - react-dev-utils@12.0.1(typescript@5.8.3)(webpack@5.99.4): + react-dev-utils@12.0.1(typescript@5.8.3)(webpack@5.99.5): dependencies: '@babel/code-frame': 7.26.2 address: 1.2.2 @@ -14515,7 +14515,7 @@ snapshots: escape-string-regexp: 4.0.0 filesize: 8.0.7 find-up: 5.0.0 - fork-ts-checker-webpack-plugin: 6.5.3(typescript@5.8.3)(webpack@5.99.4) + fork-ts-checker-webpack-plugin: 6.5.3(typescript@5.8.3)(webpack@5.99.5) global-modules: 2.0.0 globby: 11.1.0 gzip-size: 6.0.0 @@ -14530,7 +14530,7 @@ snapshots: shell-quote: 1.8.2 strip-ansi: 6.0.1 text-table: 0.2.0 - webpack: 5.99.4 + webpack: 5.99.5 optionalDependencies: typescript: 5.8.3 transitivePeerDependencies: @@ -14562,11 +14562,11 @@ snapshots: dependencies: react: 18.3.1 - react-loadable-ssr-addon-v5-slorber@1.0.1(@docusaurus/react-loadable@6.0.0(react@18.3.1))(webpack@5.99.4): + react-loadable-ssr-addon-v5-slorber@1.0.1(@docusaurus/react-loadable@6.0.0(react@18.3.1))(webpack@5.99.5): dependencies: '@babel/runtime': 7.27.0 react-loadable: '@docusaurus/react-loadable@6.0.0(react@18.3.1)' - webpack: 5.99.4 + webpack: 5.99.5 react-markdown@10.1.0(@types/react@18.3.20)(react@18.3.1): dependencies: @@ -14767,12 +14767,12 @@ snapshots: - react-native - supports-color - redocusaurus@2.2.2(@docusaurus/theme-common@3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.3.20)(react@18.3.1))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@docusaurus/utils@3.7.0(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(core-js@3.41.0)(enzyme@3.11.0)(mobx@6.13.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.17(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(webpack@5.99.4): + redocusaurus@2.2.2(@docusaurus/theme-common@3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.3.20)(react@18.3.1))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@docusaurus/utils@3.7.0(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(core-js@3.41.0)(enzyme@3.11.0)(mobx@6.13.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.17(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(webpack@5.99.5): dependencies: '@docusaurus/theme-common': 3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.3.20)(react@18.3.1))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils': 3.7.0(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) docusaurus-plugin-redoc: 2.2.2(@docusaurus/utils@3.7.0(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(core-js@3.41.0)(enzyme@3.11.0)(mobx@6.13.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.17(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) - docusaurus-theme-redoc: 2.2.2(@docusaurus/theme-common@3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.3.20)(react@18.3.1))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(core-js@3.41.0)(enzyme@3.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(webpack@5.99.4) + docusaurus-theme-redoc: 2.2.2(@docusaurus/theme-common@3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.3.20)(react@18.3.1))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(acorn@8.14.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(core-js@3.41.0)(enzyme@3.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(webpack@5.99.5) transitivePeerDependencies: - core-js - encoding @@ -15233,7 +15233,7 @@ snapshots: sirv@2.0.4: dependencies: - '@polka/url': 1.0.0-next.28 + '@polka/url': 1.0.0-next.29 mrmime: 2.0.1 totalist: 3.0.1 @@ -15531,14 +15531,14 @@ snapshots: tapable@2.2.1: {} - terser-webpack-plugin@5.3.14(webpack@5.99.4): + terser-webpack-plugin@5.3.14(webpack@5.99.5): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 4.3.0 serialize-javascript: 6.0.2 terser: 5.39.0 - webpack: 5.99.4 + webpack: 5.99.5 terser@5.39.0: dependencies: @@ -15741,14 +15741,14 @@ snapshots: dependencies: punycode: 2.3.1 - url-loader@4.1.1(file-loader@6.2.0(webpack@5.99.4))(webpack@5.99.4): + url-loader@4.1.1(file-loader@6.2.0(webpack@5.99.5))(webpack@5.99.5): dependencies: loader-utils: 2.0.4 mime-types: 2.1.35 schema-utils: 3.3.0 - webpack: 5.99.4 + webpack: 5.99.5 optionalDependencies: - file-loader: 6.2.0(webpack@5.99.4) + file-loader: 6.2.0(webpack@5.99.5) url-template@2.0.8: {} @@ -15850,16 +15850,16 @@ snapshots: - bufferutil - utf-8-validate - webpack-dev-middleware@5.3.4(webpack@5.99.4): + webpack-dev-middleware@5.3.4(webpack@5.99.5): dependencies: colorette: 2.0.20 memfs: 3.5.3 mime-types: 2.1.35 range-parser: 1.2.1 schema-utils: 4.3.0 - webpack: 5.99.4 + webpack: 5.99.5 - webpack-dev-server@4.15.2(webpack@5.99.4): + webpack-dev-server@4.15.2(webpack@5.99.5): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 @@ -15878,7 +15878,7 @@ snapshots: express: 4.21.2 graceful-fs: 4.2.11 html-entities: 2.6.0 - http-proxy-middleware: 2.0.7(@types/express@4.17.21) + http-proxy-middleware: 2.0.9(@types/express@4.17.21) ipaddr.js: 2.2.0 launch-editor: 2.10.0 open: 8.4.2 @@ -15889,10 +15889,10 @@ snapshots: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 5.3.4(webpack@5.99.4) + webpack-dev-middleware: 5.3.4(webpack@5.99.5) ws: 8.18.1 optionalDependencies: - webpack: 5.99.4 + webpack: 5.99.5 transitivePeerDependencies: - bufferutil - debug @@ -15913,7 +15913,7 @@ snapshots: webpack-sources@3.2.3: {} - webpack@5.99.4: + webpack@5.99.5: dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.7 @@ -15935,7 +15935,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.14(webpack@5.99.4) + terser-webpack-plugin: 5.3.14(webpack@5.99.5) watchpack: 2.4.2 webpack-sources: 3.2.3 transitivePeerDependencies: @@ -15943,7 +15943,7 @@ snapshots: - esbuild - uglify-js - webpackbar@6.0.1(webpack@5.99.4): + webpackbar@6.0.1(webpack@5.99.5): dependencies: ansi-escapes: 4.3.2 chalk: 4.1.2 @@ -15952,7 +15952,7 @@ snapshots: markdown-table: 2.0.0 pretty-time: 1.1.0 std-env: 3.9.0 - webpack: 5.99.4 + webpack: 5.99.5 wrap-ansi: 7.0.0 websocket-driver@0.7.4: From 6727b582dab9ff8b837bff3044e2601e8c53f4f6 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 10 Apr 2025 12:16:11 -0400 Subject: [PATCH 097/137] Fix use your own domain guide --- README.md | 15 ++++++++ .../domains/how-do-i-use-my-own-domain.mdx | 35 +++++++++++-------- sidebars.js | 22 ++++++------ 3 files changed, 47 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index bb41d4dc1d..323ae900c6 100644 --- a/README.md +++ b/README.md @@ -84,3 +84,18 @@ pnpm run build For bug reports, feature request, questions and community support please ooen an issue or discussion in our [ngrok Community](https://github.com/ngrok/ngrok). To report a problem with our documentation, please open a new [Github issue](https://github.com/ngrok/ngrok-docs/issues). + +## Troubleshooting + +### EMFILE: too many open files error + +Sometimes when you run `pnpm run dev`, docusaurus fails to build the site with the following error: + +```bash +Error: Docusaurus could not load module at path "C:/.../ngrok-docs/sidebars.js" +Cause: EMFILE: too many open files, open 'C:/.../ngrok-docs/sidebars.js' +``` + +You can fix this by running `pnpm run clean-dev`. + +The issue appears to be related to the npm cache being too large. `pnpm run clean-dev` clears and verifies the cache before running `pnpm run dev` for you. diff --git a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx index a04027aad9..beaec09d29 100644 --- a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx +++ b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx @@ -3,26 +3,33 @@ title: How Do I Use My Own Domain? description: Learn how to use your own domain with ngrok. --- -You can use any domain name that you already own with ngrok, e.g. -`app.your-domain.com`. To do so: +This guide will show you the steps to use any domain name that you already own with ngrok, e.g. `app.your-domain.com`. + +:::note +ngrok is not a domain registrar; you must already own a domain name to use it +with ngrok. +::: + +## Step 1 - Create a domain in ngrok + +You can create a domain in the ngrok dashboard. [You can do so by going here](https://dashboard.ngrok.com/domains). + +When your domain is created, you'll be given a `CNAME` value such as `exampledata.otherdata.ngrok-cname.com`. Copy it. + +:::info +You can also create a Domain via the [ngrok API](/api/resources/reserved-domains/#request). The `CNAME` will be in the `"cname_target"` field of [the response object](/api/resources/reserved-domains/#response). +::: + +## Step 2 - Add the CNAME record to your domain -1. Create a Domain in the ngrok dashboard. [You can do so by going here](https://dashboard.ngrok.com/domains). - - You can also create a Domain via the [ngrok API](/api/resources/reserved-domains/#request). -1. When you create a Domain in the dashboard, you'll be given a `CNAME` value such as `exampledata.otherdata.ngrok-cname.com`. Copy it. - - This value will be in the `"cname_target"` field of [the response object](/api/resources/reserved-domains/#response) if you create a Domain via the API. 1. In a new browser tab, navigate to your domain hosting provider's dashboard and create a CNAME record. Check your hosting provider's support content or documentation to learn how. + - Typically, this process includes creating a [DNS record](https://en.wikipedia.org/wiki/List_of_DNS_record_types). + 1. When configuring the record, use the following values: - Its **type** should be `CNAME` - Its **name** should be `@` - - Its **value** should be the `CNAME` value you copied from the ngrok dashboard. -1. Add the `CNAME` value you copied from to point traffic from the domain to ngrok's cloud service. When you create a Domain, you will be presented with a target value for the CNAME record you need to create. If you [create the Domain via - API](/api/resources/reserved-domains/), this value is the `cname_target` field. - -:::note -ngrok is not a domain registrar; you must already own a domain name to use it -with ngrok. -::: + - Its **value** should be the `CNAME` value you copied from the ngrok dashboard or API response. ## Wildcard domains diff --git a/sidebars.js b/sidebars.js index 5d21b4012f..9b59401620 100644 --- a/sidebars.js +++ b/sidebars.js @@ -61,6 +61,17 @@ const sidebars = { "universal-gateway/wildcard-domains/wildcard-endpoints", ], }, + { + label: "What are TCP Addresses?", + type: "category", + link: { + type: "doc", + id: "universal-gateway/tcp-addresses/what-are-tcp-addresses", + }, + items: [ + "universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned", + ], + }, { label: "What are Endpoints?", type: "category", @@ -110,17 +121,6 @@ const sidebars = { "universal-gateway/migrate-from-tunnels", ], }, - { - label: "What are TCP Addresses?", - type: "category", - link: { - type: "doc", - id: "universal-gateway/tcp-addresses/what-are-tcp-addresses", - }, - items: [ - "universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned", - ], - }, { label: "How Do I Handle HTTP/S Traffic?", type: "category", From 366fdda6728aa845a9dd140ede9250bff07216e7 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 10 Apr 2025 13:44:03 -0400 Subject: [PATCH 098/137] Fix linting --- .../domains/how-do-i-use-my-own-domain.mdx | 2 +- src/components/CodeBlockWithInfo/index.tsx | 19 ++++---- src/components/LangSwitcher/index.tsx | 12 ++--- src/components/LangSwitcher/utils.ts | 47 ++++++++++++++----- 4 files changed, 52 insertions(+), 28 deletions(-) diff --git a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx index beaec09d29..157af26dcc 100644 --- a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx +++ b/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx @@ -26,7 +26,7 @@ You can also create a Domain via the [ngrok API](/api/resources/reserved-domains - Typically, this process includes creating a [DNS record](https://en.wikipedia.org/wiki/List_of_DNS_record_types). -1. When configuring the record, use the following values: +2. When configuring the record, use the following values: - Its **type** should be `CNAME` - Its **name** should be `@` - Its **value** should be the `CNAME` value you copied from the ngrok dashboard or API response. diff --git a/src/components/CodeBlockWithInfo/index.tsx b/src/components/CodeBlockWithInfo/index.tsx index 135ccca8a8..bc11f6c57f 100644 --- a/src/components/CodeBlockWithInfo/index.tsx +++ b/src/components/CodeBlockWithInfo/index.tsx @@ -10,18 +10,21 @@ import { CodeBlockTitle, fmtCode, } from "@ngrok/mantle/code-block"; -import clsx from "clsx"; import type { ReactNode } from "react"; import type { LanguageInfo } from "../LangSwitcher/data"; import { LanguageData } from "../LangSwitcher/LanguageData"; type CodeBlockWithInfoProps = { content: string; + // biome-ignore lint/suspicious/noExplicitAny: language: any; collapseLineNumber: number; - meta: Record | undefined; - className: string | undefined; + // biome-ignore lint/suspicious/noExplicitAny: + meta: any; + // biome-ignore lint/suspicious/noExplicitAny: + className?: any; headerContent: ReactNode; + // biome-ignore lint/suspicious/noExplicitAny: codeBlockProps?: any; info?: LanguageInfo | undefined; }; @@ -43,7 +46,7 @@ export function CodeBlockWithInfo({ return (
- + {headerContent} @@ -51,18 +54,18 @@ export function CodeBlockWithInfo({ {meta?.title && (
<> - {meta.mode ? ( - + {meta?.mode ? ( + ) : ( )} - {meta.titleLink ? ( + {meta?.titleLink ? ( {meta.title} ) : ( - {meta.title} + {meta?.title} )} diff --git a/src/components/LangSwitcher/index.tsx b/src/components/LangSwitcher/index.tsx index 37b5bcb540..3585d5f3fd 100644 --- a/src/components/LangSwitcher/index.tsx +++ b/src/components/LangSwitcher/index.tsx @@ -24,7 +24,7 @@ export function LangSwitcher({ children, className, ...props }: any) { // biome-ignore lint/suspicious/noExplicitAny: codeBlocks.find((child: any) => child.language === defaultLanguage) || codeBlocks[0]; - updateSelectedLanguage(startingLanguage.language); + updateSelectedLanguage(startingLanguage?.language); // if no default language is set, set the first tab as the selected tab } @@ -32,7 +32,7 @@ export function LangSwitcher({ children, className, ...props }: any) { codeBlocks.find( (child: any) => child.language === selectedLanguage || - languagesAreSynonyms(child.language, selectedLanguage), + languagesAreSynonyms(child.language, selectedLanguage) ) || codeBlocks[0]; return ( @@ -43,10 +43,10 @@ export function LangSwitcher({ children, className, ...props }: any) { > {() => ( @@ -68,7 +68,7 @@ export function LangSwitcher({ children, className, ...props }: any) { ))}
} - info={matchingBlock.info} + info={matchingBlock?.info} codeBlockProps={props} /> )} diff --git a/src/components/LangSwitcher/utils.ts b/src/components/LangSwitcher/utils.ts index c351f804cf..0be863ba82 100644 --- a/src/components/LangSwitcher/utils.ts +++ b/src/components/LangSwitcher/utils.ts @@ -1,9 +1,14 @@ -import { parseLanguage } from "@ngrok/mantle/code-block"; +import { + parseLanguage, + type Meta, + type SupportedLanguage, +} from "@ngrok/mantle/code-block"; import { languageInfo, type LanguageInfo } from "./data"; +import type { ReactElement, ReactNode } from "react"; export function getMetaDataWithQuotes( propertyName: string, - metastring: string, + metastring: string ) { const property = `${propertyName}=`; if (!metastring.includes(property)) return null; @@ -24,6 +29,7 @@ export function getMetaData(metastring: string | undefined) { } const meta = metastring.split(/\s+/); const metaData: Record = {}; + // biome-ignore lint/complexity/noForEach: meta.forEach((item) => { const [key, value] = item.split("="); if (key && value) { @@ -31,6 +37,7 @@ export function getMetaData(metastring: string | undefined) { } }); // Add the properties that use quotes to the metaData object + // biome-ignore lint/complexity/noForEach: ["tabName", "title"].forEach((property) => { const quotedData = getMetaDataWithQuotes(property, metastring); if (quotedData) { @@ -40,10 +47,22 @@ export function getMetaData(metastring: string | undefined) { return metaData; } -export const getCodeBlocks = (children: any) => { - return children.map((child: any) => { +export type CodeBlockData = { + language: SupportedLanguage | string | undefined; + content: ReactNode[]; + meta: Meta & { + collapsible: boolean; + titleLink?: string; + tabName?: string; + title?: string; + }; + info?: LanguageInfo; +}; + +export const getCodeBlocks = (children: ReactElement[]): CodeBlockData[] => { + return children.map((child: ReactElement) => { const { className, metastring, children, language } = - child.props.children.props ?? child.props; + child?.props.children.props ?? child.props; const parsedLanguage = language || parseLanguage(className); const meta = getMetaData(metastring); @@ -55,9 +74,10 @@ export const getCodeBlocks = (children: any) => { ...meta, // Make it collapsible by default collapsible: true, - // If no title found yet, check for a tabName. - // If a tabName exists, use the parsedLanguage as the title - title: title ? title : meta.tabName ? parsedLanguage : null, + titleLink: meta.titleLink, + tabName: meta.tabName, + title, + disableCopy: false, }, info: getLanguageInfo(parsedLanguage), }; @@ -67,17 +87,17 @@ export const getCodeBlocks = (children: any) => { export const getLanguageInfo = (language: string) => { return languageInfo.find( (item) => - item.name === language || item?.allNames?.some((alt) => alt === language), + item.name === language || item?.allNames?.some((alt) => alt === language) ); }; export function languagesAreSynonyms( languageToCheck: string, - selectedLanguage: string | null, + selectedLanguage: string | null ) { if (!selectedLanguage) return false; const synonymousLanguage = languageInfo.find((lang: LanguageInfo) => - lang.allNames?.includes(selectedLanguage), + lang.allNames?.includes(selectedLanguage) ); return ( synonymousLanguage?.name === languageToCheck || @@ -101,9 +121,10 @@ export const getStorageLanguageAndTab = (): { return null; } const searchParams = new URLSearchParams(window?.location?.search); - let tempLang = + const tempLang = searchParams.get(langParamName) || getStorageItem(langParamName); - let tempTab = searchParams.get(tabParamName) || getStorageItem(tabParamName); + const tempTab = + searchParams.get(tabParamName) || getStorageItem(tabParamName); return { defaultLanguage: tempLang ?? null, defaultTabItem: tempTab ?? null }; }; From 148934b526b21f1470f759e2e3ac77398feeb14d Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 10 Apr 2025 15:09:02 -0400 Subject: [PATCH 099/137] Cleaning up TLS termination location --- docs/agent/agent-tls-termination.mdx | 2 +- docs/agent/ssh-reverse-tunnel-agent.mdx | 2 +- ...o-terminate-traffic-with-ngrok-configs.mdx | 2 +- .../other-guides/securing-your-tunnels.mdx | 4 +- .../end-customers.mdx | 4 +- .../http-s/http-s-endpoints.mdx | 2 +- docs/universal-gateway/http-s/index.mdx | 2 +- docs/universal-gateway/overview.mdx | 2 +- ...x => automatic-certificate-management.mdx} | 0 .../tls-certificates/custom-certificates.mdx | 2 +- .../how-does-ngrok-handle-tls.mdx | 4 +- docs/universal-gateway/tls-termination.mdx | 271 ------------- docs/universal-gateway/tls/index.mdx | 6 +- docs/universal-gateway/tls/tls-clients.mdx | 2 +- .../tls/tls-termination/index.mdx | 50 +-- .../tls-termination/termination-location.mdx | 365 +++++++++++------- sidebars.js | 2 +- 17 files changed, 257 insertions(+), 465 deletions(-) rename docs/universal-gateway/tls-certificates/{what-is-automatic-certificate-management.mdx => automatic-certificate-management.mdx} (100%) delete mode 100644 docs/universal-gateway/tls-termination.mdx diff --git a/docs/agent/agent-tls-termination.mdx b/docs/agent/agent-tls-termination.mdx index ba209af108..e851237670 100644 --- a/docs/agent/agent-tls-termination.mdx +++ b/docs/agent/agent-tls-termination.mdx @@ -7,7 +7,7 @@ title: Agent TLS Termination Agent TLS termination enables you to secure your traffic with end-to-end encryption without needing to reconfigure your server. :::tip -If your service doesn't support TLS termination, you can still use Agent TLS termination with [Zero-Knowledge TLS](/universal-gateway/tls-termination/#end-to-end-encryption). +If your service doesn't support TLS termination, you can still use Agent TLS termination with [Zero-Knowledge TLS](/universal-gateway/tls/tls-termination/#end-to-end-encryption). ::: ## Quickstart diff --git a/docs/agent/ssh-reverse-tunnel-agent.mdx b/docs/agent/ssh-reverse-tunnel-agent.mdx index a016e343ee..c73af39627 100644 --- a/docs/agent/ssh-reverse-tunnel-agent.mdx +++ b/docs/agent/ssh-reverse-tunnel-agent.mdx @@ -183,7 +183,7 @@ differences from the ngrok agent includes: - You can't [forward to upstream https services](/universal-gateway/http/#https-forwarding) - You can't create multiple endpoints over the same connection - You can't [serve file system directories](/universal-gateway/http/#serving-file-directories) with the `file://` protocol -- You can't terminate TLS at the agent when using [end-to-end encryption](/universal-gateway/tls-termination/#end-to-end-encryption) +- You can't terminate TLS at the agent when using [end-to-end encryption](/universal-gateway/tls/tls-termination/#end-to-end-encryption) - You can't run labeled tunnels for use with [Edges](/universal-gateway/edges). ## Pricing diff --git a/docs/guides/other-guides/how-to-terminate-traffic-with-ngrok-configs.mdx b/docs/guides/other-guides/how-to-terminate-traffic-with-ngrok-configs.mdx index 86680c3393..c7483f72f7 100644 --- a/docs/guides/other-guides/how-to-terminate-traffic-with-ngrok-configs.mdx +++ b/docs/guides/other-guides/how-to-terminate-traffic-with-ngrok-configs.mdx @@ -3,7 +3,7 @@ Agent TLS termination enables you to secure your traffic with end-to-end encryption without needing to reconfigure your server. :::tip -If your service doesn't support TLS termination, you can still use Agent TLS termination with [Zero-Knowledge TLS](/universal-gateway/tls-termination/#end-to-end-encryption). +If your service doesn't support TLS termination, you can still use Agent TLS termination with [Zero-Knowledge TLS](/universal-gateway/tls/tls-termination/#end-to-end-encryption). ::: ## Quickstart diff --git a/docs/guides/other-guides/securing-your-tunnels.mdx b/docs/guides/other-guides/securing-your-tunnels.mdx index 148587ef95..4e971520a3 100644 --- a/docs/guides/other-guides/securing-your-tunnels.mdx +++ b/docs/guides/other-guides/securing-your-tunnels.mdx @@ -26,7 +26,7 @@ For our HTTP tunnel type, use `scheme https` to configure the ngrok agent to ope If your local service is not running on the same machine as the ngrok agent, we recommend that you set up TLS encryption for the ngrok agent to upstream service leg of the tunnel using our [local HTTPS feature](/universal-gateway/http/#https-forwarding). -For custom domains, use ngrok's [Automated TLS certificates](/universal-gateway/tls-certificates/what-is-automatic-certificate-management/) to have ngrok automatically provision a TLS certificate for your endpoint from Let's Encrypt. +For custom domains, use ngrok's [Automated TLS certificates](/universal-gateway/tls-certificatesautomatic-certificate-management/) to have ngrok automatically provision a TLS certificate for your endpoint from Let's Encrypt. :::note @@ -42,7 +42,7 @@ If your organization uses a custom ingress domain, your default ngrok configurat ### TLS termination -TLS Encryption is terminated at different locations depending on the ngrok Tunnel / Edge type and configuration. See the documentation on [Terminating TLS Connections](/universal-gateway/tls-termination/) for more details. +TLS Encryption is terminated at different locations depending on the ngrok Tunnel / Edge type and configuration. See the documentation on [Terminating TLS Connections](/universal-gateway/tls/tls-termination/) for more details. ### Minimum TLS version diff --git a/docs/guides/site-to-site-connectivity/end-customers.mdx b/docs/guides/site-to-site-connectivity/end-customers.mdx index c8d7a49284..a68859e6f7 100644 --- a/docs/guides/site-to-site-connectivity/end-customers.mdx +++ b/docs/guides/site-to-site-connectivity/end-customers.mdx @@ -140,8 +140,8 @@ your vendor. The agent always connects to the ngrok network via TLS. We support three encryption models based on where TLS is _terminated_: 1. **TLS termination at the ngrok network**. This is the default behavior when using HTTPS tunnels, where ngrok manages TLS certificate generation and renewal for both you and your vendor. -2. **TLS termination at the ngrok agent**. Often referred to as [zero-knowledge TLS](/universal-gateway/tls-termination/#end-to-end-encryption), this model encrypts your TLS tunnels end-to-end, using filesystem paths to your TLS certificate and key, without requiring you to reconfigure your upstream service for TLS termination. -3. **TLS termination at your upstream service**. This model implements [end-to-end zero-knowledge encryption](/universal-gateway/tls-termination/#end-to-end-encryption), where the ngrok network forwards unterminated connections through to your upstream application. +2. **TLS termination at the ngrok agent**. Often referred to as [zero-knowledge TLS](/universal-gateway/tls/tls-termination/#end-to-end-encryption), this model encrypts your TLS tunnels end-to-end, using filesystem paths to your TLS certificate and key, without requiring you to reconfigure your upstream service for TLS termination. +3. **TLS termination at your upstream service**. This model implements [end-to-end zero-knowledge encryption](/universal-gateway/tls/tls-termination/#end-to-end-encryption), where the ngrok network forwards unterminated connections through to your upstream application. ### Is my data end-to-end encrypted? diff --git a/docs/universal-gateway/http-s/http-s-endpoints.mdx b/docs/universal-gateway/http-s/http-s-endpoints.mdx index 5ebbe1d850..da2ea8edfc 100644 --- a/docs/universal-gateway/http-s/http-s-endpoints.mdx +++ b/docs/universal-gateway/http-s/http-s-endpoints.mdx @@ -50,6 +50,6 @@ additional details. ## Well Known URIs ngrok handles the `/.well-known/acme-challenge` path of any HTTP endpoint matching a -[domain](/universal-gateway/domains/what-are-domains) with [automated certificate management](/universal-gateway/tls-certificates/what-is-automatic-certificate-management/) +[domain](/universal-gateway/domains/what-are-domains) with [automated certificate management](/universal-gateway/tls-certificatesautomatic-certificate-management/) enabled. You may disable this behavior by [uploading your own certificate](/universal-gateway/tls-certificates/custom-certificates/) on the matching domain. diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx index c8d5584a9e..df93f91f42 100644 --- a/docs/universal-gateway/http-s/index.mdx +++ b/docs/universal-gateway/http-s/index.mdx @@ -161,7 +161,7 @@ ngrok api endpoints create \ - **Traffic Policy** — Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate and transform the traffic through the endpoint. - **Agent Forwarding** — The [ngrok agent](/agent/) and [Agent SDKs](/agent-sdks/) forward traffic that your endpoints receive to upstream services. See [the agent forwarding documentation](/universal-gateway/agent-forwarding/) for more information. - **Traffic Observability** — [Traffic Inspector](/obs/traffic-inspection/) gives you a real-time view in the ngrok dashboard of the HTTP traffic flowing through your HTTP/S endpoints. You can even [export traffic logs with the Traffic Events system](/docs/obs/events/reference/#traffic-events). -- **TLS** — Learn how [ngrok automatically handles TLS](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) and [TLS termination](/universal-gateway/tls-termination/) for HTTP/S endpoints for you. +- **TLS** — Learn how [ngrok automatically handles TLS](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) and [TLS termination](/universal-gateway/tls/tls-termination/) for HTTP/S endpoints for you. ## Errors diff --git a/docs/universal-gateway/overview.mdx b/docs/universal-gateway/overview.mdx index 786be626a2..d568d2a6e8 100644 --- a/docs/universal-gateway/overview.mdx +++ b/docs/universal-gateway/overview.mdx @@ -46,7 +46,7 @@ ngrok automatically handles TLS (SSL) termination and certificate management for you. There is typically nothing to setup, configure or manage. - [Learn more about TLS Certificates →](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) -- [Learn more about the TLS Termination →](/universal-gateway/tls-termination/) +- [Learn more about the TLS Termination →](/universal-gateway/tls/tls-termination/) ## Global Load Balancer diff --git a/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx b/docs/universal-gateway/tls-certificates/automatic-certificate-management.mdx similarity index 100% rename from docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management.mdx rename to docs/universal-gateway/tls-certificates/automatic-certificate-management.mdx diff --git a/docs/universal-gateway/tls-certificates/custom-certificates.mdx b/docs/universal-gateway/tls-certificates/custom-certificates.mdx index 8f3d337252..998ca5872f 100644 --- a/docs/universal-gateway/tls-certificates/custom-certificates.mdx +++ b/docs/universal-gateway/tls-certificates/custom-certificates.mdx @@ -3,7 +3,7 @@ title: How Do I Use My Own Certificates? description: Learn how to use your own TLS certificates rather than automatic certificate management. --- -ngrok [manages TLS certificates for your domains automatically](/universal-gateway/tls-certificates/what-is-automatic-certificate-management) by default, and in general automatic management is recommended. However, you may also upload and manage the renewal and rotation of your TLS certificates yourself. +ngrok [manages TLS certificates for your domains automatically](/universal-gateway/tls-certificatesautomatic-certificate-management) by default, and in general automatic management is recommended. However, you may also upload and manage the renewal and rotation of your TLS certificates yourself. :::warning You cannot use your own certificates with [ngrok's managed domains](/universal-gateway/domains/what-are-managed-domains). diff --git a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx index a6a24a7772..d59923e88a 100644 --- a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx +++ b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx @@ -3,7 +3,7 @@ title: How Does ngrok Handle TLS Certificates? description: Learn how ngrok handles TLS certificates. --- -ngrok [automatically handles](/universal-gateway/tls-certificates/what-is-automatic-certificate-management) TLS (SSL) certificate management and termination for you out of the box, but you can also [customize how termination works](/traffic-policy/actions/terminate-tls/) and [use your own certificates](/universal-gateway/tls-certificates/custom-certificates). +ngrok [automatically handles](/universal-gateway/tls-certificatesautomatic-certificate-management) TLS (SSL) certificate management and termination for you out of the box, but you can also [customize how termination works](/traffic-policy/actions/terminate-tls/) and [use your own certificates](/universal-gateway/tls-certificates/custom-certificates). You can manage TLS certificates with: @@ -19,7 +19,7 @@ TLS certificates are composed of a private key and a certificate. These are pres ## Certificates with domains -TLS certificates are attached to [domains](/universal-gateway/domains/what-are-domains/) for [termination of TLS connections to endpoints](/universal-gateway/tls-termination/) whose URLs match that domain. +TLS certificates are attached to [domains](/universal-gateway/domains/what-are-domains/) for [termination of TLS connections to endpoints](/universal-gateway/tls/tls-termination/) whose URLs match that domain. ## Wildcard domains diff --git a/docs/universal-gateway/tls-termination.mdx b/docs/universal-gateway/tls-termination.mdx deleted file mode 100644 index 7c71e2071a..0000000000 --- a/docs/universal-gateway/tls-termination.mdx +++ /dev/null @@ -1,271 +0,0 @@ ---- -title: How Do I Terminate TLS? -description: Learn how to terminate TLS with ngrok. ---- - -import TabItem from "@theme/TabItem"; -import Tabs from "@theme/Tabs"; - -import TlsLimits from "./_tls_limits.mdx"; - -import AtAgentAgentCliExample from "/examples/agent-cli/tls-terminate-at-agent.mdx"; -import AtAgentAgentConfigExample from "/examples/agent-config/tls-terminate-at-agent.mdx"; -import AtAgentGoSdkExample from "/examples/go-sdk/tls-terminate-at-agent.mdx"; -import AtAgentJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-agent.mdx"; -import AtAgentKubernetesExample from "/examples/k8s/tls-terminate-at-agent.mdx"; -import AtAgentPythonSdkExample from "/examples/python-sdk/tls-terminate-at-agent.mdx"; -import AtAgentRustSdkExample from "/examples/rust-sdk/tls-terminate-at-agent.mdx"; -import AtAgentSshExample from "/examples/ssh/tls-terminate-at-agent.mdx"; - -import AtUpstreamAgentCliExample from "/examples/agent-cli/tls-terminate-at-upstream.mdx"; -import AtUpstreamAgentConfigExample from "/examples/agent-config/tls-terminate-at-upstream.mdx"; -import AtUpstreamGoSdkExample from "/examples/go-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamKubernetesExample from "/examples/k8s/tls-terminate-at-upstream.mdx"; -import AtUpstreamPythonSdkExample from "/examples/python-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamRustSdkExample from "/examples/rust-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamSshExample from "/examples/ssh/tls-terminate-at-upstream.mdx"; - -import CustomDomainAgentCliExample from "/examples/agent-cli/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainAgentConfigExample from "/examples/agent-config/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainGoSdkExample from "/examples/go-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainKubernetesExample from "/examples/k8s/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainPythonSdkExample from "/examples/python-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainRustSdkExample from "/examples/rust-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainSshExample from "/examples/ssh/tls-terminate-at-edge-custom-domain.mdx"; - -# TLS Termination - -ngrok automatically handles TLS (SSL) termination and certificate management -for you. There is typically nothing to setup, configure or manage. - -## Overview - -ngrok's TLS termination behavior is determined by an endpoint's protocol and -traffic policy. You may customize each endpoint to choose where TLS is -terminated, how it is terminated and even whether it is terminated at all. When -ngrok's cloud service terminates TLS, it: - -- Uses latest and most secure version of TLS -- Uses the [TLS - Certificate](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) attached to the - [Domain](/universal-gateway/domains/what-are-domains/) which matches the Endpoint URL's - hostname -- Accelerates your traffic by using the global load balancer to terminate at its - closest point of presence - -ngrok supports [end-to-end encryption](#end-to-end-encryption) where the ngrok -cloud service does not terminate TLS connections and only sees enciphered -traffic. When configured this way, you are responsible for configuring TLS -termination in your upstream service or at the ngrok agent. - -## Termination Location - -TLS connections to your ngrok endpoints are terminated at one of three -locations. - -- **ngrok's cloud service**: This is the easiest and most common. All HTTPS - endpoints terminate TLS at ngrok's cloud service. When connections are - terminated by ngrok's cloud service, they are re-encrypted before they are - transmitted over a Secure Tunnel to an agent. -- **ngrok agent**: This is a form of [end-to-end - encryption](#end-to-end-encryption) where the ngrok cloud service does not - terminate TLS and you instead configure the ngrok agent to terminate TLS - connections for you. -- **your upstream service**: This is another form of [end-to-end - encryption](#end-to-end-encryption) where neither the cloud service nor an - agent terminates TLS connections. Instead, your upstream application service is - responsible for TLS termination. - -An endpoint's protocol determines the ngrok cloud service's default TLS -termination behavior. - -| Endpoint Protocol | TLS Termination | -| --------------------------------- | --------------------------------------------------------- | -| [HTTP](/universal-gateway/http/) | None | -| [HTTPS](/universal-gateway/http/) | Always at ngrok's cloud service. | -| [TLS](/universal-gateway/tls/) | Default no termination, configurable with `terminate-tls` | -| [TCP](/universal-gateway/tcp/) | Default no termination, configurable with `terminate-tls` | - -### Examples - -#### Cloud Service - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -#### Terminate at Agent - -See [Zero-Knowledge TLS at the Agent](/agent/agent-tls-termination/) for additional details. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -#### Terminate at Upstream - - - - - - - - - - - - - - - - - - - - - - - - - - - - -## `terminate-tls` - -The [`terminate-tls` Traffic Policy -Action](/traffic-policy/actions/terminate-tls) enables you to terminate TLS -connections at ngrok's cloud service for TCP and TLS endpoints. - -You may also use this action on HTTPS endpoints to customize how TLS is -terminated. When you use the `terminate-tls` action on an HTTPS endpoint, ngrok -will skip the default TLS termination step that it runs for all HTTPS endpoints -so as not to terminate TLS twice. - -## Acceleration - -The ngrok cloud service improves the performance of your endpoints by -accelerating TLS termination using ngrok's [global points -of presence](/universal-gateway/points-of-presence). - -TLS connection set up requires multiple network round-trips. When round-trip -times (RTTs) are long, TLS connection establishment slows down. ngrok reduces -the latency of these round-trip times between the client and your endpoint by -terminating connections at the closest [point of -presence](/universal-gateway/points-of-presence/) via its [global load -balancer](/universal-gateway/global-load-balancer). - -## Certificates - -When the ngrok cloud service terminates TLS connections, it does so with the -[TLS Certificate](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) attached to the -[Domain](/universal-gateway/domains/what-are-domains/) which matches the Endpoint URL's -hostname. See the documentation on [TLS -Certificates](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) for more details on -how they are -[selected](/universal-gateway/tls-certificates/how-are-certificates-selected), -managed, provisioned and renewed. - -You may customize which TLS certificate is chosen for termination with the -[`terminate-tls`](/traffic-policy/actions/terminate-tls) traffic policy action. - -## Mutual TLS - -Mutual TLS is supported when terminating TLS at ngrok's cloud service via the -`mutual_tls_certificate_authorities` field of the -[`terminate-tls`](/traffic-policy/actions/terminate-tls) traffic policy action. - -Mutual TLS is supported when terminating TLS at the agent via the -`mutual_tls_certificate_authorities` property of the [`agent_tls_termination` -section of an endpoint -configuration](/agent/config/v3/#endpoint-configuration-options) in the agent -configuration file. - -## FIPS Compliance - -ngrok does not use a FIPS-compliant TLS implementation by default, but one can -be enabled for your endpoints. - -[Contact us](mailto:support@ngrok.com) if you require a FIPS-compliant TLS -implementation. - -## End-to-end encryption - -You may choose to terminate TLS at your upstream service or at the ngrok agent -to achieve end-to-end encryption (E2EE), often referred to as Zero-knowledge TLS. When your endpoints operate in this -mode, the ngrok cloud service can not see the payloads that transfer through -your endpoints. - -Creating an endpoint with end-to-end encryption is simple: - -- Create a TLS or TCP endpoint -- **Do not** add a `terminate-tls` action to its traffic policy. - -That's it! Read the [Agent TLS Termination -Guide](/agent/agent-tls-termination/) for a step by step approach to set it up. - -To set up the agent to terminate TLS for you, consult the following table -because the configuration depends on which kind of agent you are using. - -| Agent | Documentation | -| ------------------- | ------------------------------------------------------------------------------------------------------- | -| Agent Config File | [`agent_tls_termination`](/agent/config/v3/#endpoint-configuration-options) | -| Go SDK | [WithTLSTerminationKeyPair](https://pkg.go.dev/golang.ngrok.com/ngrok/config#WithTLSTerminationKeyPair) | -| Other SDKs | not supported | -| Kubernetes Operator | not supported | - -## Limits and Timeouts - - diff --git a/docs/universal-gateway/tls/index.mdx b/docs/universal-gateway/tls/index.mdx index 583d9e83b4..029f7d37ee 100644 --- a/docs/universal-gateway/tls/index.mdx +++ b/docs/universal-gateway/tls/index.mdx @@ -174,17 +174,17 @@ TLS termination at the edge is not supported for: - **Traffic Policy** — Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate and transform the traffic through the endpoint. - **Agent Forwarding** — The [ngrok agent](/agent/) and [Agent SDKs](/agent-sdks/) forward traffic that your endpoints receive to upstream services. See [the agent forwarding documentation](/universal-gateway/agent-forwarding/) for more information. - **Traffic Observability** — [Traffic Inspector](/obs/traffic-inspection/) gives you a real-time view in the ngrok dashboard of the traffic flowing through your TLS endpoints. You can even [export traffic logs with the Traffic Events system](/docs/obs/events/reference/). -- **TLS Certificates** — Learn how [ngrok automatically handles TLS](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) and [TLS termination](/universal-gateway/tls-termination/) for TLS endpoints for you. +- **TLS Certificates** — Learn how [ngrok automatically handles TLS](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) and [TLS termination](/universal-gateway/tls/tls-termination/) for TLS endpoints for you. ## TLS termination -TLS Endpoints enable you to to define where [TLS termination](/universal-gateway/tls-termination/) occurs. You can configure your endpoint to terminate TLS at the ngrok cloud service. You can also achieve [end-to-end encryption](/universal-gateway/tls-termination/#end-to-end-encryption) by terminating at the agent or your upstream service. +TLS Endpoints enable you to to define where [TLS termination](/universal-gateway/tls/tls-termination/) occurs. You can configure your endpoint to terminate TLS at the ngrok cloud service. You can also achieve [end-to-end encryption](/universal-gateway/tls/tls-termination/#end-to-end-encryption) by terminating at the agent or your upstream service. :::tip When you use end-to-end encryption, the ngrok cloud service can not see payloads that transit through your endpoints. ::: -See [the TLS Termination documentation](/universal-gateway/tls-termination/#termination-location) for more information. +See [the TLS Termination documentation](/universal-gateway/tls/tls-termination/#termination-location) for more information. ## Errors diff --git a/docs/universal-gateway/tls/tls-clients.mdx b/docs/universal-gateway/tls/tls-clients.mdx index 78bf31e220..0165abf812 100644 --- a/docs/universal-gateway/tls/tls-clients.mdx +++ b/docs/universal-gateway/tls/tls-clients.mdx @@ -9,7 +9,7 @@ ngrok's TLS endpoints are designed to work with TLS clients that fit the criteri TLS endpoints only work with modern TLS clients that populate the SNI extension. See the documentation on [TLS -Termination](/universal-gateway/tls-termination/#sni) for additional +Termination](/universal-gateway/tls/tls-termination/#sni) for additional details on compatible clients. ## STARTTLS diff --git a/docs/universal-gateway/tls/tls-termination/index.mdx b/docs/universal-gateway/tls/tls-termination/index.mdx index 8eea0649fa..74bec9efdc 100644 --- a/docs/universal-gateway/tls/tls-termination/index.mdx +++ b/docs/universal-gateway/tls/tls-termination/index.mdx @@ -7,7 +7,7 @@ import ConfigExample from "/src/components/ConfigExample.tsx"; You can configure TLS termination for HTTPS, TCP, and TLS endpoints with ngrok. By default, ngrok automatically terminates TLS for HTTPS endpoints, but you can still customize how that termination is done using the [`terminate-tls`](/traffic-policy/actions/terminate-tls/) Traffic Policy action. -TLS (SSL) certificate management is automatically handled for you by default for all endpoints, though you can also [bring your own TLS certificates](/universal-gateway/tls-certificates/bring-your-own-certs/). +TLS (SSL) certificate management is [automatically handled for you](/universal-gateway/automatic-certificate-management) by default for all endpoints, though you can also [bring your own TLS certificates](/universal-gateway/tls-certificates/bring-your-own-certs/). ## How is TLS terminated by default? @@ -21,53 +21,9 @@ termination behavior. | [TLS](/universal-gateway/tls/) | Default no termination, configurable with `terminate-tls` | | [TCP](/universal-gateway/tcp/) | Default no termination, configurable with `terminate-tls` | -## Example +## Using `terminate-tls` -This example sets the minimum and maximum TLS versions that the endpoint will support for incoming connections to TLS version 1.3. Clients can then only connect to the endpoint using TLS version 1.3 and will receive a handshake error if they attempt to connect using a different version. - -### **Step 1** — Create a Traffic Policy - - - -### **Step 2** — Start an endpoint - -```shell -ngrok http 8080 --url https://terminate-tls-example.ngrok.app --traffic-policy-file /path/to/policy.yml -``` - -### **Step 3** — Make a request - -```shell -curl https://terminate-tls-example.ngrok.app -``` - -If your curl was built with a version of OpenSSL that supports TLS 1.3, the request will succeed. However, we can verify that the endpoint only supports TLS 1.3 by telling curl to use a different version of TLS: - -```shell -curl https://terminate-tls-example.ngrok.app --tlsv1.2 --tls-max 1.2 -``` - -You should receive an "alert protocol version" error indicating that the endpoint only supports TLS 1.3. +Visit the Traffic Policy docs to [see examples using the `terminate-tls` action](/traffic-policy/actions/terminate-tls/). ## Learn more diff --git a/docs/universal-gateway/tls/tls-termination/termination-location.mdx b/docs/universal-gateway/tls/tls-termination/termination-location.mdx index c015836140..67f563a71d 100644 --- a/docs/universal-gateway/tls/tls-termination/termination-location.mdx +++ b/docs/universal-gateway/tls/tls-termination/termination-location.mdx @@ -3,145 +3,252 @@ title: Where Is TLS Terminated? description: Learn about the different locations where TLS termination can occur in ngrok. --- +import CustomDomainAgentConfigExample from "/examples/agent-config/tls-terminate-at-edge-custom-domain.mdx"; +import AtAgentAgentConfigExample from "/examples/agent-config/tls-terminate-at-agent.mdx"; +import AtUpstreamAgentConfigExample from "/examples/agent-config/tls-terminate-at-upstream.mdx"; + import TabItem from "@theme/TabItem"; import Tabs from "@theme/Tabs"; -import TlsLimits from "../../_tls_limits.mdx"; +import { LangSwitcher } from "@site/src/components/LangSwitcher"; +import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitcher"; + +[TLS connections](/universal-gateway/tls/) to your ngrok endpoints are terminated at one of three locations. + +:::info +TLS endpoints are not supported by the ngrok Kubernetes Operator +::: + +## At ngrok's cloud service + +You can terminate TLS at the edge with ngrok's cloud service. + +This is the easiest and most common. All HTTPS endpoints terminate TLS at ngrok's cloud service. When connections are terminated by ngrok's cloud service, they are re-encrypted before they are transmitted over a Secure Tunnel to an agent. + +You can get started with the following example. + + + + + +Use a Traffic Policy file configured like the following: + +```yaml mode=traffic-policy +on_tcp_connect: + - actions: + - type: terminate-tls +``` + +Then use the following command to start your ngrok agent: + + + + +```bash +ngrok tls 80 \ + --url tls://your-name.ngrok.app \ + --traffic-policy-file traffic-policy.yml +``` + +```go +import ( + "context" + "net" + + "golang.ngrok.com/ngrok" + "golang.ngrok.com/ngrok/config" +) + +func ngrokListener(ctx context.Context) (net.Listener, error) { + return ngrok.Listen(ctx, + config.TLSEndpoint( + config.WithDomain("your-name.ngrok.app"), + config.WithTLSTermination( + config.WithTLSTerminationAt(config.TLSAtEdge), + ), + ), + ngrok.WithAuthtokenFromEnv(), + ) +} +``` + +```jsx +const ngrok = require("@ngrok/ngrok"); +const fs = require("fs"); + +(async function () { + const listener = await ngrok.forward({ + addr: 8080, + authtoken_from_env: true, + proto: "tls", + domain: "app.example.com", + crt: fs.readFileSync("/path/to/app-example-com-crt.pem", "utf8"), + key: fs.readFileSync("/path/to/app-example-com-key.pem", "utf8"), + mutual_tls_cas: [fs.readFileSync("/path/to/cas.pem", "utf8")], + }); + + console.log(`Ingress established at: ${listener.url()}`); +})(); +``` + +```python +import ngrok + +def load_file(name): + with open(name, "r") as crt: + return bytearray(crt.read().encode()) + +listener = ngrok.forward("localhost:8080", authtoken_from_env=True, + proto="tls", + domain="app.example.com", + crt=load_file("/path/to/app-example-com-crt.pem"), + key=load_file("/path/to/app-example-com-key.pem")) + +print(f"Ingress established at: {listener.url()}"); +``` + + + + + + -import AtAgentAgentCliExample from "/examples/agent-cli/tls-terminate-at-agent.mdx"; -import AtAgentAgentConfigExample from "/examples/agent-config/tls-terminate-at-agent.mdx"; -import AtAgentGoSdkExample from "/examples/go-sdk/tls-terminate-at-agent.mdx"; -import AtAgentJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-agent.mdx"; -import AtAgentKubernetesExample from "/examples/k8s/tls-terminate-at-agent.mdx"; -import AtAgentPythonSdkExample from "/examples/python-sdk/tls-terminate-at-agent.mdx"; -import AtAgentRustSdkExample from "/examples/rust-sdk/tls-terminate-at-agent.mdx"; -import AtAgentSshExample from "/examples/ssh/tls-terminate-at-agent.mdx"; - -import AtUpstreamAgentCliExample from "/examples/agent-cli/tls-terminate-at-upstream.mdx"; -import AtUpstreamAgentConfigExample from "/examples/agent-config/tls-terminate-at-upstream.mdx"; -import AtUpstreamGoSdkExample from "/examples/go-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamKubernetesExample from "/examples/k8s/tls-terminate-at-upstream.mdx"; -import AtUpstreamPythonSdkExample from "/examples/python-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamRustSdkExample from "/examples/rust-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamSshExample from "/examples/ssh/tls-terminate-at-upstream.mdx"; - -import CustomDomainAgentCliExample from "/examples/agent-cli/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainAgentConfigExample from "/examples/agent-config/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainGoSdkExample from "/examples/go-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainKubernetesExample from "/examples/k8s/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainPythonSdkExample from "/examples/python-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainRustSdkExample from "/examples/rust-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainSshExample from "/examples/ssh/tls-terminate-at-edge-custom-domain.mdx"; - -[TLS connections](/universal-gateway/tls/) to your ngrok endpoints are terminated at one of three -locations. - -- **ngrok's cloud service**: This is the easiest and most common. All HTTPS - endpoints terminate TLS at ngrok's cloud service. When connections are - terminated by ngrok's cloud service, they are re-encrypted before they are - transmitted over a Secure Tunnel to an agent. -- **ngrok agent**: This is a form of [end-to-end - encryption](#end-to-end-encryption) where the ngrok cloud service does not - terminate TLS and you instead configure the ngrok agent to terminate TLS - connections for you. -- **your upstream service**: This is another form of [end-to-end - encryption](#end-to-end-encryption) where neither the cloud service nor an - agent terminates TLS connections. Instead, your upstream application service is - responsible for TLS termination. - -### Examples - -#### Cloud Service - - - - - - - - - - - - - - - - - - - - - - - - - - +:::info +TLS Termination at the edge is not supported for: + +- SSH +- Rust +- Kubernetes + ::: +
-#### Terminate at Agent - -See [Zero-Knowledge TLS at the Agent](/agent/agent-tls-termination/) for additional details. - - - - - - - - - - - - - - - - - - - - - - - - - - +## At your ngrok agent + +You can terminate TLS at your ngrok agent. Doing so prevents TLS from being terminated at ngrok's cloud service, ensuring [end-to-end encryption](/universal-gateway/tls/tls-termination/termination-mechanics/#end-to-end-encryption) between visitors and your upstream service. + +You can get started with the following example. + + + +```bash +ngrok tls 80 \ + --terminate-at agent \ + --url tls://app.example.com \ + --crt /path/to/app-example-com-crt.pem \ + --key /path/to/app-example-com-key.pem +``` + + + + + + +:::info +Termination at the agent is not supported for: + +- SSH +- Rust +- Go +- Javascript +- Python +- Kubernetes + ::: +
-#### Terminate at Upstream - - - - - - - - - - - - - - - - - - - - - - - - - - +## At your upstream service + +You can handle TLS termination at your upstream services. This is another form of [end-to-end encryption](/universal-gateway/tls/tls-termination/termination-mechanics/#end-to-end-encryption) where neither the cloud service nor an agent terminates TLS connections. Instead, your upstream application service is responsible for TLS termination. + +You can get started with the following example. + + + + +```bash +ngrok tls 443 \ + --terminate-at upstream \ + --url tls://app.example.com +``` + +```go +import ( + "context" + "net" + + "golang.ngrok.com/ngrok" + "golang.ngrok.com/ngrok/config" +) + +func ngrokListener(ctx context.Context) (net.Listener, error) { + return ngrok.Listen(ctx, + config.TLSEndpoint( + config.WithDomain("app.example.com"), + ), + ngrok.WithAuthtokenFromEnv(), + ) +} +``` + +```ssh tabName="SSH" +ssh -R app.example.com:443:localhost:443 v2@connect.ngrok-agent.com tls +``` + +```jsx +const ngrok = require("@ngrok/ngrok"); + +(async function () { + const listener = await ngrok.forward({ + addr: 8080, + authtoken_from_env: true, + proto: "tls", + domain: "app.example.com", + }); + + console.log(`Ingress established at: ${listener.url()}`); +})(); +``` + +```python +import ngrok + +listener = ngrok.forward("localhost:8080", authtoken_from_env=True, + proto="tls", + domain="app.example.com") + +print(f"Ingress established at: {listener.url()}"); +``` + +```rust +use ngrok::prelude::*; + +async fn listen_ngrok() -> anyhow::Result { + let sess = ngrok::Session::builder() + .authtoken_from_env() + .connect() + .await?; + + let tun = sess + .tls_endpoint() + .domain("app.example.com") + .listen() + .await?; + + println!("Listening on URL: {:?}", tun.url()); + + Ok(tun) +} +``` + + + + + + + diff --git a/sidebars.js b/sidebars.js index 9b59401620..a7a1e1b680 100644 --- a/sidebars.js +++ b/sidebars.js @@ -159,7 +159,7 @@ const sidebars = { id: "universal-gateway/tls-certificates/how-does-ngrok-handle-tls", }, items: [ - "universal-gateway/tls-certificates/what-is-automatic-certificate-management", + "universal-gateway/tls-certificates/automatic-certificate-management", "universal-gateway/tls-certificates/how-are-certificates-selected", "universal-gateway/tls-certificates/custom-certificates", "universal-gateway/tls-certificates/what-is-a-certificate-bundle", From a838089f42ad10fdaeb1c9cfb067c34400072eed Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 10 Apr 2025 15:33:40 -0400 Subject: [PATCH 100/137] Breaking down the TCP page --- docs/errors/index.md | 11 + docs/pricing-limits/endpoint-limits.mdx | 10 +- .../global-load-balancer.mdx | 2 +- docs/universal-gateway/http-s/index.mdx | 2 +- docs/universal-gateway/overview.mdx | 2 +- .../public-endpoints/index.mdx | 4 +- .../{what-are-tcp-addresses.mdx => index.mdx} | 0 docs/universal-gateway/tcp.mdx | 243 ------------------ docs/universal-gateway/tcp/index.mdx | 131 ++-------- docs/universal-gateway/tcp/static-tcp-url.mdx | 52 ++++ docs/universal-gateway/tls/handshake.mdx | 6 +- docs/universal-gateway/tls/index.mdx | 4 +- .../tls/tls-termination/index.mdx | 2 - .../what-are-endpoint-urls.mdx | 2 +- docs/whats-new.mdx | 2 +- sidebars.js | 6 +- 16 files changed, 106 insertions(+), 373 deletions(-) rename docs/universal-gateway/tcp-addresses/{what-are-tcp-addresses.mdx => index.mdx} (100%) delete mode 100644 docs/universal-gateway/tcp.mdx create mode 100644 docs/universal-gateway/tcp/static-tcp-url.mdx diff --git a/docs/errors/index.md b/docs/errors/index.md index 2c6bc664e8..addc5b5c8c 100644 --- a/docs/errors/index.md +++ b/docs/errors/index.md @@ -88,3 +88,14 @@ failures are encountered. Use the [observability](#observability) features to understand connection handling errors. + +## TCP Errors + +If an error is encountered while handling connections to a TCP endpoint for any +reason (e.g. traffic policy action error, internal server error), the +connection will be closed. Because of the low-level nature of the TCP protocol, +there is no mechanism used to transmit information about what error code was +encountered. + +Use the [observability](/obs/events/reference/#tcp-connection-closed) features to understand connection +handling errors. diff --git a/docs/pricing-limits/endpoint-limits.mdx b/docs/pricing-limits/endpoint-limits.mdx index 774a718608..16bcf6e69c 100644 --- a/docs/pricing-limits/endpoint-limits.mdx +++ b/docs/pricing-limits/endpoint-limits.mdx @@ -7,7 +7,7 @@ import TabItem from "@theme/TabItem"; import Tabs from "@theme/Tabs"; import TlsLimits from "../universal-gateway/_tls_limits.mdx"; -[Contact us](mailto:support@ngrok.com) if you need to configure limits and timeouts on connections to endpoints. +[Contact us](mailto:support@ngrok.com) if you need to configure limits and timeouts on connections to HTTP/S, TLS, or TCP endpoints. ## Connection limits @@ -62,3 +62,11 @@ import TlsLimits from "../universal-gateway/_tls_limits.mdx"; | No timeout | Response Timeout | Time to read the entire HTTP response from the server | | No timeout | Response Header Timeout | Time to read the HTTP response header from the server | | No limit | Response Body Size | | + +## TCP timeout limits + +| Limit | Name | Notes | +| --------- | ------------------- | ------------------------------------------------------------ | +| 5 minutes | Client Idle Timeout | Time since data was last transmitted by the upstream service | +| 5 minutes | Server Idle Timeout | Time since data was last transmitted by the upstream service | +| No limit | Data transmitted | Data transmitted by the client or upstream service | diff --git a/docs/universal-gateway/global-load-balancer.mdx b/docs/universal-gateway/global-load-balancer.mdx index c1e1d22b18..a97883c068 100644 --- a/docs/universal-gateway/global-load-balancer.mdx +++ b/docs/universal-gateway/global-load-balancer.mdx @@ -137,7 +137,7 @@ of presence. TCP Endpoints do not support GSLB. Unlike domains, TCP addresses are provisioned for a specific [Point of Presence](/universal-gateway/points-of-presence). When you create a TCP Address, you must select the point of presence where it will accept traffic. Connections to matching TCP Endpoints on a TCP Address will always route to the TCP Address's point of presence, no matter where those connections originated in the world. -[Learn more about TCP Address load balancing](/universal-gateway/tcp-addresses/what-are-tcp-addresses/#tcp-address-load-balancing). +[Learn more about TCP Address load balancing](/universal-gateway/tcp-addresses/#tcp-address-load-balancing). ## Domains diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx index df93f91f42..c61559634f 100644 --- a/docs/universal-gateway/http-s/index.mdx +++ b/docs/universal-gateway/http-s/index.mdx @@ -154,7 +154,7 @@ ngrok api endpoints create \ ## Learn more -- **URLS** — URLs are validated differently depending on their [binding](/universal-gateway/bindings). To learn more about valid URLs for HTTP/S endpoints, see [the Endpoint URLs documentation](/docs/universal-gateway/what-are-endpoint-urls/#http). +- **URL Validation** — URLs are validated differently depending on their [binding](/universal-gateway/bindings). To learn more about valid URLs for HTTP/S endpoints, see [the Endpoint URLs documentation](/docs/universal-gateway/what-are-endpoint-urls/#http). - **Domains** — Public HTTP/S endpoints must match a domain on your account. See [the domains documentation](/universal-gateway/domains/what-are-domains/) for more information. - **Bring your own domain** — To use your own domain with HTTP/S endpoints, see [the guide on the subject](/universal-gateway/how-do-i-use-my-own-domain). - **Wildcard Endpoints** — You can create HTTP/S endpoints that receive traffic from all of the subdomains matching a given wildcard domain. See [the wildcard domain docs](/universal-gateway/wildcard-domains/) for more information. diff --git a/docs/universal-gateway/overview.mdx b/docs/universal-gateway/overview.mdx index d568d2a6e8..b66f2a79dc 100644 --- a/docs/universal-gateway/overview.mdx +++ b/docs/universal-gateway/overview.mdx @@ -17,7 +17,7 @@ Bindings, Pools and Domains to understand how they work. Learn more about Universal Gateway Concepts: - [Domains →](/universal-gateway/domains/what-are-domains/) -- [TCP Addresses →](/universal-gateway/tcp-addresses/what-are-tcp-addresses/) +- [TCP Addresses →](/universal-gateway/tcp-addresses/) - [TLS Certificates →](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) - [Edges →](/universal-gateway/edges/) diff --git a/docs/universal-gateway/public-endpoints/index.mdx b/docs/universal-gateway/public-endpoints/index.mdx index 1a95d72c04..a36203980e 100644 --- a/docs/universal-gateway/public-endpoints/index.mdx +++ b/docs/universal-gateway/public-endpoints/index.mdx @@ -7,7 +7,7 @@ Public endpoints enable your services to receive geo-balanced internet traffic u [Public endpoint URLs](/docs/universal-gateway/what-are-endpoint-urls/) must: -- Use either a [Domain](/universal-gateway/domains/what-are-domains/) or [TCP Address](/universal-gateway/tcp-addresses/what-are-tcp-addresses/) +- Use either a [Domain](/universal-gateway/domains/what-are-domains/) or [TCP Address](/universal-gateway/tcp-addresses/) - Use the `public` [binding](/docs/universal-gateway/bindings/) ## Get started @@ -33,7 +33,7 @@ To keep such services both public and secure, you can add a Traffic Policy to yo ## Matching endpoints -A matching endpoint is a public endpoint with a [hostname](https://en.wikipedia.org/wiki/Hostname.) matching a [Domain](/universal-gateway/what-are-domains) or [TCP Address](/universal-gateway/what-are-tcp-addresses) you've configured with ngrok. +A matching endpoint is a public endpoint with a [hostname](https://en.wikipedia.org/wiki/Hostname.) matching a [Domain](/universal-gateway/what-are-domains) or [TCP Address](/universal-gateway/) you've configured with ngrok. Matching endpoints are subject to the following restrictions: diff --git a/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx b/docs/universal-gateway/tcp-addresses/index.mdx similarity index 100% rename from docs/universal-gateway/tcp-addresses/what-are-tcp-addresses.mdx rename to docs/universal-gateway/tcp-addresses/index.mdx diff --git a/docs/universal-gateway/tcp.mdx b/docs/universal-gateway/tcp.mdx deleted file mode 100644 index 8cbab47816..0000000000 --- a/docs/universal-gateway/tcp.mdx +++ /dev/null @@ -1,243 +0,0 @@ ---- -title: TCP Endpoints ---- - -import TabItem from "@theme/TabItem"; -import Tabs from "@theme/Tabs"; - -import RandomAgentCliExample from "/examples/agent-cli/tcp-random.mdx"; -import RandomAgentConfigExample from "/examples/agent-config/tcp-random.mdx"; -import RandomGoSdkExample from "/examples/go-sdk/tcp-random.mdx"; -import RandomJavascriptSdkExample from "/examples/javascript-sdk/tcp-random.mdx"; -import RandomKubernetesExample from "/examples/k8s/tcp-random.mdx"; -import RandomPythonSdkExample from "/examples/python-sdk/tcp-random.mdx"; -import RandomRustSdkExample from "/examples/rust-sdk/tcp-random.mdx"; -import RandomSshExample from "/examples/ssh/tcp-random.mdx"; - -import FixedAgentCliExample from "/examples/agent-cli/tcp-fixed.mdx"; -import FixedAgentConfigExample from "/examples/agent-config/tcp-fixed.mdx"; -import FixedGoSdkExample from "/examples/go-sdk/tcp-fixed.mdx"; -import FixedJavascriptSdkExample from "/examples/javascript-sdk/tcp-fixed.mdx"; -import FixedKubernetesExample from "/examples/k8s/tcp-fixed.mdx"; -import FixedPythonSdkExample from "/examples/python-sdk/tcp-fixed.mdx"; -import FixedRustSdkExample from "/examples/rust-sdk/tcp-fixed.mdx"; -import FixedSshExample from "/examples/ssh/tcp-fixed.mdx"; - -import NonLocalAgentCliExample from "/examples/agent-cli/tcp-nonlocal.mdx"; -import NonLocalAgentConfigExample from "/examples/agent-config/tcp-nonlocal.mdx"; -import NonLocalGoSdkExample from "/examples/go-sdk/tcp-nonlocal.mdx"; -import NonLocalJavascriptSdkExample from "/examples/javascript-sdk/tcp-nonlocal.mdx"; -import NonLocalKubernetesExample from "/examples/k8s/tcp-nonlocal.mdx"; -import NonLocalPythonSdkExample from "/examples/python-sdk/tcp-nonlocal.mdx"; -import NonLocalRustSdkExample from "/examples/rust-sdk/tcp-nonlocal.mdx"; -import NonLocalSshExample from "/examples/ssh/tcp-nonlocal.mdx"; - -import ProxyProtoAgentCliExample from "/examples/agent-cli/tcp-proxyproto.mdx"; -import ProxyProtoAgentConfigExample from "/examples/agent-config/tcp-proxyproto.mdx"; -import ProxyProtoGoSdkExample from "/examples/go-sdk/tcp-proxyproto.mdx"; -import ProxyProtoJavascriptSdkExample from "/examples/javascript-sdk/tcp-proxyproto.mdx"; -import ProxyProtoKubernetesExample from "/examples/k8s/tcp-proxyproto.mdx"; -import ProxyProtoPythonSdkExample from "/examples/python-sdk/tcp-proxyproto.mdx"; -import ProxyProtoRustSdkExample from "/examples/rust-sdk/tcp-proxyproto.mdx"; -import ProxyProtoSshExample from "/examples/ssh/tcp-proxyproto.mdx"; - -# TCP Endpoints - -## Overview - -TCP endpoints enable you to deliver any network service with a TCP-based -protocol. They are commonly used to create connectivity for: - -- Remote access protocols like SSH, VNC and RDP -- Databases like MySQL, Postgres, MSSQL and SQLite -- IoT protocols like MQTT -- Gaming servers like Minecraft - -If you are accepting TLS traffic, you may prefer to create a [TLS Endpoint](/universal-gateway/tls/). - -::::info Free Plan Usage -TCP endpoints are only available on a free plan after [adding a valid payment method](https://dashboard.ngrok.com/settings#id-verification) to your account. -:::: - -## Quickstart - -Agent Endpoints are the easiest way to get started with ngrok. An [agent -endpoint](/universal-gateway/cloud-endpoints/) is started by a -[Secure Tunnels](/agent/) agent. The endpoint lives for the lifetime -of the process and forwards traffic to a port or URL of your choosing. - -This example creates a TCP endpoint on a randomly-assigned URL - e.g. -`tcp://1.tcp.ngrok.io:12345` and forwards its traffic to a local port. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -## URLs - -URLs are validated differently depending on their -[binding](/universal-gateway/bindings). Consult the -following documentation for details on valid URLs for TCP endpoints: - -- [Public Endpoint URLs](/universal-gateway/public-endpoints/#tcp) -- [Internal Endpoint URLs](/universal-gateway/internal-endpoints/#urls) -- [Kubernetes Endpoint URLs](/universal-gateway/kubernetes-endpoints/#urls) - -There is no standard scheme for TCP URLs so ngrok renders them as `tcp://`. - -### Static URLs - -If you would like a public TCP endpoint to have a static URL, you must first -create a [TCP Address](/universal-gateway/tcp-addresses/what-are-tcp-addresses/). When you create a TCP -address, a random hostname and port will be assigned to you, e.g. -`1.tcp.ngrok.io:12345`. - -A TCP address is only needed to make a public TCP endpoint have a static URL. -They are not needed for TCP endpoints on other bindings, like `internal` or -`kubernetes`. - -After you have created a TCP Address, specify the address (e.g. -`1.tcp.eu.ngrok.io:12345`) in the URL when you create the endpoint. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -### Custom domains - -Public TCP endpoints are assigned randomly on an ngrok-controlled hostname with -a randomly-assigned port. You may not choose the hostname and you may not -select the port. - -You may, however, simulate a customized hostname by creating a CNAME record to -the hostname of your assigned TCP address. If you do so, be aware that all -ports on that hostname, even those provisioned to other accounts will then be -available on your domain. - -For example if your TCP address is `5.tcp.ngrok.io:12345`, you could create the -following CNAME record: - -``` -CNAME tcp.mydomain.com -> 5.tcp.ngrok.io -``` - -And then you can access that TCP endpoint with - -``` -telnet tcp.mydomain.com 12345 -``` - -## Traffic Policy - -Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate -and transform the traffic through the endpoint. - -### Authentication - -When you create public TCP endpoints, you often want to secure them with -authentication. You can secure your TCP endpoints with the following [Traffic -Policy](/traffic-policy/) actions. There is a limited set of actions available -to authenticate TCP traffic because the TCP protocol is low-level. - -- [IP Restriction](/traffic-policy/actions/restrict-ips/) -- [Mutual TLS](/traffic-policy/actions/terminate-tls/) - -## Observability - -### Traffic Inspector - -[Traffic Inspector](/obs/traffic-inspection) does not support TCP endpoints. - -### Log Export Events - -You can export logs of traffic to TCP endpoints with [ngrok's events -system](/obs/events/). The following events are published for log exporting: - -| Event | When | -| ------------------------------------------------------------------------ | ------------------------------------------------------------------ | -| [tcp_connection_closed.v0](/obs/events/reference/#tcp-connection-closed) | Published when a TCP connection to any type of endpoint completes. | - -## Limits & Timeouts - -[Contact us](mailto:support@ngrok.com) if you need to configure limits and timeouts on -connections to TCP endpoints. - -| Limit | Name | Notes | -| --------- | ------------------- | ------------------------------------------------------------ | -| 5 minutes | Client Idle Timeout | Time since data was last transmitted by the upstream service | -| 5 minutes | Server Idle Timeout | Time since data was last transmitted by the upstream service | -| No limit | Data transmitted | Data transmitted by the client or upstream service | - -## Errors - -If an error is encountered while handling connections to a TCP endpoint for any -reason (e.g. traffic policy action error, internal server error), the -connection will be closed. Because of the low-level nature of the TCP protocol, -there is no mechanism used to transmit information about what error code was -encountered. - -Use the [observability](#observability) features to understand connection -handling errors. - -## API - -TCP Endpoints can be created programatically. Consult the documentation on -[Endpoint APIs](/api/resources/endpoints/). - -## Pricing - -TCP endpoints are available on all plans. Consult the [Endpoints -Pricing](/universal-gateway/endpoints/#pricing) documentation for -billing details. - -TCP endpoints are only available on a free plan after [adding a valid payment -method](https://dashboard.ngrok.com/settings#id-verification) to your account. - -See [TCP Addresses pricing](/universal-gateway/tcp-addresses/#pricing) for -details on pricing for fixed TCP Addresses. diff --git a/docs/universal-gateway/tcp/index.mdx b/docs/universal-gateway/tcp/index.mdx index 8cbab47816..4ed11dc0b9 100644 --- a/docs/universal-gateway/tcp/index.mdx +++ b/docs/universal-gateway/tcp/index.mdx @@ -1,5 +1,6 @@ --- -title: TCP Endpoints +title: How Do I Handle TCP Traffic? +description: Learn how to handle TCP traffic with ngrok. --- import TabItem from "@theme/TabItem"; @@ -14,15 +15,6 @@ import RandomPythonSdkExample from "/examples/python-sdk/tcp-random.mdx"; import RandomRustSdkExample from "/examples/rust-sdk/tcp-random.mdx"; import RandomSshExample from "/examples/ssh/tcp-random.mdx"; -import FixedAgentCliExample from "/examples/agent-cli/tcp-fixed.mdx"; -import FixedAgentConfigExample from "/examples/agent-config/tcp-fixed.mdx"; -import FixedGoSdkExample from "/examples/go-sdk/tcp-fixed.mdx"; -import FixedJavascriptSdkExample from "/examples/javascript-sdk/tcp-fixed.mdx"; -import FixedKubernetesExample from "/examples/k8s/tcp-fixed.mdx"; -import FixedPythonSdkExample from "/examples/python-sdk/tcp-fixed.mdx"; -import FixedRustSdkExample from "/examples/rust-sdk/tcp-fixed.mdx"; -import FixedSshExample from "/examples/ssh/tcp-fixed.mdx"; - import NonLocalAgentCliExample from "/examples/agent-cli/tcp-nonlocal.mdx"; import NonLocalAgentConfigExample from "/examples/agent-config/tcp-nonlocal.mdx"; import NonLocalGoSdkExample from "/examples/go-sdk/tcp-nonlocal.mdx"; @@ -41,10 +33,6 @@ import ProxyProtoPythonSdkExample from "/examples/python-sdk/tcp-proxyproto.mdx" import ProxyProtoRustSdkExample from "/examples/rust-sdk/tcp-proxyproto.mdx"; import ProxyProtoSshExample from "/examples/ssh/tcp-proxyproto.mdx"; -# TCP Endpoints - -## Overview - TCP endpoints enable you to deliver any network service with a TCP-based protocol. They are commonly used to create connectivity for: @@ -53,7 +41,7 @@ protocol. They are commonly used to create connectivity for: - IoT protocols like MQTT - Gaming servers like Minecraft -If you are accepting TLS traffic, you may prefer to create a [TLS Endpoint](/universal-gateway/tls/). +If you are accepting TLS traffic, consider using a [TLS Endpoint](/universal-gateway/tls/). ::::info Free Plan Usage TCP endpoints are only available on a free plan after [adding a valid payment method](https://dashboard.ngrok.com/settings#id-verification) to your account. @@ -96,58 +84,17 @@ This example creates a TCP endpoint on a randomly-assigned URL - e.g. -## URLs - -URLs are validated differently depending on their -[binding](/universal-gateway/bindings). Consult the -following documentation for details on valid URLs for TCP endpoints: - -- [Public Endpoint URLs](/universal-gateway/public-endpoints/#tcp) -- [Internal Endpoint URLs](/universal-gateway/internal-endpoints/#urls) -- [Kubernetes Endpoint URLs](/universal-gateway/kubernetes-endpoints/#urls) - -There is no standard scheme for TCP URLs so ngrok renders them as `tcp://`. - -### Static URLs - -If you would like a public TCP endpoint to have a static URL, you must first -create a [TCP Address](/universal-gateway/tcp-addresses/what-are-tcp-addresses/). When you create a TCP -address, a random hostname and port will be assigned to you, e.g. -`1.tcp.ngrok.io:12345`. - -A TCP address is only needed to make a public TCP endpoint have a static URL. -They are not needed for TCP endpoints on other bindings, like `internal` or -`kubernetes`. - -After you have created a TCP Address, specify the address (e.g. -`1.tcp.eu.ngrok.io:12345`) in the URL when you create the endpoint. +## Learn more - - - - - - - - - - - - - - - - - - - - - - - - - - +- **URL Validation** — URLs are validated differently depending on their [binding](/universal-gateway/bindings). To learn more about valid URLs for TCP endpoints, see [the Endpoint URLs documentation](/docs/universal-gateway/what-are-endpoint-urls/#tcp). +- **Static URLs** — To create a public TCP endpoint with a static URL, you must first create a [TCP Address](/universal-gateway/tcp-addresses/). See [the documentation on static TCP URLs](/universal-gateway/tcp/static-tcp-urls/) for more information. +- **Authentication** — You can secure your TCP endpoints with the [IP Restriction](/traffic-policy/actions/restrict-ips/) and [Mutual TLS](/docs/guides/other-guides/how-to-terminate-traffic-with-ngrok-configs/#mutual-tls-example) Traffic Policy actions. There is a limited set of actions available to authenticate TCP traffic because the protocol is low-level. +- **Bring your own domain** — To use your own domain with TLS endpoints, see [the guide on the subject](/universal-gateway/how-do-i-use-my-own-domain). +- **Wildcard Endpoints** — You can create TLS endpoints that receive traffic from all of the subdomains matching a given wildcard domain. See [the wildcard domain docs](/universal-gateway/wildcard-domains/) for more information. +- **Traffic Policy** — Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate and transform the traffic through the endpoint. +- **Agent Forwarding** — The [ngrok agent](/agent/) and [Agent SDKs](/agent-sdks/) forward traffic that your endpoints receive to upstream services. See [the agent forwarding documentation](/universal-gateway/agent-forwarding/) for more information. +- **Traffic Observability** — [Traffic Inspector](/obs/traffic-inspection/) gives you a real-time view in the ngrok dashboard of the traffic flowing through your TLS endpoints. You can even [export traffic logs with the Traffic Events system](/docs/obs/events/reference/). +- **TLS Certificates** — Learn how [ngrok automatically handles TLS](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) and [TLS termination](/universal-gateway/tls/tls-termination/) for TLS endpoints for you. ### Custom domains @@ -173,27 +120,6 @@ And then you can access that TCP endpoint with telnet tcp.mydomain.com 12345 ``` -## Traffic Policy - -Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate -and transform the traffic through the endpoint. - -### Authentication - -When you create public TCP endpoints, you often want to secure them with -authentication. You can secure your TCP endpoints with the following [Traffic -Policy](/traffic-policy/) actions. There is a limited set of actions available -to authenticate TCP traffic because the TCP protocol is low-level. - -- [IP Restriction](/traffic-policy/actions/restrict-ips/) -- [Mutual TLS](/traffic-policy/actions/terminate-tls/) - -## Observability - -### Traffic Inspector - -[Traffic Inspector](/obs/traffic-inspection) does not support TCP endpoints. - ### Log Export Events You can export logs of traffic to TCP endpoints with [ngrok's events @@ -203,41 +129,22 @@ system](/obs/events/). The following events are published for log exporting: | ------------------------------------------------------------------------ | ------------------------------------------------------------------ | | [tcp_connection_closed.v0](/obs/events/reference/#tcp-connection-closed) | Published when a TCP connection to any type of endpoint completes. | -## Limits & Timeouts - -[Contact us](mailto:support@ngrok.com) if you need to configure limits and timeouts on -connections to TCP endpoints. - -| Limit | Name | Notes | -| --------- | ------------------- | ------------------------------------------------------------ | -| 5 minutes | Client Idle Timeout | Time since data was last transmitted by the upstream service | -| 5 minutes | Server Idle Timeout | Time since data was last transmitted by the upstream service | -| No limit | Data transmitted | Data transmitted by the client or upstream service | - ## Errors -If an error is encountered while handling connections to a TCP endpoint for any -reason (e.g. traffic policy action error, internal server error), the -connection will be closed. Because of the low-level nature of the TCP protocol, -there is no mechanism used to transmit information about what error code was -encountered. - -Use the [observability](#observability) features to understand connection -handling errors. +Learn how ngrok handles errors for TCP endpoints in the [Errors documentation](/errors/#tcp-errors). ## API TCP Endpoints can be created programatically. Consult the documentation on [Endpoint APIs](/api/resources/endpoints/). -## Pricing +## Limits & Pricing -TCP endpoints are available on all plans. Consult the [Endpoints -Pricing](/universal-gateway/endpoints/#pricing) documentation for -billing details. +TCP endpoints are available on all plans. To access them on the free plan, [add a payment method to your ngrok account](https://dashboard.ngrok.com/settings#id-verification). Consult the [pricing](/pricing-limits/) documentation for general billing details. -TCP endpoints are only available on a free plan after [adding a valid payment -method](https://dashboard.ngrok.com/settings#id-verification) to your account. +For TCP limits, see the [endpoint Limits documentation](/pricing-limits/endpoint-limits/#tcp-timeout-limits). +:::tip See [TCP Addresses pricing](/universal-gateway/tcp-addresses/#pricing) for details on pricing for fixed TCP Addresses. +::: diff --git a/docs/universal-gateway/tcp/static-tcp-url.mdx b/docs/universal-gateway/tcp/static-tcp-url.mdx new file mode 100644 index 0000000000..015e07dc2a --- /dev/null +++ b/docs/universal-gateway/tcp/static-tcp-url.mdx @@ -0,0 +1,52 @@ +--- +title: Static URLs for TCP Endpoints +description: Learn how to create TCP endpoints with URLs. +--- + +import FixedAgentCliExample from "/examples/agent-cli/tcp-fixed.mdx"; +import FixedAgentConfigExample from "/examples/agent-config/tcp-fixed.mdx"; +import FixedGoSdkExample from "/examples/go-sdk/tcp-fixed.mdx"; +import FixedJavascriptSdkExample from "/examples/javascript-sdk/tcp-fixed.mdx"; +import FixedKubernetesExample from "/examples/k8s/tcp-fixed.mdx"; +import FixedPythonSdkExample from "/examples/python-sdk/tcp-fixed.mdx"; +import FixedRustSdkExample from "/examples/rust-sdk/tcp-fixed.mdx"; +import FixedSshExample from "/examples/ssh/tcp-fixed.mdx"; + +If you would like a public TCP endpoint to have a static URL, you must first +create a [TCP Address](/universal-gateway/tcp-addresses/). When you create a TCP +address, a random hostname and port will be assigned to you, e.g. +`1.tcp.ngrok.io:12345`. + +A TCP address is only needed to make a public TCP endpoint have a static URL. +They are not needed for TCP endpoints on other bindings, like `internal` or +`kubernetes`. + +After you have created a TCP Address, specify the address (e.g. +`1.tcp.eu.ngrok.io:12345`) in the URL when you create the endpoint. + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/universal-gateway/tls/handshake.mdx b/docs/universal-gateway/tls/handshake.mdx index 692d08918d..93811c38de 100644 --- a/docs/universal-gateway/tls/handshake.mdx +++ b/docs/universal-gateway/tls/handshake.mdx @@ -3,9 +3,9 @@ title: How Does the TLS Handshake Work? description: Learn how the TLS handshake works with ngrok. --- -ngrok uses TLS 1.3 (the latest version) by default. If a client does not -support TLS 1.3, ngrok will use the highest possible version that the client -supports, down to TLS 1.1. +ngrok uses TLS `1.3` (the latest version) by default. If a client does not +support TLS `1.3`, ngrok will use the highest possible version that the client +supports, down to TLS `1.1`. You may customize the minimum and maximum supported versions of TLS with the [`terminate-tls`](/traffic-policy/actions/terminate-tls) traffic policy action. diff --git a/docs/universal-gateway/tls/index.mdx b/docs/universal-gateway/tls/index.mdx index 029f7d37ee..3d12c0f2dd 100644 --- a/docs/universal-gateway/tls/index.mdx +++ b/docs/universal-gateway/tls/index.mdx @@ -166,9 +166,9 @@ TLS termination at the edge is not supported for: ## Learn more -- **URLS** — URLs are validated differently depending on their [binding](/universal-gateway/bindings). To learn more about valid URLs for TLS endpoints, see [the Endpoint URLs documentation](/docs/universal-gateway/what-are-endpoint-urls/#http). +- **URL Validation** — URLs are validated differently depending on their [binding](/universal-gateway/bindings). To learn more about valid URLs for TLS endpoints, see [the Endpoint URLs documentation](/docs/universal-gateway/what-are-endpoint-urls/#https-tls). - **Domains** — Public TLS endpoints must match a domain on your account. See [the domains documentation](/universal-gateway/domains/what-are-domains/) for more information. -- **Authentication** — You can secure your TLS endpoints with the [IP Restriction](/traffic-policy/actions/restrict-ips/) and [Mutual TLS](/docs/guides/other-guides/how-to-terminate-traffic-with-ngrok-configs/#mutual-tls-example) Traffic Policy actions. There is a limited set of actions available to authenticate TLS traffic because the TLS protocol is low-level. +- **Authentication** — You can secure your TLS endpoints with the [IP Restriction](/traffic-policy/actions/restrict-ips/) and [Mutual TLS](/docs/guides/other-guides/how-to-terminate-traffic-with-ngrok-configs/#mutual-tls-example) Traffic Policy actions. There is a limited set of actions available to authenticate TLS traffic because the protocol is low-level. - **Bring your own domain** — To use your own domain with TLS endpoints, see [the guide on the subject](/universal-gateway/how-do-i-use-my-own-domain). - **Wildcard Endpoints** — You can create TLS endpoints that receive traffic from all of the subdomains matching a given wildcard domain. See [the wildcard domain docs](/universal-gateway/wildcard-domains/) for more information. - **Traffic Policy** — Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate and transform the traffic through the endpoint. diff --git a/docs/universal-gateway/tls/tls-termination/index.mdx b/docs/universal-gateway/tls/tls-termination/index.mdx index 74bec9efdc..86f42ed79b 100644 --- a/docs/universal-gateway/tls/tls-termination/index.mdx +++ b/docs/universal-gateway/tls/tls-termination/index.mdx @@ -3,8 +3,6 @@ title: How Do I Terminate TLS? description: Learn how to terminate TLS with ngrok. --- -import ConfigExample from "/src/components/ConfigExample.tsx"; - You can configure TLS termination for HTTPS, TCP, and TLS endpoints with ngrok. By default, ngrok automatically terminates TLS for HTTPS endpoints, but you can still customize how that termination is done using the [`terminate-tls`](/traffic-policy/actions/terminate-tls/) Traffic Policy action. TLS (SSL) certificate management is [automatically handled for you](/universal-gateway/automatic-certificate-management) by default for all endpoints, though you can also [bring your own TLS certificates](/universal-gateway/tls-certificates/bring-your-own-certs/). diff --git a/docs/universal-gateway/what-are-endpoint-urls.mdx b/docs/universal-gateway/what-are-endpoint-urls.mdx index 3f0d617ea6..ff4658744b 100644 --- a/docs/universal-gateway/what-are-endpoint-urls.mdx +++ b/docs/universal-gateway/what-are-endpoint-urls.mdx @@ -56,7 +56,7 @@ Invalid: - You must specify a port number in TCP URLs. - The hostname and port must match the address of a [TCP - Address](/universal-gateway/tcp-addresses/what-are-tcp-addresses/) in your account. + Address](/universal-gateway/tcp-addresses/) in your account. #### Examples diff --git a/docs/whats-new.mdx b/docs/whats-new.mdx index a0a4e81ae0..f4b8ecf75d 100644 --- a/docs/whats-new.mdx +++ b/docs/whats-new.mdx @@ -179,7 +179,7 @@ You can expect this page to update regularly (at least monthly). We'll include t - 2023-12-20 - Removed the ability to use ngrok without an account. All users need to register for an account and use a valid authtoken to use ngrok. - 2023-12-11 - Added the ability to use [HTTP/2 between the agent and your upstream service](/universal-gateway/http/#http2-forwarding). - 2023-12-06 - Release [ngrok Agent JavaScript SDK](https://ngrok.com/blog-post/ngrok-js) and [ngrok Agent Python SDK](https://ngrok.com/blog-post/ngrok-python) allowing developers to integrate ngrok natively into their application. -- 2023-12-04 - [Cross Region TCP Endpoints](/universal-gateway/tcp-addresses/what-are-tcp-addresses/#tcp-address-load-balancing) are available meaning ngrok TCP addresses can be served from agents in any region. +- 2023-12-04 - [Cross Region TCP Endpoints](/universal-gateway/tcp-addresses/#tcp-address-load-balancing) are available meaning ngrok TCP addresses can be served from agents in any region. - 2023-12-01 - Released [ngrok Agent 3.5.0](/agent/changelog/#ngrok-agent-350---2023-12-01) - 2023-12-01 - [ngrok-go 1.7.0 Released](https://github.com/ngrok/ngrok-go/releases/tag/v1.7.0) diff --git a/sidebars.js b/sidebars.js index a7a1e1b680..aa82903835 100644 --- a/sidebars.js +++ b/sidebars.js @@ -66,7 +66,7 @@ const sidebars = { type: "category", link: { type: "doc", - id: "universal-gateway/tcp-addresses/what-are-tcp-addresses", + id: "universal-gateway/tcp-addresses/index", }, items: [ "universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned", @@ -122,7 +122,7 @@ const sidebars = { ], }, { - label: "How Do I Handle HTTP/S Traffic?", + label: "Handling HTTP/S Traffic", type: "category", link: { type: "doc", id: "universal-gateway/http-s/index" }, items: [ @@ -131,7 +131,7 @@ const sidebars = { ], }, { - label: "How Do I Handle TLS Traffic?", + label: "Handling TLS Traffic", type: "category", link: { type: "doc", From eb52b5fcd7e8a4a566dea28a1f0e957c51103bd1 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 10 Apr 2025 16:21:26 -0400 Subject: [PATCH 101/137] Fix biome complaints --- src/components/LangSwitcher/LanguageData.tsx | 21 ++++++++------- src/components/LangSwitcher/index.tsx | 1 + src/theme/DocItem/Content/index.tsx | 9 ++++--- src/theme/Tabs/TabListContext.tsx | 2 +- src/theme/Tabs/index.tsx | 27 ++++++++++---------- static/scripts/fix-redirect.js | 10 ++++---- 6 files changed, 38 insertions(+), 32 deletions(-) diff --git a/src/components/LangSwitcher/LanguageData.tsx b/src/components/LangSwitcher/LanguageData.tsx index 89afd31bb3..bce2cfdac2 100644 --- a/src/components/LangSwitcher/LanguageData.tsx +++ b/src/components/LangSwitcher/LanguageData.tsx @@ -1,23 +1,26 @@ import type { LanguageInfo } from "./data"; export function LanguageData({ data }: { data: LanguageInfo }) { - let anchoredLinks = data.links.map((link) => { + const anchoredLinks = data.links.map((link) => { return ( - + here ); }); - const linkText = anchoredLinks.reduce((prev, curr, index): any => { - if (index === 0) { - return [prev, curr]; - } else if (index === data.links.length - 1) { - return [prev, ", and ", curr]; - } else { + const linkText = anchoredLinks.reduce( + // biome-ignore lint/suspicious/noExplicitAny: + (prev, curr, index): any => { + if (index === 0) { + return [prev, curr]; + } + if (index === data.links.length - 1) { + return [prev, ", and ", curr]; + } return [prev, ", ", curr]; } - }); + ); return (
diff --git a/src/components/LangSwitcher/index.tsx b/src/components/LangSwitcher/index.tsx index 3585d5f3fd..ebc8133179 100644 --- a/src/components/LangSwitcher/index.tsx +++ b/src/components/LangSwitcher/index.tsx @@ -30,6 +30,7 @@ export function LangSwitcher({ children, className, ...props }: any) { const matchingBlock = codeBlocks.find( + // biome-ignore lint/suspicious/noExplicitAny: (child: any) => child.language === selectedLanguage || languagesAreSynonyms(child.language, selectedLanguage) diff --git a/src/theme/DocItem/Content/index.tsx b/src/theme/DocItem/Content/index.tsx index b91d81f8bb..e8fc77720e 100644 --- a/src/theme/DocItem/Content/index.tsx +++ b/src/theme/DocItem/Content/index.tsx @@ -9,7 +9,7 @@ import { } from "@site/src/components/LangSwitcher/utils"; import Content from "@theme-original/DocItem/Content"; import type ContentType from "@theme/DocItem/Content"; -import React, { useState, type ReactNode } from "react"; +import { useState, type ReactNode } from "react"; import TabListContext from "../../Tabs/TabListContext"; type Props = WrapperProps; @@ -19,10 +19,10 @@ export default function ContentWrapper(props: Props): ReactNode { const storageData = isBrowser ? getStorageLanguageAndTab() : null; const [selectedLanguage, setSelectedLanguage] = useState( - storageData?.defaultLanguage ?? null, + storageData?.defaultLanguage ?? null ); const [selectedTabItem, setSelectedTabItem] = useState( - storageData?.defaultLanguage ?? null, + storageData?.defaultLanguage ?? null ); const updateSelectedLanguage = (newLang: string | SupportedLanguage) => { if (isBrowser) { @@ -30,7 +30,8 @@ export default function ContentWrapper(props: Props): ReactNode { } setSelectedLanguage(newLang); }; - const updateSelectedTabItem = (newItem: string) => { + const updateSelectedTabItem = (newItem: string | undefined) => { + if (!newItem) return; if (isBrowser) { localStorage.setItem(tabParamName, newItem); } diff --git a/src/theme/Tabs/TabListContext.tsx b/src/theme/Tabs/TabListContext.tsx index 987e313230..ce17867cc0 100644 --- a/src/theme/Tabs/TabListContext.tsx +++ b/src/theme/Tabs/TabListContext.tsx @@ -3,7 +3,7 @@ import { createContext } from "react"; export type TabListContextType = { localStorageTab: string | null; selectedTabItem: string | null; - updateSelectedTabItem: null | ((newTabItem: string) => void); + updateSelectedTabItem: null | ((newTabItem: string | undefined) => void); }; const TabListContext = createContext({ diff --git a/src/theme/Tabs/index.tsx b/src/theme/Tabs/index.tsx index d909e9bea3..bbd87a6cc5 100644 --- a/src/theme/Tabs/index.tsx +++ b/src/theme/Tabs/index.tsx @@ -14,14 +14,14 @@ import { } from "@ngrok/mantle/tabs"; import type { Props } from "@theme/Tabs"; import clsx from "clsx"; -import React, { useContext, type ReactElement, type ReactNode } from "react"; +import { useContext, type ReactElement, type ReactNode } from "react"; import styles from "./styles.module.css"; import TabListContext from "./TabListContext"; function getValidTabToShow( tabValues: readonly TabValue[], selectedValue: string | undefined, - defaultTab: string | undefined, + defaultTab: string | undefined ) { if (selectedValue) { const selectedTab = tabValues.find((tab) => tab.label === selectedValue); @@ -34,15 +34,15 @@ function getValidTabToShow( function getValidDefaultTab( tabValues: readonly TabValue[], - localStorageTab: string | null | undefined, + localStorageTab: string | null | undefined ) { const defaultTab = tabValues.find( - (tab) => tab.label === localStorageTab || tab.value === localStorageTab, + (tab) => tab.label === localStorageTab || tab.value === localStorageTab ); if (defaultTab) { return defaultTab.label; } - return tabValues[0]!.label; + return tabValues[0]?.label; } function TabList({ @@ -63,12 +63,12 @@ function TabList({ event: | React.FocusEvent | React.MouseEvent - | React.KeyboardEvent, + | React.KeyboardEvent ) => { const newTab = event.currentTarget; const newTabIndex = tabRefs.indexOf(newTab); const newTabValue = - tabValues[newTabIndex]!.label || tabValues[newTabIndex]!.value; + tabValues[newTabIndex]?.label || tabValues[newTabIndex]?.value; if (newTabValue !== selectedTabItem && updateSelectedTabItem) { blockElementScrollPositionUntilNextRender(newTab); @@ -86,12 +86,12 @@ function TabList({ } case "ArrowRight": { const nextTab = tabRefs.indexOf(event.currentTarget) + 1; - focusElement = tabRefs[nextTab] ?? tabRefs[0]!; + focusElement = tabRefs[nextTab] ?? tabRefs[0] ?? null; break; } case "ArrowLeft": { const prevTab = tabRefs.indexOf(event.currentTarget) - 1; - focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1]!; + focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1] ?? null; break; } default: @@ -131,6 +131,7 @@ function TabList({ tabValues={tabValues} selectValue={selectValue} selectedValue={selectedValue} + // biome-ignore lint/correctness/noChildrenProp: children={props.children} /> @@ -139,13 +140,13 @@ function TabList({ function TabContent({ children }: Props & ReturnType) { const childTabs = (Array.isArray(children) ? children : [children]).filter( - Boolean, + Boolean ) as ReactElement[]; return childTabs.map((tabItem, i) => { return ( {tabItem.props.children} @@ -159,8 +160,8 @@ function TabsComponent(props: Props): ReactNode { ...tabs, tabValues: tabs.tabValues .slice(0) - .sort((a: any, b: any) => - a.label ? a.label.localeCompare(b.label) : -1, + .sort((a, b) => + a.label && b.label ? a.label.localeCompare(b.label) : -1 ), }; return ( diff --git a/static/scripts/fix-redirect.js b/static/scripts/fix-redirect.js index 382f9af882..5b3310b2b4 100644 --- a/static/scripts/fix-redirect.js +++ b/static/scripts/fix-redirect.js @@ -714,8 +714,8 @@ const redirects = [ ], // JAN 2025 - [ fromIncludes(`/docs/tls/tls-termination/`), `/docs/traffic-policy/actions/terminate-tls/` ], - [ fromIncludes(`/docs/traffic-policy/templates/`), `/docs/traffic-policy/examples/a-b-tests/` ], + [ fromIncludes('/docs/tls/tls-termination/'), '/docs/traffic-policy/actions/terminate-tls/' ], + [ fromIncludes('/docs/traffic-policy/templates/'), '/docs/traffic-policy/examples/a-b-tests/' ], // IA Restructure redirects [ fromIncludes('/docs/tls/termination/agent-tls-termination/'), '/docs/agent/agent-tls-termination/'], @@ -748,11 +748,11 @@ const redirects = [ [ fromIncludes('/docs/tcp/traffic-policy/actions/log/'), '/docs/traffic-policy/actions/log'], [ fromIncludes('/docs/tcp/traffic-policy/actions/restrict-ips/'), '/docs/traffic-policy/actions/restrict-ips'], [ fromIncludes('/docs/tcp/traffic-policy/actions/'), '/docs/traffic-policy/actions/'], - [ fromExact(`/docs/tcp/traffic-policy/`), `/docs/traffic-policy/` ], + [ fromExact('/docs/tcp/traffic-policy/'), '/docs/traffic-policy/' ], // tls [ fromExact('/docs/tls/ip-restrictions/'), '/docs/traffic-policy/actions/restrict-ips'], [ fromExact('/docs/tls/mutual-tls/'), '/docs/traffic-policy/actions/terminate-tls/#enabling-mutual-tls'], - [ fromExact(`/docs/tls/termination/`), '/docs/traffic-policy/actions/terminate-tls/'], + [ fromExact('/docs/tls/termination/'), '/docs/traffic-policy/actions/terminate-tls/'], // Universal Gateway [ fromExact('/docs/http/'), '/docs/universal-gateway/http/'], [ fromExact('/docs/tcp/'), '/docs/universal-gateway/tcp/'], @@ -807,6 +807,6 @@ if (newPath !== currentPath && newPath !== window.location.pathname) { window.location.href = newPath; } else { console.error( - `ignoring redirect from ${window.location.href} to ${newPath}; looks loopy`, + 'ignoring redirect from ${window.location.href} to ${newPath}; looks loopy', ); } From 2619909a6992d2b7912a073cfd045e21dfe26a69 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 10 Apr 2025 16:47:09 -0400 Subject: [PATCH 102/137] Broke up forward original connection data --- docs/guides/api-gateway/get-started.mdx | 4 +- .../forward-original-connection-data.mdx | 367 ++++--- ...n-domain.mdx => bring-your-own-domain.mdx} | 18 + .../domains/what-are-domains.mdx | 2 +- .../domains/what-are-managed-domains.mdx | 2 +- docs/universal-gateway/http-s/index.mdx | 2 +- docs/universal-gateway/http.mdx | 914 ------------------ docs/universal-gateway/tcp/index.mdx | 158 ++- docs/universal-gateway/tls/index.mdx | 2 +- sidebars.js | 9 +- 10 files changed, 282 insertions(+), 1196 deletions(-) rename docs/universal-gateway/domains/{how-do-i-use-my-own-domain.mdx => bring-your-own-domain.mdx} (76%) delete mode 100644 docs/universal-gateway/http.mdx diff --git a/docs/guides/api-gateway/get-started.mdx b/docs/guides/api-gateway/get-started.mdx index 30c6c6aaab..1e6c92f11d 100644 --- a/docs/guides/api-gateway/get-started.mdx +++ b/docs/guides/api-gateway/get-started.mdx @@ -79,7 +79,7 @@ ngrok api reserved-domains create --domain {YOUR_NGROK_DOMAIN} This example uses an [ngrok-managed domain](/universal-gateway/domains/what-are-managed-domains), but you can use -your own [branded domain](/universal-gateway/how-do-i-use-my-own-domain) when you're ready for production. +your own [branded domain](/universal-gateway/bring-your-own-domain) when you're ready for production. In that case, substitute your branded domain for `{YOUR_NGROK_DOMAIN}` in the command above, and [follow the steps](/guides/other-guides/how-to-set-up-a-custom-domain/#create-cname-record-in-domain-dns) to configure DNS. @@ -540,7 +540,7 @@ out our [integrations guides](/integrations/) for specific examples. 1. Leave the default values for **JSON Web Token (JWT) Profile \*** and **JSON Web Token Signing Algorithm \***. 1. Click **Create**. -Auth0 Create API +Auth0 Create API #### Access your JWT diff --git a/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx b/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx index c67c39aa0f..5495fd6614 100644 --- a/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx +++ b/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx @@ -8,151 +8,11 @@ import Tabs from "@theme/Tabs"; import { LangSwitcher } from "@site/src/components/LangSwitcher"; import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitcher"; -import RandomAgentCliExample from "/examples/agent-cli/http-random.mdx"; -import RandomAgentConfigExample from "/examples/agent-config/http-random.mdx"; -import RandomGoSdkExample from "/examples/go-sdk/http-random.mdx"; -import RandomJavascriptSdkExample from "/examples/javascript-sdk/http-random.mdx"; -import RandomPythonSdkExample from "/examples/python-sdk/http-random.mdx"; -import RandomRustSdkExample from "/examples/rust-sdk/http-random.mdx"; -import RandomSshExample from "/examples/ssh/http-random.mdx"; - -import StaticDomainAgentCliExample from "/examples/agent-cli/http-static-domain.mdx"; -import StaticDomainAgentConfigExample from "/examples/agent-config/http-static-domain.mdx"; -import StaticDomainGoSdkExample from "/examples/go-sdk/http-static-domain.mdx"; -import StaticDomainJavascriptSdkExample from "/examples/javascript-sdk/http-static-domain.mdx"; -import StaticDomainKubernetesExample from "/examples/k8s/http-static-domain.mdx"; -import StaticDomainPythonSdkExample from "/examples/python-sdk/http-static-domain.mdx"; -import StaticDomainRustSdkExample from "/examples/rust-sdk/http-static-domain.mdx"; -import StaticDomainSshExample from "/examples/ssh/http-static-domain.mdx"; - -import BrandedDomainAgentCliExample from "/examples/agent-cli/http-branded-domain.mdx"; -import BrandedDomainAgentConfigExample from "/examples/agent-config/http-branded-domain.mdx"; -import BrandedDomainGoSdkExample from "/examples/go-sdk/http-branded-domain.mdx"; -import BrandedDomainJavascriptSdkExample from "/examples/javascript-sdk/http-branded-domain.mdx"; -import BrandedDomainKubernetesExample from "/examples/k8s/http-branded-domain.mdx"; -import BrandedDomainPythonSdkExample from "/examples/python-sdk/http-branded-domain.mdx"; -import BrandedDomainRustSdkExample from "/examples/rust-sdk/http-branded-domain.mdx"; -import BrandedDomainSshExample from "/examples/ssh/http-branded-domain.mdx"; - -import BasicAuthAgentCliExample from "/examples/agent-cli/http-basic-auth.mdx"; -import BasicAuthAgentConfigExample from "/examples/agent-config/http-basic-auth.mdx"; -import BasicAuthGoSdkExample from "/examples/go-sdk/http-basic-auth.mdx"; -import BasicAuthJavascriptSdkExample from "/examples/javascript-sdk/http-basic-auth.mdx"; -import BasicAuthKubernetesExample from "/examples/k8s/http-basic-auth.mdx"; -import BasicAuthPythonSdkExample from "/examples/python-sdk/http-basic-auth.mdx"; -import BasicAuthRustSdkExample from "/examples/rust-sdk/http-basic-auth.mdx"; -import BasicAuthSshExample from "/examples/ssh/http-basic-auth.mdx"; - -import OAuthAgentCliExample from "/examples/agent-cli/http-oauth-authn.mdx"; -import OAuthAgentConfigExample from "/examples/agent-config/http-oauth-authn.mdx"; -import OAuthGoSdkExample from "/examples/go-sdk/http-oauth-authn.mdx"; -import OAuthJavascriptSdkExample from "/examples/javascript-sdk/http-oauth-authn.mdx"; -import OAuthKubernetesExample from "/examples/k8s/http-oauth-authn.mdx"; -import OAuthPythonSdkExample from "/examples/python-sdk/http-oauth-authn.mdx"; -import OAuthRustSdkExample from "/examples/rust-sdk/http-oauth-authn.mdx"; -import OAuthSshExample from "/examples/ssh/http-oauth-authn.mdx"; - -import ForwardHttpsAgentConfigExample from "/examples/agent-config/http-forward-https.mdx"; -import ForwardHttpsKubernetesExample from "/examples/k8s/http-forward-https.mdx"; - -import HostHeaderAgentCliExample from "/examples/agent-cli/http-rewrite-host-header.mdx"; -import HostHeaderAgentConfigExample from "/examples/agent-config/http-rewrite-host-header.mdx"; -import HostHeaderGoSdkExample from "/examples/go-sdk/http-rewrite-host-header.mdx"; -import HostHeaderJavascriptSdkExample from "/examples/javascript-sdk/http-rewrite-host-header.mdx"; -import HostHeaderKubernetesExample from "/examples/k8s/http-rewrite-host-header.mdx"; -import HostHeaderPythonSdkExample from "/examples/python-sdk/http-rewrite-host-header.mdx"; -import HostHeaderRustSdkExample from "/examples/rust-sdk/http-rewrite-host-header.mdx"; -import HostHeaderSshExample from "/examples/ssh/http-rewrite-host-header.mdx"; - -import NonLocalAgentCliExample from "/examples/agent-cli/http-nonlocal.mdx"; -import NonLocalGoSdkExample from "/examples/go-sdk/http-nonlocal.mdx"; -import NonLocalJavascriptSdkExample from "/examples/javascript-sdk/http-nonlocal.mdx"; -import NonLocalPythonSdkExample from "/examples/python-sdk/http-nonlocal.mdx"; -import NonLocalRustSdkExample from "/examples/rust-sdk/http-nonlocal.mdx"; -import NonLocalSshExample from "/examples/ssh/http-nonlocal.mdx"; - -import RandomAgentCliExampleTCP from "/examples/agent-cli/tcp-random.mdx"; -import RandomAgentConfigExampleTCP from "/examples/agent-config/tcp-random.mdx"; -import RandomGoSdkExampleTCP from "/examples/go-sdk/tcp-random.mdx"; -import RandomJavascriptSdkExampleTCP from "/examples/javascript-sdk/tcp-random.mdx"; -import RandomKubernetesExampleTCP from "/examples/k8s/tcp-random.mdx"; -import RandomPythonSdkExampleTCP from "/examples/python-sdk/tcp-random.mdx"; -import RandomRustSdkExampleTCP from "/examples/rust-sdk/tcp-random.mdx"; -import RandomSshExampleTCP from "/examples/ssh/tcp-random.mdx"; - -import FixedAgentCliExampleTCP from "/examples/agent-cli/tcp-fixed.mdx"; -import FixedAgentConfigExampleTCP from "/examples/agent-config/tcp-fixed.mdx"; -import FixedGoSdkExampleTCP from "/examples/go-sdk/tcp-fixed.mdx"; -import FixedJavascriptSdkExampleTCP from "/examples/javascript-sdk/tcp-fixed.mdx"; -import FixedKubernetesExampleTCP from "/examples/k8s/tcp-fixed.mdx"; -import FixedPythonSdkExampleTCP from "/examples/python-sdk/tcp-fixed.mdx"; -import FixedRustSdkExampleTCP from "/examples/rust-sdk/tcp-fixed.mdx"; -import FixedSshExampleTCP from "/examples/ssh/tcp-fixed.mdx"; - -import NonLocalAgentCliExampleTCP from "/examples/agent-cli/tcp-nonlocal.mdx"; -import NonLocalAgentConfigExampleTCP from "/examples/agent-config/tcp-nonlocal.mdx"; -import NonLocalGoSdkExampleTCP from "/examples/go-sdk/tcp-nonlocal.mdx"; -import NonLocalJavascriptSdkExampleTCP from "/examples/javascript-sdk/tcp-nonlocal.mdx"; -import NonLocalKubernetesExampleTCP from "/examples/k8s/tcp-nonlocal.mdx"; -import NonLocalPythonSdkExampleTCP from "/examples/python-sdk/tcp-nonlocal.mdx"; -import NonLocalRustSdkExampleTCP from "/examples/rust-sdk/tcp-nonlocal.mdx"; -import NonLocalSshExampleTCP from "/examples/ssh/tcp-nonlocal.mdx"; - import ProxyProtoAgentCliExample from "/examples/agent-cli/tcp-proxyproto.mdx"; -import ProxyProtoAgentConfigExample from "/examples/agent-config/tcp-proxyproto.mdx"; -import ProxyProtoGoSdkExample from "/examples/go-sdk/tcp-proxyproto.mdx"; -import ProxyProtoJavascriptSdkExample from "/examples/javascript-sdk/tcp-proxyproto.mdx"; import ProxyProtoKubernetesExample from "/examples/k8s/tcp-proxyproto.mdx"; -import ProxyProtoPythonSdkExample from "/examples/python-sdk/tcp-proxyproto.mdx"; -import ProxyProtoRustSdkExample from "/examples/rust-sdk/tcp-proxyproto.mdx"; -import ProxyProtoSshExample from "/examples/ssh/tcp-proxyproto.mdx"; - -import AtAgentAgentCliExample from "/examples/agent-cli/tls-terminate-at-agent.mdx"; -import AtAgentAgentConfigExample from "/examples/agent-config/tls-terminate-at-agent.mdx"; -import AtAgentGoSdkExample from "/examples/go-sdk/tls-terminate-at-agent.mdx"; -import AtAgentJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-agent.mdx"; -import AtAgentKubernetesExample from "/examples/k8s/tls-terminate-at-agent.mdx"; -import AtAgentPythonSdkExample from "/examples/python-sdk/tls-terminate-at-agent.mdx"; -import AtAgentRustSdkExample from "/examples/rust-sdk/tls-terminate-at-agent.mdx"; -import AtAgentSshExample from "/examples/ssh/tls-terminate-at-agent.mdx"; - -import AtUpstreamAgentCliExample from "/examples/agent-cli/tls-terminate-at-upstream.mdx"; -import AtUpstreamAgentConfigExample from "/examples/agent-config/tls-terminate-at-upstream.mdx"; -import AtUpstreamGoSdkExample from "/examples/go-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamKubernetesExample from "/examples/k8s/tls-terminate-at-upstream.mdx"; -import AtUpstreamPythonSdkExample from "/examples/python-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamRustSdkExample from "/examples/rust-sdk/tls-terminate-at-upstream.mdx"; -import AtUpstreamSshExample from "/examples/ssh/tls-terminate-at-upstream.mdx"; - -import CustomDomainAgentCliExample from "/examples/agent-cli/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainAgentConfigExample from "/examples/agent-config/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainGoSdkExample from "/examples/go-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainJavascriptSdkExample from "/examples/javascript-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainKubernetesExample from "/examples/k8s/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainPythonSdkExample from "/examples/python-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainRustSdkExample from "/examples/rust-sdk/tls-terminate-at-edge-custom-domain.mdx"; -import CustomDomainSshExample from "/examples/ssh/tls-terminate-at-edge-custom-domain.mdx"; - -import ReencryptUpstreamAgentCliExample from "/examples/agent-cli/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamAgentConfigExample from "/examples/agent-config/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamGoSdkExample from "/examples/go-sdk/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamJavascriptSdkExample from "/examples/javascript-sdk/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamKubernetesExample from "/examples/k8s/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamPythonSdkExample from "/examples/python-sdk/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamRustSdkExample from "/examples/rust-sdk/tls-reencrypt-upstream.mdx"; -import ReencryptUpstreamSshExample from "/examples/ssh/tls-reencrypt-upstream.mdx"; - -import ProxyProtoAgentCliExampleTLS from "/examples/agent-cli/tls-proxyproto.mdx"; + import ProxyProtoAgentConfigExampleTLS from "/examples/agent-config/tls-proxyproto.mdx"; -import ProxyProtoGoSdkExampleTLS from "/examples/go-sdk/tls-proxyproto.mdx"; -import ProxyProtoJavascriptSdkExampleTLS from "/examples/javascript-sdk/tls-proxyproto.mdx"; import ProxyProtoKubernetesExampleTLS from "/examples/k8s/tls-proxyproto.mdx"; -import ProxyProtoPythonSdkExampleTLS from "/examples/python-sdk/tls-proxyproto.mdx"; -import ProxyProtoRustSdkExampleTLS from "/examples/rust-sdk/tls-proxyproto.mdx"; -import ProxyProtoSshExampleTLS from "/examples/ssh/tls-proxyproto.mdx"; - -### TCP When you forward traffic to an upstream TCP service, becuase traffic is coming from the ngrok agent, it won't know the client's original IP address. You can @@ -162,63 +22,182 @@ on connections to your upstream service to send connection information like the original client IP address to your upstream service. You will need to configure your upstream service to handle the PROXY protocol header. - - - - - - - - - - - - - - - - - - - - - - - - - +:::info + +PROXY protocol is not support for: SSH + +::: + +## TCP proxy protocol + + + + +```bash +ngrok tcp 22 --upstream-proxy-protocol=2 +``` + +```go +import ( + "context" + "net" + + "golang.ngrok.com/ngrok" + "golang.ngrok.com/ngrok/config" +) + +func ngrokListener(ctx context.Context) (net.Listener, error) { + return ngrok.Listen(ctx, + config.TCPEndpoint( + config.WithProxyProto(2), + ), + ngrok.WithAuthtokenFromEnv(), + ) +} +``` + +```python +import ngrok + +listener = ngrok.forward("localhost:8080", authtoken_from_env=True, + proto="tcp", + proxy_proto="2") + +print(f"Ingress established at: {listener.url()}"); +``` + +```rust +use ngrok::prelude::*; + +async fn listen_ngrok() -> anyhow::Result { + let sess = ngrok::Session::builder() + .authtoken_from_env() + .connect() + .await?; + + let tun = sess + .tcp_endpoint() + .proxy_proto(ProxyProto::V2) + .listen() + .await?; + + println!("Listening on URL: {:?}", tun.url()); + + Ok(tun) +} +``` + +```jsx +const ngrok = require("@ngrok/ngrok"); + +(async function () { + const listener = await ngrok.forward({ + addr: 8080, + authtoken_from_env: true, + proto: "tcp", + proxy_proto: "2", + }); + + console.log(`Ingress established at: ${listener.url()}`); +})(); +``` + + + + + + + + + + -### TLS +## TLS proxy protocol -Add a [PROXY -protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) header +Add a [PROXY protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) header on connection to your upstream service. This sends connection information like the original client IP address to your upstream service. - - - - - - - - - - - - - - - - - - - - - - - - - + + + +```bash +ngrok tls 443 --upstream-proxy-protocol=2 +``` + +```go +import ( + "context" + "net" + + "golang.ngrok.com/ngrok" + "golang.ngrok.com/ngrok/config" +) + +func ngrokListener(ctx context.Context) (net.Listener, error) { + return ngrok.Listen(ctx, + config.TLSEndpoint( + config.WithProxyProto(2), + ), + ngrok.WithAuthtokenFromEnv(), + ) +} +``` + +```jsx +const ngrok = require("@ngrok/ngrok"); + +(async function () { + const listener = await ngrok.forward({ + addr: 8080, + authtoken_from_env: true, + proto: "tls", + proxy_proto: "2", + }); + + console.log(`Ingress established at: ${listener.url()}`); +})(); +``` + +```python +import ngrok + +listener = ngrok.forward("localhost:8080", authtoken_from_env=True, + proto="tls", + proxy_proto="2") + +print(f"Ingress established at: {listener.url()}"); +``` + +```rust +use ngrok::prelude::*; + +async fn listen_ngrok() -> anyhow::Result { + let sess = ngrok::Session::builder() + .authtoken_from_env() + .connect() + .await?; + + let tun = sess + .tls_endpoint() + .proxy_proto(ProxyProto::V2) + .listen() + .await?; + + println!("Listening on URL: {:?}", tun.url()); + + Ok(tun) +} +``` + + + + + + + + + + diff --git a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx b/docs/universal-gateway/domains/bring-your-own-domain.mdx similarity index 76% rename from docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx rename to docs/universal-gateway/domains/bring-your-own-domain.mdx index 157af26dcc..8d08cf31ff 100644 --- a/docs/universal-gateway/domains/how-do-i-use-my-own-domain.mdx +++ b/docs/universal-gateway/domains/bring-your-own-domain.mdx @@ -40,3 +40,21 @@ If you bring your own [wildcard domain](/universal-gateway/wildcard-domains), e. Because it's not possible to create `CNAME` records for apex domains, if you want to use an apex domain, e.g. `example.com`, you must use a DNS provider that supports an `ALIAS` record or `CNAME` flattening. Because of how `ALIAS`/`CNAME` flattening is implemented, apex domains will not take advantage of the [Global Load Balancer](/universal-gateway/global-load-balancer/#domains). If you're trying to create your apex domain because you need to create endpoints for multiple subdomains, use a [wildcard domain](/universal-gateway/what-are-public-endpoints#wildcard-domains) instead. + +## Using custom domains with TCP endpoints + +Public TCP endpoints are assigned randomly on an ngrok-controlled hostname with a randomly-assigned port. You may not choose the hostname and you may not select the port. + +You may, however, simulate a customized hostname by creating a `CNAME` record to the hostname of your assigned TCP address. If you do so, be aware that all ports on that hostname, even those provisioned to other accounts will then be available on your domain. + +For example if your TCP address is `5.tcp.ngrok.io:12345`, you could create the following `CNAME` record: + +```bash +CNAME tcp.mydomain.com -> 5.tcp.ngrok.io +``` + +And then you can access that TCP endpoint with: + +```bash +telnet tcp.mydomain.com 12345 +``` diff --git a/docs/universal-gateway/domains/what-are-domains.mdx b/docs/universal-gateway/domains/what-are-domains.mdx index d5f92dbc04..7e69f89d1e 100644 --- a/docs/universal-gateway/domains/what-are-domains.mdx +++ b/docs/universal-gateway/domains/what-are-domains.mdx @@ -8,7 +8,7 @@ Domains enable you to create [public endpoints](/universal-gateway/domains/publi Valid Domain names include: - [ngrok-managed domains](/docs/universal-gateway/domains/what-are-managed-domains), like `foo.ngrok.app`. -- Your own [custom domains](/docs/universal-gateway/domains/how-do-i-use-my-own-domain/), like `example.your-domain.com`, by creating a `CNAME` DNS record with your domain's DNS provider. +- Your own [custom domains](/docs/universal-gateway/domains/bring-your-own-domain/), like `example.your-domain.com`, by creating a `CNAME` DNS record with your domain's DNS provider. ## Configuration diff --git a/docs/universal-gateway/domains/what-are-managed-domains.mdx b/docs/universal-gateway/domains/what-are-managed-domains.mdx index b16086c1b3..66640d52b6 100644 --- a/docs/universal-gateway/domains/what-are-managed-domains.mdx +++ b/docs/universal-gateway/domains/what-are-managed-domains.mdx @@ -8,7 +8,7 @@ import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitch import TabItem from "@theme/TabItem"; import Tabs from "@theme/Tabs"; -If you don't [already own a Domain](/universal-gateway/how-do-i-use-my-own-domain) that you want to use with ngrok, you can create a domain that is a subdomain of an ngrok-managed base domain. +If you don't [already own a Domain](/universal-gateway/bring-your-own-domain) that you want to use with ngrok, you can create a domain that is a subdomain of an ngrok-managed base domain. | Domain | Availability | HSTS Global Preload | | ------------------ | ------------------------------------------------- | ------------------- | diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx index c61559634f..122625cba3 100644 --- a/docs/universal-gateway/http-s/index.mdx +++ b/docs/universal-gateway/http-s/index.mdx @@ -156,7 +156,7 @@ ngrok api endpoints create \ - **URL Validation** — URLs are validated differently depending on their [binding](/universal-gateway/bindings). To learn more about valid URLs for HTTP/S endpoints, see [the Endpoint URLs documentation](/docs/universal-gateway/what-are-endpoint-urls/#http). - **Domains** — Public HTTP/S endpoints must match a domain on your account. See [the domains documentation](/universal-gateway/domains/what-are-domains/) for more information. -- **Bring your own domain** — To use your own domain with HTTP/S endpoints, see [the guide on the subject](/universal-gateway/how-do-i-use-my-own-domain). +- **Bring your own domain** — To use your own domain with HTTP/S endpoints, see [the guide on the subject](/universal-gateway/bring-your-own-domain). - **Wildcard Endpoints** — You can create HTTP/S endpoints that receive traffic from all of the subdomains matching a given wildcard domain. See [the wildcard domain docs](/universal-gateway/wildcard-domains/) for more information. - **Traffic Policy** — Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate and transform the traffic through the endpoint. - **Agent Forwarding** — The [ngrok agent](/agent/) and [Agent SDKs](/agent-sdks/) forward traffic that your endpoints receive to upstream services. See [the agent forwarding documentation](/universal-gateway/agent-forwarding/) for more information. diff --git a/docs/universal-gateway/http.mdx b/docs/universal-gateway/http.mdx deleted file mode 100644 index 155d0e3980..0000000000 --- a/docs/universal-gateway/http.mdx +++ /dev/null @@ -1,914 +0,0 @@ ---- -title: How Do I Handle HTTP/S Traffic? ---- - -import TabItem from "@theme/TabItem"; -import Tabs from "@theme/Tabs"; - -import TlsLimits from "./_tls_limits.mdx"; - -import RandomAgentCliExample from "/examples/agent-cli/http-random.mdx"; -import RandomAgentConfigExample from "/examples/agent-config/http-random.mdx"; -import RandomGoSdkExample from "/examples/go-sdk/http-random.mdx"; -import RandomJavascriptSdkExample from "/examples/javascript-sdk/http-random.mdx"; -import RandomPythonSdkExample from "/examples/python-sdk/http-random.mdx"; -import RandomRustSdkExample from "/examples/rust-sdk/http-random.mdx"; -import RandomSshExample from "/examples/ssh/http-random.mdx"; - -import StaticDomainAgentCliExample from "/examples/agent-cli/http-static-domain.mdx"; -import StaticDomainAgentConfigExample from "/examples/agent-config/http-static-domain.mdx"; -import StaticDomainGoSdkExample from "/examples/go-sdk/http-static-domain.mdx"; -import StaticDomainJavascriptSdkExample from "/examples/javascript-sdk/http-static-domain.mdx"; -import StaticDomainKubernetesExample from "/examples/k8s/http-static-domain.mdx"; -import StaticDomainPythonSdkExample from "/examples/python-sdk/http-static-domain.mdx"; -import StaticDomainRustSdkExample from "/examples/rust-sdk/http-static-domain.mdx"; -import StaticDomainSshExample from "/examples/ssh/http-static-domain.mdx"; - -import BrandedDomainAgentCliExample from "/examples/agent-cli/http-branded-domain.mdx"; -import BrandedDomainAgentConfigExample from "/examples/agent-config/http-branded-domain.mdx"; -import BrandedDomainGoSdkExample from "/examples/go-sdk/http-branded-domain.mdx"; -import BrandedDomainJavascriptSdkExample from "/examples/javascript-sdk/http-branded-domain.mdx"; -import BrandedDomainKubernetesExample from "/examples/k8s/http-branded-domain.mdx"; -import BrandedDomainPythonSdkExample from "/examples/python-sdk/http-branded-domain.mdx"; -import BrandedDomainRustSdkExample from "/examples/rust-sdk/http-branded-domain.mdx"; -import BrandedDomainSshExample from "/examples/ssh/http-branded-domain.mdx"; - -import BasicAuthAgentCliExample from "/examples/agent-cli/http-basic-auth.mdx"; -import BasicAuthAgentConfigExample from "/examples/agent-config/http-basic-auth.mdx"; -import BasicAuthGoSdkExample from "/examples/go-sdk/http-basic-auth.mdx"; -import BasicAuthJavascriptSdkExample from "/examples/javascript-sdk/http-basic-auth.mdx"; -import BasicAuthKubernetesExample from "/examples/k8s/http-basic-auth.mdx"; -import BasicAuthPythonSdkExample from "/examples/python-sdk/http-basic-auth.mdx"; -import BasicAuthRustSdkExample from "/examples/rust-sdk/http-basic-auth.mdx"; -import BasicAuthSshExample from "/examples/ssh/http-basic-auth.mdx"; - -import OAuthAgentCliExample from "/examples/agent-cli/http-oauth-authn.mdx"; -import OAuthAgentConfigExample from "/examples/agent-config/http-oauth-authn.mdx"; -import OAuthGoSdkExample from "/examples/go-sdk/http-oauth-authn.mdx"; -import OAuthJavascriptSdkExample from "/examples/javascript-sdk/http-oauth-authn.mdx"; -import OAuthKubernetesExample from "/examples/k8s/http-oauth-authn.mdx"; -import OAuthPythonSdkExample from "/examples/python-sdk/http-oauth-authn.mdx"; -import OAuthRustSdkExample from "/examples/rust-sdk/http-oauth-authn.mdx"; -import OAuthSshExample from "/examples/ssh/http-oauth-authn.mdx"; - -import ForwardHttpsAgentCliExample from "/examples/agent-cli/http-forward-https.mdx"; -import ForwardHttpsAgentConfigExample from "/examples/agent-config/http-forward-https.mdx"; -import ForwardHttpsGoSdkExample from "/examples/go-sdk/http-forward-https.mdx"; -import ForwardHttpsJavascriptSdkExample from "/examples/javascript-sdk/http-forward-https.mdx"; -import ForwardHttpsKubernetesExample from "/examples/k8s/http-forward-https.mdx"; -import ForwardHttpsPythonSdkExample from "/examples/python-sdk/http-forward-https.mdx"; -import ForwardHttpsRustSdkExample from "/examples/rust-sdk/http-forward-https.mdx"; -import ForwardHttpsSshExample from "/examples/ssh/http-forward-https.mdx"; - -import HostHeaderAgentCliExample from "/examples/agent-cli/http-rewrite-host-header.mdx"; -import HostHeaderAgentConfigExample from "/examples/agent-config/http-rewrite-host-header.mdx"; -import HostHeaderGoSdkExample from "/examples/go-sdk/http-rewrite-host-header.mdx"; -import HostHeaderJavascriptSdkExample from "/examples/javascript-sdk/http-rewrite-host-header.mdx"; -import HostHeaderKubernetesExample from "/examples/k8s/http-rewrite-host-header.mdx"; -import HostHeaderPythonSdkExample from "/examples/python-sdk/http-rewrite-host-header.mdx"; -import HostHeaderRustSdkExample from "/examples/rust-sdk/http-rewrite-host-header.mdx"; -import HostHeaderSshExample from "/examples/ssh/http-rewrite-host-header.mdx"; - -import NonLocalAgentCliExample from "/examples/agent-cli/http-nonlocal.mdx"; -import NonLocalAgentConfigExample from "/examples/agent-config/http-nonlocal.mdx"; -import NonLocalGoSdkExample from "/examples/go-sdk/http-nonlocal.mdx"; -import NonLocalJavascriptSdkExample from "/examples/javascript-sdk/http-nonlocal.mdx"; -import NonLocalKubernetesExample from "/examples/k8s/http-nonlocal.mdx"; -import NonLocalPythonSdkExample from "/examples/python-sdk/http-nonlocal.mdx"; -import NonLocalRustSdkExample from "/examples/rust-sdk/http-nonlocal.mdx"; -import NonLocalSshExample from "/examples/ssh/http-nonlocal.mdx"; - -import AbsPathFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-abs-path.mdx"; -import AbsPathFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-abs-path.mdx"; -import AbsPathFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverKubernetesExample from "/examples/k8s/http-fileserver-abs-path.mdx"; -import AbsPathFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-abs-path.mdx"; -import AbsPathFileserverSshExample from "/examples/ssh/http-fileserver-abs-path.mdx"; - -import WorkingDirFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverKubernetesExample from "/examples/k8s/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-working-dir.mdx"; -import WorkingDirFileserverSshExample from "/examples/ssh/http-fileserver-working-dir.mdx"; - -import WindowsFileserverAgentCliExample from "/examples/agent-cli/http-fileserver-windows.mdx"; -import WindowsFileserverAgentConfigExample from "/examples/agent-config/http-fileserver-windows.mdx"; -import WindowsFileserverGoSdkExample from "/examples/go-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverJavascriptSdkExample from "/examples/javascript-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverKubernetesExample from "/examples/k8s/http-fileserver-windows.mdx"; -import WindowsFileserverPythonSdkExample from "/examples/python-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverRustSdkExample from "/examples/rust-sdk/http-fileserver-windows.mdx"; -import WindowsFileserverSshExample from "/examples/ssh/http-fileserver-windows.mdx"; - -HTTP/S endpoints enable you to serve web services like REST APIs, web -applications, websites, and websocket servers. - -You can create HTTP/S endpoints locally with the [Agent CLI](/agent/cli) or as [Cloud Endpoints](/universal-gateway/cloud-endpoints/) via the ngrok Dashboard. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -### Agent Endpoint - -Agent Endpoints are the easiest way to get started with ngrok. An [agent -endpoint](/universal-gateway/cloud-endpoints/) is started by a -[Secure Tunnels](/agent/) agent. The endpoint lives for the lifetime of the -process and forwards traffic to a port or URL of your choosing. - -Create the endpoint `https://example.ngrok.app` and forward its traffic to a -local port. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -### Cloud Endpoint - -[Cloud endpoints](/universal-gateway/cloud-endpoints/) are created via the -ngrok Dashboard or [API](/api/). They are persistent and live until they are -deleted. [Traffic Policy](/traffic-policy/) controls how a cloud endpoint -handles traffic. - -[Create an HTTPS cloud endpoint](https://dashboard.ngrok.com/endpoints/new) -which returns a `Hello world!` 200 OK response. - - - - -```sh title="Command line" -ngrok api endpoints create \ - --url https://example.ngrok.app \ - --traffic-policy "$( - - - -## URL - -URLs are validated differently depending on their -[binding](/universal-gateway/bindings). Consult the -following documentation for details on valid URLs for TCP endpoints: - -- [Public Endpoint URLs](/universal-gateway/public-endpoints/#urls) -- [Internal Endpoint URLs](/universal-gateway/internal-endpoints/#urls) -- [Kubernetes Endpoint URLs](/universal-gateway/kubernetes-endpoints/#urls) - -#### Public - -###### HTTP - -- The hostname must be a domain with a valid [public suffix](https://publicsuffix.org/). -- The port must be `80`. If you do not specify a port, the default `80` will be used for you. - -**Examples** - -- `http://example.ngrok.app` -- `http://example.ngrok.app:80` -- `http://example.party` -- `http://example.ngrok.app:81` - invalid port: port number must be `80`, not `81` -- `http://example.doesnotexist` - invalid hostname: `.doesnotexist` is not a public suffix domain -- `http://example.internal` - invalid hostname: `.internal` is not a public suffix domain - -###### HTTPS - -- The hostname must be a domain with a valid [public suffix](https://publicsuffix.org/). -- The port must be `443`. If you do not specify a port, the default `443` will be used for you. - -#### Internal - -#### Kubernetes - -##### Valid URLs - -- https://example.ngrok.app -- https://example.ngrok.app:443 -- https://example.party - -##### Invalid URLs - -- https://example.ngrok.app:8443 -- https://example.nosuchtld -- https://example.internal - -### Validation - -When you create an agent endpoint, if you do not specify a complete URL, -following defaults are used to construct an endpoint URL. When you create a -cloud endpoint, you must always specify both a scheme and hostname. - -| URL Part | Default | -| -------- | --------------------------------------------------------- | -| Scheme | `https` | -| Hostname | randomly selected | -| Port | `443` if scheme is `https`
`80` if scheme is `http` | - -Consult the following table of examples of URL defaulting: - -| Value | Endpoint URL | -| ------------------------------- | -------------------------------------------------------- | -| `https://example.ngrok.app` | `https://example.ngrok.app` | -| `http://example.ngrok.app` | `http://example.ngrok.app` | -| `example.ngrok.app` | `https://example.ngrok.app` | -| `app.example.com` | `https://app.example.com` | -| `https://example.internal` | `https://example.internal` | -| `https://example.internal:1234` | `https://example.internal:1234` | -| `http://example.internal` | `http://example.internal` | -| `foo.internal` | `https://foo.internal` | -| `{empty}` | `https://1eb2-181-80-12-3.ngrok.app` (randomly selected) | - -If you would like to listen for both http and https traffic, create two endpoints. - -#### Domains - -When you create a public endpoint, it must match a -[Domain](/universal-gateway/domains/what-are-domains) on your account. Domains help you set up -branded domains and manage TLS certificates. You may create endpoints with -wildcard domains as well. - -Endpoints with randomly-assigned hostnames are an exception and won't match an -existing Domain object. - -### Bring your own domain {#bring-your-own-domain} - -If you want to bring your own domain, first [create a Domain record and set up -a DNS CNAME record](/universal-gateway/how-do-i-use-my-own-domain). Then -create an endpoint on that domain by specifying a URL with a matching hostname. - -For example, to create an HTTPS endpoint on `https://app.example.com`, [create -a Domain](https://dashboard.ngrok.com/domains) and follow the instructions to -set up a CNAME record. Then use the following example to start an endpoint on -your domain: - - - - - - - - - - - - - - - - - - - - - - - - - - - - -### Use multiple endpoints with wildcard subdomains - -With the [Agent CLI](/agent/cli), you can create separate public endpoints for subdomains of a wildcard domain no matter where the upstream services are running. See [the Domains docs](/docs/universal-gateway/domains/#wildcard-domains) for more information. - -For example, if you reserve `*.example.com` and want to route requests to `api1.example.com` and `api2.example.com`, you can specify subdomains via the CLI. ngrok will handle routing requests to the correct endpoint, even if they're on different ports. - -The first one might be at port `80`: - -```bash -ngrok http 80 --url https://api1.example.com -``` - -While the second is at port `81`: - -```bash -ngrok http 81 --url https://api2.example.com -``` - -:::tip -This is only necessary for creating _public_ endpoints to subdomains. Internal endpoints don't require a domain. -::: - -### Randomly assigned hostnames - -If you run create a public endpoint without specifying a hostname, ngrok will -automatically assign a random one for you.by selecting a random subdomain of one of our [ngrok-managed -Domains](/universal-gateway/domains#ngrok-managed-domains) to your endpoint. -For example, the command `ngrok http 80` may create an endpoint like -`https://1eb2-181-80-12-3.ngrok.app`. - -The following example create an HTTPS endpoint on a randomly assigned hostname -that forwards to port 8080. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -## Traffic Policy - -Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate and transform the traffic through the endpoint. - -### Authentication - -Public endpoints are accessible to the public internet unless you secure them -with authentication. That's desirable if you're hosting a public website but -most often you want to add authentication. You can secure your endpoints with -[Traffic Policy](/traffic-policy) with any of the following actions: - -- [Basic Auth](/traffic-policy/actions/basic-auth) -- [OAuth](/traffic-policy/actions/oauth) -- [IP Restriction](/traffic-policy/actions/restrict-ips/) -- [Webhook Verification](/traffic-policy/actions/verify-webhook/) -- [JWT](/traffic-policy/actions/jwt-validation/) -- [Mutual TLS](/traffic-policy/actions/terminate-tls/) -- [OpenID Connect](/traffic-policy/actions/oidc/) -- [SAML](/traffic-policy/actions/saml/) - -#### Basic Auth Example - -Adds a username and password with the [Basic -Auth](/traffic-policy/actions/basic-auth) Traffic Policy action. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -#### Google OAuth Example - -The following example enforces a browser-based OAuth redirect flow in front of -your endpoint using Google as the identity provider by using the -[OAuth](/traffic-policy/actions/oauth) Traffic Policy action. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#### Rewriting the `host` header {#rewrite-host-header} - -Some application servers expect the `host` header to match a specific value -when they receive requests and some use the `host` header to determine which of -many sites to display. ngrok can rewrite the `host` header of incoming requests -so that your application behaves correctly. - -When you rewrite the `host` header, ngrok also rewrites the `location` header of -HTTP responses automatically to match the hostname of your Endpoint URL. - -The following example rewrites the `host` header to the value `localhost` using -the [`add-headers`](/traffic-policy/actions/add-headers) Traffic Policy action. -Adding the `Host` header [is a special -case](/traffic-policy/actions/add-headers/#special-cases) that replaces the existing -`Host` header instead of appending a second value. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -## Agent Forwarding - -The [ngrok agent](/agent/) and [Agent -SDKs](/agent-sdks/) forward traffic that your endpoints receive -to upstream services. You specify a URL or port number to instruct the ngrok -agent where and how to forward traffic. - -### HTTPS forwarding - -The scheme in your upstream URL is used to determine whether to forward HTTP or -HTTPS traffic to the upstream service. If you do not specify a scheme, the -default `http` scheme is chosen _unless_ you forward to port `443`, in which -case ngrok will use `https`. Consult the following table of examples. - -| Upstream URL | Normalized Value | -| ------------------------ | ------------------------ | -| `http://localhost:1234` | `http://localhost:1234` | -| `https://localhost:1234` | `https://localhost:1234` | -| `localhost:1234` | `http://localhost:1234` | -| `1234` | `http://localhost:1234` | -| `localhost:443` | `https://localhost:443` | -| `443` | `https://localhost:443` | - -ngrok assumes that the network you run the agent on is private and it does not -verify the TLS certificate presented by the upstream service. You may change -this behavior with the [flags `--upstream-tls-verify` and -`upstream-tls-verify-cas`](/agent/cli/#ngrok-http). - - - - - - - - - - - - - - - - - - - - - - - - - - - - -### Non-local forwarding - -Agents don't just forward to ports on your localhost. You can forward traffic -to any address or URL reachable from the agent. For example, if you want to -forward traffic to a HTTP server running on your network at `192.168.1.2:80`: - - - - - - - - - - - - - - - - - - - - - - - - - - - - -### HTTP/2 forwarding - -When agents forward to upstream http/2 services, connections use HTTP/1.1 by -default. - -You can configure the agent, SDKs and Kubernetes Operator to instead use HTTP/2 -when forwarding to your upstream service. - -| Forwarder | Option | Docs | -| ------------------- | --------------------------------- | ----------------------------------------- | -| Agent | `--upstream-protocol` | [Agent CLI flags](/agent/cli/#ngrok-http) | -| Agent SDKs | language-dependent | [Agent SDKs](/agent-sdks) | -| Kubernetes Operator | `appProtocol` on the `Tunnel` CRD | [Kubernetes Operator](/k8s) | - -When http2 forwarding is enabled, all requests to your upstream service will be -transmitted over HTTP/2 Cleartext since TLS was already terminated at the ngrok -cloud service. We cannot use -[TLS-ALPN](https://httpwg.org/specs/rfc7540.html#TLS-ALPN) at this time. We -rely on [HTTP/2 with Prior -Knowledge](https://httpwg.org/specs/rfc7540.html#known-http) currently. - -### Serving file directories - -The ngrok agent supports the `file://` scheme in a forwarding URL. When you use -the `file://` scheme, the ngrok agent serves local file system directories by -using its own built-in file server, no separate server needed. It works just -like `python3 -m http.server` but it is built directly into the ngrok agent. - -Paths in `file://` URLs must be specified as absolute paths. - -#### Serve files in `/var/log` - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -#### Serve files on Windows - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -#### Serve files in your current working directory - - - - - - - - - - - - - - - - - - - - - - - - - - - - -## Traffic Observability - -### Traffic Inspector - -[Traffic Inspector](/obs/traffic-inspection/) gives you a real-time view in the -ngrok dashboard of the HTTP traffic flowing through your HTTP/S endpoints. You -can choose whether Traffic Inspector captures only request metadata or full -request and response bodies. - -### Log Export Events - -You can export logs of traffic to HTTP/S endpoints with [ngrok's events -system](/obs/). The following events are published for log exporting: - -| Event | When | -| ------------------------------------------------------------------------ | ------------------------------------------------------------------ | -| [http_request_complete.v0](/obs/events/reference/#http-request-complete) | Published when an HTTP request to an HTTP/S endpoint completes. | -| [tcp_connection_closed.v0](/obs/events/reference/#tcp-connection-closed) | Published when a TCP connection to any type of endpoint completes. | - -## Advanced - -HTTP/S endpoints are standards-compliant HTTP reverse proxies. - -### Versions - -- HTTP/S endpoints support HTTP/1.1. -- HTTPS endpoints support HTTP/1.1 and HTTP/2. -- HTTP/1.0, HTTP/3 and QUIC are **not** supported. - -### HTTP/2 - -HTTPS endpoints will automatically use HTTP/2 for all connections if the client -supports it. Client support is determined via standard ALPN negotiation. - -HTTP/2 is used between the client and your endpoint even even if your upstream -service does not support HTTP/2. - -The section on [HTTP/2 agent forwarding](#http2-forwarding) has details on how to -configure the use of HTTP/2 when sending traffic to an upstream service. - -### Websockets - -Websocket connections are supported out-of-the-box. No configuration is required. - -### Hop by hop headers - -ngrok does not forward any [hop-by-hop -headers](https://datatracker.ietf.org/doc/html/rfc2616#section-13.5.1) to the -upstream service. As an exception, `Connection: upgrade` headers are forwarded -to support [websockets](#websockets). - -For information on headers added automatically by ngrok, see -[Upstream Headers](#upstream-headers). - -### Persistent connections - -When a connection is made to HTTP/S ngrok endpoints with HTTP/1.1, ngrok may -choose to use persistent connections (aka HTTP keep-alive) to improve the -performance of future requests from the same client if the client supports it. - -This behavior is not guaranteed and it is not configurable. - -See [RFC 7230](https://datatracker.ietf.org/doc/html/rfc7230#section-6.3) for -additional details. - -### Well Known URIs - -#### `/.well-known/acme-challenge` - -ngrok takes over handling of this path of any HTTP endpoint matching a -[Domain](/universal-gateway/domains/what-are-domains) with automated certificate management -enabled. You may disable this behavior by uploading your own certificate on the -matching Domain. - -## TLS - -ngrok automatically handles TLS (SSL) certificate management and termination for you. -There is nothing to setup, configure or manage. - -TLS connections to `https` endpoints are terminated at ngrok's cloud service. -If you wish to terminate TLS traffic at the ngrok agent or in your upstream -application, use a [TLS Endpoint](/universal-gateway/tls) instead. - -Consult the following documentation for additional details on how ngrok handles -TLS termination and certificiate management: - -- [TLS Certificates](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls) -- [TLS Termination](/universal-gateway/tls-termination) - -## Upstream Headers - -ngrok adds headers to each HTTP request with information about the original -client IP, request scheme and request `host` header value. - -| Header | Description | -| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -| `x-forwarded-for` | The IP address of the client who initiated the request. If this header exists on the original request, ngrok will append a new value. | -| `x-forwarded-proto` | The scheme of the original request, either `http` or `https`. If this header exists on the original request, ngrok will append a new value. | -| `x-forwarded-host` | The header from the client's request if it existed, otherwise is set to the request's `Host` header value. | - -Because ngrok appends values to `x-forwarded-for` and `x-forwarded-proto`, be -sure to use the last value of the header in your application code to read the -values injected by ngrok. - -You may remove these headers with the [Remove -Headers](/traffic-policy/actions/remove-headers/) Traffic Policy action. - -## Limits & Timeouts - -[Contact us](mailto:support@ngrok.com) if you need to configure limits and -timeouts on connections to HTTP endpoints. - -#### Connection - -| Limit | Name | Notes | -| --------- | ------------------- | ------------------------------------------------------------ | -| 5 minutes | Client Idle Timeout | Time since data was last transmitted by the upstream service | -| 5 minutes | Server Idle Timeout | Time since data was last transmitted by the upstream service | -| No limit | Data transmitted | Data transmitted by the client or upstream service | - -#### TLS - - - -#### HTTP - -| Limit | Name | Notes | -| ---------- | ------------------ | --------------------------------------------- | -| No timeout | Round Trip Timeout | Time for the entire HTTP request and response | - -#### HTTP Request - -| Limit | Name | Notes | -| ---------- | ---------------------- | ---------------------------------------------------- | -| 1 MB | Request Header Size | Includes method, URI and headers | -| 1 MB | Request URI Length | Limited by the size of the request header | -| No timeout | Request Timeout | Time to read the entire HTTP request from the client | -| No timeout | Request Header Timeout | Time to read the HTTP request header from the client | -| No limit | Request Body Size | | - -#### HTTP Response - -| Limit | Name | Notes | -| ---------- | ----------------------- | ----------------------------------------------------- | -| 1 MB | Response Header Size | Includes method, URI and headers | -| No timeout | Response Timeout | Time to read the entire HTTP response from the server | -| No timeout | Response Header Timeout | Time to read the HTTP response header from the server | -| No limit | Response Body Size | | - -## Errors - -If ngrok fails to handle an HTTP request it will set the `ngrok-error-code` -header in the HTTP response with a [unique ngrok Error Code](/errors/) -describing the failure. - -ngrok guarantees that the upstream service may never set the `ngrok-error-code` -HTTP response header so you know reliably that it was set by ngrok. - -ngrok may return an error under the following conditions: - -- Your upstream service timed out or rejected the connection -- Your upstream service returned a response that was not valid HTTP -- A [Traffic Policy](/traffic-policy) action rejected the request. -- [Traffic Policy](/traffic-policy) execution encountered a runtime error. -- ngrok encountered an internal error - -## API - -HTTP/S Endpoints can be created programatically. Consult the documentation on -[Endpoint APIs](/api/resources/endpoints/). - -## Pricing - -HTTP/S endpoints are available on all plans. Consult the [Endpoints -Pricing](/universal-gateway/endpoints/#pricing) documentation for -billing details. - -See [Domains pricing](/universal-gateway/domains/#pricing) for details on -pricing for custom domains, wildcard domains and more. diff --git a/docs/universal-gateway/tcp/index.mdx b/docs/universal-gateway/tcp/index.mdx index 4ed11dc0b9..b44917dc75 100644 --- a/docs/universal-gateway/tcp/index.mdx +++ b/docs/universal-gateway/tcp/index.mdx @@ -3,35 +3,13 @@ title: How Do I Handle TCP Traffic? description: Learn how to handle TCP traffic with ngrok. --- +import { LangSwitcher } from "@site/src/components/LangSwitcher"; + import TabItem from "@theme/TabItem"; import Tabs from "@theme/Tabs"; -import RandomAgentCliExample from "/examples/agent-cli/tcp-random.mdx"; import RandomAgentConfigExample from "/examples/agent-config/tcp-random.mdx"; -import RandomGoSdkExample from "/examples/go-sdk/tcp-random.mdx"; -import RandomJavascriptSdkExample from "/examples/javascript-sdk/tcp-random.mdx"; import RandomKubernetesExample from "/examples/k8s/tcp-random.mdx"; -import RandomPythonSdkExample from "/examples/python-sdk/tcp-random.mdx"; -import RandomRustSdkExample from "/examples/rust-sdk/tcp-random.mdx"; -import RandomSshExample from "/examples/ssh/tcp-random.mdx"; - -import NonLocalAgentCliExample from "/examples/agent-cli/tcp-nonlocal.mdx"; -import NonLocalAgentConfigExample from "/examples/agent-config/tcp-nonlocal.mdx"; -import NonLocalGoSdkExample from "/examples/go-sdk/tcp-nonlocal.mdx"; -import NonLocalJavascriptSdkExample from "/examples/javascript-sdk/tcp-nonlocal.mdx"; -import NonLocalKubernetesExample from "/examples/k8s/tcp-nonlocal.mdx"; -import NonLocalPythonSdkExample from "/examples/python-sdk/tcp-nonlocal.mdx"; -import NonLocalRustSdkExample from "/examples/rust-sdk/tcp-nonlocal.mdx"; -import NonLocalSshExample from "/examples/ssh/tcp-nonlocal.mdx"; - -import ProxyProtoAgentCliExample from "/examples/agent-cli/tcp-proxyproto.mdx"; -import ProxyProtoAgentConfigExample from "/examples/agent-config/tcp-proxyproto.mdx"; -import ProxyProtoGoSdkExample from "/examples/go-sdk/tcp-proxyproto.mdx"; -import ProxyProtoJavascriptSdkExample from "/examples/javascript-sdk/tcp-proxyproto.mdx"; -import ProxyProtoKubernetesExample from "/examples/k8s/tcp-proxyproto.mdx"; -import ProxyProtoPythonSdkExample from "/examples/python-sdk/tcp-proxyproto.mdx"; -import ProxyProtoRustSdkExample from "/examples/rust-sdk/tcp-proxyproto.mdx"; -import ProxyProtoSshExample from "/examples/ssh/tcp-proxyproto.mdx"; TCP endpoints enable you to deliver any network service with a TCP-based protocol. They are commonly used to create connectivity for: @@ -57,77 +35,95 @@ of the process and forwards traffic to a port or URL of your choosing. This example creates a TCP endpoint on a randomly-assigned URL - e.g. `tcp://1.tcp.ngrok.io:12345` and forwards its traffic to a local port. - - - - - - - - - - - - - - - - - - - - - - - - - - + + + +```bash +ngrok tcp 22 +``` -## Learn more +```ssh tabName="SSH" +ssh -R 0:localhost:22 v2@connect.ngrok-agent.com tcp +``` -- **URL Validation** — URLs are validated differently depending on their [binding](/universal-gateway/bindings). To learn more about valid URLs for TCP endpoints, see [the Endpoint URLs documentation](/docs/universal-gateway/what-are-endpoint-urls/#tcp). -- **Static URLs** — To create a public TCP endpoint with a static URL, you must first create a [TCP Address](/universal-gateway/tcp-addresses/). See [the documentation on static TCP URLs](/universal-gateway/tcp/static-tcp-urls/) for more information. -- **Authentication** — You can secure your TCP endpoints with the [IP Restriction](/traffic-policy/actions/restrict-ips/) and [Mutual TLS](/docs/guides/other-guides/how-to-terminate-traffic-with-ngrok-configs/#mutual-tls-example) Traffic Policy actions. There is a limited set of actions available to authenticate TCP traffic because the protocol is low-level. -- **Bring your own domain** — To use your own domain with TLS endpoints, see [the guide on the subject](/universal-gateway/how-do-i-use-my-own-domain). -- **Wildcard Endpoints** — You can create TLS endpoints that receive traffic from all of the subdomains matching a given wildcard domain. See [the wildcard domain docs](/universal-gateway/wildcard-domains/) for more information. -- **Traffic Policy** — Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate and transform the traffic through the endpoint. -- **Agent Forwarding** — The [ngrok agent](/agent/) and [Agent SDKs](/agent-sdks/) forward traffic that your endpoints receive to upstream services. See [the agent forwarding documentation](/universal-gateway/agent-forwarding/) for more information. -- **Traffic Observability** — [Traffic Inspector](/obs/traffic-inspection/) gives you a real-time view in the ngrok dashboard of the traffic flowing through your TLS endpoints. You can even [export traffic logs with the Traffic Events system](/docs/obs/events/reference/). -- **TLS Certificates** — Learn how [ngrok automatically handles TLS](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) and [TLS termination](/universal-gateway/tls/tls-termination/) for TLS endpoints for you. +```go +import ( + "context" + "net" + + "golang.ngrok.com/ngrok" + "golang.ngrok.com/ngrok/config" +) + +func ngrokListener(ctx context.Context) (net.Listener, error) { + return ngrok.Listen(ctx, + config.TCPEndpoint(), + ngrok.WithAuthtokenFromEnv(), + ) +} +``` -### Custom domains +```jsx +const ngrok = require("@ngrok/ngrok"); -Public TCP endpoints are assigned randomly on an ngrok-controlled hostname with -a randomly-assigned port. You may not choose the hostname and you may not -select the port. +(async function () { + const listener = await ngrok.forward({ + addr: 8080, + authtoken_from_env: true, + proto: "tcp", + }); -You may, however, simulate a customized hostname by creating a CNAME record to -the hostname of your assigned TCP address. If you do so, be aware that all -ports on that hostname, even those provisioned to other accounts will then be -available on your domain. + console.log(`Ingress established at: ${listener.url()}`); +})(); +``` -For example if your TCP address is `5.tcp.ngrok.io:12345`, you could create the -following CNAME record: +```python +import ngrok -``` -CNAME tcp.mydomain.com -> 5.tcp.ngrok.io +listener = ngrok.forward("localhost:8080", authtoken_from_env=True, + proto="tcp") + +print(f"Ingress established at: {listener.url()}"); ``` -And then you can access that TCP endpoint with +```rust +use ngrok::prelude::*; +async fn listen_ngrok() -> anyhow::Result { + let sess = ngrok::Session::builder() + .authtoken_from_env() + .connect() + .await?; + + let tun = sess + .tcp_endpoint() + .listen() + .await?; + + println!("Listening on URL: {:?}", tun.url()); + + Ok(tun) +} ``` -telnet tcp.mydomain.com 12345 -``` -### Log Export Events + + + + + + + + + + -You can export logs of traffic to TCP endpoints with [ngrok's events -system](/obs/events/). The following events are published for log exporting: +## Learn more -| Event | When | -| ------------------------------------------------------------------------ | ------------------------------------------------------------------ | -| [tcp_connection_closed.v0](/obs/events/reference/#tcp-connection-closed) | Published when a TCP connection to any type of endpoint completes. | +- **URL Validation** — URLs are validated differently depending on their [binding](/universal-gateway/bindings). To learn more about valid URLs for TCP endpoints, see [the Endpoint URLs documentation](/docs/universal-gateway/what-are-endpoint-urls/#tcp). +- **Static URLs** — To create a public TCP endpoint with a static URL, you must first create a [TCP Address](/universal-gateway/tcp-addresses/). See [the documentation on static TCP URLs](/universal-gateway/tcp/static-tcp-urls/) for more information. +- **Authentication** — You can secure your TCP endpoints with the [IP Restriction](/traffic-policy/actions/restrict-ips/) and [Mutual TLS](/docs/guides/other-guides/how-to-terminate-traffic-with-ngrok-configs/#mutual-tls-example) Traffic Policy actions. There is a limited set of actions available to authenticate TCP traffic because the protocol is low-level. +- **Bring your own domain** — To use your own domain with TCP endpoints, see [the guide on the subject](/universal-gateway/bring-your-own-domain/#using-custom-domains-with-tcp-endpoints). +- **Traffic Observability** — [Traffic Inspector](/obs/traffic-inspection/) gives you a real-time view in the ngrok dashboard of the traffic flowing through your TLS endpoints. You can even [export traffic logs with the Traffic Events system](/docs/obs/events/reference/). ## Errors diff --git a/docs/universal-gateway/tls/index.mdx b/docs/universal-gateway/tls/index.mdx index 3d12c0f2dd..075ef5a9e6 100644 --- a/docs/universal-gateway/tls/index.mdx +++ b/docs/universal-gateway/tls/index.mdx @@ -169,7 +169,7 @@ TLS termination at the edge is not supported for: - **URL Validation** — URLs are validated differently depending on their [binding](/universal-gateway/bindings). To learn more about valid URLs for TLS endpoints, see [the Endpoint URLs documentation](/docs/universal-gateway/what-are-endpoint-urls/#https-tls). - **Domains** — Public TLS endpoints must match a domain on your account. See [the domains documentation](/universal-gateway/domains/what-are-domains/) for more information. - **Authentication** — You can secure your TLS endpoints with the [IP Restriction](/traffic-policy/actions/restrict-ips/) and [Mutual TLS](/docs/guides/other-guides/how-to-terminate-traffic-with-ngrok-configs/#mutual-tls-example) Traffic Policy actions. There is a limited set of actions available to authenticate TLS traffic because the protocol is low-level. -- **Bring your own domain** — To use your own domain with TLS endpoints, see [the guide on the subject](/universal-gateway/how-do-i-use-my-own-domain). +- **Bring your own domain** — To use your own domain with TLS endpoints, see [the guide on the subject](/universal-gateway/bring-your-own-domain). - **Wildcard Endpoints** — You can create TLS endpoints that receive traffic from all of the subdomains matching a given wildcard domain. See [the wildcard domain docs](/universal-gateway/wildcard-domains/) for more information. - **Traffic Policy** — Attach [Traffic Policy](/traffic-policy/) to endpoints to route, authenticate and transform the traffic through the endpoint. - **Agent Forwarding** — The [ngrok agent](/agent/) and [Agent SDKs](/agent-sdks/) forward traffic that your endpoints receive to upstream services. See [the agent forwarding documentation](/universal-gateway/agent-forwarding/) for more information. diff --git a/sidebars.js b/sidebars.js index aa82903835..219e8337ab 100644 --- a/sidebars.js +++ b/sidebars.js @@ -55,7 +55,7 @@ const sidebars = { id: "universal-gateway/domains/what-are-domains", }, items: [ - "universal-gateway/domains/how-do-i-use-my-own-domain", + "universal-gateway/domains/bring-your-own-domain", "universal-gateway/domains/what-are-managed-domains", "universal-gateway/wildcard-domains/index", "universal-gateway/wildcard-domains/wildcard-endpoints", @@ -169,11 +169,18 @@ const sidebars = { "universal-gateway/tls/tls-clients", ], }, + { + label: "Handling TCP Traffic", + type: "category", + link: { type: "doc", id: "universal-gateway/tcp/index" }, + items: ["universal-gateway/tcp/static-tcp-url"], + }, { label: "How Do I Forward Traffic?", type: "category", link: { type: "doc", id: "universal-gateway/agent-forwarding/index" }, items: [ + "universal-gateway/agent-forwarding/forward-original-connection-data", "universal-gateway/agent-forwarding/non-local-forwarding", "universal-gateway/agent-forwarding/serving-file-directories", ], From 46fb2871f827c31a99cd9facbd31d0314e86a631 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 10 Apr 2025 20:47:51 +0000 Subject: [PATCH 103/137] ci: apply automated fixes --- src/components/CodeBlockWithInfo/index.tsx | 2 +- src/components/LangSwitcher/LanguageData.tsx | 2 +- src/components/LangSwitcher/index.tsx | 4 +- src/components/LangSwitcher/utils.ts | 12 +- src/theme/DocItem/Content/index.tsx | 6 +- src/theme/Tabs/index.tsx | 20 +- static/scripts/fix-redirect.js | 237 ++++++++++++------ .../redirects/question-answer-redirects.js | 109 ++++++-- 8 files changed, 268 insertions(+), 124 deletions(-) diff --git a/src/components/CodeBlockWithInfo/index.tsx b/src/components/CodeBlockWithInfo/index.tsx index bc11f6c57f..c819be1813 100644 --- a/src/components/CodeBlockWithInfo/index.tsx +++ b/src/components/CodeBlockWithInfo/index.tsx @@ -11,8 +11,8 @@ import { fmtCode, } from "@ngrok/mantle/code-block"; import type { ReactNode } from "react"; -import type { LanguageInfo } from "../LangSwitcher/data"; import { LanguageData } from "../LangSwitcher/LanguageData"; +import type { LanguageInfo } from "../LangSwitcher/data"; type CodeBlockWithInfoProps = { content: string; diff --git a/src/components/LangSwitcher/LanguageData.tsx b/src/components/LangSwitcher/LanguageData.tsx index bce2cfdac2..7b2c144066 100644 --- a/src/components/LangSwitcher/LanguageData.tsx +++ b/src/components/LangSwitcher/LanguageData.tsx @@ -19,7 +19,7 @@ export function LanguageData({ data }: { data: LanguageInfo }) { return [prev, ", and ", curr]; } return [prev, ", ", curr]; - } + }, ); return ( diff --git a/src/components/LangSwitcher/index.tsx b/src/components/LangSwitcher/index.tsx index ebc8133179..4635883344 100644 --- a/src/components/LangSwitcher/index.tsx +++ b/src/components/LangSwitcher/index.tsx @@ -1,8 +1,8 @@ import BrowserOnly from "@docusaurus/BrowserOnly"; import { Button } from "@ngrok/mantle/button"; import { useContext } from "react"; -import { CodeBlockFallback } from "../code-block"; import { CodeBlockWithInfo } from "../CodeBlockWithInfo"; +import { CodeBlockFallback } from "../code-block"; import LangSwitcherContext, { type LangSwitcherContextType, } from "./LangSwitcherContext"; @@ -33,7 +33,7 @@ export function LangSwitcher({ children, className, ...props }: any) { // biome-ignore lint/suspicious/noExplicitAny: (child: any) => child.language === selectedLanguage || - languagesAreSynonyms(child.language, selectedLanguage) + languagesAreSynonyms(child.language, selectedLanguage), ) || codeBlocks[0]; return ( diff --git a/src/components/LangSwitcher/utils.ts b/src/components/LangSwitcher/utils.ts index 0be863ba82..c06dfb31fe 100644 --- a/src/components/LangSwitcher/utils.ts +++ b/src/components/LangSwitcher/utils.ts @@ -1,14 +1,14 @@ import { - parseLanguage, type Meta, type SupportedLanguage, + parseLanguage, } from "@ngrok/mantle/code-block"; -import { languageInfo, type LanguageInfo } from "./data"; import type { ReactElement, ReactNode } from "react"; +import { type LanguageInfo, languageInfo } from "./data"; export function getMetaDataWithQuotes( propertyName: string, - metastring: string + metastring: string, ) { const property = `${propertyName}=`; if (!metastring.includes(property)) return null; @@ -87,17 +87,17 @@ export const getCodeBlocks = (children: ReactElement[]): CodeBlockData[] => { export const getLanguageInfo = (language: string) => { return languageInfo.find( (item) => - item.name === language || item?.allNames?.some((alt) => alt === language) + item.name === language || item?.allNames?.some((alt) => alt === language), ); }; export function languagesAreSynonyms( languageToCheck: string, - selectedLanguage: string | null + selectedLanguage: string | null, ) { if (!selectedLanguage) return false; const synonymousLanguage = languageInfo.find((lang: LanguageInfo) => - lang.allNames?.includes(selectedLanguage) + lang.allNames?.includes(selectedLanguage), ); return ( synonymousLanguage?.name === languageToCheck || diff --git a/src/theme/DocItem/Content/index.tsx b/src/theme/DocItem/Content/index.tsx index e8fc77720e..eb9655ae60 100644 --- a/src/theme/DocItem/Content/index.tsx +++ b/src/theme/DocItem/Content/index.tsx @@ -9,7 +9,7 @@ import { } from "@site/src/components/LangSwitcher/utils"; import Content from "@theme-original/DocItem/Content"; import type ContentType from "@theme/DocItem/Content"; -import { useState, type ReactNode } from "react"; +import { type ReactNode, useState } from "react"; import TabListContext from "../../Tabs/TabListContext"; type Props = WrapperProps; @@ -19,10 +19,10 @@ export default function ContentWrapper(props: Props): ReactNode { const storageData = isBrowser ? getStorageLanguageAndTab() : null; const [selectedLanguage, setSelectedLanguage] = useState( - storageData?.defaultLanguage ?? null + storageData?.defaultLanguage ?? null, ); const [selectedTabItem, setSelectedTabItem] = useState( - storageData?.defaultLanguage ?? null + storageData?.defaultLanguage ?? null, ); const updateSelectedLanguage = (newLang: string | SupportedLanguage) => { if (isBrowser) { diff --git a/src/theme/Tabs/index.tsx b/src/theme/Tabs/index.tsx index bbd87a6cc5..9d327497a7 100644 --- a/src/theme/Tabs/index.tsx +++ b/src/theme/Tabs/index.tsx @@ -1,9 +1,9 @@ import { + type TabItemProps, + type TabValue, sanitizeTabsChildren, useScrollPositionBlocker, useTabs, - type TabItemProps, - type TabValue, } from "@docusaurus/theme-common/internal"; import useIsBrowser from "@docusaurus/useIsBrowser"; import { @@ -14,14 +14,14 @@ import { } from "@ngrok/mantle/tabs"; import type { Props } from "@theme/Tabs"; import clsx from "clsx"; -import { useContext, type ReactElement, type ReactNode } from "react"; -import styles from "./styles.module.css"; +import { type ReactElement, type ReactNode, useContext } from "react"; import TabListContext from "./TabListContext"; +import styles from "./styles.module.css"; function getValidTabToShow( tabValues: readonly TabValue[], selectedValue: string | undefined, - defaultTab: string | undefined + defaultTab: string | undefined, ) { if (selectedValue) { const selectedTab = tabValues.find((tab) => tab.label === selectedValue); @@ -34,10 +34,10 @@ function getValidTabToShow( function getValidDefaultTab( tabValues: readonly TabValue[], - localStorageTab: string | null | undefined + localStorageTab: string | null | undefined, ) { const defaultTab = tabValues.find( - (tab) => tab.label === localStorageTab || tab.value === localStorageTab + (tab) => tab.label === localStorageTab || tab.value === localStorageTab, ); if (defaultTab) { return defaultTab.label; @@ -63,7 +63,7 @@ function TabList({ event: | React.FocusEvent | React.MouseEvent - | React.KeyboardEvent + | React.KeyboardEvent, ) => { const newTab = event.currentTarget; const newTabIndex = tabRefs.indexOf(newTab); @@ -140,7 +140,7 @@ function TabList({ function TabContent({ children }: Props & ReturnType) { const childTabs = (Array.isArray(children) ? children : [children]).filter( - Boolean + Boolean, ) as ReactElement[]; return childTabs.map((tabItem, i) => { return ( @@ -161,7 +161,7 @@ function TabsComponent(props: Props): ReactNode { tabValues: tabs.tabValues .slice(0) .sort((a, b) => - a.label && b.label ? a.label.localeCompare(b.label) : -1 + a.label && b.label ? a.label.localeCompare(b.label) : -1, ), }; return ( diff --git a/static/scripts/fix-redirect.js b/static/scripts/fix-redirect.js index 5b3310b2b4..72ae9b5086 100644 --- a/static/scripts/fix-redirect.js +++ b/static/scripts/fix-redirect.js @@ -1,27 +1,27 @@ questionAnswerRedirects = require("./redirects/question-answer-redirects"); export const getNormalizedPaths = (from, path) => { - return { - normalizedFrom: from.endsWith('/') ? from.slice(0, -1) : from, - normalizedPath: path.endsWith('/') ? path.slice(0, -1) : path - } -} + return { + normalizedFrom: from.endsWith("/") ? from.slice(0, -1) : from, + normalizedPath: path.endsWith("/") ? path.slice(0, -1) : path, + }; +}; export const fromExact = (from) => (path) => { - const {normalizedFrom, normalizedPath} = getNormalizedPaths(from, path); - return [ normalizedFrom, normalizedPath === normalizedFrom ] // [xyz] -} + const { normalizedFrom, normalizedPath } = getNormalizedPaths(from, path); + return [normalizedFrom, normalizedPath === normalizedFrom]; // [xyz] +}; export const fromIncludes = (from) => (path) => { - // Normalize both paths by removing trailing slashes if present - - const {normalizedFrom, normalizedPath} = getNormalizedPaths(from, path); + // Normalize both paths by removing trailing slashes if present + + const { normalizedFrom, normalizedPath } = getNormalizedPaths(from, path); - return [normalizedFrom, normalizedPath.includes(normalizedFrom)]; - }; - -export const toExact = (to) => () => to // x -> y -export const toReplace = (to) => (path, from) => path.replace(from, to) // abc/x -> xyz/x + return [normalizedFrom, normalizedPath.includes(normalizedFrom)]; +}; + +export const toExact = (to) => () => to; // x -> y +export const toReplace = (to) => (path, from) => path.replace(from, to); // abc/x -> xyz/x // List of redirects // String values are treated as exacts by default. @@ -713,64 +713,151 @@ const redirects = [ "/docs/traffic-policy/getting-started/agent-endpoints/cli", ], - // JAN 2025 - [ fromIncludes('/docs/tls/tls-termination/'), '/docs/traffic-policy/actions/terminate-tls/' ], - [ fromIncludes('/docs/traffic-policy/templates/'), '/docs/traffic-policy/examples/a-b-tests/' ], - - // IA Restructure redirects - [ fromIncludes('/docs/tls/termination/agent-tls-termination/'), '/docs/agent/agent-tls-termination/'], - [ fromIncludes('/docs/concepts/'), '/docs/'], - // HTTP Redirects - [ fromIncludes('/docs/http/basic-auth'), '/docs/traffic-policy/actions/basic-auth/'], - [ fromIncludes('/docs/http/circuit-breaker'), '/docs/traffic-policy/actions/circuit-breaker/'], - [ fromIncludes('/docs/http/compression/'), '/docs/traffic-policy/actions/compress-response/'], - [ fromIncludes('/docs/http/ip-restrictions/'), '/docs/traffic-policy/actions/restrict-ips/'], - [ fromIncludes('/docs/http/mutual-tls/'), '/docs/traffic-policy/actions/terminate-tls/#enabling-mutual-tls'], - [ fromIncludes('/docs/http/oauth/'), '/docs/traffic-policy/actions/oauth'], - [ fromIncludes('/docs/http/openid-connect/'), '/docs/traffic-policy/actions/oidc'], - [ fromIncludes('/docs/http/request-headers/'), '/docs/traffic-policy/actions/add-headers'], - [ fromIncludes('/docs/http/response-headers/'), '/docs/traffic-policy/actions/custom-response'], - [ fromIncludes('/docs/http/saml/'), '/docs/traffic-policy/actions/saml'], - // Network Edge - [ fromIncludes('/docs/network-edge/edges'), '/docs/universal-gateway/edges'], - [ fromIncludes('/docs/network-edge/cloud-endpoints'), '/docs/universal-gateway/cloud-endpoints'], - [ fromIncludes('/docs/network-edge/domains-and-tcp-addresses'), '/docs/universal-gateway/domains'], - [ fromIncludes('/docs/network-edge/internal-endpoints'), '/docs/universal-gateway/internal-endpoints'], - [ fromIncludes('/docs/network-edge/tls-certificates'), '/docs/universal-gateway/tls-certificates'], - [ fromIncludes('/docs/network-edge/app-users/'), '/docs/traffic-policy/identities/'], - [ fromIncludes('/docs/network-edge/gslb/'), '/docs/universal-gateway/global-load-balancer/'], - [ fromIncludes('/docs/network-edge/'), '/docs/universal-gateway/edges'], - // obs - [ fromIncludes('/docs/obs/reference'), '/docs/obs/events/reference'], - // tcp - [ fromIncludes('/docs/tcp/ip-restrictions'), '/docs/traffic-policy/actions/restrict-ips/'], - [ fromIncludes('/docs/tcp/traffic-policy/actions/deny/'), '/docs/traffic-policy/actions/deny/'], - [ fromIncludes('/docs/tcp/traffic-policy/actions/log/'), '/docs/traffic-policy/actions/log'], - [ fromIncludes('/docs/tcp/traffic-policy/actions/restrict-ips/'), '/docs/traffic-policy/actions/restrict-ips'], - [ fromIncludes('/docs/tcp/traffic-policy/actions/'), '/docs/traffic-policy/actions/'], - [ fromExact('/docs/tcp/traffic-policy/'), '/docs/traffic-policy/' ], - // tls - [ fromExact('/docs/tls/ip-restrictions/'), '/docs/traffic-policy/actions/restrict-ips'], - [ fromExact('/docs/tls/mutual-tls/'), '/docs/traffic-policy/actions/terminate-tls/#enabling-mutual-tls'], - [ fromExact('/docs/tls/termination/'), '/docs/traffic-policy/actions/terminate-tls/'], - // Universal Gateway - [ fromExact('/docs/http/'), '/docs/universal-gateway/http/'], - [ fromExact('/docs/tcp/'), '/docs/universal-gateway/tcp/'], - [ fromExact('/docs/tls/'), '/docs/universal-gateway/tls/'], - ...questionAnswerRedirects, - // Kubernetes Operator Revamp - [ fromExact('/docs/k8s/advanced-deployments/'), '/docs/k8s/installation/install/'], - [ fromExact('/docs/k8s/deployment-guide/'), '/docs/k8s/installation/install/'], - [ fromExact('/docs/k8s/developer-guide/'), '/docs/k8s/installation/install/'], - [ fromExact('/docs/k8s/developer-guide/architecture/'), '/docs/k8s/installation/architecture/'], - [ fromExact('/docs/k8s/developer-guide/releasing/'), '/docs/k8s/releasing/'], - [ fromExact('/docs/k8s/developer-guide/internal-crds/'), '/docs/k8s/crds/'], - [ fromExact('/docs/k8s/getting-started-gwapi/'), '/docs/k8s/guides/using-gwapi'], - [ fromExact('/docs/k8s/getting-started-kic/'), '/docs/k8s/guides/using-ingresses/'], - [ fromExact('/docs/k8s/custom-domain/'), '/docs/k8s/guides/custom-domain/'], - [ fromExact('/docs/k8s/user-guide/'), '/docs/k8s/'], - [ fromExact('/docs/k8s/with-edges/'), '/docs/k8s/guides/using-ingresses/'], -] + // JAN 2025 + [ + fromIncludes("/docs/tls/tls-termination/"), + "/docs/traffic-policy/actions/terminate-tls/", + ], + [ + fromIncludes("/docs/traffic-policy/templates/"), + "/docs/traffic-policy/examples/a-b-tests/", + ], + + // IA Restructure redirects + [ + fromIncludes("/docs/tls/termination/agent-tls-termination/"), + "/docs/agent/agent-tls-termination/", + ], + [fromIncludes("/docs/concepts/"), "/docs/"], + // HTTP Redirects + [ + fromIncludes("/docs/http/basic-auth"), + "/docs/traffic-policy/actions/basic-auth/", + ], + [ + fromIncludes("/docs/http/circuit-breaker"), + "/docs/traffic-policy/actions/circuit-breaker/", + ], + [ + fromIncludes("/docs/http/compression/"), + "/docs/traffic-policy/actions/compress-response/", + ], + [ + fromIncludes("/docs/http/ip-restrictions/"), + "/docs/traffic-policy/actions/restrict-ips/", + ], + [ + fromIncludes("/docs/http/mutual-tls/"), + "/docs/traffic-policy/actions/terminate-tls/#enabling-mutual-tls", + ], + [fromIncludes("/docs/http/oauth/"), "/docs/traffic-policy/actions/oauth"], + [ + fromIncludes("/docs/http/openid-connect/"), + "/docs/traffic-policy/actions/oidc", + ], + [ + fromIncludes("/docs/http/request-headers/"), + "/docs/traffic-policy/actions/add-headers", + ], + [ + fromIncludes("/docs/http/response-headers/"), + "/docs/traffic-policy/actions/custom-response", + ], + [fromIncludes("/docs/http/saml/"), "/docs/traffic-policy/actions/saml"], + // Network Edge + [fromIncludes("/docs/network-edge/edges"), "/docs/universal-gateway/edges"], + [ + fromIncludes("/docs/network-edge/cloud-endpoints"), + "/docs/universal-gateway/cloud-endpoints", + ], + [ + fromIncludes("/docs/network-edge/domains-and-tcp-addresses"), + "/docs/universal-gateway/domains", + ], + [ + fromIncludes("/docs/network-edge/internal-endpoints"), + "/docs/universal-gateway/internal-endpoints", + ], + [ + fromIncludes("/docs/network-edge/tls-certificates"), + "/docs/universal-gateway/tls-certificates", + ], + [ + fromIncludes("/docs/network-edge/app-users/"), + "/docs/traffic-policy/identities/", + ], + [ + fromIncludes("/docs/network-edge/gslb/"), + "/docs/universal-gateway/global-load-balancer/", + ], + [fromIncludes("/docs/network-edge/"), "/docs/universal-gateway/edges"], + // obs + [fromIncludes("/docs/obs/reference"), "/docs/obs/events/reference"], + // tcp + [ + fromIncludes("/docs/tcp/ip-restrictions"), + "/docs/traffic-policy/actions/restrict-ips/", + ], + [ + fromIncludes("/docs/tcp/traffic-policy/actions/deny/"), + "/docs/traffic-policy/actions/deny/", + ], + [ + fromIncludes("/docs/tcp/traffic-policy/actions/log/"), + "/docs/traffic-policy/actions/log", + ], + [ + fromIncludes("/docs/tcp/traffic-policy/actions/restrict-ips/"), + "/docs/traffic-policy/actions/restrict-ips", + ], + [ + fromIncludes("/docs/tcp/traffic-policy/actions/"), + "/docs/traffic-policy/actions/", + ], + [fromExact("/docs/tcp/traffic-policy/"), "/docs/traffic-policy/"], + // tls + [ + fromExact("/docs/tls/ip-restrictions/"), + "/docs/traffic-policy/actions/restrict-ips", + ], + [ + fromExact("/docs/tls/mutual-tls/"), + "/docs/traffic-policy/actions/terminate-tls/#enabling-mutual-tls", + ], + [ + fromExact("/docs/tls/termination/"), + "/docs/traffic-policy/actions/terminate-tls/", + ], + // Universal Gateway + [fromExact("/docs/http/"), "/docs/universal-gateway/http/"], + [fromExact("/docs/tcp/"), "/docs/universal-gateway/tcp/"], + [fromExact("/docs/tls/"), "/docs/universal-gateway/tls/"], + ...questionAnswerRedirects, + // Kubernetes Operator Revamp + [ + fromExact("/docs/k8s/advanced-deployments/"), + "/docs/k8s/installation/install/", + ], + [fromExact("/docs/k8s/deployment-guide/"), "/docs/k8s/installation/install/"], + [fromExact("/docs/k8s/developer-guide/"), "/docs/k8s/installation/install/"], + [ + fromExact("/docs/k8s/developer-guide/architecture/"), + "/docs/k8s/installation/architecture/", + ], + [fromExact("/docs/k8s/developer-guide/releasing/"), "/docs/k8s/releasing/"], + [fromExact("/docs/k8s/developer-guide/internal-crds/"), "/docs/k8s/crds/"], + [ + fromExact("/docs/k8s/getting-started-gwapi/"), + "/docs/k8s/guides/using-gwapi", + ], + [ + fromExact("/docs/k8s/getting-started-kic/"), + "/docs/k8s/guides/using-ingresses/", + ], + [fromExact("/docs/k8s/custom-domain/"), "/docs/k8s/guides/custom-domain/"], + [fromExact("/docs/k8s/user-guide/"), "/docs/k8s/"], + [fromExact("/docs/k8s/with-edges/"), "/docs/k8s/guides/using-ingresses/"], +]; // get current href from window const currentPath = window.location.pathname; @@ -807,6 +894,6 @@ if (newPath !== currentPath && newPath !== window.location.pathname) { window.location.href = newPath; } else { console.error( - 'ignoring redirect from ${window.location.href} to ${newPath}; looks loopy', + "ignoring redirect from ${window.location.href} to ${newPath}; looks loopy", ); } diff --git a/static/scripts/redirects/question-answer-redirects.js b/static/scripts/redirects/question-answer-redirects.js index 994977beff..7246ab76f0 100644 --- a/static/scripts/redirects/question-answer-redirects.js +++ b/static/scripts/redirects/question-answer-redirects.js @@ -1,32 +1,89 @@ -import { fromExact } from "../fix-redirect" +import { fromExact } from "../fix-redirect"; export default [ /** * Universal Gateway > Concepts */ - // Domains - [ fromExact('/docs/universal-gateway/domains/'), '/docs/universal-gateway/domains/what-are-domains/' ], - // hashes - [ fromExact('/docs/universal-gateway/domains/#branded-domains'), '/docs/universal-gateway/domains/how-do-i-use-my-own-domain/' ], - [ fromExact('/docs/universal-gateway/domains/#global-load-balancer'), '/docs/universal-gateway/global-load-balancer/' ], - [ fromExact('/docs/universal-gateway/domains/#public-endpoints'), '/docs/universal-gateway/public-endpoints/' ], - [ fromExact('/docs/universal-gateway/domains/#ngrok-managed-domains'), '/docs/universal-gateway/domains/what-are-managed-domains/' ], - [ fromExact('/docs/universal-gateway/domains/#hsts-preload'), '/docs/universal-gateway/domains/what-are-managed-domains/#hsts-preload' ], - [ fromExact('/docs/universal-gateway/domains/#public-suffix-list'), '/docs/universal-gateway/domains/what-are-managed-domains/#public-suffix-list' ], - - // TCP Addresses - [ fromExact('/docs/universal-gateway/tcp-addresses/'), '/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses/' ], - // hashes - [ fromExact('/docs/universal-gateway/tcp-addresses/#public-endpoint-creation'), '/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses/' ], - [ fromExact('/docs/universal-gateway/tcp-addresses/#address-assignment'), '/docs/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned/' ], - [ fromExact('/docs/universal-gateway/tcp-addresses/#global-load-balancer/'), '/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses/#tcp-address-load-balancing' ], + // Domains + [ + fromExact("/docs/universal-gateway/domains/"), + "/docs/universal-gateway/domains/what-are-domains/", + ], + // hashes + [ + fromExact("/docs/universal-gateway/domains/#branded-domains"), + "/docs/universal-gateway/domains/how-do-i-use-my-own-domain/", + ], + [ + fromExact("/docs/universal-gateway/domains/#global-load-balancer"), + "/docs/universal-gateway/global-load-balancer/", + ], + [ + fromExact("/docs/universal-gateway/domains/#public-endpoints"), + "/docs/universal-gateway/public-endpoints/", + ], + [ + fromExact("/docs/universal-gateway/domains/#ngrok-managed-domains"), + "/docs/universal-gateway/domains/what-are-managed-domains/", + ], + [ + fromExact("/docs/universal-gateway/domains/#hsts-preload"), + "/docs/universal-gateway/domains/what-are-managed-domains/#hsts-preload", + ], + [ + fromExact("/docs/universal-gateway/domains/#public-suffix-list"), + "/docs/universal-gateway/domains/what-are-managed-domains/#public-suffix-list", + ], - //TLS Certificates - [fromExact('/docs/universal-gateway/tls-certificates/'), '/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls' ], - // hashes - [fromExact('/docs/universal-gateway/tls-certificates/#automated'), '/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management' ], - [fromExact('/docs/universal-gateway/tls-certificates/#certificate-selection'), '/docs/universal-gateway/tls-certificates/how-are-certificates-selected' ], - [fromExact('/docs/universal-gateway/tls-certificates/#certificate-provisioning'), '/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls#how-certificates-work' ], - [fromExact('/docs/universal-gateway/tls-certificates/#certificate-bundles'), '/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle/' ], - [fromExact('/docs/universal-gateway/tls-certificates/#private-keys'), '/docs/universal-gateway/tls-certificates/what-are-private-tls-keys/' ], -] + // TCP Addresses + [ + fromExact("/docs/universal-gateway/tcp-addresses/"), + "/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses/", + ], + // hashes + [ + fromExact( + "/docs/universal-gateway/tcp-addresses/#public-endpoint-creation", + ), + "/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses/", + ], + [ + fromExact("/docs/universal-gateway/tcp-addresses/#address-assignment"), + "/docs/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned/", + ], + [ + fromExact("/docs/universal-gateway/tcp-addresses/#global-load-balancer/"), + "/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses/#tcp-address-load-balancing", + ], + + //TLS Certificates + [ + fromExact("/docs/universal-gateway/tls-certificates/"), + "/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls", + ], + // hashes + [ + fromExact("/docs/universal-gateway/tls-certificates/#automated"), + "/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management", + ], + [ + fromExact( + "/docs/universal-gateway/tls-certificates/#certificate-selection", + ), + "/docs/universal-gateway/tls-certificates/how-are-certificates-selected", + ], + [ + fromExact( + "/docs/universal-gateway/tls-certificates/#certificate-provisioning", + ), + "/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls#how-certificates-work", + ], + [ + fromExact("/docs/universal-gateway/tls-certificates/#certificate-bundles"), + "/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle/", + ], + [ + fromExact("/docs/universal-gateway/tls-certificates/#private-keys"), + "/docs/universal-gateway/tls-certificates/what-are-private-tls-keys/", + ], +]; From b761fb72c808058e1b3e60cce41df313f593f903 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 15 Apr 2025 09:40:46 -0400 Subject: [PATCH 104/137] Cleaned up wildcard endpoints page --- docs/getting-started/go.mdx | 2 +- docs/getting-started/index.mdx | 2 +- docs/getting-started/rust.mdx | 2 +- .../forward-original-connection-data.mdx | 5 +- docs/universal-gateway/tcp/static-tcp-url.mdx | 4 + .../wildcard-domains/wildcard-endpoints.mdx | 120 +++++++++++++----- 6 files changed, 96 insertions(+), 39 deletions(-) diff --git a/docs/getting-started/go.mdx b/docs/getting-started/go.mdx index fb18544462..7b2dd9968d 100644 --- a/docs/getting-started/go.mdx +++ b/docs/getting-started/go.mdx @@ -1,6 +1,6 @@ --- title: Go -pagination_next: universal-gateway/http +pagination_next: universal-gateway/http-s/index --- # Quickstart: ngrok-go diff --git a/docs/getting-started/index.mdx b/docs/getting-started/index.mdx index 3ad6d5313b..1959df4d10 100644 --- a/docs/getting-started/index.mdx +++ b/docs/getting-started/index.mdx @@ -1,6 +1,6 @@ --- title: Quickstart -pagination_next: universal-gateway/http +pagination_next: universal-gateway/http-s/index --- import TabItem from "@theme/TabItem"; diff --git a/docs/getting-started/rust.mdx b/docs/getting-started/rust.mdx index 1c8195f514..8ebfd32396 100644 --- a/docs/getting-started/rust.mdx +++ b/docs/getting-started/rust.mdx @@ -1,6 +1,6 @@ --- title: Rust -pagination_next: universal-gateway/http +pagination_next: universal-gateway/http-s/index --- # Quickstart: ngrok-rust diff --git a/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx b/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx index 5495fd6614..3a75c22fe7 100644 --- a/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx +++ b/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx @@ -8,12 +8,9 @@ import Tabs from "@theme/Tabs"; import { LangSwitcher } from "@site/src/components/LangSwitcher"; import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitcher"; -import ProxyProtoAgentCliExample from "/examples/agent-cli/tcp-proxyproto.mdx"; +import ProxyProtoAgentConfigExample from "/examples/agent-config/tcp-proxyproto.mdx"; import ProxyProtoKubernetesExample from "/examples/k8s/tcp-proxyproto.mdx"; -import ProxyProtoAgentConfigExampleTLS from "/examples/agent-config/tls-proxyproto.mdx"; -import ProxyProtoKubernetesExampleTLS from "/examples/k8s/tls-proxyproto.mdx"; - When you forward traffic to an upstream TCP service, becuase traffic is coming from the ngrok agent, it won't know the client's original IP address. You can add the [PROXY diff --git a/docs/universal-gateway/tcp/static-tcp-url.mdx b/docs/universal-gateway/tcp/static-tcp-url.mdx index 015e07dc2a..28e9e053fc 100644 --- a/docs/universal-gateway/tcp/static-tcp-url.mdx +++ b/docs/universal-gateway/tcp/static-tcp-url.mdx @@ -3,6 +3,10 @@ title: Static URLs for TCP Endpoints description: Learn how to create TCP endpoints with URLs. --- +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; +import { LangSwitcher } from "@site/src/components/LangSwitcher"; +import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitcher"; import FixedAgentCliExample from "/examples/agent-cli/tcp-fixed.mdx"; import FixedAgentConfigExample from "/examples/agent-config/tcp-fixed.mdx"; import FixedGoSdkExample from "/examples/go-sdk/tcp-fixed.mdx"; diff --git a/docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx b/docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx index 57804eed7c..06fad18073 100644 --- a/docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx +++ b/docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx @@ -4,14 +4,9 @@ title: How Do I Use Wildcard Endpoints? import TabItem from "@theme/TabItem"; import Tabs from "@theme/Tabs"; -import WildcardAgentCliExample from "/examples/agent-cli/http-wildcard-domain.mdx"; import WildcardAgentConfigExample from "/examples/agent-config/http-wildcard-domain.mdx"; -import WildcardGoSdkExample from "/examples/go-sdk/http-wildcard-domain.mdx"; -import WildcardJavascriptSdkExample from "/examples/javascript-sdk/http-wildcard-domain.mdx"; import WildcardKubernetesExample from "/examples/k8s/http-wildcard-domain.mdx"; -import WildcardPythonSdkExample from "/examples/python-sdk/http-wildcard-domain.mdx"; -import WildcardRustSdkExample from "/examples/rust-sdk/http-wildcard-domain.mdx"; -import WildcardSshExample from "/examples/ssh/http-wildcard-domain.mdx"; +import { LangSwitcher } from "@site/src/components/LangSwitcher"; You can create an endpoint which will receive traffic for all of the subdomains matching a given wildcard domain like `*.example.com`. You must create a [wildcard domain](/universal-gateway/domains/what-are-domains/#wildcard-domains) to create a public wildcard endpoint. @@ -28,38 +23,99 @@ will receive traffic for `https://foo.example.com` and online, a connection to `https://app.example.com` will not be routed to the wildcard endpoint. - - - - - - - - - - - - - - - - - - - - - - - - - +## Getting started + +The following example creates a wildcard endpoint that forwards traffic to port `80`. + + + + +```bash +ngrok http 80 --url "https://*.example.com" +``` + +```sh tabName="SSH" +ssh -R '*.example.com:443:localhost:80' v2@connect.ngrok-agent.com http +``` + +```go +import ( + "context" + "net" + + "golang.ngrok.com/ngrok" + "golang.ngrok.com/ngrok/config" +) + +func ngrokListener(ctx context.Context) (net.Listener, error) { + return ngrok.Listen(ctx, + config.HTTPEndpoint( + config.WithDomain("*.example.com"), + ), + ngrok.WithAuthtokenFromEnv(), + ) +} +``` + +```jsx +const ngrok = require("@ngrok/ngrok"); + +(async function () { + const listener = await ngrok.forward({ + addr: 8080, + authtoken_from_env: true, + domain: "*.example.com", + }); + + console.log(`Ingress established at: ${listener.url()}`); +})(); +``` + +```python +import ngrok + +listener = ngrok.forward("localhost:8080", authtoken_from_env=True, + domain="*.example.com") + +print(f"Ingress established at: {listener.url()}"); +``` + +```rust +use ngrok::prelude::*; + +async fn listen_ngrok() -> anyhow::Result { + let sess = ngrok::Session::builder() + .authtoken_from_env() + .connect() + .await?; + + let tun = sess + .http_endpoint() + .domain("*.example.com") + .listen() + .await?; + + println!("Listening on URL: {:?}", tun.url()); + + Ok(tun) +} +``` + + + + + + + + + ## Wildcard endpoint pooling Wildcard endpoints do not pool with non-wildcard URLs. For example, if you have two endpoints online, `https://foo.example.com` and `https://*.example.com`, they will not pool together and traffic to `https://foo.example.com` will not be load balanced. -### How do I use multiple endpoints with wildcard subdomains? +## Using multiple endpoints with wildcard subdomains With the [Agent CLI](/agent/cli), you can create separate public endpoints for subdomains of a wildcard domain no matter where the upstream services are running. See [the Domains docs](/docs/universal-gateway/domains/#wildcard-domains) for more information. From 10f45c3d45485be5f96d3359866e80af2317abef Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 15 Apr 2025 09:42:09 -0400 Subject: [PATCH 105/137] Fix default tabs for code blocks --- .../forward-original-connection-data.mdx | 8 ++++---- docs/universal-gateway/agent-forwarding/index.mdx | 8 ++++---- .../agent-forwarding/non-local-forwarding.mdx | 8 ++++---- .../agent-forwarding/serving-file-directories.mdx | 12 ++++++------ docs/universal-gateway/global-load-balancer.mdx | 2 +- docs/universal-gateway/http-s/index.mdx | 2 +- docs/universal-gateway/tcp/index.mdx | 2 +- docs/universal-gateway/tcp/static-tcp-url.mdx | 6 +++--- docs/universal-gateway/tls/index.mdx | 4 ++-- .../tls/tls-termination/termination-location.mdx | 12 ++++++------ .../wildcard-domains/wildcard-endpoints.mdx | 4 ++-- 11 files changed, 34 insertions(+), 34 deletions(-) diff --git a/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx b/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx index 3a75c22fe7..519740c21b 100644 --- a/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx +++ b/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx @@ -28,7 +28,7 @@ PROXY protocol is not support for: SSH ## TCP proxy protocol - + ```bash ngrok tcp 22 --upstream-proxy-protocol=2 @@ -101,7 +101,7 @@ const ngrok = require("@ngrok/ngrok"); - + @@ -117,7 +117,7 @@ on connection to your upstream service. This sends connection information like the original client IP address to your upstream service. - + ```bash ngrok tls 443 --upstream-proxy-protocol=2 @@ -190,7 +190,7 @@ async fn listen_ngrok() -> anyhow::Result { - + diff --git a/docs/universal-gateway/agent-forwarding/index.mdx b/docs/universal-gateway/agent-forwarding/index.mdx index 26fde07d2c..cdc243c82c 100644 --- a/docs/universal-gateway/agent-forwarding/index.mdx +++ b/docs/universal-gateway/agent-forwarding/index.mdx @@ -39,7 +39,7 @@ Forwarding to an upstream HTTPS service is not supported via SSH. ::: - + ```bash ngrok http https://localhost:8443 @@ -117,7 +117,7 @@ async fn forward_ngrok() -> Result, Error> { - + @@ -159,7 +159,7 @@ re-encrypt the connection from the agent to your upstream service. The ngrok agent supports this behavior by using the non-standard `tls://` scheme syntax. - + ```bash @@ -204,7 +204,7 @@ const ngrok = require("@ngrok/ngrok"); - + diff --git a/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx b/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx index 144a39828a..9c00d1b0e0 100644 --- a/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx +++ b/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx @@ -20,7 +20,7 @@ Aside from ports on your localhost, ngrok Agents can [forward traffic](/universa The following example demonstrates how to forward traffic to an HTTP server running on your network at `192.168.1.2:80`: - + ```bash ngrok http 192.168.1.2:80 @@ -96,7 +96,7 @@ The following example demonstrates how to forward traffic to an HTTP server runn - + @@ -111,7 +111,7 @@ The following example demonstrates how to forward traffic to an HTTP server runn The following example demonstrates how to forward traffic to a Postgres server running on your network at `192.168.1.2:5432`: - + ```bash @@ -190,7 +190,7 @@ async fn forward_ngrok() -> Result, Error> { - + diff --git a/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx b/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx index 7a239b0bc4..81b5f30ad2 100644 --- a/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx +++ b/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx @@ -25,7 +25,7 @@ Serving directory files is not supported with: #### Serve files in `/var/log` - + ```bash ngrok http "file:///var/log" @@ -53,7 +53,7 @@ Serving directory files is not supported with: - + ```yaml version: 3 endpoints: @@ -70,7 +70,7 @@ endpoints: #### Serve files on Windows - + ```bash @@ -98,7 +98,7 @@ func serveFiles(ctx context.Context) error { - + ```yaml version: 3 @@ -118,7 +118,7 @@ endpoints: #### Serve files in your current working directory - + ```bash ngrok http file://`pwd` @@ -144,7 +144,7 @@ func serveFiles(ctx context.Context) error { - + Serving the current working directory is not supported via the agent configuration file. diff --git a/docs/universal-gateway/global-load-balancer.mdx b/docs/universal-gateway/global-load-balancer.mdx index a97883c068..0764589377 100644 --- a/docs/universal-gateway/global-load-balancer.mdx +++ b/docs/universal-gateway/global-load-balancer.mdx @@ -184,7 +184,7 @@ do so with the following configuration: - + diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx index 122625cba3..24d47d611f 100644 --- a/docs/universal-gateway/http-s/index.mdx +++ b/docs/universal-gateway/http-s/index.mdx @@ -16,7 +16,7 @@ You can create HTTP/S endpoints to serve web services like REST APIs, web applic ## Quickstart - + [Agent Endpoints](/agent/) are the easiest way to create an HTTP/S endpoint. You can start agent endpoints on your local machine. The endpoint wil llive for the lifetime of the process and forward traffic to a port or URL of your choosing. The following example creates the endpoint `https://example.ngrok.app` and forwards its traffic to a local port. diff --git a/docs/universal-gateway/tcp/index.mdx b/docs/universal-gateway/tcp/index.mdx index b44917dc75..d60bd7d82f 100644 --- a/docs/universal-gateway/tcp/index.mdx +++ b/docs/universal-gateway/tcp/index.mdx @@ -108,7 +108,7 @@ async fn listen_ngrok() -> anyhow::Result { - + diff --git a/docs/universal-gateway/tcp/static-tcp-url.mdx b/docs/universal-gateway/tcp/static-tcp-url.mdx index 28e9e053fc..7fc75729bf 100644 --- a/docs/universal-gateway/tcp/static-tcp-url.mdx +++ b/docs/universal-gateway/tcp/static-tcp-url.mdx @@ -28,11 +28,11 @@ They are not needed for TCP endpoints on other bindings, like `internal` or After you have created a TCP Address, specify the address (e.g. `1.tcp.eu.ngrok.io:12345`) in the URL when you create the endpoint. - - + + - + diff --git a/docs/universal-gateway/tls/index.mdx b/docs/universal-gateway/tls/index.mdx index 075ef5a9e6..2b593b2e15 100644 --- a/docs/universal-gateway/tls/index.mdx +++ b/docs/universal-gateway/tls/index.mdx @@ -28,7 +28,7 @@ Endpoint](/universal-gateway/http/). ## Quickstart - + ```bash @@ -109,7 +109,7 @@ on_tcp_connect: - + ```yaml version: 3 diff --git a/docs/universal-gateway/tls/tls-termination/termination-location.mdx b/docs/universal-gateway/tls/tls-termination/termination-location.mdx index 67f563a71d..63a2d6335a 100644 --- a/docs/universal-gateway/tls/tls-termination/termination-location.mdx +++ b/docs/universal-gateway/tls/tls-termination/termination-location.mdx @@ -28,7 +28,7 @@ This is the easiest and most common. All HTTPS endpoints terminate TLS at ngrok' You can get started with the following example. - + Use a Traffic Policy file configured like the following: @@ -109,7 +109,7 @@ print(f"Ingress established at: {listener.url()}"); - + @@ -132,7 +132,7 @@ You can terminate TLS at your ngrok agent. Doing so prevents TLS from being term You can get started with the following example. - + ```bash ngrok tls 80 \ --terminate-at agent \ @@ -142,7 +142,7 @@ ngrok tls 80 \ ``` - + @@ -168,7 +168,7 @@ You can handle TLS termination at your upstream services. This is another form o You can get started with the following example. - + ```bash ngrok tls 443 \ @@ -247,7 +247,7 @@ async fn listen_ngrok() -> anyhow::Result { - + diff --git a/docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx b/docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx index 06fad18073..6834f1d18d 100644 --- a/docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx +++ b/docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx @@ -28,7 +28,7 @@ will receive traffic for `https://foo.example.com` and The following example creates a wildcard endpoint that forwards traffic to port `80`. - + ```bash ngrok http 80 --url "https://*.example.com" @@ -103,7 +103,7 @@ async fn listen_ngrok() -> anyhow::Result { - + From 12cdc942954e94f36fbc63c21d2fba3a5e1a6faa Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 15 Apr 2025 09:47:00 -0400 Subject: [PATCH 106/137] Fix static URL page code snippets --- docs/universal-gateway/tcp/static-tcp-url.mdx | 99 ++++++++++++++----- 1 file changed, 77 insertions(+), 22 deletions(-) diff --git a/docs/universal-gateway/tcp/static-tcp-url.mdx b/docs/universal-gateway/tcp/static-tcp-url.mdx index 7fc75729bf..ccd98831ad 100644 --- a/docs/universal-gateway/tcp/static-tcp-url.mdx +++ b/docs/universal-gateway/tcp/static-tcp-url.mdx @@ -7,14 +7,8 @@ import TabItem from "@theme/TabItem"; import Tabs from "@theme/Tabs"; import { LangSwitcher } from "@site/src/components/LangSwitcher"; import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitcher"; -import FixedAgentCliExample from "/examples/agent-cli/tcp-fixed.mdx"; import FixedAgentConfigExample from "/examples/agent-config/tcp-fixed.mdx"; -import FixedGoSdkExample from "/examples/go-sdk/tcp-fixed.mdx"; -import FixedJavascriptSdkExample from "/examples/javascript-sdk/tcp-fixed.mdx"; import FixedKubernetesExample from "/examples/k8s/tcp-fixed.mdx"; -import FixedPythonSdkExample from "/examples/python-sdk/tcp-fixed.mdx"; -import FixedRustSdkExample from "/examples/rust-sdk/tcp-fixed.mdx"; -import FixedSshExample from "/examples/ssh/tcp-fixed.mdx"; If you would like a public TCP endpoint to have a static URL, you must first create a [TCP Address](/universal-gateway/tcp-addresses/). When you create a TCP @@ -30,26 +24,87 @@ After you have created a TCP Address, specify the address (e.g. - + + +```bash +ngrok tcp 3389 --url tcp://1.tcp.eu.ngrok.io:12345 +``` + +```sh tabName="SSH" +ssh -R 1.tcp.eu.ngrok.io:12345:localhost:3389 connect.eu.ngrok-agent.com tcp +``` + +```go +import ( + "context" + "net" + + "golang.ngrok.com/ngrok" + "golang.ngrok.com/ngrok/config" +) + +func ngrokListener(ctx context.Context) (net.Listener, error) { + return ngrok.Listen(ctx, + config.TCPEndpoint( + config.WithRemoteAddr("1.tcp.ngrok.io:12345"), + ), + ngrok.WithRegion("eu"), + ngrok.WithAuthtokenFromEnv(), + ) +} +``` + +```jsx +const ngrok = require("@ngrok/ngrok"); + +(async function () { + const listener = await ngrok.forward({ + addr: 8080, + authtoken_from_env: true, + proto: "tcp", + remote_addr: "1.tcp.eu.ngrok.io:12345", + }); + + console.log(`Ingress established at: ${listener.url()}`); +})(); +``` + +```python +import ngrok + +listener = ngrok.forward("localhost:8080", authtoken_from_env=True, + proto="tcp", + remote_addr="1.tcp.eu.ngrok.io:12345") + +print(f"Ingress established at: {listener.url()}"); +``` + +```rust +use ngrok::prelude::*; + +async fn listen_ngrok() -> anyhow::Result { + let sess = ngrok::Session::builder() + .authtoken_from_env() + .connect() + .await?; + + let tun = sess + .tcp_endpoint() + .remote_addr("1.tcp.eu.ngrok.io:12345") + .listen() + .await?; + + println!("Listening on URL: {:?}", tun.url()); + + Ok(tun) +} +``` + + - - - - - - - - - - - - - - - From 1230088ab51f2765e803242709624313f6832fa2 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 15 Apr 2025 13:06:12 -0400 Subject: [PATCH 107/137] Fix load balancing docs --- docs/pricing-limits/pooling-limits.mdx | 41 +++++++++ docs/universal-gateway/http-s/index.mdx | 2 +- docs/universal-gateway/pooling/index.mdx | 49 +++++++++++ .../pooling/pool-load-balancing.mdx | 75 ++++++++++++++++ .../pooling/pooling-quickstart.mdx | 87 +++++++++++++++++++ docs/universal-gateway/tcp/index.mdx | 2 +- docs/universal-gateway/tls/index.mdx | 2 +- .../tls/tls-termination/index.mdx | 2 +- sidebars.js | 11 ++- 9 files changed, 266 insertions(+), 5 deletions(-) create mode 100644 docs/pricing-limits/pooling-limits.mdx create mode 100644 docs/universal-gateway/pooling/index.mdx create mode 100644 docs/universal-gateway/pooling/pool-load-balancing.mdx create mode 100644 docs/universal-gateway/pooling/pooling-quickstart.mdx diff --git a/docs/pricing-limits/pooling-limits.mdx b/docs/pricing-limits/pooling-limits.mdx new file mode 100644 index 0000000000..369d019606 --- /dev/null +++ b/docs/pricing-limits/pooling-limits.mdx @@ -0,0 +1,41 @@ +--- +title: Endpoint Pooling Limits +description: Learn about the technical limits associated with ngrok's endpoint pools. +--- + +Learn about the technical limits associated with ngrok's endpoint pools. + +## Endpoint pool lifecycle + +An Endpoint Pool is automatically created whenever you create two endpoints with: + +- The same URL +- The same binding +- Pooling enabled + +When only a single endpoint remains in a pool, the pool is deleted. + +## Max pool size + +There is no limit on the number of endpoints that may be in a pool. + +## Supported protocols, bindings, and types + +Endpoint pooling supports all: + +- Protocols +- Bindings +- Types (and you can mix types in an endpoint pool) + +## Conflicting endpoints + +Endpoint pooling happens when two or more endpoints share a URL and binding, but both **only if these endpoints have [pooling enabled](/universal-gatway/pooling/#enabling-pooling)**. If an existing endpoint does not have pooling enabled, ngrok will return a conflict error when you try to create a new endpoint with the same URL and binding. + +:::note +Conflicts can only occur during endpoint creation because both the URL and the `pooling_enabled` property may not be updated after an endpoint has been created. +::: + +### Endpoint pool protocols + +The URLs of all endpoints in a pool must share the same protocol. For example, you may not pool the endpoints `https://foo.internal:1234` and +`tcp://foo.internal:1234` together because they have a different protocol. diff --git a/docs/universal-gateway/http-s/index.mdx b/docs/universal-gateway/http-s/index.mdx index 24d47d611f..babb52ab2c 100644 --- a/docs/universal-gateway/http-s/index.mdx +++ b/docs/universal-gateway/http-s/index.mdx @@ -171,7 +171,7 @@ Learn how ngrok handles errors for HTTP/S endpoints in the [Errors documentation HTTP/S Endpoints can be created programatically. Consult the documentation on [Endpoint APIs](/api/resources/endpoints/). -## Limits & Pricing +## Limits & pricing HTTP/S endpoints are available on all plans. Consult the [pricing](/pricing-limits/) documentation for general billing details. diff --git a/docs/universal-gateway/pooling/index.mdx b/docs/universal-gateway/pooling/index.mdx new file mode 100644 index 0000000000..91d5b1237e --- /dev/null +++ b/docs/universal-gateway/pooling/index.mdx @@ -0,0 +1,49 @@ +--- +title: Endpoint Pooling +description: Learn how ngrok enables you to load balance traffic with endpoint pools. +--- + +When you create two endpoints with the same URL and binding, they automatically form a "pool" that load balances traffic between them. Load balancing helps you scale traffic across multiple replicas of your app to increase capacity, tolerate failures, and geo-distribute load. + +Endpoint pooling is vastly more flexible than comparable load balancing +systems: + +- Endpoints join and leave pools automatically as they are created and + destroyed, there is no need to register your upstreams ahead of time. +- You can define your own _dyanmic_ load balancing strategies. For example, you can define strategies that adjust traffic distribution based on the performance of upstream services or properties of the incoming requests. +- You can pool endpoints with different Traffic Policies. This means that not only can you blue-green and canary deploy your own apps, you can also do that with the Traffic Policies themselves. This helps you dramatically mitigate the risk of gateway changes that so often cause site-wide outages. + +## When to use Endpoint Pooling + +Endpoint pooling is a good choice when you want to: + +- Load balance among multiple replicas of the same application, even running in different cloud providers, on-prem, etc. +- Switch from agent endpoints to cloud endpoints with no downtime (or vice-versa) +- Implement [blue-green deployments](https://en.wikipedia.org/wiki/Blue%E2%80%93green_deployment) to reduce risk and rollback times +- A/B test different versions of your apps with blue-green deployments +- Deploy canary version of your application +- Gradually roll out changes to an endpoint's Traffic Policy + +## Enabling Pooling + +Endpoint pooling is disabled by default, and can be enabled on a per-endpoint basis. You must enable pooling on each endpoint you want to pool by setting `pooling_enabled` to `true`. + +## Getting started + +To try out endpoint pooling, see [the endpoint pooling quickstart guide](/universal-gateway/pooling/pooling-quickstart). + +## Using pooling with wildcard endpoints + +[Wildcard endpoints](/universal-gateway/wildcard-domains/wildcard-endpoints) do not pool with non-wildcard URLs. See [the docs on Wildcard Endpoints](/universal-gateway/wildcard-domains/wildcard-endpoints/#wildcard-endpoint-pooling) for more information. + +## API + +Because endpoint pools are created on-demand when two endpoints share the same URL and binding, there is no API resource for endpoint pools. Instead, each [Endpoint API Resource](/api/resources/endpoints/) has a read-only `pools` field which lists the other endpoints in the same pool as the requested endpoint. + +## Limits & pricing + +Endpoint pooling is available on the Pay-As-You-Go plan. Each endpoint in a pool is billed separately. + +See the [pooling limits documentation](/pricing-limits/pooling-limits/) for limits on pooling. + +See the [pricing](/pricing-limits/) documentation for general billing details. diff --git a/docs/universal-gateway/pooling/pool-load-balancing.mdx b/docs/universal-gateway/pooling/pool-load-balancing.mdx new file mode 100644 index 0000000000..23fa311ee8 --- /dev/null +++ b/docs/universal-gateway/pooling/pool-load-balancing.mdx @@ -0,0 +1,75 @@ +--- +title: Load Balancing With Endpoint Pools +description: Learn about the different load balancing strategies available for endpoint pools with ngrok. +--- + +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; + +[Endpoint pools](/universal-gateway/pooling) automatically load balance traffic between their endpoints. Load balancing is applied in two places: + +- When pooled public and kubernetes endpoints load balance traffic received from external clients. +- When pooled internal endpoints receive traffic that is forwarded to them via the `forward-internal` Traffic Policy action. + +### Granularity + +ngrok intelligently chooses the load balancing layer automatically for you. + + + + +Traffic to TCP and TLS endpoints is balanced on a per-connection basis (layer 4). + + + + +Traffic to HTTP and HTTPS endpoints balanced on a per-request basis (layer 7). If multiple endpoints in a pool have different `on_tcp_connect` phases in their Traffic Policy, load balancing is instead done on a per-connection basis (layer 4). + + + + +## Default load balancing strategy + +ngrok's default balancing strategy attempts to strike a balance between +performance and faireness by prioritizing the following: + +1. Identify all endpoints in the pool which are in the [point of presence](/universal-gateway/points-of-presence/) closest to where a connection is received. +1. Balance the connections in a random distribution among those endpoints. + +For the purposes of the first step, [cloud endpoints](/universal-gateway/cloud-endpoints) are considered to be online in +all points of presence. + +### Example + +If an endpoint pool consist of the following endpoints: + +- **Endpoint A**: Agent Endpoint connected to `eu` +- **Endpoint B**: Agent Endpoint connected `eu` +- **Endpoint C**: Agent Endpoint connected `us` +- **Endpoint D**: Cloud Endpoint + +Then: + +- A connection received in `eu` will be balanced among endpoints A, B, D +- A connection received in `us` will be balanced among endpoints C, D +- A connection received in `jp` will be balanced among endpoints D + +### Connection retries with load balancing + +Currently, there's no support for [connection failover](https://en.wikipedia.org/wiki/Failover) with endpoint pools. Failed connections to an endpoint in a pool are neither retried not sent to other endpoints in the pool. + +## Custom Strategies + +:::info Coming Soon + +Custom load balancing strategies are not yet generally available. [Request access to the developer preview](mailto:support@ngrok.com). + +::: + +When balancing traffic to internal endpoints, you may define your own balancing strategy by setting the `endpoint_selectors` and `endpoint_weights` fields on the `forward-internal` Traffic Policy action configuration. + +## Using Traffic Policy with pools + +Endpoints in a pool may have different Traffic Policies. This lets you run old and new Traffic Policies side-by-side during a transition. It also enables you to roll out new Traffic Policy changes without risking an all-or-nothing deployment. + +When traffic is balanced among endpoints with different Traffic Policies, ngrok first chooses an endpoint to balance to, then executes the Traffic Policy of the chosen endpoint. diff --git a/docs/universal-gateway/pooling/pooling-quickstart.mdx b/docs/universal-gateway/pooling/pooling-quickstart.mdx new file mode 100644 index 0000000000..811905f7b8 --- /dev/null +++ b/docs/universal-gateway/pooling/pooling-quickstart.mdx @@ -0,0 +1,87 @@ +--- +title: Endpoint Pooling Quickstart +sidebar_label: Quickstart +description: Get started using endpoint pooling to load balance traffic with ngrok. +--- + +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; + +Endpoint pooling allows you to load balance traffic across multiple endpoints. See the [Endpoint Pooling documentation](/universal-gateway/pooling/) for more details. + + + + +Create two endpoints with the same URL forwarding to two different ports. They will automatically be pooled together. + +``` +ngrok http 8080 --url https://your-domain.ngrok.app --pooling-enabled true +``` + +``` +ngrok http 9090 --url https://your-domain.ngrok.app --pooling-enabled true +``` + +When you make requests to the endpoints' URL, you will see responses balanced +among each endpoint in the pool. + +``` +curl https://your-domain.ngrok.app + + +curl https://your-domain.ngrok.app + +``` + + + + +Create two endpoints with the same URL and two different traffic policies. They will automatically be pooled together. + +First, create two traffic policy files, `policy-a.yml` and `policy-b.yml`. + +```yaml title="policy-a.yml" mode=traffic-policy +on_http_request: + - actions: + - type: custom-response + config: + status_code: 200 + content: Policy A +``` + +```yaml title="policy-b.yml" mode=traffic-policy +on_http_request: + - actions: + - type: custom-response + config: + status_code: 200 + content: Policy B +``` + +Then create two cloud endpoints, one with each policy: + +```sh title="Command line" +ngrok api endpoints create \ + --url https://your-domain.ngrok.app \ + --traffic-policy "$(cat policy-a.yml)" \ + --pooling-enabled=true + +ngrok api endpoints create \ + --url https://your-domain.ngrok.app \ + --traffic-policy "$(cat policy-b.yml)" \ + --pooling-enabled=true +``` + +When you make requests to the endpoints' URL, you will see responses balanced +among each endpoint in the pool. + +```sh title="Command line" +curl https://your-domain.ngrok.app + + +curl https://your-domain.ngrok.app + +``` + + + diff --git a/docs/universal-gateway/tcp/index.mdx b/docs/universal-gateway/tcp/index.mdx index d60bd7d82f..f16192c0de 100644 --- a/docs/universal-gateway/tcp/index.mdx +++ b/docs/universal-gateway/tcp/index.mdx @@ -134,7 +134,7 @@ Learn how ngrok handles errors for TCP endpoints in the [Errors documentation](/ TCP Endpoints can be created programatically. Consult the documentation on [Endpoint APIs](/api/resources/endpoints/). -## Limits & Pricing +## Limits & pricing TCP endpoints are available on all plans. To access them on the free plan, [add a payment method to your ngrok account](https://dashboard.ngrok.com/settings#id-verification). Consult the [pricing](/pricing-limits/) documentation for general billing details. diff --git a/docs/universal-gateway/tls/index.mdx b/docs/universal-gateway/tls/index.mdx index 2b593b2e15..26f6f3af86 100644 --- a/docs/universal-gateway/tls/index.mdx +++ b/docs/universal-gateway/tls/index.mdx @@ -195,7 +195,7 @@ Learn how ngrok handles errors for TLS endpoints in the [Errors documentation](/ TLS Endpoints can be created programatically. Consult the documentation on [Endpoint APIs](/api/resources/endpoints/). -## Limits & Pricing +## Limits & pricing TLS endpoints are available on Pay-as-you-go, Pro, and Enterprise plans. Consult the [pricing](/pricing-limits/) documentation for general billing details. diff --git a/docs/universal-gateway/tls/tls-termination/index.mdx b/docs/universal-gateway/tls/tls-termination/index.mdx index 86f42ed79b..363b746739 100644 --- a/docs/universal-gateway/tls/tls-termination/index.mdx +++ b/docs/universal-gateway/tls/tls-termination/index.mdx @@ -32,7 +32,7 @@ Visit the Traffic Policy docs to [see examples using the `terminate-tls` action] - **Certificates** — ngrok makes managing TLS certificates simple. See [the TLS Certificates documentation](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) for more details on how they are [selected](/universal-gateway/tls-certificates/how-are-certificates-selected), managed, provisioned and renewed. - **End-to-end encryption** — Enabling end-to-end encryption for TLS endpoints is straightforward. See the docs on [how TLS termination works](/universal-gateway/tls-termination/termination-mechanics/#end-to-end-encryption) to learn more. -## Limits & Pricing +## Limits & pricing TLS endpoints are available on Pay-as-you-go, Pro, and Enterprise plans. Consult the [pricing](/pricing-limits/) documentation for general billing details. diff --git a/sidebars.js b/sidebars.js index 219e8337ab..78ba2453b5 100644 --- a/sidebars.js +++ b/sidebars.js @@ -81,7 +81,6 @@ const sidebars = { }, items: [ "universal-gateway/bindings", - "universal-gateway/agent-endpoints", "universal-gateway/public-endpoints/index", { label: "What are Internal Endpoints?", @@ -92,6 +91,7 @@ const sidebars = { }, items: ["universal-gateway/internal-endpoints/quickstart"], }, + "universal-gateway/agent-endpoints", { label: "What are Cloud Endpoints?", type: "category", @@ -185,6 +185,15 @@ const sidebars = { "universal-gateway/agent-forwarding/serving-file-directories", ], }, + { + label: "What is Endpoint Pooling?", + type: "category", + link: { type: "doc", id: "universal-gateway/pooling/index" }, + items: [ + "universal-gateway/pooling/pooling-quickstart", + "universal-gateway/pooling/pool-load-balancing", + ], + }, // { // label: "Endpoints", // type: "category", From d97cdc03603db0748c9b7daa3644b5e460a7bbf9 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 15 Apr 2025 13:19:25 -0400 Subject: [PATCH 108/137] Another fix to pool load balancing --- .../pooling/pool-load-balancing.mdx | 12 +++++++++++- .../universal-gateway/pooling/pooling-quickstart.mdx | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/universal-gateway/pooling/pool-load-balancing.mdx b/docs/universal-gateway/pooling/pool-load-balancing.mdx index 23fa311ee8..9ab5c47698 100644 --- a/docs/universal-gateway/pooling/pool-load-balancing.mdx +++ b/docs/universal-gateway/pooling/pool-load-balancing.mdx @@ -70,6 +70,16 @@ When balancing traffic to internal endpoints, you may define your own balancing ## Using Traffic Policy with pools -Endpoints in a pool may have different Traffic Policies. This lets you run old and new Traffic Policies side-by-side during a transition. It also enables you to roll out new Traffic Policy changes without risking an all-or-nothing deployment. +Endpoints in a pool may have different Traffic Policies. This lets you run old and new Traffic Policies side-by-side when transitioning endpoints into and out of a pool, so you can control and monitor traffic as you make changes. + +It also enables you to roll out new Traffic Policy changes without risking an all-or-nothing deployment, because you can apply changes to endpoints individually rather than being forced to apply them to all endpoints in a pool at once + +### Example scenario + +You might want to transition from using one data center to a different data center for request handling, and the new data center might require a different Traffic Policy configuration. Because traffic policy is applied on a per-endpoint basis in endpoint pools, you could add your new endpoints associated with your new data center to the pool of old endpoints on by one, while gradually removing the old endpoints. + +Such a transition would be easier to monitor and control than if you had to change the traffic policy for all endpoints in the pool at once. You could also use this strategy to roll out a new Traffic Policy to a subset of your endpoints, and then gradually roll it out to the rest of your endpoints. + +### How it works When traffic is balanced among endpoints with different Traffic Policies, ngrok first chooses an endpoint to balance to, then executes the Traffic Policy of the chosen endpoint. diff --git a/docs/universal-gateway/pooling/pooling-quickstart.mdx b/docs/universal-gateway/pooling/pooling-quickstart.mdx index 811905f7b8..f115d68e47 100644 --- a/docs/universal-gateway/pooling/pooling-quickstart.mdx +++ b/docs/universal-gateway/pooling/pooling-quickstart.mdx @@ -9,6 +9,8 @@ import Tabs from "@theme/Tabs"; Endpoint pooling allows you to load balance traffic across multiple endpoints. See the [Endpoint Pooling documentation](/universal-gateway/pooling/) for more details. +The following instructions will help you get started with endpoint pooling using both agent and cloud endpoints. + From b67770910f62e7a42de6bca575ed8f9db246e4b5 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 15 Apr 2025 14:19:48 -0400 Subject: [PATCH 109/137] breaking GSLB, ip addresses, and pop out, but not editing much of the content in depth --- docs/universal-gateway/ddos-protection.mdx | 8 +- .../global-load-balancer.mdx | 9 +- .../global-load-balancer/gslb-agents.mdx | 81 +++++++++++++++++ .../global-load-balancer/gslb-endpoints.mdx | 91 +++++++++++++++++++ .../global-load-balancer/index.mdx | 25 +++++ docs/universal-gateway/ip-addresses.mdx | 5 +- docs/universal-gateway/points-of-presence.mdx | 5 +- sidebars.js | 3 + 8 files changed, 212 insertions(+), 15 deletions(-) create mode 100644 docs/universal-gateway/global-load-balancer/gslb-agents.mdx create mode 100644 docs/universal-gateway/global-load-balancer/gslb-endpoints.mdx create mode 100644 docs/universal-gateway/global-load-balancer/index.mdx diff --git a/docs/universal-gateway/ddos-protection.mdx b/docs/universal-gateway/ddos-protection.mdx index 7ca81dd83c..d3ef10db97 100644 --- a/docs/universal-gateway/ddos-protection.mdx +++ b/docs/universal-gateway/ddos-protection.mdx @@ -1,11 +1,9 @@ --- -title: DDoS Protection +title: How Does ngrok Handle DDoS Attacks? +description: Learn how ngrok protects your applications from DDoS attacks. --- -# DDoS Protection - -ngrok automatically protects your applications with out-of-the-box protection -from distributed denial of service (DDoS) attacks. +ngrok automatically protects your applications from distributed denial of service (DDoS) attacks. ## DDoS Firewall diff --git a/docs/universal-gateway/global-load-balancer.mdx b/docs/universal-gateway/global-load-balancer.mdx index 0764589377..fc76b90902 100644 --- a/docs/universal-gateway/global-load-balancer.mdx +++ b/docs/universal-gateway/global-load-balancer.mdx @@ -1,3 +1,8 @@ +--- +title: What is the Global Load Balancer? +description: Learn about how ngrok's Global Load Balancer and how it improves the performance and resiliency of your applications. +--- + import TabItem from "@theme/TabItem"; import Tabs from "@theme/Tabs"; @@ -10,10 +15,6 @@ import ExplicitRegionPythonSdkExample from "/examples/python-sdk/explicit-region import ExplicitRegionRustSdkExample from "/examples/rust-sdk/explicit-region.mdx"; import ExplicitRegionSshExample from "/examples/ssh/explicit-region.mdx"; -# Global Load Balancer - -## Overview - ngrok's Global Load Balancer improves the performance and resiliency of your applications by distributing traffic to the nearest healthy point of presence, measured by latency, from the perspective of the connecting client. Every diff --git a/docs/universal-gateway/global-load-balancer/gslb-agents.mdx b/docs/universal-gateway/global-load-balancer/gslb-agents.mdx new file mode 100644 index 0000000000..c4fc417b7d --- /dev/null +++ b/docs/universal-gateway/global-load-balancer/gslb-agents.mdx @@ -0,0 +1,81 @@ +--- +title: Global Load Balancing for Agents +description: Learn how ngrok's Global Load Balancer improves the resiliency of your ngrok agents, agent SDKs and the Kubernetes Controller. +--- + +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; + +import ExplicitRegionAgentCliExample from "/examples/agent-cli/explicit-region.mdx"; +import ExplicitRegionAgentConfigExample from "/examples/agent-config/explicit-region.mdx"; +import ExplicitRegionGoSdkExample from "/examples/go-sdk/explicit-region.mdx"; +import ExplicitRegionJavascriptSdkExample from "/examples/javascript-sdk/explicit-region.mdx"; +import ExplicitRegionKubernetesExample from "/examples/k8s/explicit-region.mdx"; +import ExplicitRegionPythonSdkExample from "/examples/python-sdk/explicit-region.mdx"; +import ExplicitRegionRustSdkExample from "/examples/rust-sdk/explicit-region.mdx"; +import ExplicitRegionSshExample from "/examples/ssh/explicit-region.mdx"; + +ngrok's GSLB automatically improves the performance and resiliency of your +ngrok agents, agent SDKs and the Kubernetes Controller. Agents automatically +connect to ngrok's geographically-closest healthy point of presence. + +### Acceleration + +Similar to endpoints, when an ngrok agent connects, DNS resolution returns the +IPs of the closest ngrok point of presence. Connecting to the closest ngrok +point of presence reduces agent initialization time and also reduces the +latency of connections that are routed to that agent. + +### Losing a Point of Presence {#agents-losing-a-pop} + +If an ngrok point of presence fails, health checks automatically detect that +failure and update our DNS resolution such that agents will attempt to connect +to the next-closest healthy point of presence. + +The ngrok agent connects to a single region at a time. If you want the ngrok +agent to simultaneously connect to multiple regions, you must instead run +multiple ngrok agents and [explicitly disable agent +GSLB](#agents-disabling-gslb). + +### Disabling GSLB in the Agent {#agents-disabling-gslb} + +You should always prefer to allow the ngrok agent to use GSLB and connect to +the closest point of presence. However, the ngrok agent does support disabling +GSLB and explicitly choosing which point of presence to connect to. + +If you wish to configure the agent to use a specific point of presence you may +do so with the following configuration: + + + + + + + + + + + + + + + + + + + + + + + + + + + + +### Legacy Agent Behavior + +Beginning with the [ngrok v3 +agent](/agent/changelog#ngrok-agent-300---2022-03-28), the agent uses GSLB to +connect to the lowest-latency point point of presence. Prior to that, v2 ngrok +agents would always connect to the US region by default. diff --git a/docs/universal-gateway/global-load-balancer/gslb-endpoints.mdx b/docs/universal-gateway/global-load-balancer/gslb-endpoints.mdx new file mode 100644 index 0000000000..d0ec797b25 --- /dev/null +++ b/docs/universal-gateway/global-load-balancer/gslb-endpoints.mdx @@ -0,0 +1,91 @@ +--- +title: Global Load Balancing for Endpoints +description: Learn how ngrok's Global Load Balancer improves connection performance to your endpoints. +--- + +ngrok's GSLB improves the performance and resiliency of connections to your +ngrok endpoints (e.g. `https://your-app.ngrok.app`). + +### Connection Acceleration + +When a client (like a web browser) connects to your ngrok endpoint it is routed +to the closest point of presence. DNS resolution of your endpoint's address +returns the IP addresses of ngrok's closest point of presence. The closest point +of presence is determined by the shortest latency from the resolving DNS server +to our points of presence. This ensures that clients are routed to the fastest +point of presence even as internet routing conditions change. + +Connecting to the closest point of presence accelerates your traffic by +reducing the initialization time for TCP and TLS connections. TCP and TLS +connection set up requires network round-trips. ngrok accelerates connections +by reducing the latency of these round-trip times (RTTs) between the client and +your endpoint by routing them to the closest point of presence. + +### Module Acceleration + +In addition to accelerating connection initialization, ngrok also accelerates +the execution of [Modules](/traffic-policy/actions/) that you configure on your +endpoints. Modules execute where the request is first received by the ngrok +edge, at the geographically-closest point of presence. This means that any +behaviors you define in your modules are automatically globally accelerated for +all customers. + +### Geo-Aware Load Balancing + +When you are using a [Tunnel Group Backend](/universal-gateway/edges/#tunnel-group) +with [Edges](/universal-gateway/edges), ngrok can automatically distribute traffic +to the closest upstream if you run geographically distributed copies of your +upstream application service. + +First, consider a case _without_ geo-aware load-balancing. Let's say you have +instances of your application running in Japan. When someone in Belgium makes +a request to your app's endpoint, that request will first be routed to the +closest ngrok point of presence in Europe, like Frankfurt. From Frankfurt, it +will then be routed through ngrok's internal network and finally to your +upstream services in Japan. + +Then let's say you start additional copies of your application service in +France. With zero changes in configuration, those same requests from Belgium +will still be routed to ngrok's point of presence in Frankfurt, but instead of +routing to your upstream services in Japan, they will instead be routed to your +new upstreams in France. That's Geo-Aware Load Balancing. + +### Losing an Upstream {#losing-an-upstream} + +Consider the example in [Geo-Aware Load Balancing](#geo-aware-load-balancing) +where you are running upstream application services in both Japan and France. +Let's then assume that all of your upstream services in Japan fail. Requests +that were being routed to your Japanese upstream services will instead be +routed to your remaining upstream services in France. Requests that were +already being routed to your upstreams in France will be unaffected. + +### Losing a Point of Presence {#endpoints-losing-a-pop} + +In [losing an upstream](#losing-an-upstream), we considered a case where your +upstream services fail. But what if an ngrok point of presence fails? + +If an ngrok point of presence fails, health checks automatically detect that +failure and update our DNS resolution such that clients will attempt to connect +to your endpoints via the next-closest healthy point of presence. + +### Disabling GSLB for an Endpoint {#endpoints-disabling-gslb} + +There is no way to disable GSLB for HTTPS and TLS endpoints. All endpoints you +create in ngrok are available on ngrok's worldwide global delivery network and +inbound requests and connections are routed to the geographically closest point +of presence. + +### TCP Endpoints + +TCP Endpoints do not support GSLB. Unlike domains, TCP addresses are +provisioned for a specific [Point of Presence](/universal-gateway/points-of-presence). When you create a TCP Address, you must select the point of presence where it will accept traffic. Connections to matching TCP Endpoints on a TCP Address will always route to the TCP Address's point of presence, no matter where those connections originated in the world. + +[Learn more about TCP Address load balancing](/universal-gateway/tcp-addresses/#tcp-address-load-balancing). + +## Domains + +[Domains](/universal-gateway/domains/what-are-domains) allow you to configure which points of presence the Global Load +Balancer may resolve clients to. This allows you to select which points of +presence will receive traffic for the Domain's matching endpoints. To disable +the Global Load Balancer, you may configure a domain to only resolve a single +point of presence. diff --git a/docs/universal-gateway/global-load-balancer/index.mdx b/docs/universal-gateway/global-load-balancer/index.mdx new file mode 100644 index 0000000000..fe2e89b4cd --- /dev/null +++ b/docs/universal-gateway/global-load-balancer/index.mdx @@ -0,0 +1,25 @@ +--- +title: What is the Global Load Balancer? +description: Learn about how ngrok's Global Load Balancer and how it improves the performance and resiliency of your applications. +--- + +ngrok's Global Load Balancer improves the performance and resiliency of your +applications by distributing traffic to the nearest healthy point of presence, measured by latency, from the perspective of the connecting client. Every application you deliver with ngrok is automatically accelerated with our always-on, zero-configuration global load balancer. + +Global lobal balancing is sometimes called 'Global Server Load Balancing' or +GSLB. + +Conceptually, a GSLB is simple. A GSLB accelerates traffic by adjusting DNS +resolution so that when clients connect to your endpoints on the internet, they +connect to the nearest point of presence (PoP). A GSLB adds resiliency by +adjusting that same DNS resolution process to steer traffic away from failing +PoPs. + +## vs. Traditional GSLBs + +ngrok operates differently from a traditional GSLB to give you some important +benefits. + +1. In a traditional GSLB deployment, you are responsible for running geographically redundant copies of your application and configuring networking technologies to distribute and failover traffic among these deployments. By contrast, ngrok runs a [global delivery network of PoPs](/universal-gateway/points-of-presence/) for you. This means that even if you only deploy your upstream service to a single geography, your apps still get faster from [Connection Acceleration](#connection-acceleration) and [Module Acceleration](#module-acceleration). +1. Unlike a traditional GSLB deployment, when you deploy your application services to a new geographic location, ngrok automatically routes nearby traffic to those services without any configuration. Traditional GSLB deployments require many network configuration updates to bring these new locations online like IP provisioning and DNS record changes. With ngrok, there is zero configuration, just start your new application services with their ngrok agents and you're done. +1. Unlike a traditional reverse proxy, ngrok forwards traffic to your upstream services over secure connections established by the [ngrok agent](/agent/), [Agent SDKs](/agent-sdks) or [Kubernetes Controller](/k8s/). So which PoPs do those agents connect to? ngrok also applies GSLB principles to those connections as well to ensure that your agents connect to the geographically closest PoPs. diff --git a/docs/universal-gateway/ip-addresses.mdx b/docs/universal-gateway/ip-addresses.mdx index ef7ade9c4c..2f6ce3aadc 100644 --- a/docs/universal-gateway/ip-addresses.mdx +++ b/docs/universal-gateway/ip-addresses.mdx @@ -1,9 +1,8 @@ --- -title: IP Addresses +title: How Do ngrok's IP Addresses Work? +description: Learn how ngrok assigns IPs for endpoints, agent connections, and the dashboard API. --- -# IP Addresses {#ip-addresses} - ngrok's cloud service uses a dynamic, rotating set of multitenant IPs to serve your public Endpoints. Endpoint IPs may change frequently **_and without notice_**. If you hardcode any of ngrok's IPs or rely on DNS answers past their diff --git a/docs/universal-gateway/points-of-presence.mdx b/docs/universal-gateway/points-of-presence.mdx index 44c02a395c..acc25995df 100644 --- a/docs/universal-gateway/points-of-presence.mdx +++ b/docs/universal-gateway/points-of-presence.mdx @@ -1,9 +1,8 @@ --- -title: Points of Presence +title: Where Are ngrok's Points of Presence? +description: Learn about ngrok's globally distributed points of presence. --- -# Points of Presence - ngrok's globally distributed cloud service runs on points of presence all around the world to enable fast, low latency traffic to your applications. diff --git a/sidebars.js b/sidebars.js index 78ba2453b5..733c8d84c1 100644 --- a/sidebars.js +++ b/sidebars.js @@ -194,6 +194,9 @@ const sidebars = { "universal-gateway/pooling/pool-load-balancing", ], }, + "universal-gateway/ip-addresses", + "universal-gateway/points-of-presence", + "universal-gateway/ddos-protection", // { // label: "Endpoints", // type: "category", From 5d03bbc311f9493b61c3b93f79bd959a033d7989 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 15 Apr 2025 15:10:17 -0400 Subject: [PATCH 110/137] Done with rough draft of GSLB endpoints --- .../global-load-balancer/gslb-endpoints.mdx | 82 ++++++++----------- .../universal-gateway/tcp-addresses/index.mdx | 10 +-- sidebars.js | 12 +++ 3 files changed, 47 insertions(+), 57 deletions(-) diff --git a/docs/universal-gateway/global-load-balancer/gslb-endpoints.mdx b/docs/universal-gateway/global-load-balancer/gslb-endpoints.mdx index d0ec797b25..0cf449e562 100644 --- a/docs/universal-gateway/global-load-balancer/gslb-endpoints.mdx +++ b/docs/universal-gateway/global-load-balancer/gslb-endpoints.mdx @@ -4,83 +4,67 @@ description: Learn how ngrok's Global Load Balancer improves connection performa --- ngrok's GSLB improves the performance and resiliency of connections to your -ngrok endpoints (e.g. `https://your-app.ngrok.app`). +endpoints. -### Connection Acceleration +When a client (like a web browser) connects to your endpoint, it's routed to the closest [point of presence](/universal-gateway/points-of-presence/). The closest point of presence is the one with the shortest latency to the resolving DNS server for the connection. This ensures that clients are routed to the fastest point of presence even as internet routing conditions change. -When a client (like a web browser) connects to your ngrok endpoint it is routed -to the closest point of presence. DNS resolution of your endpoint's address -returns the IP addresses of ngrok's closest point of presence. The closest point -of presence is determined by the shortest latency from the resolving DNS server -to our points of presence. This ensures that clients are routed to the fastest -point of presence even as internet routing conditions change. +## Connection Acceleration Connecting to the closest point of presence accelerates your traffic by reducing the initialization time for TCP and TLS connections. TCP and TLS connection set up requires network round-trips. ngrok accelerates connections -by reducing the latency of these round-trip times (RTTs) between the client and -your endpoint by routing them to the closest point of presence. +by reducing the latency of these round-trip times (RTTs) between the client and your endpoint by routing them to the closest point of presence. ### Module Acceleration -In addition to accelerating connection initialization, ngrok also accelerates -the execution of [Modules](/traffic-policy/actions/) that you configure on your -endpoints. Modules execute where the request is first received by the ngrok -edge, at the geographically-closest point of presence. This means that any -behaviors you define in your modules are automatically globally accelerated for -all customers. +In addition to accelerating connection initialization, ngrok also accelerates the execution of [Modules](/traffic-policy/actions/) that you configure on your endpoints. Modules execute where the request is first received by the ngrok edge, at the geographically-closest point of presence. This means that any behaviors you define in your modules are automatically globally accelerated for all customers. -### Geo-Aware Load Balancing +## Geo-Aware Load Balancing When you are using a [Tunnel Group Backend](/universal-gateway/edges/#tunnel-group) with [Edges](/universal-gateway/edges), ngrok can automatically distribute traffic to the closest upstream if you run geographically distributed copies of your upstream application service. -First, consider a case _without_ geo-aware load-balancing. Let's say you have -instances of your application running in Japan. When someone in Belgium makes -a request to your app's endpoint, that request will first be routed to the -closest ngrok point of presence in Europe, like Frankfurt. From Frankfurt, it -will then be routed through ngrok's internal network and finally to your -upstream services in Japan. +### Example scenario -Then let's say you start additional copies of your application service in -France. With zero changes in configuration, those same requests from Belgium -will still be routed to ngrok's point of presence in Frankfurt, but instead of -routing to your upstream services in Japan, they will instead be routed to your -new upstreams in France. That's Geo-Aware Load Balancing. +Let's say you have instances of your application running in Japan. When someone in Belgium makes a request to your app's endpoint, they will: -### Losing an Upstream {#losing-an-upstream} +1. First, be routed to the + closest ngrok point of presence in Europe, such as Germany +1. Then, be routed through ngrok's internal network and finally to your + upstream services in Japan -Consider the example in [Geo-Aware Load Balancing](#geo-aware-load-balancing) -where you are running upstream application services in both Japan and France. -Let's then assume that all of your upstream services in Japan fail. Requests -that were being routed to your Japanese upstream services will instead be -routed to your remaining upstream services in France. Requests that were -already being routed to your upstreams in France will be unaffected. +If you were to deploy additional copies of your application in +France, those same requests from Belgium would: -### Losing a Point of Presence {#endpoints-losing-a-pop} +1. First, be routed to ngrok's nearest point of presence in Europe, which would be Germany +1. Then, be routed to your new upstreams in France rather than Japan -In [losing an upstream](#losing-an-upstream), we considered a case where your -upstream services fail. But what if an ngrok point of presence fails? +That's Geo-Aware Load Balancing. + +### Upstream failover + +When upstream services fail, ngrok's GSLB will automatically route traffic to the next-closest running upstream service. + +### Losing a Point of Presence If an ngrok point of presence fails, health checks automatically detect that -failure and update our DNS resolution such that clients will attempt to connect -to your endpoints via the next-closest healthy point of presence. +failure and update our DNS resolution such that clients will attempt to connect to your endpoints via the next-closest healthy point of presence. + +## Disabling GSLB for an endpoint -### Disabling GSLB for an Endpoint {#endpoints-disabling-gslb} +**There is no way to disable GSLB for HTTP/S and TLS endpoints**. TCP endpoints do not support GSLB. -There is no way to disable GSLB for HTTPS and TLS endpoints. All endpoints you -create in ngrok are available on ngrok's worldwide global delivery network and -inbound requests and connections are routed to the geographically closest point -of presence. +## GSLB for TCP endpoints -### TCP Endpoints +ngrok does not support global load balancing for TCP Addresses, but you can connect TCP Addresses to [Agent Endpoints](/agent/) in different [Points of Presence](/universal-gateway/points-of-presence). This allows you to accept traffic to a TCP Address in one region, then forward it to an Agent in a different region. -TCP Endpoints do not support GSLB. Unlike domains, TCP addresses are -provisioned for a specific [Point of Presence](/universal-gateway/points-of-presence). When you create a TCP Address, you must select the point of presence where it will accept traffic. Connections to matching TCP Endpoints on a TCP Address will always route to the TCP Address's point of presence, no matter where those connections originated in the world. +The following example [CLI command](/agent/cli) creates an agent in the `jp` region that connects to a TCP address in the `eu` region: -[Learn more about TCP Address load balancing](/universal-gateway/tcp-addresses/#tcp-address-load-balancing). +```sh +ngrok tcp 3389 --region jp --url tcp://1.tcp.eu.ngrok.io:12345 +``` ## Domains diff --git a/docs/universal-gateway/tcp-addresses/index.mdx b/docs/universal-gateway/tcp-addresses/index.mdx index e2d72a5f77..8163fb5971 100644 --- a/docs/universal-gateway/tcp-addresses/index.mdx +++ b/docs/universal-gateway/tcp-addresses/index.mdx @@ -16,15 +16,9 @@ Only TCP Endpoints may be created on TCP Addresses. For other endpoint types, create a [Domain](/universal-gateway/domains/what-are-domains/). ::: -## TCP Address load balancing +## TCP address load balancing -ngrok does not support global load balancing for TCP Addresses, but you can connect TCP Addresses to [Agent Endpoints](/agent/) in different [Points of Presence](/universal-gateway/points-of-presence). This allows you to accept traffic to a TCP Address in one region, then forward it to an Agent in a different region. - -The following example [CLI command](/agent/cli) creates an agent in the `jp` region that connects to a TCP address in the `eu` region: - -```sh -ngrok tcp 3389 --region jp --url tcp://1.tcp.eu.ngrok.io:12345 -``` +Global load balancing is not supported for TCP Addresses. See the [Load Balancing documentation](/universal-gateway/global-load-balancer/#gslb-for-tcp-endpoints) for more information. ## Pricing diff --git a/sidebars.js b/sidebars.js index 733c8d84c1..091f9c88dd 100644 --- a/sidebars.js +++ b/sidebars.js @@ -194,6 +194,18 @@ const sidebars = { "universal-gateway/pooling/pool-load-balancing", ], }, + { + label: "What is the Global Load Balancer?", + type: "category", + link: { + type: "doc", + id: "universal-gateway/global-load-balancer/index", + }, + items: [ + "universal-gateway/global-load-balancer/gslb-endpoints", + "universal-gateway/global-load-balancer/gslb-agents", + ], + }, "universal-gateway/ip-addresses", "universal-gateway/points-of-presence", "universal-gateway/ddos-protection", From 53d0a883e029da21d6716c4be5b69362b8e086ee Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 15 Apr 2025 15:16:11 -0400 Subject: [PATCH 111/137] more gslb cleanup --- .../global-load-balancer/gslb-agents.mdx | 6 +++--- .../universal-gateway/global-load-balancer/index.mdx | 12 +++++------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/docs/universal-gateway/global-load-balancer/gslb-agents.mdx b/docs/universal-gateway/global-load-balancer/gslb-agents.mdx index c4fc417b7d..09d35f1fbe 100644 --- a/docs/universal-gateway/global-load-balancer/gslb-agents.mdx +++ b/docs/universal-gateway/global-load-balancer/gslb-agents.mdx @@ -19,14 +19,14 @@ ngrok's GSLB automatically improves the performance and resiliency of your ngrok agents, agent SDKs and the Kubernetes Controller. Agents automatically connect to ngrok's geographically-closest healthy point of presence. -### Acceleration +## Acceleration Similar to endpoints, when an ngrok agent connects, DNS resolution returns the IPs of the closest ngrok point of presence. Connecting to the closest ngrok point of presence reduces agent initialization time and also reduces the latency of connections that are routed to that agent. -### Losing a Point of Presence {#agents-losing-a-pop} +### Losing a Point of Presence If an ngrok point of presence fails, health checks automatically detect that failure and update our DNS resolution such that agents will attempt to connect @@ -37,7 +37,7 @@ agent to simultaneously connect to multiple regions, you must instead run multiple ngrok agents and [explicitly disable agent GSLB](#agents-disabling-gslb). -### Disabling GSLB in the Agent {#agents-disabling-gslb} +### Disabling GSLB in the Agent You should always prefer to allow the ngrok agent to use GSLB and connect to the closest point of presence. However, the ngrok agent does support disabling diff --git a/docs/universal-gateway/global-load-balancer/index.mdx b/docs/universal-gateway/global-load-balancer/index.mdx index fe2e89b4cd..f24d48aa7c 100644 --- a/docs/universal-gateway/global-load-balancer/index.mdx +++ b/docs/universal-gateway/global-load-balancer/index.mdx @@ -4,16 +4,14 @@ description: Learn about how ngrok's Global Load Balancer and how it improves th --- ngrok's Global Load Balancer improves the performance and resiliency of your -applications by distributing traffic to the nearest healthy point of presence, measured by latency, from the perspective of the connecting client. Every application you deliver with ngrok is automatically accelerated with our always-on, zero-configuration global load balancer. +applications by distributing traffic to the point of presence with the least latency from the client, and away from failing points of presence and upstream services. +Every application you deliver with ngrok is automatically accelerated with our always-on, zero-configuration global load balancer. + +:::tip Global lobal balancing is sometimes called 'Global Server Load Balancing' or GSLB. - -Conceptually, a GSLB is simple. A GSLB accelerates traffic by adjusting DNS -resolution so that when clients connect to your endpoints on the internet, they -connect to the nearest point of presence (PoP). A GSLB adds resiliency by -adjusting that same DNS resolution process to steer traffic away from failing -PoPs. +::: ## vs. Traditional GSLBs From 2e02f20ffe501077107d844b2706132e5b3784a3 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 15 Apr 2025 16:17:27 -0400 Subject: [PATCH 112/137] cleaning up the gslb index page --- .../global-load-balancer.mdx | 216 ------------------ .../global-load-balancer/gslb-agents.mdx | 150 ++++++++---- .../global-load-balancer/gslb-endpoints.mdx | 2 +- .../global-load-balancer/index.mdx | 16 +- 4 files changed, 119 insertions(+), 265 deletions(-) delete mode 100644 docs/universal-gateway/global-load-balancer.mdx diff --git a/docs/universal-gateway/global-load-balancer.mdx b/docs/universal-gateway/global-load-balancer.mdx deleted file mode 100644 index fc76b90902..0000000000 --- a/docs/universal-gateway/global-load-balancer.mdx +++ /dev/null @@ -1,216 +0,0 @@ ---- -title: What is the Global Load Balancer? -description: Learn about how ngrok's Global Load Balancer and how it improves the performance and resiliency of your applications. ---- - -import TabItem from "@theme/TabItem"; -import Tabs from "@theme/Tabs"; - -import ExplicitRegionAgentCliExample from "/examples/agent-cli/explicit-region.mdx"; -import ExplicitRegionAgentConfigExample from "/examples/agent-config/explicit-region.mdx"; -import ExplicitRegionGoSdkExample from "/examples/go-sdk/explicit-region.mdx"; -import ExplicitRegionJavascriptSdkExample from "/examples/javascript-sdk/explicit-region.mdx"; -import ExplicitRegionKubernetesExample from "/examples/k8s/explicit-region.mdx"; -import ExplicitRegionPythonSdkExample from "/examples/python-sdk/explicit-region.mdx"; -import ExplicitRegionRustSdkExample from "/examples/rust-sdk/explicit-region.mdx"; -import ExplicitRegionSshExample from "/examples/ssh/explicit-region.mdx"; - -ngrok's Global Load Balancer improves the performance and resiliency of your -applications by distributing traffic to the nearest healthy point of presence, -measured by latency, from the perspective of the connecting client. Every -application you deliver with ngrok is automatically accelerated with our -always-on, zero-configuration global load balancer. - -Global lobal balancing is sometimes called 'Global Server Load Balancing' or -GSLB. - -Conceptually, a GSLB is simple. A GSLB accelerates traffic by adjusting DNS -resolution so that when clients connect to your endpoints on the internet, they -connect to the nearest point of presence (PoP). A GSLB adds resiliency by -adjusting that same DNS resolution process to steer traffic away from failing -PoPs. - -## vs. Traditional GSLBs - -ngrok operates differently from a traditional GSLB to give you some important -benefits. - -1. In a traditional GSLB deployment, you are responsible for running - geographically redundant copies of your application and configuring networking - technologies to distribute and failover traffic among these deployments. By - contrast, ngrok runs a [global delivery network of - PoPs](/universal-gateway/points-of-presence/) for you. This means that even if you - only deploy your upstream service to a single geography, your apps still get - faster from [Connection Acceleration](#connection-acceleration) and [Module - Acceleration](#module-acceleration). - -2. Unlike a traditional GSLB deployment, when you deploy your application - services to a new geographic location, ngrok automatically routes nearby - traffic to those services without any configuration. Traditional GSLB - deployments require many network configuration updates to bring these new - locations online like IP provisioning and DNS record changes. With ngrok, there - is zero configuration, just start your new application services with their - ngrok agents and you're done. - -3. Unlike a traditional reverse proxy, ngrok forwards traffic to your upstream - services over secure connections established by the [ngrok agent](/agent/), - [Agent SDKs](/agent-sdks) or [Kubernetes Controller](/k8s/). So which PoPs do - those agents connect to? ngrok also applies GSLB principles to those - connections as well to ensure that your agents connect to the geographically - closest PoPs. - -## Endpoints - -ngrok's GSLB improves the performance and resiliency of connections to your -ngrok endpoints (e.g. `https://your-app.ngrok.app`). - -### Connection Acceleration - -When a client (like a web browser) connects to your ngrok endpoint it is routed -to the closest point of presence. DNS resolution of your endpoint's address -returns the IP addresses of ngrok's closest point of presence. The closest point -of presence is determined by the shortest latency from the resolving DNS server -to our points of presence. This ensures that clients are routed to the fastest -point of presence even as internet routing conditions change. - -Connecting to the closest point of presence accelerates your traffic by -reducing the initialization time for TCP and TLS connections. TCP and TLS -connection set up requires network round-trips. ngrok accelerates connections -by reducing the latency of these round-trip times (RTTs) between the client and -your endpoint by routing them to the closest point of presence. - -### Module Acceleration - -In addition to accelerating connection initialization, ngrok also accelerates -the execution of [Modules](/traffic-policy/actions/) that you configure on your -endpoints. Modules execute where the request is first received by the ngrok -edge, at the geographically-closest point of presence. This means that any -behaviors you define in your modules are automatically globally accelerated for -all customers. - -### Geo-Aware Load Balancing - -When you are using a [Tunnel Group Backend](/universal-gateway/edges/#tunnel-group) -with [Edges](/universal-gateway/edges), ngrok can automatically distribute traffic -to the closest upstream if you run geographically distributed copies of your -upstream application service. - -First, consider a case _without_ geo-aware load-balancing. Let's say you have -instances of your application running in Japan. When someone in Belgium makes -a request to your app's endpoint, that request will first be routed to the -closest ngrok point of presence in Europe, like Frankfurt. From Frankfurt, it -will then be routed through ngrok's internal network and finally to your -upstream services in Japan. - -Then let's say you start additional copies of your application service in -France. With zero changes in configuration, those same requests from Belgium -will still be routed to ngrok's point of presence in Frankfurt, but instead of -routing to your upstream services in Japan, they will instead be routed to your -new upstreams in France. That's Geo-Aware Load Balancing. - -### Losing an Upstream {#losing-an-upstream} - -Consider the example in [Geo-Aware Load Balancing](#geo-aware-load-balancing) -where you are running upstream application services in both Japan and France. -Let's then assume that all of your upstream services in Japan fail. Requests -that were being routed to your Japanese upstream services will instead be -routed to your remaining upstream services in France. Requests that were -already being routed to your upstreams in France will be unaffected. - -### Losing a Point of Presence {#endpoints-losing-a-pop} - -In [losing an upstream](#losing-an-upstream), we considered a case where your -upstream services fail. But what if an ngrok point of presence fails? - -If an ngrok point of presence fails, health checks automatically detect that -failure and update our DNS resolution such that clients will attempt to connect -to your endpoints via the next-closest healthy point of presence. - -### Disabling GSLB for an Endpoint {#endpoints-disabling-gslb} - -There is no way to disable GSLB for HTTPS and TLS endpoints. All endpoints you -create in ngrok are available on ngrok's worldwide global delivery network and -inbound requests and connections are routed to the geographically closest point -of presence. - -### TCP Endpoints - -TCP Endpoints do not support GSLB. Unlike domains, TCP addresses are -provisioned for a specific [Point of Presence](/universal-gateway/points-of-presence). When you create a TCP Address, you must select the point of presence where it will accept traffic. Connections to matching TCP Endpoints on a TCP Address will always route to the TCP Address's point of presence, no matter where those connections originated in the world. - -[Learn more about TCP Address load balancing](/universal-gateway/tcp-addresses/#tcp-address-load-balancing). - -## Domains - -[Domains](/universal-gateway/domains/what-are-domains) allow you to configure which points of presence the Global Load -Balancer may resolve clients to. This allows you to select which points of -presence will receive traffic for the Domain's matching endpoints. To disable -the Global Load Balancer, you may configure a domain to only resolve a single -point of presence. - -## Agents - -ngrok's GSLB automatically improves the performance and resiliency of your -ngrok agents, agent SDKs and the Kubernetes Controller. Agents automatically -connect to ngrok's geographically-closest healthy point of presence. - -### Acceleration - -Similar to endpoints, when an ngrok agent connects, DNS resolution returns the -IPs of the closest ngrok point of presence. Connecting to the closest ngrok -point of presence reduces agent initialization time and also reduces the -latency of connections that are routed to that agent. - -### Losing a Point of Presence {#agents-losing-a-pop} - -If an ngrok point of presence fails, health checks automatically detect that -failure and update our DNS resolution such that agents will attempt to connect -to the next-closest healthy point of presence. - -The ngrok agent connects to a single region at a time. If you want the ngrok -agent to simultaneously connect to multiple regions, you must instead run -multiple ngrok agents and [explicitly disable agent -GSLB](#agents-disabling-gslb). - -### Disabling GSLB in the Agent {#agents-disabling-gslb} - -You should always prefer to allow the ngrok agent to use GSLB and connect to -the closest point of presence. However, the ngrok agent does support disabling -GSLB and explicitly choosing which point of presence to connect to. - -If you wish to configure the agent to use a specific point of presence you may -do so with the following configuration: - - - - - - - - - - - - - - - - - - - - - - - - - - - - -### Legacy Agent Behavior - -Beginning with the [ngrok v3 -agent](/agent/changelog#ngrok-agent-300---2022-03-28), the agent uses GSLB to -connect to the lowest-latency point point of presence. Prior to that, v2 ngrok -agents would always connect to the US region by default. diff --git a/docs/universal-gateway/global-load-balancer/gslb-agents.mdx b/docs/universal-gateway/global-load-balancer/gslb-agents.mdx index 09d35f1fbe..22dd24ebe7 100644 --- a/docs/universal-gateway/global-load-balancer/gslb-agents.mdx +++ b/docs/universal-gateway/global-load-balancer/gslb-agents.mdx @@ -5,15 +5,10 @@ description: Learn how ngrok's Global Load Balancer improves the resiliency of y import TabItem from "@theme/TabItem"; import Tabs from "@theme/Tabs"; +import { LangSwitcher } from "@site/src/components/LangSwitcher"; -import ExplicitRegionAgentCliExample from "/examples/agent-cli/explicit-region.mdx"; import ExplicitRegionAgentConfigExample from "/examples/agent-config/explicit-region.mdx"; -import ExplicitRegionGoSdkExample from "/examples/go-sdk/explicit-region.mdx"; -import ExplicitRegionJavascriptSdkExample from "/examples/javascript-sdk/explicit-region.mdx"; import ExplicitRegionKubernetesExample from "/examples/k8s/explicit-region.mdx"; -import ExplicitRegionPythonSdkExample from "/examples/python-sdk/explicit-region.mdx"; -import ExplicitRegionRustSdkExample from "/examples/rust-sdk/explicit-region.mdx"; -import ExplicitRegionSshExample from "/examples/ssh/explicit-region.mdx"; ngrok's GSLB automatically improves the performance and resiliency of your ngrok agents, agent SDKs and the Kubernetes Controller. Agents automatically @@ -21,23 +16,19 @@ connect to ngrok's geographically-closest healthy point of presence. ## Acceleration -Similar to endpoints, when an ngrok agent connects, DNS resolution returns the -IPs of the closest ngrok point of presence. Connecting to the closest ngrok -point of presence reduces agent initialization time and also reduces the -latency of connections that are routed to that agent. +Similar to endpoints, when an ngrok agent connects, DNS resolution returns the IPs of the closest ngrok point of presence. Connecting to the closest ngrok point of presence reduces agent initialization time and also reduces the latency of connections that are routed to that agent. -### Losing a Point of Presence +## Losing a Point of Presence If an ngrok point of presence fails, health checks automatically detect that -failure and update our DNS resolution such that agents will attempt to connect -to the next-closest healthy point of presence. +failure and update our DNS resolution such that agents will attempt to connect to the next-closest healthy point of presence. The ngrok agent connects to a single region at a time. If you want the ngrok agent to simultaneously connect to multiple regions, you must instead run multiple ngrok agents and [explicitly disable agent -GSLB](#agents-disabling-gslb). +GSLB](#disabling-gslb-in-the-agent). -### Disabling GSLB in the Agent +## Disabling GSLB in the Agent You should always prefer to allow the ngrok agent to use GSLB and connect to the closest point of presence. However, the ngrok agent does support disabling @@ -46,36 +37,105 @@ GSLB and explicitly choosing which point of presence to connect to. If you wish to configure the agent to use a specific point of presence you may do so with the following configuration: - - - - - - - - - - - - - - - - - - - - - - - - - + + + + +```bash +ngrok http 80 --region eu +``` + +```ssh tabName="SSH" +ssh -R 0:localhost:80 connect.eu.ngrok-agent.com http +``` + +```go +import ( + "context" + "net" + + "golang.ngrok.com/ngrok" + "golang.ngrok.com/ngrok/config" +) + +func ngrokListener(ctx context.Context) (net.Listener, error) { + return ngrok.Listen(ctx, + config.HTTPEndpoint(), + ngrok.WithRegion("eu"), + ngrok.WithAuthtokenFromEnv(), + ) +} +``` + +```jsx +const ngrok = require("@ngrok/ngrok"); + +(async function () { + const session = await new ngrok.SessionBuilder() + .authtokenFromEnv() + .serverAddr("connect.eu.ngrok-agent.com:443") + .connect(); + + const listener = await session + .httpEndpoint() + .listenAndForward("http://localhost:8080"); + + console.log(`Ingress established at: ${listener.url()}`); +})(); +``` + +```python +import ngrok, asyncio + +async def create_listener() -> ngrok.Listener: + session: ngrok.Session = ( + await ngrok.SessionBuilder() + .authtoken_from_env() + .server_addr("connect.eu.ngrok-agent.com:443") + .connect() + ) + + return (await session.http_endpoint() + .listen_and_forward("http://localhost:8080")) + +listener = asyncio.run(create_listener()) + +print(f"Ingress established at: {listener.url()}"); +``` + +```rust +use ngrok::prelude::*; + +async fn listen_ngrok() -> anyhow::Result { + let sess = ngrok::Session::builder() + .authtoken_from_env() + .server_addr("connect.eu.ngrok-agent.com:443"), + .connect() + .await?; + + let tun = sess + .http_endpoint() + .listen() + .await?; + + println!("Listening on URL: {:?}", tun.url()); + + Ok(tun) +} +``` + + + + + + + + + + + -### Legacy Agent Behavior +## Legacy Agent Behavior -Beginning with the [ngrok v3 -agent](/agent/changelog#ngrok-agent-300---2022-03-28), the agent uses GSLB to -connect to the lowest-latency point point of presence. Prior to that, v2 ngrok -agents would always connect to the US region by default. +Beginning with the [ngrok v3 agent](/agent/changelog#ngrok-agent-300---2022-03-28), the agent uses GSLB to connect to the lowest-latency point point of presence. Prior to that, v2 ngrok agents would always connect to the US region by default. diff --git a/docs/universal-gateway/global-load-balancer/gslb-endpoints.mdx b/docs/universal-gateway/global-load-balancer/gslb-endpoints.mdx index 0cf449e562..ffbbfd506c 100644 --- a/docs/universal-gateway/global-load-balancer/gslb-endpoints.mdx +++ b/docs/universal-gateway/global-load-balancer/gslb-endpoints.mdx @@ -6,7 +6,7 @@ description: Learn how ngrok's Global Load Balancer improves connection performa ngrok's GSLB improves the performance and resiliency of connections to your endpoints. -When a client (like a web browser) connects to your endpoint, it's routed to the closest [point of presence](/universal-gateway/points-of-presence/). The closest point of presence is the one with the shortest latency to the resolving DNS server for the connection. This ensures that clients are routed to the fastest point of presence even as internet routing conditions change. +When a client (such as a web browser) connects to your endpoint, it's routed to the closest [point of presence](/universal-gateway/points-of-presence/). The closest point of presence is the one with the shortest latency to the resolving DNS server for the connection. This ensures that clients are routed to the fastest point of presence even as internet routing conditions change. ## Connection Acceleration diff --git a/docs/universal-gateway/global-load-balancer/index.mdx b/docs/universal-gateway/global-load-balancer/index.mdx index f24d48aa7c..03610fb478 100644 --- a/docs/universal-gateway/global-load-balancer/index.mdx +++ b/docs/universal-gateway/global-load-balancer/index.mdx @@ -18,6 +18,16 @@ GSLB. ngrok operates differently from a traditional GSLB to give you some important benefits. -1. In a traditional GSLB deployment, you are responsible for running geographically redundant copies of your application and configuring networking technologies to distribute and failover traffic among these deployments. By contrast, ngrok runs a [global delivery network of PoPs](/universal-gateway/points-of-presence/) for you. This means that even if you only deploy your upstream service to a single geography, your apps still get faster from [Connection Acceleration](#connection-acceleration) and [Module Acceleration](#module-acceleration). -1. Unlike a traditional GSLB deployment, when you deploy your application services to a new geographic location, ngrok automatically routes nearby traffic to those services without any configuration. Traditional GSLB deployments require many network configuration updates to bring these new locations online like IP provisioning and DNS record changes. With ngrok, there is zero configuration, just start your new application services with their ngrok agents and you're done. -1. Unlike a traditional reverse proxy, ngrok forwards traffic to your upstream services over secure connections established by the [ngrok agent](/agent/), [Agent SDKs](/agent-sdks) or [Kubernetes Controller](/k8s/). So which PoPs do those agents connect to? ngrok also applies GSLB principles to those connections as well to ensure that your agents connect to the geographically closest PoPs. +### Automatic geo-aware failover + +Traditional GSLBs require you to run geographically redundant copies of your application and configuring networking technologies to distribute and failover traffic among these deployments. By contrast, ngrok runs a [global delivery network of PoPs](/universal-gateway/points-of-presence/) for you. This means that even if you only deploy your upstream service to a single geography, your apps still get faster from [Connection Acceleration](/universal-gateway/global-load-balancer/gslb-endpoints/#connection-acceleration) and [Module Acceleration](/universal-gateway/global-load-balancer/gslb-endpoints/#module-acceleration). + +### Zero configuration + +Traditional GSLB deployments require network configuration updates, such as IP provisioning and DNS record changes, to bring new applications and services online. + +With ngrok, when you deploy your applications and services to a new geographic location, nearby traffic is automatically routed to those services. + +### Secure connections + +Unlike a traditional reverse proxy, ngrok forwards traffic to your upstream services over secure connections established by the [ngrok agent](/agent/), [Agent SDKs](/agent-sdks) or [Kubernetes Controller](/k8s/). So which PoPs do those agents connect to? ngrok also applies GSLB principles to those connections, ensuring that your agents connect to the geographically closest PoPs. From 89babdaca918959d50685fa40eea4cbe434c48bb Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 15 Apr 2025 16:19:24 -0400 Subject: [PATCH 113/137] Fix types --- src/components/CodeBlockWithInfo/index.tsx | 2 +- src/components/LangSwitcher/LangSwitcherContext.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/CodeBlockWithInfo/index.tsx b/src/components/CodeBlockWithInfo/index.tsx index c819be1813..2ff515f157 100644 --- a/src/components/CodeBlockWithInfo/index.tsx +++ b/src/components/CodeBlockWithInfo/index.tsx @@ -15,7 +15,7 @@ import { LanguageData } from "../LangSwitcher/LanguageData"; import type { LanguageInfo } from "../LangSwitcher/data"; type CodeBlockWithInfoProps = { - content: string; + content: string | undefined; // biome-ignore lint/suspicious/noExplicitAny: language: any; collapseLineNumber: number; diff --git a/src/components/LangSwitcher/LangSwitcherContext.tsx b/src/components/LangSwitcher/LangSwitcherContext.tsx index b1cd792ff0..3106518e5f 100644 --- a/src/components/LangSwitcher/LangSwitcherContext.tsx +++ b/src/components/LangSwitcher/LangSwitcherContext.tsx @@ -6,7 +6,7 @@ export type LangSwitcherContextType = { defaultLanguage: string | null; updateSelectedLanguage: | null - | ((newLang: string | SupportedLanguage) => void); + | ((newLang: string | SupportedLanguage | undefined) => void); }; const LangSwitcherContext = createContext({ From 6dcbce29dab61bdea8fd49afd3e48d215598c681 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 15 Apr 2025 20:23:32 +0000 Subject: [PATCH 114/137] ci: apply automated fixes --- src/components/LangSwitcher/index.tsx | 2 +- src/components/LangSwitcher/utils.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/LangSwitcher/index.tsx b/src/components/LangSwitcher/index.tsx index 3a66b54538..4635883344 100644 --- a/src/components/LangSwitcher/index.tsx +++ b/src/components/LangSwitcher/index.tsx @@ -33,7 +33,7 @@ export function LangSwitcher({ children, className, ...props }: any) { // biome-ignore lint/suspicious/noExplicitAny: (child: any) => child.language === selectedLanguage || - languagesAreSynonyms(child.language, selectedLanguage) + languagesAreSynonyms(child.language, selectedLanguage), ) || codeBlocks[0]; return ( diff --git a/src/components/LangSwitcher/utils.ts b/src/components/LangSwitcher/utils.ts index af893ad53b..ca3bb30511 100644 --- a/src/components/LangSwitcher/utils.ts +++ b/src/components/LangSwitcher/utils.ts @@ -8,7 +8,7 @@ import { type LanguageInfo, languageInfo } from "./data"; export function getMetaDataWithQuotes( propertyName: string, - metastring: string + metastring: string, ) { const property = `${propertyName}=`; if (!metastring.includes(property)) return null; @@ -88,17 +88,17 @@ export const getCodeBlocks = (children: ReactElement[]): CodeBlockData[] => { export const getLanguageInfo = (language: string) => { return languageInfo.find( (item) => - item.name === language || item?.allNames?.some((alt) => alt === language) + item.name === language || item?.allNames?.some((alt) => alt === language), ); }; export function languagesAreSynonyms( languageToCheck: string, - selectedLanguage: string | null + selectedLanguage: string | null, ) { if (!selectedLanguage) return false; const synonymousLanguage = languageInfo.find((lang: LanguageInfo) => - lang.allNames?.includes(selectedLanguage) + lang.allNames?.includes(selectedLanguage), ); return ( synonymousLanguage?.name === languageToCheck || From d3d70014440a35307861875d2b03fd2ae60a5f4f Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 15 Apr 2025 16:23:38 -0400 Subject: [PATCH 115/137] Another tsx fix --- src/components/LangSwitcher/index.tsx | 2 +- src/components/LangSwitcher/utils.ts | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/components/LangSwitcher/index.tsx b/src/components/LangSwitcher/index.tsx index 4635883344..3a66b54538 100644 --- a/src/components/LangSwitcher/index.tsx +++ b/src/components/LangSwitcher/index.tsx @@ -33,7 +33,7 @@ export function LangSwitcher({ children, className, ...props }: any) { // biome-ignore lint/suspicious/noExplicitAny: (child: any) => child.language === selectedLanguage || - languagesAreSynonyms(child.language, selectedLanguage), + languagesAreSynonyms(child.language, selectedLanguage) ) || codeBlocks[0]; return ( diff --git a/src/components/LangSwitcher/utils.ts b/src/components/LangSwitcher/utils.ts index c06dfb31fe..af893ad53b 100644 --- a/src/components/LangSwitcher/utils.ts +++ b/src/components/LangSwitcher/utils.ts @@ -8,7 +8,7 @@ import { type LanguageInfo, languageInfo } from "./data"; export function getMetaDataWithQuotes( propertyName: string, - metastring: string, + metastring: string ) { const property = `${propertyName}=`; if (!metastring.includes(property)) return null; @@ -55,6 +55,7 @@ export type CodeBlockData = { titleLink?: string; tabName?: string; title?: string; + language?: string; }; info?: LanguageInfo; }; @@ -87,17 +88,17 @@ export const getCodeBlocks = (children: ReactElement[]): CodeBlockData[] => { export const getLanguageInfo = (language: string) => { return languageInfo.find( (item) => - item.name === language || item?.allNames?.some((alt) => alt === language), + item.name === language || item?.allNames?.some((alt) => alt === language) ); }; export function languagesAreSynonyms( languageToCheck: string, - selectedLanguage: string | null, + selectedLanguage: string | null ) { if (!selectedLanguage) return false; const synonymousLanguage = languageInfo.find((lang: LanguageInfo) => - lang.allNames?.includes(selectedLanguage), + lang.allNames?.includes(selectedLanguage) ); return ( synonymousLanguage?.name === languageToCheck || From 3183014e7d4f2bae4122c5ceccd93667516ac9a7 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 15 Apr 2025 16:30:18 -0400 Subject: [PATCH 116/137] More type fixes --- src/theme/DocItem/Content/index.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/theme/DocItem/Content/index.tsx b/src/theme/DocItem/Content/index.tsx index eb9655ae60..c29a258455 100644 --- a/src/theme/DocItem/Content/index.tsx +++ b/src/theme/DocItem/Content/index.tsx @@ -19,12 +19,15 @@ export default function ContentWrapper(props: Props): ReactNode { const storageData = isBrowser ? getStorageLanguageAndTab() : null; const [selectedLanguage, setSelectedLanguage] = useState( - storageData?.defaultLanguage ?? null, + storageData?.defaultLanguage ?? null ); const [selectedTabItem, setSelectedTabItem] = useState( - storageData?.defaultLanguage ?? null, + storageData?.defaultLanguage ?? null ); - const updateSelectedLanguage = (newLang: string | SupportedLanguage) => { + const updateSelectedLanguage = ( + newLang: string | SupportedLanguage | undefined + ) => { + if (!newLang) return; if (isBrowser) { localStorage.setItem(langParamName, newLang); } From 66e9ffe262e45b550276e32f43bac26078718eb0 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Tue, 15 Apr 2025 16:31:35 -0400 Subject: [PATCH 117/137] updating content --- src/theme/DocItem/Content/index.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/theme/DocItem/Content/index.tsx b/src/theme/DocItem/Content/index.tsx index c29a258455..ad3a2aab51 100644 --- a/src/theme/DocItem/Content/index.tsx +++ b/src/theme/DocItem/Content/index.tsx @@ -9,7 +9,7 @@ import { } from "@site/src/components/LangSwitcher/utils"; import Content from "@theme-original/DocItem/Content"; import type ContentType from "@theme/DocItem/Content"; -import { type ReactNode, useState } from "react"; +import { type ReactNode, useEffect, useState } from "react"; import TabListContext from "../../Tabs/TabListContext"; type Props = WrapperProps; @@ -41,6 +41,8 @@ export default function ContentWrapper(props: Props): ReactNode { setSelectedTabItem(newItem); }; + useEffect(() => {}, []); + return ( Date: Tue, 15 Apr 2025 16:38:52 -0400 Subject: [PATCH 118/137] Trying to scroll sidebar items into view --- src/theme/DocItem/Content/index.tsx | 4 +--- src/theme/DocSidebarItems/index.tsx | 36 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 src/theme/DocSidebarItems/index.tsx diff --git a/src/theme/DocItem/Content/index.tsx b/src/theme/DocItem/Content/index.tsx index ad3a2aab51..c29a258455 100644 --- a/src/theme/DocItem/Content/index.tsx +++ b/src/theme/DocItem/Content/index.tsx @@ -9,7 +9,7 @@ import { } from "@site/src/components/LangSwitcher/utils"; import Content from "@theme-original/DocItem/Content"; import type ContentType from "@theme/DocItem/Content"; -import { type ReactNode, useEffect, useState } from "react"; +import { type ReactNode, useState } from "react"; import TabListContext from "../../Tabs/TabListContext"; type Props = WrapperProps; @@ -41,8 +41,6 @@ export default function ContentWrapper(props: Props): ReactNode { setSelectedTabItem(newItem); }; - useEffect(() => {}, []); - return ( + {visibleItems.map((item, index) => { + if (isActiveSidebarItem(item, props.activePath)) { + // Scroll to the active item + const element = document.getElementById(item.id); + if (element) { + element.scrollIntoView({ + behavior: "smooth", + block: "nearest", + }); + } + } + return ( + + ); + })} + + ); +} + +// Optimize sidebar at each "level" +export default memo(DocSidebarItems); From 888ec47228c78b573e7e16605fcdb38f8c99fb42 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Wed, 16 Apr 2025 10:34:09 -0400 Subject: [PATCH 119/137] Made sidebar scroll to the item in view --- src/components/CodeBlockWithInfo/index.tsx | 4 +- src/theme/DocSidebar/{index.js => index.tsx} | 7 +- src/theme/DocSidebarItem/Link/index.tsx | 66 +++++++++++++++++++ .../DocSidebarItem/Link/styles.module.css | 3 + src/theme/DocSidebarItems/index.tsx | 36 ---------- 5 files changed, 76 insertions(+), 40 deletions(-) rename src/theme/DocSidebar/{index.js => index.tsx} (55%) create mode 100644 src/theme/DocSidebarItem/Link/index.tsx create mode 100644 src/theme/DocSidebarItem/Link/styles.module.css delete mode 100644 src/theme/DocSidebarItems/index.tsx diff --git a/src/components/CodeBlockWithInfo/index.tsx b/src/components/CodeBlockWithInfo/index.tsx index 2ff515f157..4e31664eb4 100644 --- a/src/components/CodeBlockWithInfo/index.tsx +++ b/src/components/CodeBlockWithInfo/index.tsx @@ -41,7 +41,9 @@ export function CodeBlockWithInfo({ }: CodeBlockWithInfoProps) { const collapsible = !meta ? false - : meta.collapsible && content.split("\n").length > collapseLineNumber; + : meta.collapsible && + content && + content.split("\n").length > collapseLineNumber; const indentation = meta?.indentation === "tabs" ? "tabs" : "spaces"; return ( diff --git a/src/theme/DocSidebar/index.js b/src/theme/DocSidebar/index.tsx similarity index 55% rename from src/theme/DocSidebar/index.js rename to src/theme/DocSidebar/index.tsx index a786862b4e..c2d98ba91e 100644 --- a/src/theme/DocSidebar/index.js +++ b/src/theme/DocSidebar/index.tsx @@ -1,11 +1,12 @@ import DocSidebar from "@theme-original/DocSidebar"; import SearchBar from "@theme/SearchBar"; -export default function DocSidebarWrapper(props) { +// biome-ignore lint/suspicious/noExplicitAny: +export default function DocSidebarWrapper(props: any) { return ( - <> +
- +
); } diff --git a/src/theme/DocSidebarItem/Link/index.tsx b/src/theme/DocSidebarItem/Link/index.tsx new file mode 100644 index 0000000000..cbac1d9302 --- /dev/null +++ b/src/theme/DocSidebarItem/Link/index.tsx @@ -0,0 +1,66 @@ +import { useEffect, useRef, type ReactNode } from "react"; +import clsx from "clsx"; +import { ThemeClassNames } from "@docusaurus/theme-common"; +import { isActiveSidebarItem } from "@docusaurus/plugin-content-docs/client"; +import Link from "@docusaurus/Link"; +import isInternalUrl from "@docusaurus/isInternalUrl"; +import IconExternalLink from "@theme/Icon/ExternalLink"; +import type { Props } from "@theme/DocSidebarItem/Link"; + +import styles from "./styles.module.css"; + +export default function DocSidebarItemLink({ + item, + onItemClick, + activePath, + level, + index, + ...props +}: Props): ReactNode { + const { href, label, className, autoAddBaseUrl } = item; + const isActive = isActiveSidebarItem(item, activePath); + const isInternalLink = isInternalUrl(href); + const itemRef = useRef(null); + + useEffect(() => { + if (isActive && itemRef.current) { + itemRef.current.scrollIntoView({ + behavior: "smooth", + block: "nearest", + inline: "nearest", + }); + } + }, [isActive]); + return ( +
  • + onItemClick(item) : undefined, + })} + {...props} + > + {label} + {!isInternalLink && } + +
  • + ); +} diff --git a/src/theme/DocSidebarItem/Link/styles.module.css b/src/theme/DocSidebarItem/Link/styles.module.css new file mode 100644 index 0000000000..acba7f3f2f --- /dev/null +++ b/src/theme/DocSidebarItem/Link/styles.module.css @@ -0,0 +1,3 @@ +.menuExternalLink { + align-items: center; +} diff --git a/src/theme/DocSidebarItems/index.tsx b/src/theme/DocSidebarItems/index.tsx deleted file mode 100644 index 00b72158e0..0000000000 --- a/src/theme/DocSidebarItems/index.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { memo, type ReactNode } from "react"; -import { - DocSidebarItemsExpandedStateProvider, - useVisibleSidebarItems, - isActiveSidebarItem, -} from "@docusaurus/plugin-content-docs/client"; -import DocSidebarItem from "@theme/DocSidebarItem"; - -import type { Props } from "@theme/DocSidebarItems"; - -function DocSidebarItems({ items, ...props }: Props): ReactNode { - const visibleItems = useVisibleSidebarItems(items, props.activePath); - - return ( - - {visibleItems.map((item, index) => { - if (isActiveSidebarItem(item, props.activePath)) { - // Scroll to the active item - const element = document.getElementById(item.id); - if (element) { - element.scrollIntoView({ - behavior: "smooth", - block: "nearest", - }); - } - } - return ( - - ); - })} - - ); -} - -// Optimize sidebar at each "level" -export default memo(DocSidebarItems); From 701910bc4954530cbc7f165eb2cd2ed4fce66b6f Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Wed, 16 Apr 2025 14:34:12 +0000 Subject: [PATCH 120/137] ci: apply automated fixes --- src/components/CodeBlockWithInfo/index.tsx | 4 ++-- src/theme/DocItem/Content/index.tsx | 6 +++--- src/theme/DocSidebarItem/Link/index.tsx | 14 +++++++------- src/theme/DocSidebarItem/Link/styles.module.css | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/components/CodeBlockWithInfo/index.tsx b/src/components/CodeBlockWithInfo/index.tsx index 4e31664eb4..ee512fd665 100644 --- a/src/components/CodeBlockWithInfo/index.tsx +++ b/src/components/CodeBlockWithInfo/index.tsx @@ -42,8 +42,8 @@ export function CodeBlockWithInfo({ const collapsible = !meta ? false : meta.collapsible && - content && - content.split("\n").length > collapseLineNumber; + content && + content.split("\n").length > collapseLineNumber; const indentation = meta?.indentation === "tabs" ? "tabs" : "spaces"; return ( diff --git a/src/theme/DocItem/Content/index.tsx b/src/theme/DocItem/Content/index.tsx index c29a258455..adb03e2557 100644 --- a/src/theme/DocItem/Content/index.tsx +++ b/src/theme/DocItem/Content/index.tsx @@ -19,13 +19,13 @@ export default function ContentWrapper(props: Props): ReactNode { const storageData = isBrowser ? getStorageLanguageAndTab() : null; const [selectedLanguage, setSelectedLanguage] = useState( - storageData?.defaultLanguage ?? null + storageData?.defaultLanguage ?? null, ); const [selectedTabItem, setSelectedTabItem] = useState( - storageData?.defaultLanguage ?? null + storageData?.defaultLanguage ?? null, ); const updateSelectedLanguage = ( - newLang: string | SupportedLanguage | undefined + newLang: string | SupportedLanguage | undefined, ) => { if (!newLang) return; if (isBrowser) { diff --git a/src/theme/DocSidebarItem/Link/index.tsx b/src/theme/DocSidebarItem/Link/index.tsx index cbac1d9302..daa04cfafb 100644 --- a/src/theme/DocSidebarItem/Link/index.tsx +++ b/src/theme/DocSidebarItem/Link/index.tsx @@ -1,11 +1,11 @@ -import { useEffect, useRef, type ReactNode } from "react"; -import clsx from "clsx"; -import { ThemeClassNames } from "@docusaurus/theme-common"; -import { isActiveSidebarItem } from "@docusaurus/plugin-content-docs/client"; import Link from "@docusaurus/Link"; import isInternalUrl from "@docusaurus/isInternalUrl"; -import IconExternalLink from "@theme/Icon/ExternalLink"; +import { isActiveSidebarItem } from "@docusaurus/plugin-content-docs/client"; +import { ThemeClassNames } from "@docusaurus/theme-common"; import type { Props } from "@theme/DocSidebarItem/Link"; +import IconExternalLink from "@theme/Icon/ExternalLink"; +import clsx from "clsx"; +import { type ReactNode, useEffect, useRef } from "react"; import styles from "./styles.module.css"; @@ -38,7 +38,7 @@ export default function DocSidebarItemLink({ ThemeClassNames.docs.docSidebarItemLink, ThemeClassNames.docs.docSidebarItemLinkLevel(level), "menu__list-item", - className + className, )} key={label} > @@ -48,7 +48,7 @@ export default function DocSidebarItemLink({ !isInternalLink && styles.menuExternalLink, { "menu__link--active": isActive, - } + }, )} autoAddBaseUrl={autoAddBaseUrl} aria-current={isActive ? "page" : undefined} diff --git a/src/theme/DocSidebarItem/Link/styles.module.css b/src/theme/DocSidebarItem/Link/styles.module.css index acba7f3f2f..bcadcc85b6 100644 --- a/src/theme/DocSidebarItem/Link/styles.module.css +++ b/src/theme/DocSidebarItem/Link/styles.module.css @@ -1,3 +1,3 @@ .menuExternalLink { - align-items: center; + align-items: center; } From 818453a95722396a174da47d847fc34c5e4d9322 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Wed, 16 Apr 2025 11:05:42 -0400 Subject: [PATCH 121/137] Center the sidebar item --- src/theme/DocSidebarItem/Link/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/theme/DocSidebarItem/Link/index.tsx b/src/theme/DocSidebarItem/Link/index.tsx index cbac1d9302..b7be63e59c 100644 --- a/src/theme/DocSidebarItem/Link/index.tsx +++ b/src/theme/DocSidebarItem/Link/index.tsx @@ -26,7 +26,7 @@ export default function DocSidebarItemLink({ if (isActive && itemRef.current) { itemRef.current.scrollIntoView({ behavior: "smooth", - block: "nearest", + block: "center", inline: "nearest", }); } From b12cf1e13ba7935d6fbfff7a17b288c35d66310f Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Wed, 16 Apr 2025 11:14:59 -0400 Subject: [PATCH 122/137] Cleanup comments; fix unnecessary export from redirects --- sidebars.js | 48 ---------------------------------- static/scripts/fix-redirect.js | 10 +++---- 2 files changed, 5 insertions(+), 53 deletions(-) diff --git a/sidebars.js b/sidebars.js index 091f9c88dd..6e950c60b4 100644 --- a/sidebars.js +++ b/sidebars.js @@ -209,54 +209,6 @@ const sidebars = { "universal-gateway/ip-addresses", "universal-gateway/points-of-presence", "universal-gateway/ddos-protection", - // { - // label: "Endpoints", - // type: "category", - // link: { type: "doc", id: "universal-gateway/endpoints" }, - // items: [ - // { - // label: "Bindings", - // type: "category", - // link: { type: "doc", id: "universal-gateway/bindings" }, - // items: [ - // { - // id: "universal-gateway/public-endpoints/index", - // type: "doc", - // label: "Public", - // }, - // { - // id: "universal-gateway/internal-endpoints/index", - // type: "doc", - // label: "Internal", - // }, - // { - // id: "universal-gateway/kubernetes-endpoints/index", - // type: "doc", - // label: "Kubernetes", - // }, - // ], - // }, - // { - // id: "universal-gateway/endpoint-pooling", - // type: "doc", - // label: "Pooling", - // }, - // ], - // }, - // { - // label: "Network", - // type: "category", - // link: { - // type: "doc", - // id: "universal-gateway/global-load-balancer", - // }, - // items: [ - // "universal-gateway/global-load-balancer", - // "universal-gateway/ddos-protection", - // "universal-gateway/ip-addresses", - // "universal-gateway/points-of-presence", - // ], - // }, ], }, { diff --git a/static/scripts/fix-redirect.js b/static/scripts/fix-redirect.js index 72ae9b5086..037117e407 100644 --- a/static/scripts/fix-redirect.js +++ b/static/scripts/fix-redirect.js @@ -1,18 +1,18 @@ questionAnswerRedirects = require("./redirects/question-answer-redirects"); -export const getNormalizedPaths = (from, path) => { +const getNormalizedPaths = (from, path) => { return { normalizedFrom: from.endsWith("/") ? from.slice(0, -1) : from, normalizedPath: path.endsWith("/") ? path.slice(0, -1) : path, }; }; -export const fromExact = (from) => (path) => { +const fromExact = (from) => (path) => { const { normalizedFrom, normalizedPath } = getNormalizedPaths(from, path); return [normalizedFrom, normalizedPath === normalizedFrom]; // [xyz] }; -export const fromIncludes = (from) => (path) => { +const fromIncludes = (from) => (path) => { // Normalize both paths by removing trailing slashes if present const { normalizedFrom, normalizedPath } = getNormalizedPaths(from, path); @@ -20,8 +20,8 @@ export const fromIncludes = (from) => (path) => { return [normalizedFrom, normalizedPath.includes(normalizedFrom)]; }; -export const toExact = (to) => () => to; // x -> y -export const toReplace = (to) => (path, from) => path.replace(from, to); // abc/x -> xyz/x +const toExact = (to) => () => to; // x -> y +const toReplace = (to) => (path, from) => path.replace(from, to); // abc/x -> xyz/x // List of redirects // String values are treated as exacts by default. From 0c6f17047bc1038bcc8c36e2c6d5fe9cfc3558f1 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Wed, 16 Apr 2025 12:09:18 -0400 Subject: [PATCH 123/137] Renaming some files p1 --- docs/overview/index.mdx | 6 +- .../forward-original-connection-data.mdx | 23 ++--- .../agent-forwarding/non-local-forwarding.mdx | 3 +- .../serving-file-directories.mdx | 5 +- docs/universal-gateway/ip-addresses.mdx | 3 +- docs/universal-gateway/points-of-presence.mdx | 3 +- .../universal-gateway/tcp-addresses/index.mdx | 2 +- examples/k8s/custom-agent-ingress.mdx | 2 +- examples/k8s/explicit-region.mdx | 2 +- sidebars.js | 4 +- static/scripts/fix-redirect.js | 90 ++++++++++++++++++- .../redirects/question-answer-redirects.js | 89 ------------------ 12 files changed, 113 insertions(+), 119 deletions(-) delete mode 100644 static/scripts/redirects/question-answer-redirects.js diff --git a/docs/overview/index.mdx b/docs/overview/index.mdx index 886a9f72f9..7c99a4d9d6 100644 --- a/docs/overview/index.mdx +++ b/docs/overview/index.mdx @@ -13,21 +13,21 @@ import Link from "@docusaurus/Link"; ngrok is your app's front door. ngrok is a globally distributed reverse proxy that secures, protects and accelerates your applications and network services, no matter where you run them. ngrok supports delivering HTTP, TLS or TCP-based - applications. More about how ngrok works → + applications. More about how ngrok works →

    You can use ngrok in development for webhook testing or in production as an API Gateway, Kubernetes Ingress, or Identity-Aware Proxy. You can also run ngrok to easily create secure connectivity to APIs in your customers' networks or on your devices in the field.{" "} - More about what you can do with ngrok → + More about what you can do with ngrok →

    ## Get Started
    diff --git a/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx b/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx index 519740c21b..f09ea1819c 100644 --- a/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx +++ b/docs/universal-gateway/agent-forwarding/forward-original-connection-data.mdx @@ -1,5 +1,6 @@ --- -title: How Do I Forward Original Connection Data? +title: Forwarding Original Connection Data +description: Learn how to forward original connection data to your upstream services. --- import TabItem from "@theme/TabItem"; @@ -11,21 +12,17 @@ import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitch import ProxyProtoAgentConfigExample from "/examples/agent-config/tcp-proxyproto.mdx"; import ProxyProtoKubernetesExample from "/examples/k8s/tcp-proxyproto.mdx"; -When you forward traffic to an upstream TCP service, becuase traffic is coming -from the ngrok agent, it won't know the client's original IP address. You can -add the [PROXY -protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) header -on connections to your upstream service to send connection information like the -original client IP address to your upstream service. You will need to configure -your upstream service to handle the PROXY protocol header. +When you forward traffic to an upstream TCP service, becuase traffic is coming from the ngrok agent, it won't have access to connection information like the original client IP address. You can add the [PROXY protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) header on connections to your upstream service to send original connection information to your upstream service. + +You will need to configure your upstream service to handle the PROXY protocol header. :::info -PROXY protocol is not support for: SSH +PROXY protocol is not support for SSH ::: -## TCP proxy protocol +## TCP proxy protocol example @@ -110,11 +107,7 @@ const ngrok = require("@ngrok/ngrok"); -## TLS proxy protocol - -Add a [PROXY protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) header -on connection to your upstream service. This sends connection information like -the original client IP address to your upstream service. +## TLS proxy protocol example diff --git a/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx b/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx index 9c00d1b0e0..8e8292fdae 100644 --- a/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx +++ b/docs/universal-gateway/agent-forwarding/non-local-forwarding.mdx @@ -1,5 +1,6 @@ --- -title: How Does Non-Local Forwarding Work? +title: Forwarding Traffic to External Services +description: Learn how to forward traffic to a non-local address or URL. --- import TabItem from "@theme/TabItem"; diff --git a/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx b/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx index 81b5f30ad2..42ac480ac7 100644 --- a/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx +++ b/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx @@ -1,5 +1,6 @@ --- -title: How Do I Serve File Directories? +title: Serving File Directories +description: Learn how to serve content from a local directory using the ngrok agent. --- import TabItem from "@theme/TabItem"; @@ -7,7 +8,7 @@ import Tabs from "@theme/Tabs"; import { LangSwitcher } from "@site/src/components/LangSwitcher"; -The ngrok agent supports the `file://` scheme in [a forwarding URL](/universal-gateway/agent-forwarding/). When you use the `file://` scheme, the ngrok agent serves local file system directories by using its own built-in file server, no separate server needed. It works just like `python3 -m http.server` but it is built directly into the ngrok agent. +The ngrok agent supports the `file://` scheme in [a forwarding URL](/universal-gateway/agent-forwarding/). When you use the `file://` scheme, the ngrok agent serves local file system directories by using its own built-in file server, no separate server needed. It works just like [`python3 -m http.server`](https://docs.python.org/3.4/library/http.server.html), but it is built directly into the ngrok agent. Paths in `file://` URLs must be specified as absolute paths. diff --git a/docs/universal-gateway/ip-addresses.mdx b/docs/universal-gateway/ip-addresses.mdx index 2f6ce3aadc..ebbd2a6680 100644 --- a/docs/universal-gateway/ip-addresses.mdx +++ b/docs/universal-gateway/ip-addresses.mdx @@ -1,5 +1,6 @@ --- -title: How Do ngrok's IP Addresses Work? +sidebar_label: How IP Addresses Work +title: IP Addresses description: Learn how ngrok assigns IPs for endpoints, agent connections, and the dashboard API. --- diff --git a/docs/universal-gateway/points-of-presence.mdx b/docs/universal-gateway/points-of-presence.mdx index acc25995df..1c6ae95432 100644 --- a/docs/universal-gateway/points-of-presence.mdx +++ b/docs/universal-gateway/points-of-presence.mdx @@ -1,5 +1,6 @@ --- -title: Where Are ngrok's Points of Presence? +title: Points of Presence +sidebar_label: Where Are ngrok's Points of Presence? description: Learn about ngrok's globally distributed points of presence. --- diff --git a/docs/universal-gateway/tcp-addresses/index.mdx b/docs/universal-gateway/tcp-addresses/index.mdx index 8163fb5971..307bc43f60 100644 --- a/docs/universal-gateway/tcp-addresses/index.mdx +++ b/docs/universal-gateway/tcp-addresses/index.mdx @@ -1,5 +1,5 @@ --- -title: What Are TCP Addresses? +title: Using TCP Addresses description: Learn how to use TCP Addresses with ngrok. --- diff --git a/examples/k8s/custom-agent-ingress.mdx b/examples/k8s/custom-agent-ingress.mdx index 69fa9a9ac3..ca2e009f9d 100644 --- a/examples/k8s/custom-agent-ingress.mdx +++ b/examples/k8s/custom-agent-ingress.mdx @@ -1,4 +1,4 @@ -In your Helm values.yaml file, set +In your Helm `values.yaml` file, set ``` serverAddr: "tunnel.us.ingress.example.com:443" diff --git a/examples/k8s/explicit-region.mdx b/examples/k8s/explicit-region.mdx index bd3d4b0194..4d0d0aaae9 100644 --- a/examples/k8s/explicit-region.mdx +++ b/examples/k8s/explicit-region.mdx @@ -1,4 +1,4 @@ -In your Helm values.yaml file, set +In your Helm `values.yaml` file, set ``` serverAddr: "connect.eu.ngrok-agent.com:443" diff --git a/sidebars.js b/sidebars.js index 6e950c60b4..b699f2d9f8 100644 --- a/sidebars.js +++ b/sidebars.js @@ -62,7 +62,7 @@ const sidebars = { ], }, { - label: "What are TCP Addresses?", + label: "Using TCP Addresses", type: "category", link: { type: "doc", @@ -72,6 +72,7 @@ const sidebars = { "universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned", ], }, + "universal-gateway/ip-addresses", { label: "What are Endpoints?", type: "category", @@ -206,7 +207,6 @@ const sidebars = { "universal-gateway/global-load-balancer/gslb-agents", ], }, - "universal-gateway/ip-addresses", "universal-gateway/points-of-presence", "universal-gateway/ddos-protection", ], diff --git a/static/scripts/fix-redirect.js b/static/scripts/fix-redirect.js index 037117e407..0e59302098 100644 --- a/static/scripts/fix-redirect.js +++ b/static/scripts/fix-redirect.js @@ -1,4 +1,3 @@ -questionAnswerRedirects = require("./redirects/question-answer-redirects"); const getNormalizedPaths = (from, path) => { return { @@ -832,7 +831,6 @@ const redirects = [ [fromExact("/docs/http/"), "/docs/universal-gateway/http/"], [fromExact("/docs/tcp/"), "/docs/universal-gateway/tcp/"], [fromExact("/docs/tls/"), "/docs/universal-gateway/tls/"], - ...questionAnswerRedirects, // Kubernetes Operator Revamp [ fromExact("/docs/k8s/advanced-deployments/"), @@ -857,6 +855,94 @@ const redirects = [ [fromExact("/docs/k8s/custom-domain/"), "/docs/k8s/guides/custom-domain/"], [fromExact("/docs/k8s/user-guide/"), "/docs/k8s/"], [fromExact("/docs/k8s/with-edges/"), "/docs/k8s/guides/using-ingresses/"], + + // Question/Answer restructure redirects + + /** + * Universal Gateway > Concepts + */ + // Domains + [ + fromExact("/docs/universal-gateway/domains/"), + "/docs/universal-gateway/domains/what-are-domains/", + ], + // hashes + [ + fromExact("/docs/universal-gateway/domains/#branded-domains"), + "/docs/universal-gateway/domains/how-do-i-use-my-own-domain/", + ], + [ + fromExact("/docs/universal-gateway/domains/#global-load-balancer"), + "/docs/universal-gateway/global-load-balancer/", + ], + [ + fromExact("/docs/universal-gateway/domains/#public-endpoints"), + "/docs/universal-gateway/public-endpoints/", + ], + [ + fromExact("/docs/universal-gateway/domains/#ngrok-managed-domains"), + "/docs/universal-gateway/domains/what-are-managed-domains/", + ], + [ + fromExact("/docs/universal-gateway/domains/#hsts-preload"), + "/docs/universal-gateway/domains/what-are-managed-domains/#hsts-preload", + ], + [ + fromExact("/docs/universal-gateway/domains/#public-suffix-list"), + "/docs/universal-gateway/domains/what-are-managed-domains/#public-suffix-list", + ], + + // TCP Addresses + [ + fromExact("/docs/universal-gateway/tcp-addresses/"), + "/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses/", + ], + // hashes + [ + fromExact( + "/docs/universal-gateway/tcp-addresses/#public-endpoint-creation", + ), + "/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses/", + ], + [ + fromExact("/docs/universal-gateway/tcp-addresses/#address-assignment"), + "/docs/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned/", + ], + [ + fromExact("/docs/universal-gateway/tcp-addresses/#global-load-balancer/"), + "/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses/#tcp-address-load-balancing", + ], + + //TLS Certificates + [ + fromExact("/docs/universal-gateway/tls-certificates/"), + "/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls", + ], + // hashes + [ + fromExact("/docs/universal-gateway/tls-certificates/#automated"), + "/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management", + ], + [ + fromExact( + "/docs/universal-gateway/tls-certificates/#certificate-selection", + ), + "/docs/universal-gateway/tls-certificates/how-are-certificates-selected", + ], + [ + fromExact( + "/docs/universal-gateway/tls-certificates/#certificate-provisioning", + ), + "/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls#how-certificates-work", + ], + [ + fromExact("/docs/universal-gateway/tls-certificates/#certificate-bundles"), + "/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle/", + ], + [ + fromExact("/docs/universal-gateway/tls-certificates/#private-keys"), + "/docs/universal-gateway/tls-certificates/what-are-private-tls-keys/", + ], ]; // get current href from window diff --git a/static/scripts/redirects/question-answer-redirects.js b/static/scripts/redirects/question-answer-redirects.js deleted file mode 100644 index 7246ab76f0..0000000000 --- a/static/scripts/redirects/question-answer-redirects.js +++ /dev/null @@ -1,89 +0,0 @@ -import { fromExact } from "../fix-redirect"; - -export default [ - /** - * Universal Gateway > Concepts - */ - // Domains - [ - fromExact("/docs/universal-gateway/domains/"), - "/docs/universal-gateway/domains/what-are-domains/", - ], - // hashes - [ - fromExact("/docs/universal-gateway/domains/#branded-domains"), - "/docs/universal-gateway/domains/how-do-i-use-my-own-domain/", - ], - [ - fromExact("/docs/universal-gateway/domains/#global-load-balancer"), - "/docs/universal-gateway/global-load-balancer/", - ], - [ - fromExact("/docs/universal-gateway/domains/#public-endpoints"), - "/docs/universal-gateway/public-endpoints/", - ], - [ - fromExact("/docs/universal-gateway/domains/#ngrok-managed-domains"), - "/docs/universal-gateway/domains/what-are-managed-domains/", - ], - [ - fromExact("/docs/universal-gateway/domains/#hsts-preload"), - "/docs/universal-gateway/domains/what-are-managed-domains/#hsts-preload", - ], - [ - fromExact("/docs/universal-gateway/domains/#public-suffix-list"), - "/docs/universal-gateway/domains/what-are-managed-domains/#public-suffix-list", - ], - - // TCP Addresses - [ - fromExact("/docs/universal-gateway/tcp-addresses/"), - "/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses/", - ], - // hashes - [ - fromExact( - "/docs/universal-gateway/tcp-addresses/#public-endpoint-creation", - ), - "/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses/", - ], - [ - fromExact("/docs/universal-gateway/tcp-addresses/#address-assignment"), - "/docs/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned/", - ], - [ - fromExact("/docs/universal-gateway/tcp-addresses/#global-load-balancer/"), - "/docs/universal-gateway/tcp-addresses/what-are-tcp-addresses/#tcp-address-load-balancing", - ], - - //TLS Certificates - [ - fromExact("/docs/universal-gateway/tls-certificates/"), - "/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls", - ], - // hashes - [ - fromExact("/docs/universal-gateway/tls-certificates/#automated"), - "/docs/universal-gateway/tls-certificates/what-is-automatic-certificate-management", - ], - [ - fromExact( - "/docs/universal-gateway/tls-certificates/#certificate-selection", - ), - "/docs/universal-gateway/tls-certificates/how-are-certificates-selected", - ], - [ - fromExact( - "/docs/universal-gateway/tls-certificates/#certificate-provisioning", - ), - "/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls#how-certificates-work", - ], - [ - fromExact("/docs/universal-gateway/tls-certificates/#certificate-bundles"), - "/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle/", - ], - [ - fromExact("/docs/universal-gateway/tls-certificates/#private-keys"), - "/docs/universal-gateway/tls-certificates/what-are-private-tls-keys/", - ], -]; From 506675c2daba71d08efc09606b3474b8385561b8 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Wed, 16 Apr 2025 16:09:20 +0000 Subject: [PATCH 124/137] ci: apply automated fixes --- static/scripts/fix-redirect.js | 1 - 1 file changed, 1 deletion(-) diff --git a/static/scripts/fix-redirect.js b/static/scripts/fix-redirect.js index 0e59302098..bf1919387c 100644 --- a/static/scripts/fix-redirect.js +++ b/static/scripts/fix-redirect.js @@ -1,4 +1,3 @@ - const getNormalizedPaths = (from, path) => { return { normalizedFrom: from.endsWith("/") ? from.slice(0, -1) : from, From bab63b93376d9c02c3cf636d965cbbdb16fe8f5f Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Wed, 16 Apr 2025 12:25:54 -0400 Subject: [PATCH 125/137] Remove mention of Edges --- docs/universal-gateway/overview.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/universal-gateway/overview.mdx b/docs/universal-gateway/overview.mdx index b66f2a79dc..467eff58b9 100644 --- a/docs/universal-gateway/overview.mdx +++ b/docs/universal-gateway/overview.mdx @@ -19,7 +19,6 @@ Learn more about Universal Gateway Concepts: - [Domains →](/universal-gateway/domains/what-are-domains/) - [TCP Addresses →](/universal-gateway/tcp-addresses/) - [TLS Certificates →](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/) -- [Edges →](/universal-gateway/edges/) ## Endpoints From 90d5b634bc1dd62f46f77e793463f940ac2b3928 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Wed, 16 Apr 2025 13:21:11 -0400 Subject: [PATCH 126/137] Remove warning about k8s endpoints; they're on paygo --- docs/universal-gateway/kubernetes-endpoints/index.mdx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/docs/universal-gateway/kubernetes-endpoints/index.mdx b/docs/universal-gateway/kubernetes-endpoints/index.mdx index 9f72a05b0c..292f49705b 100644 --- a/docs/universal-gateway/kubernetes-endpoints/index.mdx +++ b/docs/universal-gateway/kubernetes-endpoints/index.mdx @@ -2,13 +2,6 @@ title: What are Kubernetes Endpoints? --- -:::info Coming Soon - -Kubernetes endpoints are not available yet, [request access to the developer -preview](https://dashboard.ngrok.com/developer-preview) for early access. - -::: - Kubernetes endpoints are secure, private endpoints that are only addressable inside of Kubernetes clusters where you install the [Kubernetes Operator](/k8s/). They enable you to connect to ngrok endpoints without making them publicly addressable. From 674e21bacb478cf89810434aadd36c68c859a18b Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 1 May 2025 15:36:37 -0400 Subject: [PATCH 127/137] Move wildcard endpoints --- sidebars.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sidebars.js b/sidebars.js index b699f2d9f8..9f764e254b 100644 --- a/sidebars.js +++ b/sidebars.js @@ -58,7 +58,6 @@ const sidebars = { "universal-gateway/domains/bring-your-own-domain", "universal-gateway/domains/what-are-managed-domains", "universal-gateway/wildcard-domains/index", - "universal-gateway/wildcard-domains/wildcard-endpoints", ], }, { @@ -116,6 +115,7 @@ const sidebars = { ], }, "universal-gateway/what-are-endpoint-urls", + "universal-gateway/wildcard-domains/wildcard-endpoints", "universal-gateway/http-s/endpoint-url-defaults", "universal-gateway/chain-endpoints", "universal-gateway/mock-api", From 10420783d97d06b7acd71844690958b43a363424 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 1 May 2025 15:37:41 -0400 Subject: [PATCH 128/137] Moving tcp addresses and endpoints up --- sidebars.js | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/sidebars.js b/sidebars.js index 9f764e254b..f9b54e09a8 100644 --- a/sidebars.js +++ b/sidebars.js @@ -47,31 +47,6 @@ const sidebars = { link: { type: "doc", id: "universal-gateway/overview" }, items: [ "universal-gateway/overview", - { - label: "What are Domains?", - type: "category", - link: { - type: "doc", - id: "universal-gateway/domains/what-are-domains", - }, - items: [ - "universal-gateway/domains/bring-your-own-domain", - "universal-gateway/domains/what-are-managed-domains", - "universal-gateway/wildcard-domains/index", - ], - }, - { - label: "Using TCP Addresses", - type: "category", - link: { - type: "doc", - id: "universal-gateway/tcp-addresses/index", - }, - items: [ - "universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned", - ], - }, - "universal-gateway/ip-addresses", { label: "What are Endpoints?", type: "category", @@ -122,6 +97,31 @@ const sidebars = { "universal-gateway/migrate-from-tunnels", ], }, + { + label: "Using TCP Addresses", + type: "category", + link: { + type: "doc", + id: "universal-gateway/tcp-addresses/index", + }, + items: [ + "universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned", + ], + }, + { + label: "What are Domains?", + type: "category", + link: { + type: "doc", + id: "universal-gateway/domains/what-are-domains", + }, + items: [ + "universal-gateway/domains/bring-your-own-domain", + "universal-gateway/domains/what-are-managed-domains", + "universal-gateway/wildcard-domains/index", + ], + }, + "universal-gateway/ip-addresses", { label: "Handling HTTP/S Traffic", type: "category", From 6b8f82ba145f9ee2a808c76234a160220a57c58d Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 1 May 2025 16:07:26 -0400 Subject: [PATCH 129/137] Some cleanup --- .../http-s/http-s-endpoints.mdx | 4 +- .../http-s/upstream-headers.mdx | 3 +- .../automatic-certificate-management.mdx | 1 + .../tls-certificates/custom-certificates.mdx | 2 +- .../how-are-certificates-selected.mdx | 3 +- .../how-does-ngrok-handle-tls.mdx | 2 +- .../what-are-private-tls-keys.mdx | 2 +- .../what-is-a-certificate-bundle.mdx | 3 +- docs/universal-gateway/tls/handshake.mdx | 2 +- docs/universal-gateway/tls/tls-clients.mdx | 2 +- .../tls/tls-termination/index.mdx | 2 +- .../tls-termination/termination-location.mdx | 4 +- .../tls-termination/termination-mechanics.mdx | 2 +- sidebars.js | 103 ++++++++++-------- static/scripts/fix-redirect.js | 4 + 15 files changed, 77 insertions(+), 62 deletions(-) diff --git a/docs/universal-gateway/http-s/http-s-endpoints.mdx b/docs/universal-gateway/http-s/http-s-endpoints.mdx index da2ea8edfc..1adfebf921 100644 --- a/docs/universal-gateway/http-s/http-s-endpoints.mdx +++ b/docs/universal-gateway/http-s/http-s-endpoints.mdx @@ -1,6 +1,6 @@ --- -title: How do HTTP/S Endpoints Work? -description: Learn how ngrok's HTTP/S endpoints support websockets, HTTP/2, and more. +title: How HTTP/S Endpoints Work +description: Learn the technical details of how ngrok's HTTP/S endpoints work. --- [HTTP/S endpoints](/universal-gateway/https-s) are standards-compliant HTTP reverse proxies. diff --git a/docs/universal-gateway/http-s/upstream-headers.mdx b/docs/universal-gateway/http-s/upstream-headers.mdx index 99a72e1962..ab4093720f 100644 --- a/docs/universal-gateway/http-s/upstream-headers.mdx +++ b/docs/universal-gateway/http-s/upstream-headers.mdx @@ -1,5 +1,6 @@ --- -title: How Do Upstream Headers Work with HTTP/S? +title: Forwarded Headers Reference +description: ngrok adds headers to each HTTP request with information about the upstream client. --- ngrok adds headers to each [HTTP request](/universal-gateway/http-s/) with information about the original diff --git a/docs/universal-gateway/tls-certificates/automatic-certificate-management.mdx b/docs/universal-gateway/tls-certificates/automatic-certificate-management.mdx index 9e8066e349..5d99e14dfa 100644 --- a/docs/universal-gateway/tls-certificates/automatic-certificate-management.mdx +++ b/docs/universal-gateway/tls-certificates/automatic-certificate-management.mdx @@ -1,4 +1,5 @@ --- +sidebar_label: Automatic Certificate Management title: What Is Automatic Certificate Management? description: Learn how ngrok provisions TLS certificates. --- diff --git a/docs/universal-gateway/tls-certificates/custom-certificates.mdx b/docs/universal-gateway/tls-certificates/custom-certificates.mdx index 998ca5872f..86b5c241b4 100644 --- a/docs/universal-gateway/tls-certificates/custom-certificates.mdx +++ b/docs/universal-gateway/tls-certificates/custom-certificates.mdx @@ -1,5 +1,5 @@ --- -title: How Do I Use My Own Certificates? +title: Using Your Own Certificates description: Learn how to use your own TLS certificates rather than automatic certificate management. --- diff --git a/docs/universal-gateway/tls-certificates/how-are-certificates-selected.mdx b/docs/universal-gateway/tls-certificates/how-are-certificates-selected.mdx index 94280beb9c..41de6d79bf 100644 --- a/docs/universal-gateway/tls-certificates/how-are-certificates-selected.mdx +++ b/docs/universal-gateway/tls-certificates/how-are-certificates-selected.mdx @@ -1,5 +1,6 @@ --- -title: How Are Certificates Selected? +sidebar_label: How ngrok Selects TLS Certificates +title: How Are TLS Certificates Selected? description: Learn how ngrok selects certificates for TLS termination. --- diff --git a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx index d59923e88a..135253aee5 100644 --- a/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx +++ b/docs/universal-gateway/tls-certificates/how-does-ngrok-handle-tls.mdx @@ -15,7 +15,7 @@ You can also [specify the local path to a certificate file](/agent/cli/#example- ## How certificates work -TLS certificates are composed of a private key and a certificate. These are presented by the ngrok cloud service during [TLS handshakes](https://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_handshake) to terminate TLS connections to [HTTPS endpoints](/universal-gateway/http) and [TLS endpoints](/universal-gateway/tls). +TLS certificates are composed of a private key and a certificate. These are presented by the ngrok cloud service during [TLS handshakes](https://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_handshake) to terminate TLS connections to [HTTPS endpoints](/universal-gateway/http-s/) and [TLS endpoints](/universal-gateway/tls). ## Certificates with domains diff --git a/docs/universal-gateway/tls-certificates/what-are-private-tls-keys.mdx b/docs/universal-gateway/tls-certificates/what-are-private-tls-keys.mdx index f218c52a15..c5fcc497ad 100644 --- a/docs/universal-gateway/tls-certificates/what-are-private-tls-keys.mdx +++ b/docs/universal-gateway/tls-certificates/what-are-private-tls-keys.mdx @@ -1,5 +1,5 @@ --- -title: What Are Private TLS Keys? +title: Uploading Private TLS Keys description: Learn what a TLS Certificate private key is and how to upload one to ngrok. --- diff --git a/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx b/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx index 825b88dc09..7e87b63462 100644 --- a/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx +++ b/docs/universal-gateway/tls-certificates/what-is-a-certificate-bundle.mdx @@ -1,5 +1,6 @@ --- -title: What Is a Certificate Bundle? +sidebar_label: Certificate Bundles +title: How Do I Use a Certificate Bundle? description: Learn what a certificate bundle is and how to upload one to ngrok. --- diff --git a/docs/universal-gateway/tls/handshake.mdx b/docs/universal-gateway/tls/handshake.mdx index 93811c38de..962ce5a718 100644 --- a/docs/universal-gateway/tls/handshake.mdx +++ b/docs/universal-gateway/tls/handshake.mdx @@ -1,5 +1,5 @@ --- -title: How Does the TLS Handshake Work? +title: How ngrok's TLS Handshake Works description: Learn how the TLS handshake works with ngrok. --- diff --git a/docs/universal-gateway/tls/tls-clients.mdx b/docs/universal-gateway/tls/tls-clients.mdx index 0165abf812..1a01ddd519 100644 --- a/docs/universal-gateway/tls/tls-clients.mdx +++ b/docs/universal-gateway/tls/tls-clients.mdx @@ -1,5 +1,5 @@ --- -title: Which TLS Clients Do ngrok Support? +title: Supported TLS Clients description: Learn about the different TLS clients available for ngrok and how to use them. --- diff --git a/docs/universal-gateway/tls/tls-termination/index.mdx b/docs/universal-gateway/tls/tls-termination/index.mdx index 363b746739..4c41de6869 100644 --- a/docs/universal-gateway/tls/tls-termination/index.mdx +++ b/docs/universal-gateway/tls/tls-termination/index.mdx @@ -1,5 +1,5 @@ --- -title: How Do I Terminate TLS? +title: Terminating TLS description: Learn how to terminate TLS with ngrok. --- diff --git a/docs/universal-gateway/tls/tls-termination/termination-location.mdx b/docs/universal-gateway/tls/tls-termination/termination-location.mdx index 63a2d6335a..2426183922 100644 --- a/docs/universal-gateway/tls/tls-termination/termination-location.mdx +++ b/docs/universal-gateway/tls/tls-termination/termination-location.mdx @@ -13,7 +13,7 @@ import Tabs from "@theme/Tabs"; import { LangSwitcher } from "@site/src/components/LangSwitcher"; import { ContentSwitcher } from "@site/src/components/LangSwitcher/ContentSwitcher"; -[TLS connections](/universal-gateway/tls/) to your ngrok endpoints are terminated at one of three locations. +[TLS connections](/universal-gateway/tls/) to your ngrok endpoints can be terminated at ngrok's cloud service, at your ngrok agent, or at your upstream service. :::info TLS endpoints are not supported by the ngrok Kubernetes Operator @@ -163,7 +163,7 @@ Termination at the agent is not supported for: ## At your upstream service -You can handle TLS termination at your upstream services. This is another form of [end-to-end encryption](/universal-gateway/tls/tls-termination/termination-mechanics/#end-to-end-encryption) where neither the cloud service nor an agent terminates TLS connections. Instead, your upstream application service is responsible for TLS termination. +You can handle TLS termination at your upstream services. This is a form of [end-to-end encryption](/universal-gateway/tls/tls-termination/termination-mechanics/#end-to-end-encryption) where neither the cloud service nor an agent terminates TLS connections. Instead, your upstream application service is responsible for TLS termination. You can get started with the following example. diff --git a/docs/universal-gateway/tls/tls-termination/termination-mechanics.mdx b/docs/universal-gateway/tls/tls-termination/termination-mechanics.mdx index 0f73fd9f4e..bba959cfa2 100644 --- a/docs/universal-gateway/tls/tls-termination/termination-mechanics.mdx +++ b/docs/universal-gateway/tls/tls-termination/termination-mechanics.mdx @@ -1,5 +1,5 @@ --- -title: How Does ngrok TLS Termination Work? +title: TLS Termination Behavior description: Learn how ngrok's TLS termination works. --- diff --git a/sidebars.js b/sidebars.js index f9b54e09a8..f5677e5b32 100644 --- a/sidebars.js +++ b/sidebars.js @@ -58,7 +58,7 @@ const sidebars = { "universal-gateway/bindings", "universal-gateway/public-endpoints/index", { - label: "What are Internal Endpoints?", + label: "Using Internal Endpoints", type: "category", link: { type: "doc", @@ -68,7 +68,7 @@ const sidebars = { }, "universal-gateway/agent-endpoints", { - label: "What are Cloud Endpoints?", + label: "Using Cloud Endpoints", type: "category", link: { type: "doc", @@ -77,7 +77,7 @@ const sidebars = { items: ["universal-gateway/cloud-endpoints/quickstart"], }, { - label: "What are Kubernetes Endpoints?", + label: "Using Kubernetes Endpoints", type: "category", link: { type: "doc", @@ -123,71 +123,78 @@ const sidebars = { }, "universal-gateway/ip-addresses", { - label: "Handling HTTP/S Traffic", + label: "Handling Traffic", type: "category", - link: { type: "doc", id: "universal-gateway/http-s/index" }, - items: [ - "universal-gateway/http-s/http-s-endpoints", - "universal-gateway/http-s/upstream-headers", - ], - }, - { - label: "Handling TLS Traffic", - type: "category", - link: { - type: "doc", - id: "universal-gateway/tls/index", - }, items: [ { - label: "How Do I Terminate TLS?", + label: "HTTP/S", + type: "category", + link: { type: "doc", id: "universal-gateway/http-s/index" }, + items: ["universal-gateway/http-s/http-s-endpoints"], + }, + { + label: "TLS", type: "category", link: { type: "doc", - id: "universal-gateway/tls/tls-termination/index", + id: "universal-gateway/tls/index", }, items: [ - "universal-gateway/tls/handshake", - "universal-gateway/tls/tls-termination/termination-mechanics", - "universal-gateway/tls/tls-termination/termination-location", + { + label: "Terminating TLS", + type: "category", + link: { + type: "doc", + id: "universal-gateway/tls/tls-termination/index", + }, + items: [ + "universal-gateway/tls/tls-termination/termination-mechanics", + "universal-gateway/tls/tls-termination/termination-location", + "universal-gateway/tls/handshake", + ], + }, + { + label: "Managing TLS Certificates", + type: "category", + link: { + type: "doc", + id: "universal-gateway/tls-certificates/how-does-ngrok-handle-tls", + }, + items: [ + "universal-gateway/tls-certificates/automatic-certificate-management", + "universal-gateway/tls-certificates/how-are-certificates-selected", + "universal-gateway/tls-certificates/custom-certificates", + "universal-gateway/tls-certificates/what-is-a-certificate-bundle", + "universal-gateway/tls-certificates/what-are-private-tls-keys", + ], + }, + "universal-gateway/tls/tls-clients", ], }, { - label: "How Does ngrok Handle TLS Certificates?", + label: "TCP", + type: "category", + link: { type: "doc", id: "universal-gateway/tcp/index" }, + items: ["universal-gateway/tcp/static-tcp-url"], + }, + { + label: "Forwarding Traffic", type: "category", link: { type: "doc", - id: "universal-gateway/tls-certificates/how-does-ngrok-handle-tls", + id: "universal-gateway/agent-forwarding/index", }, items: [ - "universal-gateway/tls-certificates/automatic-certificate-management", - "universal-gateway/tls-certificates/how-are-certificates-selected", - "universal-gateway/tls-certificates/custom-certificates", - "universal-gateway/tls-certificates/what-is-a-certificate-bundle", - "universal-gateway/tls-certificates/what-are-private-tls-keys", + "universal-gateway/agent-forwarding/forward-original-connection-data", + "universal-gateway/http-s/upstream-headers", + "universal-gateway/agent-forwarding/non-local-forwarding", + "universal-gateway/agent-forwarding/serving-file-directories", ], }, - "universal-gateway/tls/tls-clients", - ], - }, - { - label: "Handling TCP Traffic", - type: "category", - link: { type: "doc", id: "universal-gateway/tcp/index" }, - items: ["universal-gateway/tcp/static-tcp-url"], - }, - { - label: "How Do I Forward Traffic?", - type: "category", - link: { type: "doc", id: "universal-gateway/agent-forwarding/index" }, - items: [ - "universal-gateway/agent-forwarding/forward-original-connection-data", - "universal-gateway/agent-forwarding/non-local-forwarding", - "universal-gateway/agent-forwarding/serving-file-directories", ], }, { - label: "What is Endpoint Pooling?", + label: "Endpoint Pooling", type: "category", link: { type: "doc", id: "universal-gateway/pooling/index" }, items: [ @@ -196,7 +203,7 @@ const sidebars = { ], }, { - label: "What is the Global Load Balancer?", + label: "Using the Global Load Balancer", type: "category", link: { type: "doc", diff --git a/static/scripts/fix-redirect.js b/static/scripts/fix-redirect.js index bf1919387c..901c2294c3 100644 --- a/static/scripts/fix-redirect.js +++ b/static/scripts/fix-redirect.js @@ -942,6 +942,10 @@ const redirects = [ fromExact("/docs/universal-gateway/tls-certificates/#private-keys"), "/docs/universal-gateway/tls-certificates/what-are-private-tls-keys/", ], + [ + fromExact("/docs/universal-gateway/http/"), + "/docs/universal-gateway/http-s/", + ], ]; // get current href from window From 4944acf37ef98ff7a533a67fca040bd33c54dd3c Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 1 May 2025 16:59:50 -0400 Subject: [PATCH 130/137] Working on kubernetes binding section --- docs/k8s/index.mdx | 18 ++++++++ docs/universal-gateway/bindings.mdx | 4 +- docs/universal-gateway/endpoints.mdx | 2 +- .../internal-endpoints/index.mdx | 1 + .../kubernetes-endpoints/index.mdx | 21 +++------ .../kubernetes-endpoints/quickstart.mdx | 42 ----------------- .../public-endpoints/index.mdx | 1 + sidebars.js | 46 +++++++++++-------- 8 files changed, 58 insertions(+), 77 deletions(-) delete mode 100644 docs/universal-gateway/kubernetes-endpoints/quickstart.mdx diff --git a/docs/k8s/index.mdx b/docs/k8s/index.mdx index 2705ba1194..bb3db119a1 100644 --- a/docs/k8s/index.mdx +++ b/docs/k8s/index.mdx @@ -32,6 +32,24 @@ The Operator supports its own native custom resource types, including: You can use a different configuration type for each domain. ::: + +## How do I enable or disable Kubernetes endpoints on an existing installation? + +By default, if you don't change the endpoint selector, all endpoints with a Kubernetes binding will be bound to the cluster the Operator is installed on. Changing the binding allows you to restrict which endpoints that operator will handle. + +See [the docs on enabling bindings](/docs/k8s/guides/bindings/#enable-bindings-for-the-operator) to learn more. + +## Using the API + +Kubernetes endpoints can be created programatically. Consult the documentation on [Endpoint APIs](/api/resources/endp + +## Type and Pooling + +- Kubernetes endpoints support all [Endpoint + Types](/universal-gateway/types) (`agent` and `cloud`). +- Kubernetes endpoints support [Endpoint + Pooling](/universal-gateway/endpoint-pooling). + ## Pricing The ngrok Kubernetes Operator is available to all ngrok users at no diff --git a/docs/universal-gateway/bindings.mdx b/docs/universal-gateway/bindings.mdx index 1da004651a..5340a67b62 100644 --- a/docs/universal-gateway/bindings.mdx +++ b/docs/universal-gateway/bindings.mdx @@ -1,8 +1,10 @@ --- +sidebar_label: Endpoint Bindings title: What are Endpoint Bindings? +description: Learn about the different types of ngrok endpoint bindings and how they work. --- -[Endpoints](/universal-gateway/endpoints) have a **binding**, which dictates how traffic can access it. +Every [ngrok Endpoint](/universal-gateway/endpoints) has a **binding**, which dictates how traffic can access it. ## Public Endpoints diff --git a/docs/universal-gateway/endpoints.mdx b/docs/universal-gateway/endpoints.mdx index 426591c3f4..3113816e59 100644 --- a/docs/universal-gateway/endpoints.mdx +++ b/docs/universal-gateway/endpoints.mdx @@ -1,6 +1,6 @@ --- -sidebar_position: 0 title: What are Endpoints? +description: Learn about how ngrok endpoints enable you to open up your apps and services to network traffic. --- import TypesComparison from "@site/shared/types-comparison.mdx"; diff --git a/docs/universal-gateway/internal-endpoints/index.mdx b/docs/universal-gateway/internal-endpoints/index.mdx index 18dfd5d706..19a7793f62 100644 --- a/docs/universal-gateway/internal-endpoints/index.mdx +++ b/docs/universal-gateway/internal-endpoints/index.mdx @@ -1,4 +1,5 @@ --- +sidebar_label: Internal Binding title: What are Internal Endpoints? description: Learn about staging internal services and applications using internal endpoints. --- diff --git a/docs/universal-gateway/kubernetes-endpoints/index.mdx b/docs/universal-gateway/kubernetes-endpoints/index.mdx index 292f49705b..fac247ce64 100644 --- a/docs/universal-gateway/kubernetes-endpoints/index.mdx +++ b/docs/universal-gateway/kubernetes-endpoints/index.mdx @@ -1,5 +1,7 @@ --- +sidebar_label: Kubernetes Binding title: What are Kubernetes Endpoints? +description: Learn about connecting your Kubernetes clusters with ngrok's Kubernetes endpoints. --- Kubernetes endpoints are secure, private endpoints that are only addressable @@ -8,23 +10,14 @@ Operator](/k8s/). They enable you to connect to ngrok endpoints without making t Kubernetes endpoints have a [binding](/universal-gateway/bindings) of `kubernetes`. -## Type and Pooling +## Get started -- Kubernetes endpoints support all [Endpoint - Types](/universal-gateway/types) (`agent` and `cloud`). -- Kubernetes endpoints support [Endpoint - Pooling](/universal-gateway/endpoint-pooling). +Follow the [installation instructions](/docs/k8s/installation/install/) to set up the ngrok Kubernetes Operator. -## How do I enable or disable Kubernetes endpoints on an existing installation? +## Learn more -By default, if you don't change the default endpoint selector, all endpoints with a Kubernetes binding will be bound to the cluster the Operator is installed on. Changing the binding allows you to restrict which endpoints that operator will handle. - -See [the docs on enabling bindings](/docs/k8s/guides/bindings/#enable-bindings-for-the-operator) to learn more. - -## API - -Kubernetes endpoints can be created programatically. Consult the documentation -on [Endpoint APIs](/api/resources/endpoints/). +See [the docs on using bindings with the Kubernetes Operator](/docs/k8s/guides/bindings/#kubernetes-binding) to learn more. +oints/). ## Pricing diff --git a/docs/universal-gateway/kubernetes-endpoints/quickstart.mdx b/docs/universal-gateway/kubernetes-endpoints/quickstart.mdx deleted file mode 100644 index e577ae2bd5..0000000000 --- a/docs/universal-gateway/kubernetes-endpoints/quickstart.mdx +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Kubernetes Endpoints Quickstart ---- - -Create a Kubernetes endpoint by specifying binding of `kubernetes` when you -create an endpoint. - -#### Step 1: Install the ngrok Kubernetes Operator - -```bash -helm install ngrok-operator ngrok/kubernetes-operator \ - --namespace ngrok-operator \ - --create-namespace \ - --set description="example operator" \ - --set binding.enabled=true \ - --set credentials.apiKey=$NGROK_API_KEY \ - --set credentials.authtoken=$NGROK_AUTHTOKEN -``` - -#### Step 2: Create an ngrok endpoint - -Run the following command in the same ngrok account to create the kubernetes -bound endpoint. After the command completes, the ngrok operator will [create -`Service` objects](#service-creation) in the kubernetes cluster matching the -endpoint's URL. - -```bash -ngrok http 80 --url http://customer-2.prod --binding kubernetes -``` - -#### Step 3: Connect to the endpoint - -Other pods in the Kubernetes cluster where the ngrok operator is running can -connect to the bound endpoint. - -```bash -$ kubectl run -i --tty --rm debug --restart=Never --image=appropriate/curl -- /bin/sh -# curl http://customer-2.prod -``` - -Congraulations, you just connected to your application via a private kubernetes -endpoint! diff --git a/docs/universal-gateway/public-endpoints/index.mdx b/docs/universal-gateway/public-endpoints/index.mdx index a36203980e..9f3bcb4755 100644 --- a/docs/universal-gateway/public-endpoints/index.mdx +++ b/docs/universal-gateway/public-endpoints/index.mdx @@ -1,4 +1,5 @@ --- +sidebar_label: Public Binding title: What are Public Endpoints? description: Learn about enabling internet traffic to your services with public endpoints. --- diff --git a/sidebars.js b/sidebars.js index f5677e5b32..32ee4d95f0 100644 --- a/sidebars.js +++ b/sidebars.js @@ -48,23 +48,44 @@ const sidebars = { items: [ "universal-gateway/overview", { - label: "What are Endpoints?", + label: "Endpoints", type: "category", link: { type: "doc", id: "universal-gateway/endpoints", }, items: [ - "universal-gateway/bindings", - "universal-gateway/public-endpoints/index", { - label: "Using Internal Endpoints", + label: "Endpoint Bindings", type: "category", link: { type: "doc", - id: "universal-gateway/internal-endpoints/index", + id: "universal-gateway/bindings", }, - items: ["universal-gateway/internal-endpoints/quickstart"], + items: [ + "universal-gateway/public-endpoints/index", + { + label: "Internal Binding", + type: "category", + link: { + type: "doc", + id: "universal-gateway/internal-endpoints/index", + }, + items: ["universal-gateway/internal-endpoints/quickstart"], + }, + { + label: "Kubernetes Binding", + type: "category", + link: { + type: "doc", + id: "universal-gateway/kubernetes-endpoints/index", + }, + items: [ + "universal-gateway/kubernetes-endpoints/services", + "universal-gateway/kubernetes-endpoints/selector", + ], + }, + ], }, "universal-gateway/agent-endpoints", { @@ -76,19 +97,6 @@ const sidebars = { }, items: ["universal-gateway/cloud-endpoints/quickstart"], }, - { - label: "Using Kubernetes Endpoints", - type: "category", - link: { - type: "doc", - id: "universal-gateway/kubernetes-endpoints/index", - }, - items: [ - "universal-gateway/kubernetes-endpoints/quickstart", - "universal-gateway/kubernetes-endpoints/services", - "universal-gateway/kubernetes-endpoints/selector", - ], - }, "universal-gateway/what-are-endpoint-urls", "universal-gateway/wildcard-domains/wildcard-endpoints", "universal-gateway/http-s/endpoint-url-defaults", From 2d49c8a7ade4e3e4cfcec6d947fb43c4a652f687 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 2 May 2025 09:29:42 -0400 Subject: [PATCH 131/137] Fixed k8s bindings --- docs/k8s/guides/bindings.mdx | 16 +++++++++++ .../kubernetes-endpoints/selector.mdx | 28 ------------------- .../kubernetes-endpoints/services.mdx | 4 ++- sidebars.js | 14 ++-------- 4 files changed, 21 insertions(+), 41 deletions(-) delete mode 100644 docs/universal-gateway/kubernetes-endpoints/selector.mdx diff --git a/docs/k8s/guides/bindings.mdx b/docs/k8s/guides/bindings.mdx index 9d185f62ed..9ed6ad7158 100644 --- a/docs/k8s/guides/bindings.mdx +++ b/docs/k8s/guides/bindings.mdx @@ -215,6 +215,22 @@ You can modify your operator to only process a subset of them with the `bindings It defaults to `["true"]` which causes it to process all endpoints with a Kubernetes type binding. This can be modified to anything you like to control which endpoints the operator should process. This strategy can enable you to easily only project endpoints into certain clusters running the ngrok Kubernetes operator. +### Selecting endpoints for a cluster + +If you don't want all kubernetes endpoints in your account to appear inside of +a cluster, you may specify an Endpoint Selector which filters which Kubernetes +endpoints are projected into the cluster it runs in. Endpoint Selectors are a +CEL expression which is evaluated against each Kubernetes Endpoint in your +account. The operator will only projects endpoints that the selector returns +`true` for. + +For example, to only project kubernetes endpoints in the billing namespace, you would +add the following flag when installing the Kubernetes Operator: + +```bash + --set binding.endpointSelector="ep.hostname.endsWith('.billing')" \ +``` + ## Bindings with `Ingresses` By default, creating an `Ingress` will create a `CloudEndpoint` that has a `public` binding, meaning that its URL is accessible via the public internet, and an `AgentEndpoint` with an `internal` binding, meaning that its URL is only accessible using the `forward-internal` traffic policy action. diff --git a/docs/universal-gateway/kubernetes-endpoints/selector.mdx b/docs/universal-gateway/kubernetes-endpoints/selector.mdx deleted file mode 100644 index b225103726..0000000000 --- a/docs/universal-gateway/kubernetes-endpoints/selector.mdx +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: How Do I Select Endpoints for a Cluster? ---- - -If you don't want all kubernetes endpoints in your account to appear inside of -a cluster, you may specify an Endpoint Selector which filters which Kubernetes -endpoints are projected into the cluster it runs in. Endpoint Selectors are a -CEL expression which is evaluated against each Kubernetes Endpoint in your -account. The operator will only projects endpoints that the selector returns -`true` for. - -For example, to only project kubernetes endpoints in the billing namespace, you would -add the following flag when installing the Kubernetes Operator: - -```bash - --set binding.endpointSelector="ep.hostname.endsWith('.billing')" \ -``` - -## How do I update endpoint selectors? - -If you don't want all kubernetes endpoints in your account to appear inside of -a cluster, you may specify an Endpoint Selector which filters which Kubernetes -endpoints are projected into the cluster it runs in. Endpoint Selectors are a -CEL expression which is evaluated against each Kubernetes Endpoint in your -account. The operator will only projects endpoints that the selector returns -`true` for. - -See [the docs on enabling bindings](/docs/k8s/guides/bindings/#enable-bindings-for-the-operator) to learn more. diff --git a/docs/universal-gateway/kubernetes-endpoints/services.mdx b/docs/universal-gateway/kubernetes-endpoints/services.mdx index d9503e15dd..f63ede3d7c 100644 --- a/docs/universal-gateway/kubernetes-endpoints/services.mdx +++ b/docs/universal-gateway/kubernetes-endpoints/services.mdx @@ -1,5 +1,7 @@ --- -title: How are Kubernetes Services Created? +sidebar_label: Kubernetes Services +title: How ngrok Creats Kubernetes Services +description: Learn how ngrok creates Kubernetes Services for kubernetes-bound endpoints. --- After a kubernetes-bound endpoint is created, the ngrok cloud service notifies diff --git a/sidebars.js b/sidebars.js index 32ee4d95f0..c6b6fb03db 100644 --- a/sidebars.js +++ b/sidebars.js @@ -73,18 +73,7 @@ const sidebars = { }, items: ["universal-gateway/internal-endpoints/quickstart"], }, - { - label: "Kubernetes Binding", - type: "category", - link: { - type: "doc", - id: "universal-gateway/kubernetes-endpoints/index", - }, - items: [ - "universal-gateway/kubernetes-endpoints/services", - "universal-gateway/kubernetes-endpoints/selector", - ], - }, + "universal-gateway/kubernetes-endpoints/index", ], }, "universal-gateway/agent-endpoints", @@ -357,6 +346,7 @@ const sidebars = { "k8s/guides/using-loadbalancers", "k8s/guides/endpoint-types", "k8s/guides/bindings", + "universal-gateway/kubernetes-endpoints/services", "k8s/guides/pooling", "k8s/guides/custom-domain", "k8s/guides/annotations", From 2a536caa5c378369b4b9c5d4c53ca4958b04cae8 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 2 May 2025 09:53:30 -0400 Subject: [PATCH 132/137] Fix up the endpoints docs (to some extent) --- docs/universal-gateway/agent-endpoints.mdx | 13 +++++++++---- docs/universal-gateway/chain-endpoints.mdx | 4 +++- .../cloud-endpoints/index.mdx | 17 +++++++++++++---- .../http-s/endpoint-url-defaults.mdx | 3 +++ docs/universal-gateway/mock-api.mdx | 6 ++++-- .../what-are-endpoint-urls.mdx | 1 + .../wildcard-domains/wildcard-endpoints.mdx | 2 ++ sidebars.js | 19 ++++++++++++++----- 8 files changed, 49 insertions(+), 16 deletions(-) diff --git a/docs/universal-gateway/agent-endpoints.mdx b/docs/universal-gateway/agent-endpoints.mdx index fa2aef046a..a7fa158141 100644 --- a/docs/universal-gateway/agent-endpoints.mdx +++ b/docs/universal-gateway/agent-endpoints.mdx @@ -1,6 +1,7 @@ --- +sidebar_label: Using Agent Endpoints title: What are Agent Endpoints? -description: Learn about creating endpoints managed by Secure Tunnel agents. +description: Learn about creating endpoints managed by Secure Tunnel agents run on your local machines. --- Agent Endpoints are public or internal Endpoints created by Secure Tunnel agents, which include any of the following: @@ -11,9 +12,9 @@ Agent Endpoints are public or internal Endpoints created by Secure Tunnel agents Agent Endpoints live for the lifetime of, and forward connections to, the agent process that started them. -## Get started - -To set up your first Agent endpoint, see [the Getting Started with ngrok](/getting-started/) guide. +:::tip +The counterpart to Agent Endpoints are Cloud Endpoints, which are always-on and centrally managed via the ngrok API or Dashboard. See [the Cloud Endpoints documentation](/universal-gateway/cloud-endpoints/) for more information. +::: ## Use cases @@ -26,6 +27,10 @@ Agent endpoints are a good choice when you want to: - **You can use agent endpoints to create connectivity to apps running on your localhost, an IoT device in the field, or an EC2 instance**. - Because agent endpoints are created via [Secure Tunnel agents](/agent/), they are excellent for connecting to apps running on all networks, even those behind a NAT. +## Get started + +To set up your first Agent endpoint, see [the Getting Started with ngrok](/getting-started/) guide. + ## Differences from Cloud Endpoints :::note diff --git a/docs/universal-gateway/chain-endpoints.mdx b/docs/universal-gateway/chain-endpoints.mdx index 69df8f228d..05ed30c173 100644 --- a/docs/universal-gateway/chain-endpoints.mdx +++ b/docs/universal-gateway/chain-endpoints.mdx @@ -1,10 +1,12 @@ --- +sidebar_label: Chaining Endpoints Together title: How Do I Chain Endpoints? +description: Learn how to route traffic from one endpoint to multiple other endpoints based on request attributes. --- import ConfigExample from "/src/components/ConfigExample.tsx"; -You can chain ngrok Endpoints together to route traffic from one endpoint to multiple other endpoints based on request attributes, such as URL, hostname, path, cookies, or headers. +You can route traffic from one endpoint to multiple other endpoints based on request attributes such as the URL, hostname, path, cookies, or headers. See the [Traffic Policy Action request variables documentation](/docs/traffic-policy/variables/req/) for a full list of request attributes you can use. diff --git a/docs/universal-gateway/cloud-endpoints/index.mdx b/docs/universal-gateway/cloud-endpoints/index.mdx index f753deb639..1abea77b55 100644 --- a/docs/universal-gateway/cloud-endpoints/index.mdx +++ b/docs/universal-gateway/cloud-endpoints/index.mdx @@ -1,14 +1,15 @@ --- title: What are Cloud Endpoints? +description: Learn how to use ngrok's Cloud Endpoints to centrally manage traffic to your services. --- -## Overview -Cloud Endpoints are persistent, always-on endpoints whose creation, deletion and configuration is managed centrally via the Dashboard or API. They exist pemanently 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. +Cloud Endpoints are persistent, always-on endpoints whose creation, deletion and configuration is managed centrally via the Dashboard or API. They exist permanently until they are explicitly deleted. -## Get started +:::tip +Cloud Endpoints are the counterpart to Agent Endpoints, which are created and managed by Secure Tunnel agents. See [the Agent Endpoints documentation](/universal-gateway/agent-endpoints/) for more information. +::: -You can create a Cloud Endpoint in the Dashboard or using the API. See [the Cloud Endpoints Quickstart](/universal-gateway/cloud-endpoints/quickstart) to learn more. ## Use cases @@ -29,6 +30,14 @@ action](/traffic-policy/actions/forward-internal/). The traffic policy of a Cloud Endpoint must terminate traffic via actions such as `deny`, `redirect`, `custom-response`, or `forward-internal`. +:::note +Cloud Endpoints do not forward their traffic to an agent by default. This behavior must be configured with a traffic policy. +::: + +## Get started + +You can create a Cloud Endpoint in the Dashboard or using the API. See [the Cloud Endpoints Quickstart](/universal-gateway/cloud-endpoints/quickstart) to learn more. + ## Differences from Agent Endpoints :::note diff --git a/docs/universal-gateway/http-s/endpoint-url-defaults.mdx b/docs/universal-gateway/http-s/endpoint-url-defaults.mdx index 6339c2902e..2b790b33ee 100644 --- a/docs/universal-gateway/http-s/endpoint-url-defaults.mdx +++ b/docs/universal-gateway/http-s/endpoint-url-defaults.mdx @@ -1,4 +1,5 @@ --- +sidebar_label: Default Endpoint URL Values title: How are Endpoint URLs Constructed? description: Learn what default values ngrok uses to construct endpoint URLs. --- @@ -11,6 +12,8 @@ When you create an agent endpoint, if you do not specify a complete URL, the fol | Hostname | randomly selected | | Port | `443` if scheme is `https`
    `80` if scheme is `http` | +## Examples + Consult the following table of examples of URL defaulting: | Value | Endpoint URL | diff --git a/docs/universal-gateway/mock-api.mdx b/docs/universal-gateway/mock-api.mdx index c7430acc6a..58cdbebecb 100644 --- a/docs/universal-gateway/mock-api.mdx +++ b/docs/universal-gateway/mock-api.mdx @@ -1,12 +1,14 @@ --- -title: How Do I Mock API Endpoints? +sidebar_label: Mocking API Responses With Endpoints +title: How Do I Mock API Responses With Endpoints? +description: Learn how to mock API responses using ngrok Endpoints and Traffic Policy. --- import TabItem from "@theme/TabItem"; import Tabs from "@theme/Tabs"; import ConfigExample from "/src/components/ConfigExample.tsx"; -You can mock API responses using ngrok Endpoints. This enables you to test your application's functionality without having to stand up a full backend service or make requests to real APIs. +You can mock API responses using ngrok [Endpoints](/docs/universal-gateway/endpoints). This enables you to test your application's functionality without having to stand up a full backend service or make requests to real APIs. The following steps will walk you through using [Traffic Policy](/traffic-policy/) to mock API responses. diff --git a/docs/universal-gateway/what-are-endpoint-urls.mdx b/docs/universal-gateway/what-are-endpoint-urls.mdx index ff4658744b..d88b485caa 100644 --- a/docs/universal-gateway/what-are-endpoint-urls.mdx +++ b/docs/universal-gateway/what-are-endpoint-urls.mdx @@ -1,4 +1,5 @@ --- +sidebar_label: Endpoint URLs title: What are Endpoint URLs? --- diff --git a/docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx b/docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx index 6834f1d18d..054651f9ed 100644 --- a/docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx +++ b/docs/universal-gateway/wildcard-domains/wildcard-endpoints.mdx @@ -1,5 +1,7 @@ --- +sidebar_label: Using Endpoints With Wildcard Domains title: How Do I Use Wildcard Endpoints? +description: Learn how to create endpoints that receive traffic for all subdomains matching a wildcard domain. --- import TabItem from "@theme/TabItem"; diff --git a/sidebars.js b/sidebars.js index c6b6fb03db..9643fd332e 100644 --- a/sidebars.js +++ b/sidebars.js @@ -56,7 +56,7 @@ const sidebars = { }, items: [ { - label: "Endpoint Bindings", + label: "Understanding Endpoint Bindings", type: "category", link: { type: "doc", @@ -76,6 +76,18 @@ const sidebars = { "universal-gateway/kubernetes-endpoints/index", ], }, + { + label: "Understanding Endpoint URLs", + type: "category", + link: { + type: "doc", + id: "universal-gateway/what-are-endpoint-urls", + }, + items: [ + "universal-gateway/wildcard-domains/wildcard-endpoints", + "universal-gateway/http-s/endpoint-url-defaults", + ], + }, "universal-gateway/agent-endpoints", { label: "Using Cloud Endpoints", @@ -86,12 +98,9 @@ const sidebars = { }, items: ["universal-gateway/cloud-endpoints/quickstart"], }, - "universal-gateway/what-are-endpoint-urls", - "universal-gateway/wildcard-domains/wildcard-endpoints", - "universal-gateway/http-s/endpoint-url-defaults", "universal-gateway/chain-endpoints", "universal-gateway/mock-api", - "universal-gateway/migrate-from-tunnels", + // "universal-gateway/migrate-from-tunnels", ], }, { From 2aa26f834ebf4085b0e4682c6cd57a9ae1f2369e Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 2 May 2025 09:59:59 -0400 Subject: [PATCH 133/137] Some top-level changes --- docs/universal-gateway/ddos-protection.mdx | 1 + docs/universal-gateway/points-of-presence.mdx | 4 ++-- sidebars.js | 15 ++++++++++++--- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/docs/universal-gateway/ddos-protection.mdx b/docs/universal-gateway/ddos-protection.mdx index d3ef10db97..5ccd011717 100644 --- a/docs/universal-gateway/ddos-protection.mdx +++ b/docs/universal-gateway/ddos-protection.mdx @@ -1,4 +1,5 @@ --- +sidebar_label: Automatic DDoS Protection title: How Does ngrok Handle DDoS Attacks? description: Learn how ngrok protects your applications from DDoS attacks. --- diff --git a/docs/universal-gateway/points-of-presence.mdx b/docs/universal-gateway/points-of-presence.mdx index 1c6ae95432..6f67c7c4a2 100644 --- a/docs/universal-gateway/points-of-presence.mdx +++ b/docs/universal-gateway/points-of-presence.mdx @@ -1,6 +1,6 @@ --- -title: Points of Presence -sidebar_label: Where Are ngrok's Points of Presence? +sidebar_label: Global Points of Presence +title: Where Are ngrok's Points of Presence? description: Learn about ngrok's globally distributed points of presence. --- diff --git a/sidebars.js b/sidebars.js index 9643fd332e..2f20e99e23 100644 --- a/sidebars.js +++ b/sidebars.js @@ -46,7 +46,18 @@ const sidebars = { className: "menu__list-item--category", link: { type: "doc", id: "universal-gateway/overview" }, items: [ - "universal-gateway/overview", + { + label: "Overview", + type: "category", + link: { + type: "doc", + id: "universal-gateway/overview", + }, + items: [ + "universal-gateway/points-of-presence", + "universal-gateway/ddos-protection", + ], + }, { label: "Endpoints", type: "category", @@ -220,8 +231,6 @@ const sidebars = { "universal-gateway/global-load-balancer/gslb-agents", ], }, - "universal-gateway/points-of-presence", - "universal-gateway/ddos-protection", ], }, { From 5369611adb467c0fbff0c12e44db9d0dbc0b1d93 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 2 May 2025 11:41:35 -0400 Subject: [PATCH 134/137] More fixes --- .../agent-forwarding/serving-file-directories.mdx | 6 +++--- .../domains/bring-your-own-domain.mdx | 1 + docs/universal-gateway/domains/what-are-domains.mdx | 2 +- .../domains/what-are-managed-domains.mdx | 1 + docs/universal-gateway/endpoint-pooling.mdx | 3 ++- .../global-load-balancer/gslb-agents.mdx | 1 + .../global-load-balancer/gslb-endpoints.mdx | 1 + .../global-load-balancer/index.mdx | 12 ++++++++---- docs/universal-gateway/ip-addresses.mdx | 2 +- docs/universal-gateway/points-of-presence.mdx | 8 ++++---- .../pooling/pool-load-balancing.mdx | 13 +++++++++---- .../how-are-tcp-addresses-assigned.mdx | 1 + docs/universal-gateway/tcp-addresses/index.mdx | 3 ++- docs/universal-gateway/wildcard-domains/index.mdx | 2 ++ sidebars.js | 2 +- 15 files changed, 38 insertions(+), 20 deletions(-) diff --git a/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx b/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx index 42ac480ac7..848d73d342 100644 --- a/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx +++ b/docs/universal-gateway/agent-forwarding/serving-file-directories.mdx @@ -23,7 +23,7 @@ Serving directory files is not supported with: - Kubernetes Operator ::: -#### Serve files in `/var/log` +## Serve files in `/var/log` @@ -68,7 +68,7 @@ endpoints: -#### Serve files on Windows +## Serve files on Windows @@ -116,7 +116,7 @@ endpoints:
    -#### Serve files in your current working directory +## Serve files in your current working directory diff --git a/docs/universal-gateway/domains/bring-your-own-domain.mdx b/docs/universal-gateway/domains/bring-your-own-domain.mdx index 8d08cf31ff..7ec9a1ec60 100644 --- a/docs/universal-gateway/domains/bring-your-own-domain.mdx +++ b/docs/universal-gateway/domains/bring-your-own-domain.mdx @@ -1,5 +1,6 @@ --- title: How Do I Use My Own Domain? +sidebar_label: Using Your Own Domain description: Learn how to use your own domain with ngrok. --- diff --git a/docs/universal-gateway/domains/what-are-domains.mdx b/docs/universal-gateway/domains/what-are-domains.mdx index 7e69f89d1e..dcda8386fa 100644 --- a/docs/universal-gateway/domains/what-are-domains.mdx +++ b/docs/universal-gateway/domains/what-are-domains.mdx @@ -1,5 +1,5 @@ --- -title: What Are Domains? +title: How Do Domains Work With ngrok? description: Learn how to create domains in your ngrok account. --- diff --git a/docs/universal-gateway/domains/what-are-managed-domains.mdx b/docs/universal-gateway/domains/what-are-managed-domains.mdx index 66640d52b6..2a230535fd 100644 --- a/docs/universal-gateway/domains/what-are-managed-domains.mdx +++ b/docs/universal-gateway/domains/what-are-managed-domains.mdx @@ -1,5 +1,6 @@ --- title: What Are Managed Domains? +sidebar_label: Using ngrok Subdomains description: Learn about the free and paid domains that ngrok provides. --- diff --git a/docs/universal-gateway/endpoint-pooling.mdx b/docs/universal-gateway/endpoint-pooling.mdx index ff0e4b64b6..d654fe4f34 100644 --- a/docs/universal-gateway/endpoint-pooling.mdx +++ b/docs/universal-gateway/endpoint-pooling.mdx @@ -1,5 +1,6 @@ --- -title: Endpoint Pooling +title: What Is Endpoint Pooling? +sidebar_label: Using Endpoint Pooling description: Learn how ngrok enables you to load balance traffic to endpoints with endpoint pooling. --- diff --git a/docs/universal-gateway/global-load-balancer/gslb-agents.mdx b/docs/universal-gateway/global-load-balancer/gslb-agents.mdx index 22dd24ebe7..7f9a9a1891 100644 --- a/docs/universal-gateway/global-load-balancer/gslb-agents.mdx +++ b/docs/universal-gateway/global-load-balancer/gslb-agents.mdx @@ -1,4 +1,5 @@ --- +sidebar_label: With ngrok Agents title: Global Load Balancing for Agents description: Learn how ngrok's Global Load Balancer improves the resiliency of your ngrok agents, agent SDKs and the Kubernetes Controller. --- diff --git a/docs/universal-gateway/global-load-balancer/gslb-endpoints.mdx b/docs/universal-gateway/global-load-balancer/gslb-endpoints.mdx index ffbbfd506c..ae6ad2f507 100644 --- a/docs/universal-gateway/global-load-balancer/gslb-endpoints.mdx +++ b/docs/universal-gateway/global-load-balancer/gslb-endpoints.mdx @@ -1,4 +1,5 @@ --- +sidebar_label: With Endpoints title: Global Load Balancing for Endpoints description: Learn how ngrok's Global Load Balancer improves connection performance to your endpoints. --- diff --git a/docs/universal-gateway/global-load-balancer/index.mdx b/docs/universal-gateway/global-load-balancer/index.mdx index 03610fb478..637494ccbf 100644 --- a/docs/universal-gateway/global-load-balancer/index.mdx +++ b/docs/universal-gateway/global-load-balancer/index.mdx @@ -8,9 +8,8 @@ applications by distributing traffic to the point of presence with the least lat Every application you deliver with ngrok is automatically accelerated with our always-on, zero-configuration global load balancer. -:::tip -Global lobal balancing is sometimes called 'Global Server Load Balancing' or -GSLB. +:::tip Remember +Global lobal balancing (or GSLB), balances traffic *to* endpoints. This is distinct from [endpoint pool load balancing](/universal-gateway/pooling/pool-load-balancing/), which balances traffic *between* your endpoints. ::: ## vs. Traditional GSLBs @@ -20,7 +19,12 @@ benefits. ### Automatic geo-aware failover -Traditional GSLBs require you to run geographically redundant copies of your application and configuring networking technologies to distribute and failover traffic among these deployments. By contrast, ngrok runs a [global delivery network of PoPs](/universal-gateway/points-of-presence/) for you. This means that even if you only deploy your upstream service to a single geography, your apps still get faster from [Connection Acceleration](/universal-gateway/global-load-balancer/gslb-endpoints/#connection-acceleration) and [Module Acceleration](/universal-gateway/global-load-balancer/gslb-endpoints/#module-acceleration). +Traditional GSLBs require you to: + +- Run geographically redundant copies of your application +- Configure networking technologies to distribute and failover traffic among these deployments + +By contrast, ngrok runs a [global delivery network of PoPs](/universal-gateway/points-of-presence/) for you. This means that even if you only deploy your upstream service to a single geography, your apps still get faster from [Connection Acceleration](/universal-gateway/global-load-balancer/gslb-endpoints/#connection-acceleration) and [Module Acceleration](/universal-gateway/global-load-balancer/gslb-endpoints/#module-acceleration). ### Zero configuration diff --git a/docs/universal-gateway/ip-addresses.mdx b/docs/universal-gateway/ip-addresses.mdx index ebbd2a6680..0235c63dbd 100644 --- a/docs/universal-gateway/ip-addresses.mdx +++ b/docs/universal-gateway/ip-addresses.mdx @@ -1,6 +1,6 @@ --- sidebar_label: How IP Addresses Work -title: IP Addresses +title: How Do IP Addresses Work With ngrok? description: Learn how ngrok assigns IPs for endpoints, agent connections, and the dashboard API. --- diff --git a/docs/universal-gateway/points-of-presence.mdx b/docs/universal-gateway/points-of-presence.mdx index 6f67c7c4a2..6480db5197 100644 --- a/docs/universal-gateway/points-of-presence.mdx +++ b/docs/universal-gateway/points-of-presence.mdx @@ -5,13 +5,13 @@ description: Learn about ngrok's globally distributed points of presence. --- ngrok's globally distributed cloud service runs on points of presence all -around the world to enable fast, low latency traffic to your applications. +around the world to enable low-latency traffic to your applications. We continuously expand our regional points of presence. As we add each new point of presence, your applications become faster for global customers without any changes. -## Reference +## Regions The current points of presence are: @@ -26,9 +26,9 @@ The current points of presence are: | us | United States (Ohio) | | us-cal-1 | United States (California) | -## Usage +### Usage -The table of region codes above are used throughout the product to communicate +The table of region codes on this page are used throughout the product to communicate which points of presence are being used by a particular feature and to allow you to configure pieces of the product to use specific points of presence. Region codes are used by the following features: diff --git a/docs/universal-gateway/pooling/pool-load-balancing.mdx b/docs/universal-gateway/pooling/pool-load-balancing.mdx index 9ab5c47698..ead652ad64 100644 --- a/docs/universal-gateway/pooling/pool-load-balancing.mdx +++ b/docs/universal-gateway/pooling/pool-load-balancing.mdx @@ -1,4 +1,5 @@ --- +sidebar_label: Using Pool Load Balancing title: Load Balancing With Endpoint Pools description: Learn about the different load balancing strategies available for endpoint pools with ngrok. --- @@ -6,12 +7,16 @@ description: Learn about the different load balancing strategies available for e import TabItem from "@theme/TabItem"; import Tabs from "@theme/Tabs"; -[Endpoint pools](/universal-gateway/pooling) automatically load balance traffic between their endpoints. Load balancing is applied in two places: +[Endpoint pools](/universal-gateway/pooling) automatically load balance traffic between their endpoints. Load balancing is applied when: -- When pooled public and kubernetes endpoints load balance traffic received from external clients. -- When pooled internal endpoints receive traffic that is forwarded to them via the `forward-internal` Traffic Policy action. +- Pooled **public and kubernetes** endpoints load balance traffic received from external clients. +- Pooled **internal** endpoints receive traffic that is forwarded to them via the `forward-internal` Traffic Policy action. -### Granularity +:::tip Remember +Load balancing in endpoint pools balances traffic *between* endpoints. This is distinct from the [global load balancer](/universal-gateway/global-load-balancer/), which balances traffic *to* endpoints. +::: + +## Granularity ngrok intelligently chooses the load balancing layer automatically for you. diff --git a/docs/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned.mdx b/docs/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned.mdx index 76b82beb18..b9e56384e2 100644 --- a/docs/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned.mdx +++ b/docs/universal-gateway/tcp-addresses/how-are-tcp-addresses-assigned.mdx @@ -1,4 +1,5 @@ --- +sidebar_label: Creating TCP Addresses title: How Are TCP Addresses Assigned? description: Learn how ngrok assignes TCP Addresses. --- diff --git a/docs/universal-gateway/tcp-addresses/index.mdx b/docs/universal-gateway/tcp-addresses/index.mdx index 307bc43f60..91625eeea1 100644 --- a/docs/universal-gateway/tcp-addresses/index.mdx +++ b/docs/universal-gateway/tcp-addresses/index.mdx @@ -1,5 +1,6 @@ --- -title: Using TCP Addresses +sidebar_label: Using TCP Addresses +title: What are TCP Addresses? description: Learn how to use TCP Addresses with ngrok. --- diff --git a/docs/universal-gateway/wildcard-domains/index.mdx b/docs/universal-gateway/wildcard-domains/index.mdx index cfee3f347c..268a854abe 100644 --- a/docs/universal-gateway/wildcard-domains/index.mdx +++ b/docs/universal-gateway/wildcard-domains/index.mdx @@ -1,5 +1,7 @@ --- +sidebar_label: Using Wildcard Domains title: How Do I Use Wildcard Domains? +description: Learn how to use wildcard domains with ngrok. --- You may create a Domain with a wildcard name, e.g. `*.example.com`. A wildcard domain enables you to: diff --git a/sidebars.js b/sidebars.js index 2f20e99e23..e1a8b493e4 100644 --- a/sidebars.js +++ b/sidebars.js @@ -126,7 +126,7 @@ const sidebars = { ], }, { - label: "What are Domains?", + label: "Using Domains", type: "category", link: { type: "doc", From ddd914f9144fc69c4c9ace0b15fb7e18ff9e80d5 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 2 May 2025 11:42:42 -0400 Subject: [PATCH 135/137] One more fix --- docs/universal-gateway/endpoint-pooling.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/universal-gateway/endpoint-pooling.mdx b/docs/universal-gateway/endpoint-pooling.mdx index d654fe4f34..f0a360f67c 100644 --- a/docs/universal-gateway/endpoint-pooling.mdx +++ b/docs/universal-gateway/endpoint-pooling.mdx @@ -10,6 +10,8 @@ tolerate failures and geo-distribute load. When your create two endpoints with the same URL (and binding), those endpoints automatically form a "pool" and share incoming traffic. +## vs. Other load balancing systems + Endpoint pooling is vastly more flexible than comparable load balancing systems: From cb12e1e4cdc6735984cc5c0066e667ea2bfd5df9 Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Fri, 2 May 2025 11:44:38 -0400 Subject: [PATCH 136/137] Anotha one --- docs/universal-gateway/endpoint-pooling.mdx | 6 ++---- docs/universal-gateway/pooling/pool-load-balancing.mdx | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/universal-gateway/endpoint-pooling.mdx b/docs/universal-gateway/endpoint-pooling.mdx index f0a360f67c..656ab7047d 100644 --- a/docs/universal-gateway/endpoint-pooling.mdx +++ b/docs/universal-gateway/endpoint-pooling.mdx @@ -1,14 +1,12 @@ --- title: What Is Endpoint Pooling? sidebar_label: Using Endpoint Pooling -description: Learn how ngrok enables you to load balance traffic to endpoints with endpoint pooling. +description: Learn how ngrok enables you to load balance traffic between endpoints with endpoint pooling. --- Endpoint pooling makes load balancing dead simple. Load balancing helps you scale traffic across multiple replicas of your app to increase capacity, -tolerate failures and geo-distribute load. When your create two endpoints with -the same URL (and binding), those endpoints automatically form a "pool" and -share incoming traffic. +tolerate failures and geo-distribute load. When your create two endpoints with the same URL (and binding), those endpoints automatically form a "pool" and share incoming traffic. ## vs. Other load balancing systems diff --git a/docs/universal-gateway/pooling/pool-load-balancing.mdx b/docs/universal-gateway/pooling/pool-load-balancing.mdx index ead652ad64..399bcaf1d6 100644 --- a/docs/universal-gateway/pooling/pool-load-balancing.mdx +++ b/docs/universal-gateway/pooling/pool-load-balancing.mdx @@ -1,6 +1,6 @@ --- -sidebar_label: Using Pool Load Balancing -title: Load Balancing With Endpoint Pools +sidebar_label: How Load Balancing Works +title: How Does ngrok Load Balance My Endpoint Pools? description: Learn about the different load balancing strategies available for endpoint pools with ngrok. --- From 539162b8a1a837b2c08d74a1a5ba44ec10d285ad Mon Sep 17 00:00:00 2001 From: Shaquil Hansford Date: Thu, 8 May 2025 10:55:47 -0400 Subject: [PATCH 137/137] Remove outdated custom domains guide --- .../how-to-set-up-a-custom-domain.mdx | 65 ------------------- .../domains/bring-your-own-domain.mdx | 22 +++++-- static/scripts/fix-redirect.js | 4 ++ 3 files changed, 21 insertions(+), 70 deletions(-) delete mode 100644 docs/guides/other-guides/how-to-set-up-a-custom-domain.mdx diff --git a/docs/guides/other-guides/how-to-set-up-a-custom-domain.mdx b/docs/guides/other-guides/how-to-set-up-a-custom-domain.mdx deleted file mode 100644 index 0a632fa17a..0000000000 --- a/docs/guides/other-guides/how-to-set-up-a-custom-domain.mdx +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: Custom Domains ---- - -ngrok allows for using hostnames from a custom domain that you own to be used with your tunnel endpoints or [Edges](/universal-gateway/edges/). Utilizing CNAMEs, ngrok will host an endpoint using your custom domain while also providing the ability to manage the complete TLS certficate lifecycyle for you. - -ngrok is not a domain registrar and will not provide or manage custom domains. As a prerequisite it is required that you have already reserved your custom domain from any available domain registrar. For demo purposes in this guide, we've registered the domain name `example.com` with a domain name registrar and will be using it with ngrok. - -To get the hostname `foo.example.com` working with an ngrok tunnel we'll need to perform one step within the ngrok account dashboard and one step with the DNS host for your domain. In many cases your DNS records are hosted by your domain name registrar, but not always. The process can be summed up in 3 steps. - -- Create hostname within ngrok dashboard -- Create CNAME record in domain DNS -- Start ngrok tunnel using hostname - -## **Create Hostname Within ngrok Dashboard** - -Adding your custom domain hostname will be done from within your ngrok account, this "reservation" process is performed from the domains page of [your ngrok dashboard](https://dashboard.ngrok.com/domains). - -Select "New Domain" and then put `foo.example.com` into the form that appears to add that domain hostname to your account. ngrok will validate that the custom name isn't currently reserved. Select the available name from the list provided and then you'll be able to add a Description, attach an Edge if desired and select your TLS Certificate configuration (we recommend our automated TLS certificates). - -After adding your domain you should see instructions along with the CNAME value to be used when creating the CNAME record. Copy the `value` of your newly-added domain's CNAME target hostname, which will be something like `..ngrok-cname.com.` - -## **Create CNAME Record in Domain DNS** - -Head over to your DNS provider and create a new record on the `example.com` domain. Every DNS provider has a distinct user interface but just by way of example here's what this interface looks like when setting up a DNS CNAME record within Squarespace: - -![](/img/docs/customdomain-img1.png) - -Create a record of type CNAME where the host name is `foo` and the data value is your ngrok CNAME target,`..ngrok-cname.com`. This will ensure that any DNS queries for `foo.example.com` are resolved with an IP from our service edge. - -#### Testing the CNAME - -Once created it might take a few minutes before the new record is reflected in the DNS, but you can confirm that your record is created using a command line tool like `dig` or `nslookup`. If the ngrok dashboard is still displayed with your CNAME target hostname from Step 1, the "Check Status" button at the bottom right of the page can also be used to confirm that your CNAME record is resolving correctly. - -```bash -nslookup foo.example.com - -Server: 127.0.0.1 -Address: 127.0.0.1#53 - -Non-authoritative answer: -foo.example.com canonical name = 4bvatzaa19xbdzvcv.2hgtjydm4lbzrtfge.ngrok-cname.com. -Name: 4bvatzaa19xbdzvcv.2hgtjydm4lbzrtfge.ngrok-cname.com -Address: 192.0.2.39 -Name: 4bvatzaa19xbdzvcv.2hgtjydm4lbzrtfge.ngrok-cname.com -Address: 192.0.2.75 -Name: 4bvatzaa19xbdzvcv.2hgtjydm4lbzrtfge.ngrok-cname.com -Address: 198.51.100.134 -Name: 4bvatzaa19xbdzvcv.2hgtjydm4lbzrtfge.ngrok-cname.com -Address: 198.51.100.205 -Name: 4bvatzaa19xbdzvcv.2hgtjydm4lbzrtfge.ngrok-cname.com -Address: 203.0.113.165 -Name: 4bvatzaa19xbdzvcv.2hgtjydm4lbzrtfge.ngrok-cname.com -Address: 203.0.113.94 -``` - -## **Start ngrok Tunnel using Hostname** - -Once your DNS record is in place you can create a tunnel using your new domain. Try running: - -```bash -ngrok http --url foo.example.com 8080 -``` - -and presuming you're actually running an application on port 8080 then making an HTTP request to `https://foo.example.com` should return a response from your app. diff --git a/docs/universal-gateway/domains/bring-your-own-domain.mdx b/docs/universal-gateway/domains/bring-your-own-domain.mdx index 7ec9a1ec60..b1000aaa1a 100644 --- a/docs/universal-gateway/domains/bring-your-own-domain.mdx +++ b/docs/universal-gateway/domains/bring-your-own-domain.mdx @@ -1,7 +1,7 @@ --- -title: How Do I Use My Own Domain? -sidebar_label: Using Your Own Domain -description: Learn how to use your own domain with ngrok. +title: How Do I Use A Custom Domain? +sidebar_label: Using Custom Domains +description: Learn how to use your own custom domain with ngrok. --- This guide will show you the steps to use any domain name that you already own with ngrok, e.g. `app.your-domain.com`. @@ -11,7 +11,7 @@ ngrok is not a domain registrar; you must already own a domain name to use it with ngrok. ::: -## Step 1 - Create a domain in ngrok +## 1. Create a domain in ngrok You can create a domain in the ngrok dashboard. [You can do so by going here](https://dashboard.ngrok.com/domains). @@ -21,7 +21,7 @@ When your domain is created, you'll be given a `CNAME` value such as `exampledat You can also create a Domain via the [ngrok API](/api/resources/reserved-domains/#request). The `CNAME` will be in the `"cname_target"` field of [the response object](/api/resources/reserved-domains/#response). ::: -## Step 2 - Add the CNAME record to your domain +## 2. Add the CNAME record to your domain 1. In a new browser tab, navigate to your domain hosting provider's dashboard and create a CNAME record. Check your hosting provider's support content or documentation to learn how. @@ -32,6 +32,18 @@ You can also create a Domain via the [ngrok API](/api/resources/reserved-domains - Its **name** should be `@` - Its **value** should be the `CNAME` value you copied from the ngrok dashboard or API response. +:::tip Test your CNAME record +Using a tool like [`dig`](https://www.digwebinterface.com/) or [`nslookup`](https://www.nslookup.io/), you can test your CNAME record in the terminal. +::: + +## 3. Start an endpoint using your domain: + +To start an agent endpoint at your domain, run the following command in your terminal, replacing `your-domain-here.example.com` with the domain you created in the ngrok dashboard. + + ```bash + ngrok http --url your-domain-here.example.com 8080 + ``` + ## Wildcard domains If you bring your own [wildcard domain](/universal-gateway/wildcard-domains), e.g. `*.example.com`, you will need to create a second `CNAME` record with your domain host for [wildcard TLS Certificate provisioning](/universal-gateway/tls-certificates/how-does-ngrok-handle-tls/#wildcard-domains). diff --git a/static/scripts/fix-redirect.js b/static/scripts/fix-redirect.js index 901c2294c3..4418cfc40e 100644 --- a/static/scripts/fix-redirect.js +++ b/static/scripts/fix-redirect.js @@ -946,6 +946,10 @@ const redirects = [ fromExact("/docs/universal-gateway/http/"), "/docs/universal-gateway/http-s/", ], + [ + fromExact("/docs/guides/other-guides/how-to-set-up-a-custom-domain/"), + "/docs/universal-gateway/domains/bring-your-own-domain/", + ], ]; // get current href from window