blog.thms.uk

Auto-Deploying a static site from Forgejo to CloudFlare Pages

When migrating from GitHub to my self-hosted Forgejo instance, I’ve lost the ability to use GitHub Pages to host a couple of static pages I have been hosting on GitHub.

One alternative is CloudFlare Pages. And whilst CloudFlare Pages has a direct integration with GitHub to deploy from GitHub to CloudFlare, no such direct integration exists with Forgejo.

This post walks us through setting up a Forgejo Action that will auto-deploy to CloudFlare Pages on every push.

Note: If you want to fully self host your static site, you may wish to have a look at how I’m self hosting my blog using Forgejo, Caddy, and Tailscale

Prerequisites

Here is what you need before you get started:

Creating your CloudFlare Page

Before you can deploy from your Forgejo action you must manually create a CloudFlare Page, and upload the first deployment manually by uploading it in the CloudFlare UI:

  1. Go to dash.cloudflare.com, and under Build > Compute, find Workers & Pages.
  2. Click the blue Create Application button.
  3. Find the small “Looking to deploy Pages? Get started” text underneath the card - CloudFlare are hiding it these days. CloudFlare Pages creation
  4. On the next page for “Drag and drop your files” click Get Started.
  5. Give it a name such as my-page and click ‘Create project’. You’ll need that name later, as that’s how CloudFlare identifies your page.
  6. Upload the files or folders for your first deployment (You could always just upload a folder with a single index.html file if you wanted to at this stage).
  7. Click ‘Deploy site’

Your page is now ready, and accessible at https://my-page.pages.dev (or whatever else you may have chosen for your name).

You can set up your custom domain now, if you wish, as well as any other configuration options.

Getting a CloudFlare Access Token and Account ID

Next we’ll need to get your Account ID and generate an Access Token for the automated deployments:

  1. Go to Manage Account > Account API Tokens and click ‘Create Token’.
  2. Assign the correct permissions: You’ll need Read and Edit access for Pages (which is found under the Developer Platform heading). Set your expiration and/or IP address restrictions if desired.
  3. On the next page you’ll be presented with your Account ID and your API Token. Take a note of both. You’ll need them.

Configure your Forgejo Action

We’ll need to provide the Account ID and Token to Forgejo as Secrets. That way they stay out of our code and hidden from prying eyes: Go to your repository settings, and find Actions > Secrets in the left column. Provide two secrets: CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN. It should look like this:

Forgejo Repository Settings

Creating your Forgejo Action

In your repository create a file at .forgejo/workflows/deploy.yml.

Paste the following content:

on:
  workflow_dispatch:
  push:
    branches: [main] # replace branch name, if you are not using `main`

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 22

      - name: npm install
        run: npm install

      - name: build
        run: npm run build

      - name: Deploy to Cloudflare Pages
        run: npx wrangler@latest pages deploy ./dist --project-name=my-page # replace `./dist` with your build output directory, and `my-page` with your name chosen earlier
        env:
          CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}

This action makes the following assumptions:

  1. You will be deploying from your main branch - you can adjust the branch on line 4 if needed.
  2. We’ll also add the workflow_dispatch trigger. This will enable a button in the Forgejo UI to allow you to trigger a manual deploy should you wish to do so.
  3. You are using npm install and npm run build as your build process. If you don’t need those, you can remove those steps. if you need different steps you can replace or add them.
  4. Your build output directory is ./dist and your page name my-page - replace on line 23 if needed.

If you don’t use any build process you can skip the install and build steps. E.g. I have one repo that is just static HTML, CSS and JS. In this case I just need to delete the .git and .forgejo directories before deployment:

on:
  workflow_dispatch:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 22

      - name: Delete unwanted files
        run: |
          rm -rf .forgejo
          rm -rf .git

      - name: Deploy to Cloudflare Pages
        run: npx wrangler@latest pages deploy ./ --project-name=my-page
        env:
          CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}

And that’s it - your site will be deployed to CloudFlare Pages automatically every time you push to your Forgejo instance.