How to use Codeberg Pages for MkDocs
Codeberg1 is a Website providing Git Hosting and services for free and open source software, content and projects.
It's managed by a non-profit (Codeberg e.V.) and offers a lot of things, including their own static page hosting Codeberg Pages.
Since I moved my blog to Codeberg Pages a while ago and since I find its set of features quite good did I now decide to make this little tutorial on how you can automate the publishing and updating of your MkDocs Site for Codeberg Pages.
Comparison to GitHub Pages¶
Codeberg Pages has some similarities to GitHub Pages, while also offering additional features and having some smaller issues too.
This section will only cover a comparison to GitHub Pages. Other Page services (i.e. GitLab Pages) may offer similar features as Codeberg Pages.
Similarities to GitHub Pages¶
There are a few similarities to GitHub Pages.
- Dedicated branch and repository
On GitHub Pages can you publish a site on a dedicatedgh-pages
branch, making it available under<user>.github.io
, or by publishing your page on the default branch on a repository named<user>.github.io
.
Codeberg Pages offers a similar solution, with the difference being, that the name of the branch and repository are bothpages
. But similar to GitHub Pages would thepages
branch be used for sub-pages under<user>.codeberg.page
while thepages
repository would be used for the<user>.codeberg.page
domain itself. - Custom (sub)domains
Both GitHub Pages and Codeberg Pages offer you the option to set a custom (sub)domain to use for your site.
On GitHub would such a domain be set inside aCNAME
file, while on Codeberg, the file would be named.domains
. This file has some benefits, but also drawbacks, which are all explained in the later sections.
Beneficial features¶
Codeberg Pages has some features not available in GitHub Pages, which can be very useful to have.
- Multiple custom (sub)domains
Unlike GitHub Pages does Codeberg Pages allow you to define multiple (sub)domains for one site to use. In such a case would the domain at the very top be the default one used, with every additional entry below it being redirected to it by Codeberg Pages. - Redirects
Using a_redirects
file, you can create static or even dynamic redirects.
As an example, adding the line/blog/* /blog/post/:splat
would create a redirect for any/blog/
sub-page redirecting to/blog/post/
while preserving any additional subpages (i.e./blog/01-01-hello
redirects to/blog/post/01-01-hello
). -
Special sub-domains and sub-pages
Codeberg Pages offers specific subdomains and sub-page patterns that can be used for various things. Namely...raw.codeberg.page/<user>/<repository>/
can be used to access files in their raw format. Proper MIME types (Except for HTML) will be applied and are CORS accessible.- Any domain - either custom or
codeberg.page
subdomain - suffixed with a@<branch>
will show the content of the defined<branch>
. This is extremely useful for features like a deploy-preview. Keep in mind that/
in branch names need to be replaced with~
to work
-
Let (sub)domains point to specific branches of a repository
Using DNS TXT entries, one can set custom (sub)domains that would display content of a specific repository and/or branch.
As an example setting a TXT entry with keyexample
and valueexample.repo.example.codeberg.page
would result in a domain likeexample.example.com
displaying the content ofcodeberg.org/example/repo/src/branch/example/
drawbacks¶
There are some drawbacks/issues with Codeberg Pages not present in GitHub Pages itself.
- Custom domains break
<user>.codeberg.page/<repo>
pages
Once you've set up a custom domain for your<user>.codeberg.page
domain (A user/org-level domain) will any<user>.codeberg.page/<repo>
domain stop working.
This means that while<user>.codeberg.page/repo
works,example.com/repo
will not.
This is a bug and has been reported already. - .domains file issue with site-builders
MkDocs by default ignores files that start with a dot, making it ignore and effectively not include the.domains
file itself.
A workaround for this issue is shown later in this post. - No specific folder for a site
On GitHub can you define adocs
folder to be used as the source of your page content.
Codeberg Pages unfortunetly does not offer such a solution. The static site content has to either be on thepages
branch of a repository, or the default branch of thepages
repository to be displayed.
A small workaround exists, where you either use the@<branch>
sub-page pattern or make your (sub)domain point to a specific branch through DNS. This still doesn't solve the issue of the content not being stored in a docs folder or alike. You have to put it in the root.
Preparations¶
Before your site can actually be published will you need to make sure, that you've prepared some stuff first, to ensure it will work.
First of all, you need to make sure you have a CI/CD system ready to use on your repository. I use Woodpecker-CI2, an open source CI software, in this guide, but any CI that can work with Forgejo3, a fork of Gitea4 used to manage the Git Hosting of Codeberg, should be fine to use here.
It's worth noting that Codeberg offers their own Woodpecker-CI Instance5 to use for free. Only requirement is that you have to apply for access.6
Next should you create an API token for Codeberg. This is required as otherwise, your CI won't be able to commit and push the docs to the repository.
Finally should you have prepared your repository. This means that you either set up a pages
branch (Preferably orphaned) to push towards, or have created a repository named pages
.
I will use the second option in this guide, but this also means that I'll need a second repository hosting the source (config files, markdown files, etc), as everything on the default branch of the pages
repository would be served on your user.codeberg.page
domain.
The user Tobias Bölz created a blog post covering how you can publish your site using Forgejo Actions while also using the pages
branch aproach. It can be found here.
I suggest to have the following file structure prepared for your source repository:
.woodpecker/
└── publish_docs.yml
docs/
└── index.md
domains # Used for custom domains
mkdocs.yml
requirements.txt
The usage of a .woodpecker
folder instead of a .woodpecker.yml
file is recommended, as it would allow you to later add additional CI workflows for different things.
Preparing the woodpecker file¶
Info
The below example file will show some placeholder/example values which you should change to your own stuff. Namely...
knut
will be used as user, which is Codeberg's example account and should be replaced with your username on Codeberg.docs-source
will be used as the source repository containing the raw MkDocs content and should be replaced with your source repo name.
The first thing you should do is add the source repository as a new repo in the Woodpecker-CI Dashboard. Next should you add the necessary secrets to it, to ensure that they will be present when using the file.
In my example below do I include two secrets:
cbemail
which contains the e-mail to use for the Git user. This can be replaced with your e-mail in the file if you're not afraid of others knowing it.cbtoken
which contains a valid PAT (Personal Access Token) for your Codeberg account. This ensures that we can push the final docs to the target repository without requiring login data to be included in whatever way.
DO NOT DIRECTLY INCLUDE YOUR PAT IN THE WOODPECKER FILE! This can result in your account being hijacked and abused. Always treat a PAT like a super important password nobody should know about.
In my example do I have .woodpecker/publish_docs.yml
which does the publishing for us.
Below is the entire file. You can click the for further details on the different parts:
when:
- event: push # (1)
branch: ${CI_REPO_DEFAULT_BRANCH}
path:
include: ["docs/**", "mkdocs.yml", "requirements.txt"]
variables:
setup_git: &setup_git # (2)
- apk add git
- git config --global user.email "$CBEMAIL"
- git config --global user.name "CI Docs Builder"
steps:
cloneTargetRepo:
image: alpine:3.18.4 # (3)
secrets: [cbemail]
commands:
- chmod -R a+w .
- <<: *setup_git # (4)
- git config --global --add safe.directory /woodpecker/src/codeberg.org/knut/docs-source
- git config --global init.defaultBranch pages
- git clone -b pages https://codeberg.org/knut/pages.git # (5)
- chmod -R a+w pages
buildDocs:
image: woodpeckerci/plugin-mkdocs:1.2.0 # (6)
settings:
site_dir: pages
commitAndPush:
image: alpine:3.18.4
secrets: [cbtoken, cbemail]
commands:
- <<: *setup_git
- cd pages
- git remote set-url origin https://$CBTOKEN@codeberg.org/knut/pages.git # (7)
- git add --all
- git commit -m "Update Docs ($( env TZ=Europe/Berlin date +"%d.%m.%Y %Z" )) [SKIP CI]"
- git push
- This configures our pipeline to only run when a push is made towards the repository's default branch (
${CI_REPO_DEFAULT_BRANCH}
) and if any file in the docs directory, the mkdocs.yml file, or the requirements.txt file are affected. - This is a reusable (Also known as YAML anchor) that we insert into the different steps later on using
- <<: *setup_git
. The$CBEMAIL
is a secret that we will provide in the later steps. - I use alpine here as it is a fairly lightweight system to use that offers necessary commands (
cd
,mv
, etc.). You can use any image available on Docker as long as they offer necessary features used here. - This injects the
setup_git
anchor we defined earlier in the file, adding git to the system and configuring all necessary things such as username and e-mail. - We clone our target repository to then build or site into. This particular command would result in the repository being cloned into a
pages
folder. - We use the official MkDocs Woodpecker-CI plugin7 to build our docs with. This plugin uses Material for MkDocs as its base, so certain dependencies are already included.
We also set thesite_dir
option to point topages
, so that our final site is being created in there.
Also, make sure to check if you're using the latest version available. You can uselatest
as version to always use the latest dev build from Docker. - We set the URL of the origin repository to point to our pages repository, while using our Codeberg PAT for authorization. This is important as it otherwise would not allow us to push the changes to the repository.
Adding custom domains¶
Similar to GitHub Pages does Codeberg pages allow you to define custom domains to use. The difference here is, that not only can you define multiple custom domains for one repository, but they also use a different file.
The file in question is called .domains
which is already a smaller issue. With GitHub Pages you can have a CNAME
file in the docs folder and MkDocs would carry it over into the build site. With the file from Codeberg Pages however can this not be done.
The main reason is MkDocs ignoring files starting with a dot by default.
You could now alter the configuration of MkDocs to change what files to ignore, or you can do the solution I'll show you below.
To make things work, all you have to do is make a domains
file, fill it with the custom domain(s) you want to use and then add the following line to your workflow file:
when:
- event: push
branch: master
path:
include: ["docs/**", "mkdocs.yml", "requirements.txt"]
variables:
setup_git: &setup_git
- apk add git
- git config --global user.email "$CBEMAIL"
- git config --global user.name "CI Docs Builder"
steps:
cloneTargetRepo:
image: alpine:3.18.4
secrets: [cbemail]
commands:
- chmod -R a+w .
- <<: *setup_git
- git config --global --add safe.directory /woodpecker/src/codeberg.org/knut/docs-source
- git config --global init.defaultBranch pages
- git clone -b pages https://codeberg.org/knut/pages.git
- chmod -R a+w pages
buildDocs:
image: woodpeckerci/plugin-mkdocs:1.2.0
settings:
site_dir: pages
commitAndPush:
image: alpine:3.18.4
secrets: [cbtoken, cbemail]
commands:
- <<: *setup_git
- mv domains pages/.domains
- cd pages
- git remote set-url origin https://$CBTOKEN@codeberg.org/knut/pages.git
- git add --all
- git commit -m "Update Docs ($( env TZ=Europe/Berlin date +"%d.%m.%Y %Z" )) [SKIP CI]"
- git push
domains
file into the pages
folder and also rename it to .domains
in order for Codeberg Pages to recognize it.
And that's already it. Your domain should now be available under your custom domain.
DNS settings
Remember to also configure your domain's DNS properly to have the domains work.
You can visit the Codeberg Pages documentation for how to setup and configure custom domains.
Footnotes
Comments
Comment system powered by Mastodon.
Leave a comment using Mastodon or another Fediverse-compatible account.