fbpx

Configure wkhtmltopdf for Laravel Snappy on Homestead, Sail, Forge

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.xCode 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.debCode 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:publishCode 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/wkhtmltopdfCode language: JavaScript (javascript)

And you’re all set! Happy coding.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *