If you’re generating PDFs from HTML in the Laravel world, you’re likely using something like Snappy, wrapped conveniently in a service provider by barryvdh/laravel-snappy.
Snappy depends on the wkhtmltopdf binary to function. Per the documentation, this binary is conveniently available via Composer:
composer require h4cc/wkhtmltopdf-i386 0.12.x
Code language: JavaScript (javascript)
But that package hasn’t been updated in 4+ years, meaning the binary is a bit out of date. You’re much better off with the latest and greatest version. To do that, you’ll have to install it on your server yourself. The general instructions can be found here, but I’ll outline how to set it up in a simple, automated way in your development environments, plus on Laravel Forge.
Installing wkhtmltopdf on Laravel Homestead
If you’re developing locally on Laravel Homestead, you can tinker with the included after.sh
script to do some extra provisioning for your VM. Pop open after.sh
and add the following, assuming you’re running the latest Homestead, which runs Ubuntu 20.04 (Focal):
sudo apt-get update
sudo apt-get install -y xfonts-75dpi wget
wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb \
sudo apt install -y ./wkhtmltox_0.12.6-1.focal_amd64.deb
rm ./wkhtmltox_0.12.6-1.focal_amd64.deb
Code language: JavaScript (javascript)
Of course, you can run these manually on your Homestead server after provisioning, or on any other Ubuntu 20.04 install. But by putting it in after.sh
, it should survive updates to your Homestead environment. Your wkhtmltopdf setup is now persistent and ready-to-go every time.
Installing wkhtmltopdf on Laravel Forge
For Laravel Forge, create a new recipe using the exact same code we used for Homestead. Run that recipe against any server hosting projects that use Snappy.
This isn’t as elegant because you still need to remember to run this if you provision a new server for the project. Forge is very good for simple things, but if more automation in this provisioning is a concern for you, look into more configurable provisioning services.
Installing wkhtmltopdf on Laravel Sail
Laravel Sail is a bit different than Homestead in that your dev environment is Docker-driven, so there are standardized strategies for provisioning, unlike Homestead’s arbitrary after.sh
.
First, if you haven’t already, you need to publish Sail’s Dockerfiles. Done via artisan:
sail artisan sail:publish
Code language: CSS (css)
This will create a new docker
directory in the root of your project, with both PHP 7.4 and 8.0 configurations. Your existing docker-compose.yml
file should have one of those declared already. Also note that it will have been automatically updated to reference the new docker
directory:
# For more information: https://laravel.com/docs/sail
version: '3'
services:
laravel.test:
build:
context: ./docker/8.0
dockerfile: Dockerfile
args:
WWWGROUP: '${WWWGROUP}'
image: sail-8.0/app
ports:
- '${APP_PORT:-80}:80'
environment:
WWWUSER: '${WWWUSER}'
LARAVEL_SAIL: 1
volumes:
- '.:/var/www/html'
networks:
- sail
depends_on:
- mysql
mysql:
image: 'mysql:8.0'
ports:
- '${FORWARD_DB_PORT:-3306}:3306'
environment:
MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
MYSQL_DATABASE: '${DB_DATABASE}'
MYSQL_USER: '${DB_USERNAME}'
MYSQL_PASSWORD: '${DB_PASSWORD}'
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
volumes:
- 'sailmysql:/var/lib/mysql'
networks:
- sail
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-p${DB_PASSWORD}"]
retries: 3
timeout: 5s
networks:
sail:
driver: bridge
volumes:
sailmysql:
driver: local
Code language: PHP (php)
Go ahead and open the Dockerfile
referenced in your docker-compose.yml
file. It isn’t terribly important where you add the following, but I’ve added mine after pecl
dependencies are installed.
RUN pecl channel-update https://pecl.php.net/channel.xml \
&& pecl install swoole \
&& pecl clear-cache \
&& rm -rf /tmp/* /var/tmp/*
RUN apt-get update \
&& apt-get install -y xfonts-75dpi wget \
&& wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb \
&& apt install -y ./wkhtmltox_0.12.6-1.focal_amd64.deb \
&& rm ./wkhtmltox_0.12.6-1.focal_amd64.deb
RUN setcap "cap_net_bind_service=+ep" /usr/bin/php8.0
Code language: JavaScript (javascript)
And finally, rebuild your container:
sail build --no-cache
What I love about this, and Sail / Docker in general, is that this is now ready to go for you every time you start development on this project, with no dependence on a pre-configured development environment. You never have to think about it again. This goes for anyone on your team working on this project for the first time – Docker will create their development environment with wkhtmltopdf
ready to go.
Either Way: Finishing Up
Last thing, make sure your project is using the right version of wkhtmltopdf
. By default, laravel-snappy looks in /usr/local/bin/wkhtmltopdf
, which is where this gets installed. SSH into your environment and verify the location and version:
sail@f2f875ee4ed0:/var/www/html$ which wkhtmltopdf
/usr/local/bin/wkhtmltopdf
sail@f2f875ee4ed0:/var/www/html$ wkhtmltopdf --version
wkhtmltopdf 0.12.6 (with patched qt)
Code language: JavaScript (javascript)
If, for some reason, the binary has ended up elsewhere, be sure to update your .env
file to point to the new wkhtmltopdf binary:
WKHTML_PDF_BINARY=/some/other/path/wkhtmltopdf
Code language: JavaScript (javascript)
And you’re all set! Happy coding.
Leave a Reply