soli-pdf

Installation

soli-pdf needs Ruby 3.2 or later. It has no runtime gem dependencies: it only uses the standard library (json, open3, tempfile, net/http, digest).

#Add the gem

The gem is published from the Soli repository, not from RubyGems. Add it to your Gemfile with a git: source and a glob: that points at its gemspec:

gem 'soli-pdf', git: 'https://github.com/solisoft/soli_lang', glob: 'gem/soli-pdf/*.gemspec'

Then install it:

bundle install

To pin a known revision, add ref: (a commit SHA) or tag::

gem 'soli-pdf', git: 'https://github.com/solisoft/soli_lang',
                glob: 'gem/soli-pdf/*.gemspec',
                tag: 'v2.9.0'

#Require it

Bundler requires soli-pdf automatically in a Rails app. Anywhere else, require it yourself. Both paths load the same code:

require 'soli/pdf'   # or: require 'soli-pdf'

#The renderer binary

The gem drives render_pdf, a native executable. It is not inside the gem. On the first render, the gem:

  1. picks the release asset for your platform, render-pdf-<os>-<arch>.tar.gz;
  2. downloads it from the Soli GitHub release matching Soli::PDF::BINARY_VERSION (currently 2.9.0);
  3. checks it against the published .sha256 file, and refuses it on a mismatch;
  4. unpacks it into ~/.cache/soli-pdf/2.9.0/render-pdf-<os>-<arch>/. $XDG_CACHE_HOME is used instead of ~/.cache when it is set.

Later renders reuse the cached copy. The archive also contains the bundled fonts (Titillium Web and JetBrains Mono), which the gem passes to the renderer automatically.

OSArchitecturesRequires
Linuxx86-64 (amd64), ARM64 (arm64)glibc 2.35 or later
macOSApple Silicon (arm64), Intel (amd64)
Windowsx86-64 (amd64)

Unpacking uses the system tar command. It is present on Linux, macOS and Windows 10 or later.

#Linux: glibc 2.35 or later

The Linux binaries are linked against the GNU C library and need glibc 2.35 or later. Check yours with ldd --version.

WorksDoes not work
Ubuntu 22.04 and laterUbuntu 20.04 (glibc 2.31)
Debian 12 and laterDebian 11 (glibc 2.31)
Fedora 36 and laterRHEL, Rocky Linux, AlmaLinux 9 (glibc 2.34)
RHEL, Rocky Linux, AlmaLinux 10Amazon Linux 2023 (glibc 2.34)
Alpine Linux (musl, no glibc)

On an older system the download succeeds, but every render fails with Soli::PDF::RenderError:

render_pdf: /lib64/libc.so.6: version `GLIBC_2.35' not found (required by render_pdf)

In Docker, pick a base image recent enough, such as ruby:3.3-slim-bookworm (Debian 12). On a system you can't upgrade, build render_pdf there and point SOLI_PDF_BIN at it. See The render_pdf binary.

#Check the installation

This one-liner downloads the binary if needed and prints its path:

ruby -rsoli/pdf -e 'puts Soli::PDF::Binary.path'

Then render a one-line document:

ruby -rsoli/pdf -e '
  pdf = Soli::PDF.render(template: { "content" => [{ "type" => "paragraph", "value" => "Hello" }] }, data: {})
  File.binwrite("hello.pdf", pdf)
  puts "#{pdf.bytesize} bytes"'

#Production and CI

Downloading on the first request slows that request down, and it fails when servers have no outbound network. Fetch the binary at build time instead.

#Docker

Warm the cache in your image, as the user that runs the app:

RUN bundle install
# Downloads and verifies render_pdf into the image's cache directory.
RUN bundle exec ruby -rsoli/pdf -e 'Soli::PDF::Binary.path'

#Air-gapped or pinned binaries

Download the release asset yourself, check it, and point the gem at it with SOLI_PDF_BIN. When that variable (or Soli::PDF.binary_path=) is set, the gem never downloads anything:

curl -LO https://github.com/solisoft/soli_lang/releases/download/v2.9.0/render-pdf-linux-amd64.tar.gz
curl -LO https://github.com/solisoft/soli_lang/releases/download/v2.9.0/render-pdf-linux-amd64.tar.gz.sha256
# The .sha256 file holds the bare hash, without a file name.
echo "$(cat render-pdf-linux-amd64.tar.gz.sha256)  render-pdf-linux-amd64.tar.gz" | sha256sum -c
mkdir -p /opt/render-pdf && tar -xzf render-pdf-linux-amd64.tar.gz -C /opt/render-pdf
export SOLI_PDF_BIN=/opt/render-pdf/render_pdf

Note A fonts/ directory next to the executable is picked up automatically, as it is for the downloaded copy. Keep the archive's layout when you move it.

#Caching the binary in CI

Cache ~/.cache/soli-pdf between CI runs, keyed on the gem version, to skip the download.

#Upgrading

Each gem release pins one renderer version in Soli::PDF::BINARY_VERSION. Upgrading the gem downloads the matching binary into a new cache directory, so versions never mix. You can delete old directories under ~/.cache/soli-pdf/ at any time.

#Next