tim olson

A site reliability engineer targeting all things Kubernetes. Coming from SWE I love working all parts of the stack. I specifically provide Kubernetes as a platform along with the administration, onboarding, and life-cycle of applications. Long live Linux.

St. Paul, MN

Testing Hugo Open Graph Protocol with Ngrok

Sat, Dec 18, 2021

Estimated reading time: 4 min

development proxy ngrok hugo

Intro #

I expect this to be a quick procedural type of blog post. Open Graph Protocol is a really really nice feature of web standards. If you’ve ever seen preview windows on Twitter, Discord, Slack, this is using OGP (or a variation on the spec).

Open Graph Protocol has a variety of configuration options. The base for rendering an image and description requires:

<meta property="og:title" content="The Rock" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://www.imdb.com/title/tt0117500/" />
<meta property="og:image" content="https://ia.media-imdb.com/images/rock.jpg" />

But!

In a lot of cases the original spec didn’t solve all the technical challenges. So, Twitter implemented their own spec, but often it’s easiest to consider them together. (At least in purpose, but not implementation):

<meta name="twitter:card" value="summary_large_image">
<meta name="twitter:title" content="The Rock">
<meta property="twitter:image" content="https://ia.media-imdb.com/images/rock.jpg" />
<meta property="twitter:url" content="https://www.imdb.com/title/tt0117500/" />

Put these two together and you will cover the majority of scenarios. Fortunately for us, the newer players into the OGP space, have not chosen to reinvent the wheel. A company like Discord may be using Twitter’s spec for example.

Mechanics of Open Graph Protocol #

Like most HTML rendering. It’s subject to a lot of interpretation. Where normally HTML can be dependent on a browser. OGP is dependent on third party site renders. Meaning, places you share. LinkedIn, Twitter, Slack, Discord, Reddit. All of these places know the OGP spec, but may interpret it differently.

Because we need an external third party to render our OGP, we must make it public. This is where the proxy comes in.

How to test? #

When we run a server locally we would normally run something like:

# Don't run this just yet.
hugo serve -D --debug

This is great when working on layouts, content, and so on.

But when we look at the rendered OGP, it will be loaded with localhost:1313. This certainly will not do. OGP is used by third parties to render content on their platform. For this reason the render target for the third parties must not exist outside your LAN.

It is worth pointing out at this moment that there do exist localhost OGP renderers, such as: https://addons.mozilla.org/en-US/firefox/addon/open-graph-preview-and-debug/

This is a good extension but I find sometimes the 3rd parties don’t cover all of our scenarios.

Enter ngrok #

Ngrok is a company and product that provides secure tunneling to your box. I had first heard about the solution when needing a proxy for a raspberry pi.

Aside: It might be worth pointing out, the functionality of ngrok is not unique, it’s just easy. Other options like localtunnel provide similar functions and can be self hosted. Another would be to setup a wireguard server and nginx on a remote VPS, and run a local wireguard client to the VPS. Or even simplier: An ssh tunnel out to your VPS.

First thing we need to do to make our dev environment public of OGP testing is to launch ngrok

$ ngrok http 1313

Gives output:

ngrok by @inconshreveable                                                (Ctrl+C to quit)

Session Status                online
Account                       tim (Plan: Free)
Version                       2.3.40
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://7fb1-24-15-121-5.ngrok.io -> http://localhost:1313
Forwarding                    https://7fb1-24-15-121-5.ngrok.io -> http://localhost:1313

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00

If you get an error like: The error encountered was: dial tcp: lookup localhost on 127.0.0.1:53: no such host, try running hugo with the following:

ngrok http 1313 -host-header="127.0.0.1:1313"

I’ve changed my output slightly, but you will notice, 4 random chars and then your public IPv4. You will now see that you’re tunneling to a http server that is not running.

So let’s take public domain: https://7fb1-24-15-121-5.ngrok.io, and save that for hugo.

Now when we launch hugo we will do so as:

hugo serve -D --debug -b https://7fb1-24-15-121-5.ngrok.io --appendPort=false

Tada! We now can send https://7fb1-24-15-121-5.ngrok.io, to Discord, Slack, Twitter, and test away at OGP.

This was accomplished with:

      --appendPort             append port to baseURL (default true)
  -b, --baseURL string         hostname (and path) to the root, e.g. http://spf13.com

So we get around our port 1313 and localhost. You can happily develop in this mode, but consider that ngrok is being used by us in a free tier and could be subject to limits or privacy concerns.

Have fun!

Examples: #

Let’s look at this blogpost in Slack:

ngrok-1

How about discord?:

ngrok-2

What about another type of post?:

ngrok-3