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.
Important notes¶
There are a few important notes I have to make here, before we can get started. Namely, there are a few minor issues you have to keep in mind when wanting to use Codeberg and Codeberg pages.
As of writing this (5th of november, 2023) there are the following issues/limitations with Codeberg Pages:
- You cannot define a specific folder (i.e.
docs/
) and/or a specific branch for your repository to use with Codeberg Pages. Only the root folder of thepages
branch (or default branch if repo is namedpages
) will work. - Project pages (sub-pages) are supported, but only on the
user.codeberg.page
domain. Using a custom Apex or sub-domain for a user/org-level domain (Meaning it is used for apages
repository) will cause this functionality to no longer work. This means that a repository namedproject
will not appear onhttps://example.com/project
ifexample.com
is set as a user/org-level domain. Additionally willuser.codeberg.page/project
be redirected to your custom domain. - Custom 404 pages from MkDocs are not supported nor used. Codeberg Pages will always display their own error page instead.
- Custom domains are defined in a
.domains
file in the root of the repo'spages
branch (Or default branch if the repo is namedpages
). This can have minor conflicts with MkDocs' default ignore behaviour for files. A workaround is explained in this post.
If you're okay with these limitations and issues, read on.
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, Soft-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.
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 instance. 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.
In my example do I have .woodpecker/publish_docs.yml
which does the publishing for us. Let's see how the file looks like and then go over all the necessary stuff:
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
- 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
Lets get over the different parts to look at...
when:
- event: push
branch: master
path:
include: ["docs/**", "mkdocs.yml", "requirements.txt"]
master
branch and only files defined in include
are modified.Make sure to update
master
to whatever branch you use for your doc source and also update include
to have the file paths necessary. The option supports glob patterns.
variables:
setup_git: &setup_git
- apk add git
- git config --global user.email "$CBEMAIL"
- git config --global user.name "CI Docs Builder"
$CBEMAIL
would be an enviroment variable that would be defined in a step using the secrets
option.
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
- It applies proper permissions using
chmod
to avoid access issues - It adds and setups git using the previously mentioned YAML anchor that has been created. The
<<:
tells woodpecker to inject the anchor at this position. - It configures a safe directory in git to avoid security issues
- It sets a default branch
- It clones the target repository to where the built docs would be pushed. Make sure to update the URL here to whatever target repo yours would be.
- It applies proper permission to the cloned repo folder.
Also, note that I use alpine here as image. It's a lightweight, bare-bone solution that offers necessary commands (chmod
, mv
, etc) without being too big in size.
Feel free to use any other image here, as long as they are available for Docker and offer necessary commands.
steps:
# ...
buildDocs:
image: woodpeckerci/plugin-mkdocs:1.2.0
settings:
site_dir: pages
We use the
site_dir:
setting to change the target directory for the built docs to our target repository (pages
).
steps:
# ...
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
- git add --all
- git commit -m "Update Docs ($( env TZ=Europe/Berlin date +"%d.%m.%Y %Z" )) [SKIP CI]"
- git push
pages
folder and sets the target URL to the target repository, while including the $CBTOKEN
. This should be a valid Codeberg PAT to allow pushing the changes.It then adds all the changed files, commits them (Note the
[SKIP CI]
which tells Woodpecker-CI to ignore this commit) and finally pushes it to the target repository to publish.
And that's all. Your site should now be available under your codeberg.page
subdomain.
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
You can use a Fediverse-compatible client such as Mastodon
or Pleroma to
leave a comment on this blog post!
Comment through the Fediverse! (Click to open)