The easiest and most flexible way of rendering fancy PDFs is using HTML+CSS as your source. wicked_pdf and pdfkit, the most popular Rails gems, employ
wkhtmltopdf under the hood to generate them. It seems that there are multiple options of running
wkhtmltopdf on Heroku. This post will explore them, analyze their drawbacks and identify the most reliable one.
Method 1: Apt package
First thing that comes to mind is installing
wkhtmltopdf package from Ubuntu Apt repositories. The easiest way of doing this is using
apt buildpack (provided by Heroku):
1heroku buildpacks:add --index 1 heroku-community/apt
Aptfile file in your project's root directory with the following content:
Finally, push the code to Heroku.
The build phase will list all dependencies required to install
wkhtmltopdf. The package depends on audio libraries, low-level USB libraries (!), X11 and GTK libs, etc. Once the deployment completes, we can test our setup:
1heroku run bash -a YOURAPPNAME
Once the one-off dyno boots up, run:
1$ wkhtmltopdf https://www.ruby-lang.org/en/ ruby.pdf2This application failed to start because it could not find or load the Qt platform plugin "xcb"3in "".45Reinstalling the application may fix this problem.6Aborted
Even though the Apt package downloaded so many dependencies, it was still not enough to successfully run
Even if this solution worked, it would be extremely inefficient: the application's slug size increased by 146 MB. It's crucial to keep slug size small as it affects not only deployment time but also time required to boot up any dyno (resources defined in
Procfile, one-off dynos with
rails console etc.).
TL;DR: apt package prohibitively increases bundle size and still doesn't work. Avoid.
Method 2: buildpack
This option provides
wkhtmltopdf binary as a buildpack. There are a few different buildpacks around, the most
popular (and up-to-date) being dscout/wkhtmltopdf-buildpack. It's important to note that the latest version of
0.12.6, while this buildpack offers at most
1heroku buildpacks:add https://github.com/dscout/wkhtmltopdf-buildpack.git2heroku config:set WKHTMLTOPDF_VERSION="0.12.4"
This option increases slug size by 55.6 MB.
heroku-20 stack users: if your HTML source references external resources fetched over https, they will not appear on the PDF due to SSL error caused by a missing library. To resolve this issue, add
apt buildpack and add the following package to your
In total, using
wkhtmltopdf buildpack with
libssl increases the bundle size by 56.9 MB. This increase is passable, but not perfect. The buildpack also includes
wkhtmltoimage binary. If you don't need it, you're still going to have it in your app slug, unnecessarily increasing its size.
TL;DR: fast and reliable method, with moderate slug size increase; lacks the latest version.
Method 3: Ruby gem bundling the wkhtmltopdf binary
There are three popular options:
- wkhtmltopdf-binary — provides version 0.12.6 for macOS, Linux 32bit and Linux 64bit. Not recommended for Heroku: the gem bundles three binaries and we need only one. Each binary is about 40 MB so the slug size would increase significantly. Fine for development.
- wkhtmltopdf-binary-edge — offers the latest version (0.12.6) but like the previous option, contains three binaries. Even the author recommends something else for Heroku. Good for development.
- wkhtmltopdf-heroku — offers a single Linux binary suitable for running on Heroku.
Gemfile could look like this:
1group :production do2 gem 'wkhtmltopdf-heroku'3end45group :development do6 gem 'wkhtmltopdf-binary-edge'7end
If your application is deployed on
heroku-18 stack, you'll also need to add
libssl1.0.0 to your
Aptfile to be able to fetch external resources over https.
This method appears to be extremely size-efficient: slug size increased only by 14 MB (15.9 MB with
TL;DR: Reliable and size-efficient way offering the latest version. Recommended.
Note about binary files security
Pay particular attention when dealing with any externally-downloaded binaries. We can assume that packages downloaded from Apt repository are adequately verified. What about the buildpack? We can check in its
compile phase that it downloads the files from official releases section on GitHub. That is a trusted way to download the official binary.
Finally, the gems. They merely bundle the binaries but provide no proof that they were not maliciously modified. While you should always be grateful to open source developers for their contributions, it's always a good idea to verify that the binary files are the originals provided by wkhtmltopdf maintainers. Hint: download proper .deb file (xenial for heroku-16, bionic for heroku-18), extract the package and make sure (using
diff or at least
openssl dgst -sha256) that the binaries are identical.
We evaluated different options of installing
wkhtmltopdf on Heroku for your Ruby apps. Using
wkhtmltopdf-heroku gem is the most efficient option. Before you deploy any bundled binary to production, make sure to verify that it's the original binary provided by the