Build Typst doc in GitLab CI with Guix

2026-10-08 published | 2026-10-08 edited

I am not saying this is right; it just works for me.

This is Dockerfile based on jas4711/guix:

FROM jas4711/guix
# see https://hub.docker.com/r/jas4711/guix

# From "How to use in a GitLab pipeline":
RUN groupadd --gid 0 root
RUN useradd --uid 0 --gid root --shell /bin/sh --home-dir / --system root
RUN cp -rL /gnu/store/*profile/etc/* /etc/
RUN groupadd --system guixbuild
RUN for i in $(seq -w 1 10); do useradd -g guixbuild -G guixbuild -d /var/empty -s $(command -v nologin) -c "Guix build user $i" --system guixbuilder$i; done

ENV HOME=/
ENV LANG=C.UTF-8
RUN guix archive --authorize < /share/guix/ci.guix.gnu.org.pub
RUN guix archive --authorize < /share/guix/bordeaux.guix.gnu.org.pub
RUN guix describe

# This worked for me, not saying I am right:
RUN --security=insecure nohup bash -c 'guix-daemon --build-users-group=guixbuild &' && sleep 2 && guix install typst typstyle
# - The --security=insecure relates to docker buildx and some kind of permissions.
# - nohup "runs a command immune to hangups" (from man page).
# - So we have guix-daemon running in background and wait 2 sec before guix install.

# Get ready to use Guix:
ENV GUIX_PROFILE="/.guix-profile"
RUN . "$GUIX_PROFILE/etc/profile"

# Get Typst packages we use:
WORKDIR /.local/share/
RUN git clone --sparse --no-checkout --filter=tree:0 --single-branch --branch main https://github.com/typst/packages.git typst
# - Git sparse no checkout and others are here to speed-up git clone.

WORKDIR /.local/share/typst/

# Specify what to checkout:
RUN git sparse-checkout set \
    packages/preview/diagraph/0.3.7 \
    packages/preview/cheq/0.3.1 \

# And checkout it:
RUN git checkout

# Entry point that gets Guix ready (source Guix profile):
COPY ep.sh /
ENTRYPOINT ["/ep.sh"]
CMD ["/ep.sh"]

Entry point – ep.sh – contains just:

#!/bin/sh
. "$GUIX_PROFILE/etc/profile"
exec "$@"

We need docker-buildx and create insecure-builder:

docker buildx create --name insecure-builder --buildkitd-flags '--allow-insecure-entitlement security.insecure'

Then we build the Dockerfile with it:

docker buildx build --builder=insecure-builder --allow security.insecure --load -t registry.gitlab.com/qeef/foo .

Nope, there is no repo qeef/foo on GitLab, but the idea is clear, isn’t it?

Push the image to GitLab registry when you are ready (authenticated):

docker push registry.gitlab.com/qeef/foo

Now, we can use the image from .gitlab-ci.yaml:

image: registry.gitlab.com/qeef/foo

stages:
- build
- check

typst:
  stage: build
  script:
    - typst compile what.typ what.pdf
  artifacts:
    paths:
      - "*.pdf"

typstyle:
  stage: check
  allow_failure: true
  script:
    - typstyle --check *.typ
go back | CC0 1.0