Contact Us

Generating PDFs in Rails with PDFKit and deploying to a server


April 23, 2012 | by Adam Pope

I’ve been using the rather excellent PDFKit library on a recent Ruby on Rails project to generate PDF reports.  The API is perfect: have some HTML, give me a PDF back.

In my controller I simply have:

def download_pdf
  html = render_to_string(:action => '../pdf/my_template', :layout => false)
  pdf = PDFKit.new(html)
  send_data(pdf.to_pdf)
end

Where the :action option is a path to a view file.   What could be simpler?  To get this up and running there were a couple steps.  First add a line to the Gemfile

gem 'pdfkit'

and then install the wkhtmltopdf library using

brew install wkhtmltopdf

And then I tried to deploy to a server…

Very pleased with my new sexy PDF reports I wanted to push my code to the server.  I did a quick

sudo apt-get install wkhtmltopdf

to grab the package, loaded up the site and hit the download button: Internal Server Error. Wat!? Looking in the log file:

command failed: "/usr/bin/wkhtmltopdf" "--page-size" "Letter" 
"--margin-top" "0.75in" "--margin-right" "0.75in" "--margin-bottom" 
"0.75in" "--margin-left" "0.75in" "--encoding" "UTF-8" "--print-media-type" 
"--quiet" "-" "-"

Huh? I then tried to run the command from the command line to see if I could get a more useful error message:

$ wkhtmltopdf http://google.com google.pdf
wkhtmltopdf: cannot connect to X server

Damn. It turns out that the standard wkhtmltopdf package needs the server to have a window manager running and the chances are your server, like this one, doesn’t have a GUI interface.  So what now?  Well after a bit of Googling I was starting to get worried, until somebody (I forget where, but thank you!) mentioned that the binaries that can be downloaded from the project’s repo are built against qt and don’t depend on X running! Result!

Looking at the installation instructions page we find this snippet of joy labelled ‘Or….’ under Linux (Ubuntu):

# first, installing dependencies
sudo aptitude install openssl build-essential xorg libssl-dev

# for 64bits OS
wget http://wkhtmltopdf.googlecode.com/files/wkhtmltopdf-0.9.9-static-amd64.tar.bz2
tar xvjf wkhtmltopdf-0.9.9-static-amd64.tar.bz2
mv wkhtmltopdf-amd64 /usr/local/bin/wkhtmltopdf
chmod +x /usr/local/bin/wkhtmltopdf

This worked perfectly and all that remained was to tell PDFKit where to find this new binary. I put a pdfkit.rb in my initializers directory with the following in:

PDFKit.configure do |config|
     config.wkhtmltopdf = '/usr/local/bin/wkhtmltopdf' if Rails.env.production?
end

Bingo! PDF downloads are now running on the site.