Connecting External Services With Your Local WordPress

ngrok header graphic

For years I’ve eschewed using services such as HTML validators, because I was developing on my local machine, or even on a Virtual Machine inside my local machine; and external services couldn’t get to my website while it was under development. Worse yet, involving a webhook, a callback from a web based service, to your own website, was a chore because you had to deploy your site to a public-facing server before you could test it.

Until now. (Insert maniacal laugh here.)

I’ve recently started using a clever service called ngrok, which exposes your local development site to the Internet. Even if you’re behind a firewall.

(Quick aside. I believe it’s pronounced “en-grok”, rather than “n. g. rok”. Adherents of AngularJS will have to force themselves to conform.)

Yes, to be sure this is opening a big old hole in your security, but it’s a precise hole, for a given purpose. And it’s a controlled hole, because you can shut it down anytime you want. Plus, of course, you don’t have to advertise the new temporary URL.

Here’s How It Works

You download the ngrok application (and probably move it to /usr/local/bin, or some other location on your path), and run it in a terminal window, with the following parameters:
ngrok http 80
This produces a dashboard display like so:

Screen Shot 2015-11-15 at 5.16.57 PM

Now the Internet has a tunnel to your local webserver. When someone requests, they’ll get your localhost content. Moreover, the requests will be shown on your dashboard.

If you need more detailed information about your requests and their responses, you can go to the Web Interface as shown on your dashboard. Just point your browser to and you’ll be served this helpful fellow:

Screen Shot 2015-11-15 at 5.34.24 PM

But wait! There’s more!

Virtual Hosts

What if your app isn’t located at localhost? What if you’ve got dozens of projects and each one has its own virtual domain, like, where you’ve been playing with the SVG library? Not to worry, ngrok has you covered. Here’s your invocation:

ngrok http -host-header=rewrite

Now, as requests come in, ngrok rewrites the request to ask for

Small Fly in the Ointment

I should probably mention one small fly in the ointment at this point. Every time you invoke ngrok, it’s going to generate a new, random alphanumeric subdomain name. For instance, the new one for the rewrite is This isn’t a huge bother until you need to specify it to an external service, as we discussed at the beginning of this post, or shared it with a friend or customer. It’ll still work, of course; but each time you rerun ngrok, you’ll need to go change it on the external service, or share it again.

But ngrok has a solution for that, too. It’s going to cost a bit, but I think it’s well worth it. For $60 a year you get the ability to specify and reserve your own subdomain. For instance, I could reserve Of course your invocation is going to change slightly:

ngrok http -subdomain=raphaeldev -host-header=rewrite

And for that same subscription fee I could reserve any number of subdomains.

So, when I specify my ngrok URL to an external service, it’s not going to be changing every time I want to reboot my machine. Brilliant!

In a Virtual Machine

Very good. We’ve got a tunnel to our local dev environment. But what if our dev environment is in a Virtual Machine, inside our local machine? No problem-o.

You’ve already setup your hosts file in your host machine to point to the guest machine’s IP address, so you’re good to go. Invoke ngrok as usual from the host machine, and it will rewrite the request to your; which will then be picked up by your hosts file, and marshalled through to your VM.

All Set Then?

Well, not exactly. Now you’re getting to your page, but the page may have some issues. For instance, it may refer to assets such as JavaScript, CSS and images, with a fully qualified URL, including the domain name. So that’s a problem, because your user’s browser doesn’t know from In such cases the best practice is to use relative addressing. Instead of, use /css/style.css.

In fact, there are a couple of WordPress plugins (if you’re using WordPress) which do this for you: Relative URL, and Root Relative URL’s. The second one has over 50K installs, but hasn’t been updated in a couple of years, so I used the first one.

Any Other Issues?

Well, just one more, and it’ll bite you right in your WordPress back-end. The problem is when you want to reach your WP Admin page, there’s a redirect happening. But the redirect is to your, which gets pushed to your browser, and again, the browser doesn’t know squat about

Happily, there’s a solution for this one as well. But first, let me mention that Alan Shreve, the outstanding developer who came up with ngrok, has been unflagging in his support, helping me get through every one of these hurdles. Also, when I described the redirection issue, he explained that the redirect response is passed on to the requesting client. But ngrok isn’t translating the response’s redirection URL. If it did, this would have worked at this point. So he’s planning on adding 301 and 302 rewriting to the app.

In the meantime, the solution is to rename your domain to You’ll need to make a few changes to your setup. Here are the steps:

  • Change your URL’s in wp-admin > General to;
  • Add in your host’s /etc/hosts file (points to your VM’s IP);
  • Restart ngrok on your host machine, rewriting to the new URL;
  • Modify /etc/apache2/sites-available/25-av-....conf: replace the ServerName with;
  • Restart Apache in your guest VM.

Of course, once you’v done that, you don’t need the relative URL plugins anymore. But it’s a journey.

And… You’re Done!

Be sure to test thoroughly.

Of course, in the case of webhooks, chances are you won’t run into redirects. But in case you do, this would cover you.

Now go forth and use external services with wild abandon!

2 thoughts on “Connecting External Services With Your Local WordPress

  1. This was so helpful. I’d been working on getting this going for hours. And your comments finally pulled it together. I am tunnelling wordpress multisite in circle ci to run ghost inspector tests. I gave up on relative urls and finally just converted the entire site, apache alias and all.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.