> For the complete documentation index, see [llms.txt](https://docs.release.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.release.com/guides-and-examples/common-setup-examples/using-ngrok-+-oauth-for-private-tunnels.md).

# ngrok and OAuth for private tunnels

Protect private services in Release with ngrok

You may need a simple way to keep the applications you deploy to Release ephemeral environments private. Perhaps you're deploying a basic disposable admin tool, for example, or you would like to share a link with a potential client or vendor outside your organization. In such cases, you don't want to set up expensive access controls that need time-consuming configuration.

The solution is to create a proxy layer for your Release application environment.

## ngrok vs. open-source proxy servers

We have a guide available for an [open source OAuth2 server](/guides-and-examples/common-setup-examples/opensource-oauth-proxy.md).

Alternatively, take a look at this [list of open source tunneling solutions](https://github.com/anderspitman/awesome-tunneling#open-source-at-least-with-a-reasonably-permissive-license) you can investigate.

We chose ngrok for this guide because it offers a simple, lightweight, and cost-effective way to securely expose an application without too much additional configuration or infrastructure maintenance.

## What you'll need

Here's what you'll need to follow along:

* **An ngrok account.** A free account may work for once-off environments. A business license is better for multiple accounts in a wildcard setup. Visit [ngrok's pricing page](https://ngrok.com/pricing) for more details.
* **An ngrok token.** Preferably a token generated specifically for this use case so it can be revoked or changed without impacting a regularly used token somewhere else.
* **A Release application** running in your Release account.
* **A service that you would like to expose via the proxy tunnel.**
* **An OAuth, SAML, or OIDC service provider,** such as Google Workspaces – this is optional, as it may incur vendor charges.
* **A custom domain name for your private pages,** this is also optional, as it may incur vendor charges.

## Set up

Say you want to expose the following service via the proxy tunnel:

```yaml
services:
- name: docsbuild
  image: mycoolrepo/mycoolapp/docsbuild
  registry: local
  has_repo: true
  ports:
  - type: container_port
    port: '8080'
  build:
    context: "."
    dockerfile: docs/Dockerfile
```

The `docsbuild` service is not for public consumption, but we would like to view it along with our code deployments in pre-production settings. The main application is configured with authentication and access controls, but the documentation is a set of web pages and would be difficult to protect. If you added a regular `node_port:` and `hostnames:` section to your application, the documentation would be exposed to the internet.

Let's create a private tunnel for an additional layer of protection instead.

### Add the ngrok secure tunnel

We can expose the application via ngrok using a [simple container](https://hub.docker.com/r/wernight/ngrok/). Instantiate this service alongside your other services in the application template as follows:

```yaml
services:
- name: docsbuild-tunnel
  image: wernight/ngrok
```

Next, add the following to your application's environment variables template:

```yaml
services:
  docbuild-tunnel:
  - key: NGROK_AUTH
    value: mysecretauthtoken
    secret: true
  - key: NGROK_LOOK_DOMAIN
    value: docsbuild
  - key: NGROK_PORT
    value: '8080'
  - key: NGROK_BINDTLS
    value: "true"
```

Here, the `NGROK_AUTH` key has the value of your ngrok token. We use `NGROK_LOOK_DOMAIN` to identify the service to expose via the ngrok tunnel, in this case it is `docsbuild`. The port is specified as `8080`. By default ngrok will use http (you could specify TLS or TCP as well). Therefore the full url to your internal service in this example would be `http://docsbuild:8080`. You could consider adding a [sidecar](https://docs.microsoft.com/en-us/azure/architecture/patterns/sidecar) and pointing to `http://localhost` for even more privacy. The `NGROK_BINDTLS` option tells ngrok to redirect from HTTP to HTTPS and only support `https:` traffic externally.

Add both services to your `setup` workflow, but don't add the tunnel service to your patch flow, since it doesn't need to be restarted during deploys:

```yaml
workflows:
- name: setup
  paralellize:
  - step: docs
    tasks:
    - services.docsbuild
    - services.docsbuild-tunnel
    wait_for_finish: false
- name: patch
  paralellize:
  - step: docs
    tasks:
    - services.docsbuild
    wait_for_finish: false
```

### Find the tunnel address

Exposing the tunnel service logs will reveal the one-time URL in ngrok.io similar to the following:

```
ngrok by @inconshreveable

Tunnel Status                 online
Version                       2.0/2.0
Web Interface                 http://localhost:4040
Forwarding                    https://abc.ngrok.io -> docsbuild:80

Connnections                  ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00
```

Point your browser to the `Forwarding` URL to view your documentation pages.

{% hint style="info" %}
You can also expose the ngrok dashboard that runs on port 4040 by using `hostnames:`, or by using another tunnel pointed at the ngrok tunnel server. The ngrok tunnel dashboard could be used for various development or debugging services, but the dashboard itself will be exposed on the internet and may need to be protected too.
{% endhint %}

## Release's tips for protecting private services

Here are our tips for securing private tunnels.

### 1. Use an easy subdomain

You may want to use a well-known custom domain name for your application tunnel endpoint, but this could incur additional costs and require an upgrade to your ngrok account.

You could instead add a subdomain directive to your environment variable template:

```yaml
services:
  docsbuild-tunnel:
  - key: NGROK_SUBDOMAIN
    value: mydocs
```

Which yields something like this output:

```
ngrok by @inconshreveable

...
Forwarding                    https://mydocs.ngrok.io -> docsbuild:80
```

You can also use [Environment variable mappings](/reference-documentation/environment-settings/environment-specific-environment-variables/environment-variable-mappings.md)to create a link to the tunnel port like this

```
mapping:
  NGROK_SUBDOMAIN: RELEASE_ENV_ID
```

You will also need to add [Hostnames and rules](/guides-and-examples/advanced-guides/hostnames-and-rules.md) section like the following to your application template so that you can easily click the link in the UI or pull request comments.

```
hostnames:
- ${env_id}.ngrok.io
```

### 2. Use a custom branded domain

For an even better domain name option, use a fully customised hostname. Please note this probably requires an upgrade to a paid ngrok account and features.

#### Prerequisites

A quick diversion here is required since the custom domain names will not be managed by Release (we have no way of knowing what the ngrok tunnel addresses will be). You will need to setup CNAME record(s) in your cloud DNS provider, and a custom domain and a TLS certificate in the ngrok dashboard.

Make sure you follow [ngrok's set up instructions](https://ngrok.com/docs/guides/how-to-set-up-a-custom-domain).

#### Setup example

```yaml
services:
  docsbuild-tunnel:
  - key: NGROK_HOSTNAME
    value: mydocs.private.example.com
```

Which yields something like this output:

```
ngrok by @inconshreveable

...
Forwarding                    https://mydocs.private.example.com -> docsbuild:80
```

You can also follow the same instructions as above for a mapping and hostnames section. This will avoid having to hardcode the values in your configuration file. These two sections should help guide you.

```
mapping:
  NGROK_HOSTNAME: DOCSBUILD_INGRESS_HOST
```

```
domain: example.com
hostnames:
- ${env_id}.private.${domain}
```

### 3. Use password protection

Add a basic authentication password:

```yaml
services:
  docsbuild-tunnel:
  - key: NGROK_USERNAME
    value: "myuser"
  - key: NGROK_PASSWORD
    value: "mypassword"
    secret: true
```

### 4. Use OAuth protection

Please note that these features are an upgrade in the ngrok product feature and may require additional costs. Follow the ngrok documentation to [configure an Edge](https://ngrok.com/docs/cloud-edge#creating-an-edge), then associate the `NGROK_AUTH` token with an ACL to attach to the custom Edge. You can add various Edge modules, including Mutual TLS, IP restrictions, OIDC, SAML, OAuth, and more.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.release.com/guides-and-examples/common-setup-examples/using-ngrok-+-oauth-for-private-tunnels.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
