Skip to content

Instantly share code, notes, and snippets.

@rjz
Created August 9, 2016 16:20
Show Gist options
  • Save rjz/af40158c529d7c407420fc0de490758b to your computer and use it in GitHub Desktop.
Save rjz/af40158c529d7c407420fc0de490758b to your computer and use it in GitHub Desktop.
Get ngrok hostname from command line
#!/bin/sh
# ngrok's web interface is HTML, but configuration is bootstrapped as a JSON
# string. We can hack out the forwarded hostname by extracting the next
# `*.ngrok.io` string from the JSON
#
# Brittle as all get out--YMMV. If you're still reading, usage is:
#
# $ ./ngrok_hostname.sh <proto> <addr>
#
# To retrieve the ngrok'd URL of an HTTP service running locally on :3332, use:
#
# $ ./ngrok_hostname.sh http localhost:3332
#
# The protocol (http, https, etc) of the forwarded service
PROTO=$1
# The address of the forwarded service
ADDR=$2
# Hack JSON out of the web interface bootstrap
json=$(curl -s localhost:4040/inspect/http \
| grep -oP 'window.common[^;]+' \
| sed 's/^[^\(]*("//' \
| sed 's/")\s*$//' \
| sed 's/\\"/"/g')
# Parse JSON for the URLs matching the configured `$ADDR`
hosts=$(echo $json \
| jq -r ".Session.Tunnels \
| values \
| map(select(.Config.addr == \"$ADDR\") | .URL) | .[]")
echo "$hosts" | grep "^${PROTO}:"
@michael-lins
Copy link

michael-lins commented Sep 29, 2020

for the Rails community:

With this code you run the rails app with assets pointing to the tunnel, if available 👍

Create an initializer and call it "ngrok.rb" (just for the sake of sanity) and paste this on:

require 'net/http'
require 'json'

begin
  uri = URI("http://127.0.0.1:4040/api/tunnels")
  ngork_resp = Net::HTTP.get(uri)
  ngork_json = JSON.parse(ngork_resp)
  tunnel = ngork_json["tunnels"].first
  tunnel_uri = URI(tunnel["public_url"])
  Rails.application.configure do
    config.hosts << tunnel_uri.host
    config.action_controller.asset_host = tunnel_uri.to_s
    config.action_mailer.asset_host = config.action_controller.asset_host
  end
  puts "Yep, tunnel configured! all set on #{tunnel_uri.to_s}"
rescue
  puts "no tunnel configured! skiping configuration..."
end

@scott-knight
Copy link

@michael-lins That initializer is excellent! Thank you for posting that.

@vanbwodonk
Copy link

Nice threads !! I make python scripts to send all ngrok connections to telegram bot. So, we can connect to ssh without login to ngrok web.
https://github.com/vanbwodonk/Ngrok-TelegramBot-Status

@fdeh75
Copy link

fdeh75 commented Nov 23, 2020

Thanks @fvclaus)

@funder7
Copy link

funder7 commented Dec 14, 2020

My gosh guys...thanks, this is awesome!

@funder7
Copy link

funder7 commented Dec 15, 2020

I've created a bash script with the snippets found here, which takes the ngrok hostname and copies it into a spring configuration file (yml).

#!/bin/sh
#
# Wrapper script to launch reverse proxy with local configuration
# and copy tunnel's hostname into (spring) yml configuration
#
# Created 15 december 2020 - Federico Ricchiuto <f.ricchiuto@ital.dev>
#

FILE=./ngrok
CONFIGURATION=./ngrok.yml
SPRING_CONFIG_PATH=~/yourprojectpath/src/main/resources/config/application-dev.yml
OIDC_PROTOCOL='http'
OIDC_PATH='auth/realms/jhipster'
bold=$(tput bold)

echo "Checking ngrok executable..."

if test -f "$FILE"; then

  if test -f "$CONFIGURATION"; then

    echo "Starting ngrok..."
    (./ngrok start -config ./ngrok.yml --all ) > /dev/null &

    sleep .7 # Wait for ngrok launch

    NGROK_HOSTNAME=$(curl --silent --show-error http://127.0.0.1:4040/api/tunnels | sed -nE 's/.*public_url":"https:..([^"]*).*/\1/p')

    echo "Replacing backend app IdP setting..."
    NEW_SETTING="$OIDC_PROTOCOL://$NGROK_HOSTNAME/$OIDC_PATH"
    sed -i -e "s#issuer-uri.*#issuer-uri: ${NEW_SETTING}#" "$SPRING_CONFIG_PATH"

    echo "${bold}ngrok running @ $NGROK_HOSTNAME"
    wait

  else
    echo "Missing ngrok.yml configuration file - Pull from repository if deleted"

  fi
else
    echo "ngrok executable not found" >&2
    echo "Download from: https://ngrok.com/download"
fi

It verifies also if the ngrok executable is present in the same folder. You can call directly ngrok without checking it's configuration file, but in case that you need it:

authtoken: xxxx
region: eu
tunnels:
  revproxy:
    addr: 80
    proto: http
    # bind_tls: true # enables https only
    inspect: true # enables console @ localhost:4040

Im not a bash scripting expert, it can be improved. The hard part is calling curl after it's launch, as the process is running. Without redirecting it to /dev/null it wouldn't be possible to execute the following commands.

This way ngrok's output is lost, it's kinda sad :/

@reachlin
Copy link

reachlin commented Apr 8, 2021

seems not working anymore:

% curl --silent --show-error http://127.0.0.1:4040/api/tunnels 
curl: (52) Empty reply from server
% curl -v http://localhost:4040/inspect/http                   
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 4040 (#0)
> GET /inspect/http HTTP/1.1
> Host: localhost:4040
> User-Agent: curl/7.64.1
> Accept: */*
> 
* Empty reply from server
* Connection #0 to host localhost left intact
curl: (52) Empty reply from server
* Closing connection 0

@funder7
Copy link

funder7 commented Apr 8, 2021

Which version of ngrok?

@reachlin
Copy link

reachlin commented Apr 8, 2021

Which version of ngrok?

should be latest one, just tried one hour ago

@funder7
Copy link

funder7 commented Apr 11, 2021

should be latest one, just tried one hour ago

Just tried with the latest stable, it is working as usual.
Did you add inspect: true in your config file? (ngrok.yml)

@reachlin
Copy link

no luck.thx anyway

@robin-weaver
Copy link

url_new_https = response.json()["tunnels"][0]["public_url"]

Nice, good stuff. Amazing thread here.

@ecarrera
Copy link

ecarrera commented Feb 3, 2024

Shell script

  • OSX Sonoma 14.3
  • ngrok version 3.5.0
local json_data=$(curl -s localhost:4040/api/tunnels)
local public_url=$(echo "$json_data" | python3 -c "import sys, json; print(json.load(sys.stdin)['tunnels'][0]['public_url'])")
echo $public_url

@chikitai
Copy link

local json_data=$(curl -s localhost:4040/api/tunnels)
local public_url=$(echo "$json_data" | python3 -c "import sys, json; print(json.load(sys.stdin)['tunnels'][0]['public_url'])")
echo $public_

@chikitai
Copy link

local json_data=$(curl -Chikita Isaac bitcoin.comlocalhost:4040/api/tunnels)
local public_url=$(echo "$json_data" | python3 -c "import sys, json; print(json.load(sys.stdin)['tunnels'][0]['public_url'])")varonis.com
echo $public_freewallet(100000000000000000000000000000000000000000000000000009)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment