From 52b59bbe0053808f30ddec0118e0c9f9e306f031 Mon Sep 17 00:00:00 2001 From: mfowler Date: Sat, 1 Aug 2026 21:58:47 +0000 Subject: [PATCH] docs(skills): add codeberg-pages site-publishing skill Skill covering publishing a static site to Codeberg Pages, including custom domains on the new git-pages server: pages branch, A/AAAA + CNAME DNS, the _git-pages-repository TXT authorization record, per-domain deploy webhooks (http:// for first deploy), Let's Encrypt issuance, and the obsolete .domains file. Verified against docs.codeberg.org. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_017k4W786WWd8yN1m4Ypuxzx --- skills/codeberg-pages/SKILL.md | 138 +++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 skills/codeberg-pages/SKILL.md diff --git a/skills/codeberg-pages/SKILL.md b/skills/codeberg-pages/SKILL.md new file mode 100644 index 0000000..0909231 --- /dev/null +++ b/skills/codeberg-pages/SKILL.md @@ -0,0 +1,138 @@ +--- +name: codeberg-pages +description: >- + Publish a static site to Codeberg Pages, including custom domains on the new + "git-pages" server. Use when deploying a site to Codeberg Pages, setting up or + debugging a codeberg.page / custom-domain deployment, wiring the DNS records + (A/AAAA, CNAME), the _git-pages-repository TXT authorization record, or the + deploy webhook — or when a custom domain serves a TLS error / never gets a + certificate. Covers the 2025→2026 migration off the old Pages Server v2 + (.domains file) to git-pages (webhook + TXT authorization). +--- + +# Publishing a site to Codeberg Pages + +Codeberg Pages migrated from the old **Pages Server v2** (automatic deploy, +`.domains` file) to the new **git-pages** server. On git-pages a deployment is +**webhook-triggered** and a custom domain is authorized by a **TXT record**, not +by a file in the repo. If you're following older docs or a `.domains`-based +`deploy.sh`, that's why things silently don't work. + +> All values below were verified against the official docs +> ( and `.../using-custom-domain/`). +> Codeberg changes these; re-check the docs if something behaves unexpectedly. + +## The mental model + +1. Static site content lives on a branch named **`pages`** (per-repo site) — push + your built site there. +2. On git-pages, pushing alone does **not** deploy. A **webhook** on the repo, + pointed at the domain you want, is what triggers a deployment. +3. A custom domain is bound to the repo by a **TXT authorization record** + (`_git-pages-repository.`) plus the normal A/AAAA/CNAME records. +4. TLS (Let's Encrypt) is issued **only after the first successful deployment**. + Before that, browsers show a TLS error — that is expected, not a bug. + +## Basic deploy (no custom domain, `*.codeberg.page`) + +- Put the site on a `pages` branch and push it. +- Add a webhook: repo **Settings → Webhooks → Forgejo**, Target URL + `https://.codeberg.page//`, **Branch filter: `pages`**. +- (User/org site: name the repo `pages` and use Target URL + `https://.codeberg.page/`.) + +## Custom domain setup (git-pages) + +Do all four. Missing #2 or #3 is the usual cause of "DNS looks right but the site +won't serve / no certificate." + +### 1. DNS: point the domain at Codeberg + +Exact values (verify against the docs — Codeberg has changed IPs before): + +- **Apex domain** (`example.org`): + - `A` → `217.197.84.141` + - `AAAA` → `2a0a:4580:103f:c0de::2` +- **Subdomain** (`www.example.org`, `foo.example.org`): + - `CNAME` → `codeberg.page.` ← **note the trailing dot.** + +**Trailing-dot trap:** in a zone file / most DNS UIs, a CNAME target *without* a +trailing dot is treated as relative and the zone is appended — e.g. entering +`codeberg.page` (or an old `.codeberg.page`) can resolve to +`codeberg.page.example.org.`, which is broken. Always use the fully-qualified +`codeberg.page.` with the dot. (ALIAS/ANAME works where CNAME isn't allowed, but +conflicts with DNSSEC-signed zones.) + +### 2. TXT authorization record (this is how git-pages maps domain → repo) + +Create one **per domain** you serve: + +``` +_git-pages-repository.example.org. TXT "https://codeberg.org//.git" +``` + +- Name: the `_git-pages-repository.` prefix on the exact domain (including each + subdomain you serve — apex and `www` each need their own if both are used). +- Value: the **HTTPS clone URL** of the repo, ending in `.git`. +- (If you deploy via **Forgejo Actions** instead of a webhook, the record is + `_git-pages-forge-allowlist.` with the same clone-URL value.) + +### 3. Deploy webhook (per domain) + +Repo **Settings → Webhooks → Forgejo**: + +- **Target URL:** the domain itself, and **`http://` (not `https://`) for the + first deployment** — this is documented, not a mistake (the cert doesn't exist + yet). One webhook per domain, e.g. `http://example.org`, `http://foo.example.org`. +- **Branch filter:** `pages`. +- After the first successful deploy and cert issuance, you may switch the Target + URLs to `https://`. + +### 4. Trigger the first deploy + +**Push to the `pages` branch** (re-run your deploy script / `git push origin pages`). +The push fires the webhook, git-pages pulls and deploys, then requests a +Let's Encrypt certificate. + +- **Do NOT rely on the webhook "Test delivery" button** — the official docs say it + fails by design and is not a valid way to verify or trigger a deploy. Verify by + pushing and then checking the webhook's recent-deliveries log, or just load the + site. (This corrects a common misconception that "Test delivery" triggers a deploy.) + +## The `.domains` file is obsolete + +Under the old Pages Server v2, a `.domains` file in the branch listed the domains +and did apex-vs-alias redirects. On git-pages it is **no longer used** — authorization +comes from the TXT record. It's harmless to leave, but you can delete it (and drop any +`.domains` handling from `deploy.sh`). Bonus: on git-pages each domain gets its **own** +deployment, so a second domain serves the site directly instead of 301-redirecting to +the primary as the old `.domains` system did. + +## TLS / certificate notes + +- A cert is issued **only after the first successful webhook deployment**. A TLS + error before that is expected. +- If the domain has **CAA records**, they must allow Let's Encrypt (including the + staging issuer) or the cert request is refused. +- Cert still never issues after a successful deploy → confirm the `_git-pages-repository` + TXT value exactly matches the repo's HTTPS `.git` URL, and that the webhook Target + URL matches the domain. + +## Quick troubleshooting checklist + +- Browser TLS error, no cert → no successful deploy yet. Check webhook deliveries; + push to `pages`; confirm webhook Target URL used `http://` for the first deploy. +- "DNS is correct but site won't serve" → missing `_git-pages-repository` TXT, or + missing/mis-branch-filtered webhook. +- CNAME resolves to `codeberg.page.` → missing trailing dot; set target to + `codeberg.page.`. +- CAA present → ensure Let's Encrypt is allowed. +- Old `.domains` behavior expected (redirects) → gone on git-pages; each domain now + deploys independently. + +## Sources + +- Codeberg Pages: +- Using custom domains: +- pages-server (now in maintenance, superseded by git-pages): +