Photo by Ricardo Gomez Angel on Unsplash
Sharing Local Laravel App Using Ngrok
This article explains how to use ngrok with Laravel, and how to fix the most annoying gotcha.
Table of contents
Imagine that you want to access your local Laravel app from another device. There is an amazing service for that called ngrok. This article explains how to use it, and how to fix one annoying gotcha.
Start app
Start Laravel Sail:
sail up
Note that on my PC, the APP_PORT
environment variable is set to 8000
, so it’s running on HTTP port 8000. The port number is used in the ngrok http
command used in the next step.
Start ngrok
Create an account at https://ngrok.com/.
Then, download the ngrok agent, unzip it and connect it to your account as specified in steps 1 and 2 of the Setup & Installation guide.
Finally, start ngrok. It creates an externally accessible domain, something like https://bdae-78-56-73-243.ngrok-free.app/ and resolves it to your locally running app:
ngrok http 8000
How cool is that!
Fix CSS and JS file loading
However, soon you’ll notice a problem - your CSS and JS files are not loaded. And there are 2 reasons for that.
First, you may be running npm run dev
. Unfortunately, it doesn’t play well with ngrok. So, stop it and build assets using the following command instead:
npm run build
Second, Laravel thinks that it’s running on an HTTP port while via ngrok it’s actually being served using HTTPS. To fix that, add an HTTP middleware that forces Laravel to “think HTTPS” if it runs under ngrok:
Create the
app/Http/Middleware/UpgradeToHttpsUnderNgrok.php
:<?php namespace App\\Http\\Middleware; use Closure; use Illuminate\\Http\\Request; use Illuminate\\Support\\Facades\\URL; use Symfony\\Component\\HttpFoundation\\Response; class UpgradeToHttpsUnderNgrok { public function handle(Request $request, Closure $next): Response { if (str_ends_with($request->getHost(), '.ngrok-free.app')) { URL::forceScheme('https'); } return $next($request); } }
Register the middleware in the
app/Http/Kernel.php
:protected $middlewareGroups = [ 'web' => [ ... UpgradeToHttpsUnderNgrok::class, ], ... ];
And now it works! Check it on your phone, send it to a co-worker or a client, and enjoy!