Need Assistance in Installing wkhtmltopdf in the Open edX Docker Image for Certificate PDF Generation

Dear Open edX community,

We have successfully launched our LMS using the Open edX Nutmeg release. Through theme customizations, we have tailored the LMS interface and the certificate templates to our requirements. However, we now face a challenge related to the delivery of these certificates. We wish to provide the option for users to download their certificates in PDF format directly from the LMS.

Currently, the method of downloading the certificate involves viewing it in a browser and using the Print (or CTRL + P) option to save it as a PDF. Unfortunately, this doesn’t result in a perfect fit on one page, and it requires students to modify some configurations on their end. To circumvent this inconvenience, we are exploring the possibility of generating PDF versions of the certificates and providing a direct download link to the students.

We have chosen pdfkit for the HTML-to-PDF conversion task and created a tutor plugin to listen for the “COURSE_CERT_AWARDED” signal and generate the corresponding PDF. Here’s a snippet of the code we are using:

import pdfkit
pdfkit_options = {
    "dpi": 100,
    "orientation": "Portrait",
    "encoding": "UTF-8",
    "margin-top": "0mm",
    "margin-bottom": "0mm",
    "margin-left": "0mm",
    "margin-right": "0mm",
    "page-width": "130mm",
    "page-height": "140mm",
    "zoom": 1,
    "load-media-error-handling": "skip",
}
pdfkit.from_url(cert_url, file_path, options=pdfkit_options)

The main challenge we are facing is the installation of the necessary package, wkhtmltopdf, which pdfkit depends on. While pdfkit itself is easily installable via pip, wkhtmltopdf needs to be installed system-wide. In the Nutmeg version of tutor, each service runs in a separate Docker container, and we need to install wkhtmltopdf in the openedx Docker image.

We would appreciate any assistance or advice on how to install wkhtmltopdf in the openedx Docker image.

Thank you in advance for your help.

Just add your package to this file like you’ll do in a regular requirements.txt file:
$(TUTOR_ROOT)/env/build/openedx/requirements/private.txt

Then run
tutor [local|dev] start

That should do. If not, tutor [local|dev] launch will definitely do it.

Hi @sagar

Using $(TUTOR_ROOT)/env/build/openedx/requirements/private.txt, I installed pdfkit. However, wkhtmltopdf cannot be deployed in the same manner. According to what I know, these are the procedures for installing wkhtmltopdf:

apt-get update && apt-get install -y xfonts-75dpi wget fontconfig libjpeg-turbo8 libxrender1 xfonts-base xvfb
wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb
apt install -f ./wkhtmltox_0.12.6-1.focal_amd64.deb

I updated the Dockerfile at “$(tutor config printroot)/env/build/openedx/” with the following steps.

# Add the wkhtmltopdf dependencies and wkhtmltopdf itself
RUN apt-get update && \
    apt-get install -y xfonts-75dpi wget fontconfig libjpeg-turbo8 libxrender1 xfonts-base xvfb \
    && wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb \
    && apt install -f ./wkhtmltox_0.12.6-1.focal_amd64.deb
RUN which wkhtmltopdf
RUN wkhtmltopdf --version

I then ran tutor images build openedx, and it was successful and error-free. However, the openedx docker image still does not have wkhtmltopdf installed.

Did you run tutor [dev|local] start after tutor images build openedx?

Yes @sagar

After tutor images build openedx completion I run tutor local start -d to restart docker images.

And did you by any chance, run tutor config save before building the image?

Yes, these steps are already there in tutor docs. And as I mentioned, pdfkit (pip package) was installed successfully but is an issue in wkhtmltopdf.

tutor config save removed your changes from the Dockerfile.
You should not edit the Dockerfile directly or your changes will be lost when you run tutor config save or tutor [local|dev] launch.

Recommended way to do this is to make a plugin and add things via patches.

Let me know if you need some help with plugins and patches.

Here’s all you will need to get everything working:

https://docs.tutor.overhang.io/tutorials/plugin.html

https://docs.tutor.overhang.io/reference/patches.html