A public instance of git-pages run by Catherine 'whitequark' that serves static pages from Codeberg or other Git forges. It is deployed on Fly.io.
Unlike the pull-based codeberg.page, this service is push-based: the forge must notify the pages service whenever there is a content update. This makes it extremely efficient, but also means that configuration is needed before use.
Unlike GitHub Pages and Codeberg Pages, this service sets Access-Control-Allow-Origin: *
, Cross-Origin-Embedder-Policy: credentialless
, Cross-Origin-Opener-Policy: same-origin
headers, making service worker based hacks obsolete.
See the git-pages README for details.
This service is provided as a public utility, especially for those migrating from GitHub to community-operated forges, and I plan to operate it indefinitely. It is monitored and has a status page.
Select repository > Settings > Webhooks > Add webhook > Forgejo, then configure only the following:
pages
, {username}.grebedoc.dev
, or {username}.codeberg.page
): http://{username}.grebedoc.dev/
{repository}
): http://{username}.grebedoc.dev/{repository}/
pages
Leave everything else at the default values and select Add webhook. Next update to the pages
branch will cause its contents to become available at the target URL.
Important! It is necessary to either use the http://
scheme for the webhook for the initial push (after which it may be upgraded to https://
), or perform the initial publishing using a method described below.
Method A: To prove that you control the domain, update the configuration of your domain to add a TXT
record at the _git-pages-repository
subdomain with the full git clone URL (something like https://forge.tld/user/repo.git
) as its value.
Method B: To prove that you control the domain, generate a strong password (32 or more random alphanumeric characters) and compute a challenge as: SHA256("{domain} {password}")
. This can be done by running echo -n "{domain} {password}" | sha256sum
in the terminal, or with the following JavaScript-based form:
Update the configuration of your domain to add a TXT
record at the _git-pages-challenge
subdomain with the challenge as its value.
Important! Keep the password secret. Anyone who knows it can replace the contents of your static site with anything they want.
After using Method A or Method B, configure your domain to have A
/AAAA
records pointing to the same server as grebedoc.dev
. In most cases this can be done using an ALIAS
record, but if this functionality isn't available it will need to be done by hand.
Select repository > Settings > Webhooks > Add webhook > Forgejo, then configure only the following:
http://{domain}/
or http://{domain}/{subdir}/
(only one level of directories can be used)pages
Pages {password}
Leave everything else at the default values and select Add webhook. The next time the pages
branch is pushed, its contents will be published at the target URL.
Important! It is necessary to either use the http://
scheme for the webhook for the initial push (after which it may be upgraded to https://
), or perform the initial publishing using a method described below.
This configuration method is not limited to Codeberg; it works with any Forgejo, Gitea, Gogs, or GitHub based forge. If the forge does not make it possible to supply an Authorization:
header, use http://Pages:{password}@{domain}/
as the target URL instead.
Follow the DNS configuration steps for Method A or Method B as described above. Next, configure your forge or Git repository to issue a PUT
HTTP request after a branch has been updated with this Curl command (or its equivalent):
For Method A: curl http://{domain}/ -X PUT --data "https://{forge}/{repo}.git"
For Method B: curl http://{domain}/ -X PUT -H "Authorization: Pages {password}" --data "https://{forge}/{repo}.git"
The optional -H "X-Pages-Branch: {branch}"
argument may be used to publish from a branch other than pages
. This functionality requires the PUT
method to be used, and is not available with webhooks.
Follow the DNS configuration steps for Method B (only) as described above. Next, make a ZIP or tar archive of your site and upload it with this Curl command (or its equivalent):
For a ZIP archive: curl http://{domain}/ -X PUT -H "Authorization: Pages {password}" -H "Content-Type: application/zip" --data-binary @{archive}
For a tar archive: curl http://{domain}/ -X PUT -H "Authorization: Pages {password}" -H "Content-Type: application/x-tar" --data-binary @{archive}
Follow the DNS configuration steps for Method A or Method B as described above. Before altering the ALIAS
or A
/AAAA
records, use the following Curl command (or its equivalent) to publish your site at the new server:
For Method A: curl https://grebedoc.dev/ -X PUT -H "Host: {domain}" --data "https://{forge}/{repo}.git"
For Method B: curl https://grebedoc.dev/ -X PUT -H "Host: {domain}" -H "Authorization: Pages {password}" --data "https://{forge}/{repo}.git"
Verify the deployment by requesting the index page: curl https://grebedoc.dev/ -H "Host: {domain}"
Now, alter the ALIAS
or A
/AAAA
records for your domain.
To comply with terms of service of the certificate authorities, this service only acquires certificates for domains it has a published site for, regardless of the DNS settings or HTTP headers. This means that the site cannot be published for the first time using its own https://
URL. However, the steps described above also work around this issue.
It is a great crested grebe! Original photo © Bengt Nyman, CC BY-SA 4.0.
The architecture of grebedoc.dev is the inverse of the architecture of codeberg.page; "Grebedoc" is "Codeberg" backwards.