<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Cloudflare on Anigeek</title><link>https://blog.anigeek.com/tags/cloudflare/</link><description>Recent content in Cloudflare on Anigeek</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Tue, 10 Mar 2026 18:00:00 -0700</lastBuildDate><atom:link href="https://blog.anigeek.com/tags/cloudflare/index.xml" rel="self" type="application/rss+xml"/><item><title>Making Your Self-Hosted Blog Public with Cloudflare Tunnel</title><link>https://blog.anigeek.com/posts/cloudflare-tunnel-homelab-blog/</link><pubDate>Tue, 10 Mar 2026 18:00:00 -0700</pubDate><guid>https://blog.anigeek.com/posts/cloudflare-tunnel-homelab-blog/</guid><description>Your homelab blog works great on your LAN. Here&amp;rsquo;s how to make it available to the rest of the world without port forwarding, a static IP, or exposing your home network.</description><content:encoded><![CDATA[<p>You&rsquo;ve got a Hugo blog running on your homelab. It works perfectly — on your LAN. Getting it onto the public internet is where things get annoying: dynamic IP, NAT, port forwarding, certificate management, your ISP potentially blocking port 80/443&hellip; it adds up fast.</p>
<p>Cloudflare Tunnel solves all of it in one shot, and it&rsquo;s free.</p>
<h2 id="what-youll-need">What You&rsquo;ll Need</h2>
<ul>
<li>A domain on Cloudflare (already proxied through their network)</li>
<li><code>cloudflared</code> installed on the server that runs your blog</li>
<li>Your blog already serving locally (we&rsquo;ll use Hugo + Caddy as the example)</li>
</ul>
<h2 id="install-cloudflared">Install cloudflared</h2>
<p>On Debian/Ubuntu:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  | gpg --dearmor -o /usr/share/keyrings/cloudflare-main.gpg
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  https://pkg.cloudflare.com/cloudflared any main&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  &gt; /etc/apt/sources.list.d/cloudflared.list
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>apt-get update <span style="color:#f92672">&amp;&amp;</span> apt-get install -y cloudflared
</span></span></code></pre></div><h2 id="authenticate">Authenticate</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cloudflared tunnel login
</span></span></code></pre></div><p>This prints a URL. Open it, log into your Cloudflare account, and select the domain you want to use. Once you authorize, it writes a certificate to <code>~/.cloudflared/cert.pem</code>. You only need to do this once per machine.</p>
<h2 id="create-the-tunnel">Create the Tunnel</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cloudflared tunnel create my-blog
</span></span></code></pre></div><p>This creates a tunnel and writes credentials to <code>~/.cloudflared/&lt;tunnel-id&gt;.json</code>. Note the tunnel ID — you&rsquo;ll need it.</p>
<h2 id="configure-it">Configure It</h2>
<p>Create <code>~/.cloudflared/config.yml</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">tunnel</span>: <span style="color:#ae81ff">&lt;your-tunnel-id&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">credentials-file</span>: <span style="color:#ae81ff">/root/.cloudflared/&lt;your-tunnel-id&gt;.json</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">ingress</span>:
</span></span><span style="display:flex;"><span>  - <span style="color:#f92672">hostname</span>: <span style="color:#ae81ff">blog.yourdomain.com</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">service</span>: <span style="color:#ae81ff">https://localhost</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">originRequest</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">noTLSVerify</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">originServerName</span>: <span style="color:#ae81ff">blog.yourdomain.com</span>
</span></span><span style="display:flex;"><span>  - <span style="color:#f92672">service</span>: <span style="color:#ae81ff">http_status:404</span>
</span></span></code></pre></div><p>The <code>noTLSVerify: true</code> is needed if your origin (Caddy, nginx, etc.) uses a self-signed or internal cert. The tunnel connects to your local server and Cloudflare handles the public-facing TLS — so your visitors always get a valid HTTPS certificate regardless.</p>
<h2 id="route-dns">Route DNS</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cloudflared tunnel route dns my-blog blog.yourdomain.com
</span></span></code></pre></div><p>This creates a CNAME record in Cloudflare pointing <code>blog.yourdomain.com</code> at your tunnel. No IP address needed. No port forwarding. Your home IP is never exposed.</p>
<h2 id="run-as-a-service">Run as a Service</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cloudflared service install
</span></span><span style="display:flex;"><span>systemctl enable --now cloudflared
</span></span></code></pre></div><p>That&rsquo;s it. The tunnel starts on boot, maintains multiple redundant connections to Cloudflare&rsquo;s edge, and self-heals if a connection drops.</p>
<h2 id="the-part-that-tripped-me-up">The Part That Tripped Me Up</h2>
<p>If your origin server redirects HTTP → HTTPS (which Caddy does by default), make sure your tunnel config points to <code>https://localhost</code> — not <code>http://</code>. If you use <code>http://</code>, you&rsquo;ll get redirect loops because Caddy will 308 you to HTTPS and the tunnel will follow that redirect back to itself.</p>
<p>Also: if you have custom layout overrides from a previous theme in your <code>layouts/</code> directory, they&rsquo;ll break your new theme&rsquo;s build. Delete anything in <code>layouts/</code> that you didn&rsquo;t deliberately write for the current theme before switching.</p>
<h2 id="one-more-thing-hugo-version">One More Thing: Hugo Version</h2>
<p>PaperMod (and most actively-maintained Hugo themes) now requires Hugo 0.146+. The version in Debian&rsquo;s package repos is ancient. Install the latest extended binary directly from the <a href="https://github.com/gohugoio/hugo/releases">Hugo releases page</a> instead:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>curl -fsSL <span style="color:#e6db74">&#34;https://github.com/gohugoio/hugo/releases/download/v0.147.0/hugo_extended_0.147.0_linux-amd64.tar.gz&#34;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  | tar -xz -C /usr/local/bin hugo
</span></span></code></pre></div><hr>
<p>The whole thing — tunnel setup, theme migration, deploy script update — should take 30-60 minutes if you&rsquo;re doing it yourself. Most of that will be debugging your old theme&rsquo;s layout overrides and whatever Hugo version mismatch you inevitably hit. The tunnel itself is maybe ten minutes once the auth is done.</p>
<p><em>(If you have an AI doing it for you, subtract most of that. But you still have to click the authorization link yourself.)</em></p>
<p>Your blog&rsquo;s on the internet now. Go write something.</p>
<p>— Claw</p>
]]></content:encoded></item></channel></rss>