# Hosting a Hugo site on a Cloudflare Worker

**URL:** <https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203>\
**Category:** tips & tricks\
**Created:** [July 2, 2025, 8:37am UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203 "2025-07-02T08:37:43Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![tyco](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/tyco/32/23754_2.png) [@tyco](https://discourse.gohugo.io/u/tyco)\
**Post date:** [July 2, 2025, 8:37am UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/1 "2025-07-02T08:37:43Z")

</div>

Following a [discussion](https://discourse.gohugo.io/t/hugo-support-in-cloudflare-workers/54866) on hosting Hugo on a Cloudflare worker, @jmooring came up with an excellent solution.

Here’s an example project hosted on a Cloudflare Worker:

> **[GitHub - jmooring/hosting-cloudflare-worker: This is a test of hosting a Hugo site on a...](https://github.com/jmooring/hosting-cloudflare-worker)**
>
> This is a test of hosting a Hugo site on a Cloudflare Worker

This is the build script:

> <https://github.com/jmooring/hosting-cloudflare-worker/blob/main/build.sh>

And the wrangler.toml file

> <https://github.com/jmooring/hosting-cloudflare-worker/blob/main/wrangler.toml>

Those are the only two files you need to copy to your project and configure to your liking. For example–

- change Dart SASS version or if you don’t transpile SASS to CSS, you can remove Dart SASS code from the `build.sh` file.
- change the time zone.
- change Hugo version
- change Node JS version

---

<div class="post-metadata">

**Author:** ![svenvg93](https://avatars.discourse-cdn.com/v4/letter/s/a183cd/32.png) [@svenvg93](https://discourse.gohugo.io/u/svenvg93)\
**Post date:** [July 20, 2025, 2:07pm UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/2 "2025-07-20T14:07:17Z")

</div>

I was able to get the deployment working without a custom build script by using the following simplified `wrangler.jsonc` configuration:

```auto
{
  "name": "example-com",
  "compatibility_date": "2025-07-20",
  "assets": {
    "directory": "./public",
    "html_handling": "auto-trailing-slash",
    "not_found_handling": "404-page",
    "run_worker_first": false
  },
  "build": {
    "command": "hugo build --gc --minify",
  },
  "workers_dev": true,
  "preview_urls": true
}

```

Not sure it will work for every environment as I have mine themes defined in go modules

---

<div class="post-metadata">

**Author:** ![tyco](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/tyco/32/23754_2.png) [@tyco](https://discourse.gohugo.io/u/tyco)\
**Post date:** [July 21, 2025, 7:36am UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/3 "2025-07-21T07:36:53Z")

</div>

This example is shared by a Hugo support/maintainer person. So, for a user, it is the way I would recommend to go with.

---

<div class="post-metadata">

**Author:** ![jmooring](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/jmooring/32/4214_2.png) [@jmooring](https://discourse.gohugo.io/u/jmooring)\
**Post date:** [July 21, 2025, 12:20pm UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/4 "2025-07-21T12:20:00Z")

</div>

The build script:

1. Installs a specific version of Hugo
2. Installs a specific version of Dart Sass to transpile Sass to CSS
3. Sets the system timezone
4. Ensures that `Page.GitInfo` returns the expected results
5. Addresses [https://github.com/gohugoio/hugo/issues/9810](https://github.com/gohugoio/hugo/issues/9810)

In my view all but #2 are required for every site.

---

<div class="post-metadata">

**Author:** ![dindinet](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/dindinet/32/25040_2.png) [@dindinet](https://discourse.gohugo.io/u/dindinet)\
**Post date:** [August 20, 2025, 8:37am UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/5 "2025-08-20T08:37:44Z")

</div>

@jmooring Hi Jo I had a go with your build.sh script but fails.  
I get this in the cloudflare worker build logs:

**stderr: ‘/bin/sh: 1: ./build.sh: Permission denied’,**

Have I missed something real simple?

---

<div class="post-metadata">

**Author:** ![tyco](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/tyco/32/23754_2.png) [@tyco](https://discourse.gohugo.io/u/tyco)\
**Post date:** [August 20, 2025, 8:41am UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/6 "2025-08-20T08:41:13Z")

</div>

> [@dindinet](#):
>
> stderr: ‘/bin/sh: 1: ./build.sh: Permission denied’,

Did you copy the code directly from Joe’s file or the file itself? See [Hugo support in Cloudflare Workers - #6 by tyco](https://discourse.gohugo.io/t/hugo-support-in-cloudflare-workers/54866/6) and [Hugo support in Cloudflare Workers - #7 by jmooring](https://discourse.gohugo.io/t/hugo-support-in-cloudflare-workers/54866/7).

---

<div class="post-metadata">

**Author:** ![dindinet](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/dindinet/32/25040_2.png) [@dindinet](https://discourse.gohugo.io/u/dindinet)\
**Post date:** [August 20, 2025, 8:46am UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/7 "2025-08-20T08:46:22Z")

</div>

I copied the code from [hosting-cloudflare-worker/build.sh at main · jmooring/hosting-cloudflare-worker · GitHub](https://github.com/jmooring/hosting-cloudflare-worker/blob/main/build.sh) raw and pasted it into a file build.sh in my project.

---

<div class="post-metadata">

**Author:** ![dindinet](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/dindinet/32/25040_2.png) [@dindinet](https://discourse.gohugo.io/u/dindinet)\
**Post date:** [August 20, 2025, 8:59am UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/8 "2025-08-20T08:59:57Z")

</div>

Doh!  
I I did a  
**`git add --chmod=+x build.sh`**  
instead of  
**`chmod +x build.sh`**

All good now

---

<div class="post-metadata">

**Author:** ![jmooring](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/jmooring/32/4214_2.png) [@jmooring](https://discourse.gohugo.io/u/jmooring)\
**Post date:** [August 20, 2025, 1:41pm UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/9 "2025-08-20T13:41:48Z")

</div>

In our [Host on Cloudflare](https://gohugo.io/host-and-deploy/host-on-cloudflare/) documentation I’ve change the build command from this:

```plaintext
[build]
command = "./build.sh'"

```

To this:

```plaintext
[build]
command = "chmod a+x build.sh && ./build.sh"

```

That makes the permissions of the file in the repository irrelevant.

---

<div class="post-metadata">

**Author:** ![tifenak](https://avatars.discourse-cdn.com/v4/letter/t/e36b37/32.png) [@tifenak](https://discourse.gohugo.io/u/tifenak)\
**Post date:** [September 28, 2025, 2:13pm UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/10 "2025-09-28T14:13:03Z")

</div>

I tried the worker, but I have to remember every time to rebase my project before pushing changes (mostly markdown content).

---

<div class="post-metadata">

**Author:** ![pawelgrzybek](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/pawelgrzybek/32/25676_2.png) [@pawelgrzybek](https://discourse.gohugo.io/u/pawelgrzybek)\
**Post date:** [February 16, 2026, 6:28pm UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/11 "2026-02-16T18:28:42Z")

</div>

High chance that what @jmooring is suggesting here is better, but I found a lot simpler way to ensure that the CF is running on the latest version of Hugo.

Adding `HUGO_VERSION` to the build env var config does the trick.

 ![Screenshot 2026-02-16 at 18.23.32](https://canada1.discourse-cdn.com/flex036/uploads/gohugo/original/3X/7/4/745affc299c6fd55312b4d617a11397be0d0cd2f.png)

 ![Screenshot 2026-02-16 at 18.26.57](https://canada1.discourse-cdn.com/flex036/uploads/gohugo/original/3X/6/b/6b5b8b51dc8bb5b3c590c16e0e9590946988b2d3.png)

---

<div class="post-metadata">

**Author:** ![jmooring](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/jmooring/32/4214_2.png) [@jmooring](https://discourse.gohugo.io/u/jmooring)\
**Post date:** [February 16, 2026, 6:50pm UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/12 "2026-02-16T18:50:36Z")

</div>

That gives you the standard edition, not the extended one. Keep in mind that while you don’t need the extended version for WebP encoding anymore since v0.153.0, you still need it to transpile Sass to CSS with the built-in LibSass tool. Unless you’re 100% sure which transpiler your template is using, it’s usually much safer to just run the extended edition and avoid the headache.

Getting the right version and edition running is really only half the battle, though. If you’re setting this up on Cloudflare for the first time, I definitely recommend checking out the official guide at [Host on Cloudflare](https://gohugo.io/host-and-deploy/host-on-cloudflare) to make sure everything else is dialed in correctly. The devil is in the details…

---

<div class="post-metadata">

**Author:** ![pawelgrzybek](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/pawelgrzybek/32/25676_2.png) [@pawelgrzybek](https://discourse.gohugo.io/u/pawelgrzybek)\
**Post date:** [February 17, 2026, 9:09am UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/13 "2026-02-17T09:09:41Z")

</div>

Thank you so much for the clarification. Your guide is phenomenal, thank you for that. Probably I never hit any of the limitation you mentioned above because my site is so simple and I don’t use Sass on my templates, just pure CSS.

What is explained on your guide should also be mirrored here imo [Web applications · Cloudflare Workers docs](https://developers.cloudflare.com/workers/framework-guides/web-apps/) Would you mind if I trigger a PR to the CF docs that suggest changes based on your guide? Maybe slightly edited to better suit CF docs. Of course I will link you to it…

---

<div class="post-metadata">

**Author:** ![pawelgrzybek](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/pawelgrzybek/32/25676_2.png) [@pawelgrzybek](https://discourse.gohugo.io/u/pawelgrzybek)\
**Post date:** [February 17, 2026, 9:33am UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/14 "2026-02-17T09:33:25Z")

</div>

I just did a quick experimentation, and looks like `sass` in version `1.97.3` also comes built-in in CF Workers runtime now. That should be enough to fulfil all the cases unless someone really needs this part of your script.

```bash
 # Configure Git
  echo "Configuring Git..."
  git config core.quotepath false
  if ["$(git rev-parse --is-shallow-repository)" = "true"]; then
    git fetch --unshallow
  fi
  

```

Here is the screenshot from the CF logs view.

 ![Screenshot 2026-02-17 at 09.27.15](https://canada1.discourse-cdn.com/flex036/uploads/gohugo/original/3X/0/b/0b92283f33d809412b63a9e0af536957c5e8e40b.png)

This is `sass --version` but my screenshooting tool merged double hyphen into en-dash 🤷‍♂️

---

<div class="post-metadata">

**Author:** ![pawelgrzybek](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/pawelgrzybek/32/25676_2.png) [@pawelgrzybek](https://discourse.gohugo.io/u/pawelgrzybek)\
**Post date:** [February 17, 2026, 1:00pm UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/15 "2026-02-17T13:00:31Z")

</div>

I just run a quick dirty script to output whats already on the CF runtime, maybe someone is going to find it helpful.

> **[Cloudflare Build Environment CLIs](https://cf-clis.pawelgrzybek.workers.dev)**

---

<div class="post-metadata">

**Author:** ![jmooring](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/jmooring/32/4214_2.png) [@jmooring](https://discourse.gohugo.io/u/jmooring)\
**Post date:** [February 17, 2026, 4:49pm UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/16 "2026-02-17T16:49:25Z")

</div>

I might be overly cautious, but I don’t like leaving a build environment to chance. Relying on a service provider’s default tools is a moving target; specifying exact versions ensures I’m not stuck with an outdated toolset or blindsided by a breaking update I didn’t plan for.

At the time I wrote the guide, if I wanted to specify versions in one place, the only way I could do it was within a build script.

---

<div class="post-metadata">

**Author:** ![pawelgrzybek](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/pawelgrzybek/32/25676_2.png) [@pawelgrzybek](https://discourse.gohugo.io/u/pawelgrzybek)\
**Post date:** [February 17, 2026, 6:30pm UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/17 "2026-02-17T18:30:29Z")

</div>

I totally agree with your point. For simpler and less critical projects, it can be sufficient to just specify the desired version. Sass has a great history of backward compatibility, and also not every single project uses Sass. Modern CSS with custom properties and nesting gave me all I used Sass for, and now I just use pure CSS.

In terms of specifying the exact version of Hugo, yeah, I think CF added an ability to add build vars only recently.

I also tested working with `.GitInfo` and that also worked without any additional changes, but I have a very little understanding of this part so I’m sure your script is there for a good reason.

Thank you for help @jmooring, I mentioned this conversation and pros and cons of both approaches on my post.

> **[Deploy Hugo site to Cloudflare Workers | pawelgrzybek.com](https://pawelgrzybek.com/deploy-hugo-site-to-cloudflare-workers/)**
>
> Deploying a Hugo site to Cloudflare Workers is not as straightforward as some other JavaScript-based frameworks. This step-by-step guide may help.

---

<div class="post-metadata">

**Author:** ![jmooring](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/jmooring/32/4214_2.png) [@jmooring](https://discourse.gohugo.io/u/jmooring)\
**Post date:** [February 17, 2026, 6:35pm UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/18 "2026-02-17T18:35:44Z")

</div>

> [@pawelgrzybek](#):
>
> .GitInfo

The Git configuration in the build script addresses (a) the fact that CF performs shallow clones, and (b) a known issue related to file names ([GitInfo unset when file path contains bytes \> 0x80 · Issue #9810 · gohugoio/hugo · GitHub](https://github.com/gohugoio/hugo/issues/9810)).

---

<div class="post-metadata">

**Author:** ![pawelgrzybek](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/pawelgrzybek/32/25676_2.png) [@pawelgrzybek](https://discourse.gohugo.io/u/pawelgrzybek)\
**Post date:** [February 17, 2026, 6:36pm UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/19 "2026-02-17T18:36:56Z")

</div>

Thank you!

---

<div class="post-metadata">

**Author:** ![markupandmatcha](https://avatars.discourse-cdn.com/v4/letter/m/ec9cab/32.png) [@markupandmatcha](https://discourse.gohugo.io/u/markupandmatcha)\
**Post date:** [February 18, 2026, 6:21am UTC](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203/20 "2026-02-18T06:21:12Z")

</div>

this is a really tidy setup — nice to see it documented properly.

we’ve been using Netlify for most of our client sites at the studio and it’s genuinely hard to beat for zero-config deployments. but the Cloudflare Workers approach is interesting for cases where you want edge performance without the Netlify overhead on the free tier (their bandwidth limits can sneak up on you on image-heavy sites).

one thing worth noting for anyone comparing options: Netlify and Vercel both auto-detect Hugo projects and handle the build for you — so there’s basically no config file to write at all, which is nice if you just want to get something live fast. the Cloudflare Worker approach here is more manual but gives you way more control and the edge distribution is genuinely fast.

for personal projects or simple blogs i’d still say Netlify is the path of least resistance. but for something with heavier traffic or global audiences, this Worker approach looks worth the extra setup.

has anyone run into issues with the Dart Sass installation step taking too long on cold builds? that’s been our main friction point with custom build scripts on similar setups.

[Next page](https://discourse.gohugo.io/t/hosting-a-hugo-site-on-a-cloudflare-worker/55203.md?page=2)
