Expose Phoenix app via (free) ngrok

Need to test your Phoenix app from a mobile device? ngrok is the de facto solution for expose your local machine to the internet. Without a paid plan, each time you launch ngrok you receive a new hostname that has to be copied into your Phoenix app... until now ๐Ÿ˜

With some clever bash scripting you can automatically populate the ngrok address and launch Phoenix with the correct HOST automatically set.

Configure Phoenix to use $HOST

Ensure your config/dev.exs file is configured correctly to use the ENV["HOST"] when running in development.

# config/dev.exs

config :my_app, MyApp.Endpoint,
  http: [port: 4000],
  url: [scheme: "https", host: {:system, "HOST"}, port: "443"],
  debug_errors: true,
  code_reloader: true,
  check_origin: false,
  watchers: [
    node: [
      "node_modules/webpack/bin/webpack.js",
      "--mode",
      "development",
      "--watch-stdin",
      cd: Path.expand("../assets", __DIR__)
    ]
  ]

The above assumes you want Phoenix to generate URLs with a HTTPS scheme. If you want HTTP instead, switch the port value to 80 instead of 443.

Makefile to populate HOST from ngrok

I prefer to have Makefiles for all of my projects, but if you prefer a bash script this should be easily adapted.

FYI This script expects jq and curl to be installed.

NGROK_HOST := $$(curl --silent http://127.0.0.1:4040/api/tunnels | jq '.tunnels[0].public_url' | tr -d '"' | awk -F/ '{print $$3}')


.PHONY: serve-ngrok
serve-ngrok: ## Start Phoenix bound to ngrok address
	@echo "๐ŸŒ Exposing My App @ https://$(NGROK_HOST)"
	env HOST=$(NGROK_HOST) mix phx.server

The first line extracts the host value from the built-in ngrok server and passes it into the make serve-ngrok command.

Launch Steps

My development workflow now is:

  1. Open an empty shell and run ngrok http 4000
  2. Open a second shell in our project directory and run make serve-ngrok to boot ย the Phoenix application.

And that is it! Hope this saves folks some headaches when testing remote devices in development.