August 24, 2023

Expose Clojure Service using Ngrok

clojure logo - post topic

Exposing a local running services can be valuable when writing apps and web-hooks for Cloud API products, e.g. Slack, Atlassian Confluence, Hasura, Salesforce, etc.

ngrok exposes local networked services behinds NATs and firewalls to the public internet over a secure tunnel.

Create a free ngrok account to get an authorisation token for use with the ngrok agent to create a secure tunnel. Or add an SSH public key to use SSH reverse tunnel with the ngrok service.

ngrok has additional paid services, although they are not required for exposing local services.

Example Clojure Service

Practicalli Clojure CLI Config defines the :project/create alias to generate a new project from a template. The practicalli/service template creates a project for developing web services with a REST API.

Create a project called gameboard using donut system to manage service components

clojure -T:project/create :template practicalli/service :name practicalli/gameboard :component donut

Change into the gameboard directory

make run (clojure -M:run/service) to run the service locally, serving an API endpoint on http://localhost:8080

Alternatively, make docker-build to run the service via a docker container (assuming Docker is running locally).

Install ngrok

Linux (apt) operating system, add a ngrok repository key and install the ngrock package

curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | \
  sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null && \
  echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | \
  sudo tee /etc/apt/sources.list.d/ngrok.list && \
  sudo apt update && sudo apt install ngrok

MacOS install with HomeBrew:

brew install ngrok/ngrok/ngrok

Ngrok download page for other installation options or use an SSH reverse tunnel without need to install the ngrok agent.

Setup ngrok

Create an account with multi-factor authentication.

Login to the Ngrok dashboard to obtain the Authtoken (tunnel credential) for the ngrok account. The token is used by the ngrok agent to log into the ngrok account when starting a tunnel.

ngrok config add-authtoken TOKEN

Claim a free static domain to avoid random URLs. Creating a domain of your own choosing is a paid service on ngrok.

ngrok config file

Use a configuration file to define one or more tunnels for use with the ngrok agent.

Open the default ngrok configuration file for editing:

ngrok config edit

Or open the yaml file from the default configuration location

  • Linux: ~/.config/ngrok/ngrok.yml
  • MacOS (Darwin): ~/Library/Application Support/ngrok/ngrok.yml
authtoken: ***************************_*********************
version: 2
tunnels:
  custom_tunnel_name:
    proto: http
    hostname: free-static-domain-name.ngrok-free.app
    addr: 127.0.0.1:8080

    # -------------------------
    # Additional options
    # -------------------------
    # auth: "username:password"
    # host_header: rewrite
    # inspect: true
    # bind_tls: true

ngrok agent configuration file documentation

Start the tunnel using the command line.

ngrok start custom_tunnel_name

Or start all tunnels in the configuration file

ngrok start --all

Inspecting traffic

Open http://localhost:4040 to view the ngrok web interface, allowing inspection of traffic over the secure HTTP tunnel (TCP & TLS tunnel inspection not supported).

The web interface lists each request through the tunnel and selecting a request shows all the details of that request.

  • Request body validation (JSON, XML data)
  • Filter requests on request path, response status code, response body size, request duration, or any header value
  • Replay requests, optionally modifying a request first
  • ngrok agent status to help with troubleshooting the tunnel connetion

Ngrok web inspection interface

Ngrok web inspection interface

SSH reverse tunnel

ngrok can be used with SSH reverse tunneling (ssh -R), avoiding the need to install the ngrok agent.

Add an SSH public key to the ngrok dashboard, Tunnels > SSH Public Keys

Run the command to open an SSH reverse tunnel to ngrok

ssh -R 443:localhost:80 tunnel.us.ngrok.com http

SSH reverse tunnel agent documentation

ngrok Docker service

Use a Docker image containing ngrok to avoid installing the ngrok agent.

ngrok provides the ngrok/ngrok docker image. Practicalli recommends using the alpine image variant for minimal resource use.

docker run -it -e NGROK_AUTHTOKEN=$NGROK_AUTH_TOKEN ngrok/ngrok:alpine http 8080 --domain=free-static-domain-name.ngrok-free.app

Add an ngrok service to Docker compose.yaml, optionally adding a volume and port configuration.

To manage ngrok configuration effectively, add an ngrok.yml configuration to the root of the directory where the ngrok image is to be run. The ngrok.yml config is mounted to /etc/ngrok.yml in the Docker container, allowing an simple way to update the config.

services:
    ngrok:
        image: ngrok/ngrok:alpine
        restart: unless-stopped
        command:
          - "start"
          - "--all"
          - "--config"
          - "/etc/ngrok.yml"
        volumes:
          - ./ngrok.yml:/etc/ngrok.yml
        ports:
          - 4040:4040

Run all the services defined in the Docker compose.yml file, optionally with the --detatch flag to run in the background of the shell.

docker compose up --detatch

Or run only the ngrok service

docker compose up --detatch ngrok

Add an ngrok service to a Docker compose configuration to build & run the clojure service in conjunction with a multi-stage dockerfile.

Using ngrok with Docker

Secure public endpoints

ngrok agent allows security to be dynamically added to any public endpoint, with IP restrictions

  • HTTP Basic Authentication
  • OAuth 2.0
  • OpenID Connect
  • SAML
  • Webhook Verification
  • Mutual TLS

Summary

ngrok is a secure way to expose locally running services that integrate with cloud services and can help speed development by providing faster feedback than running a full deployment cycle.

ngrok agent works on multiple operating systems and can be run in a Docker container. An SSH reverse tunnel can be used for zero agent install approach.

Using ngrok only because the continuous integration process is very time consuming is a strong indication that time should be invested in improving the CI workflow, ensuring the minimal amount of work is required to create a repeatable build.

practicalli GitHub profile I @practical_li

Tags: clojure ngrok