Skip to main content

How to Install Pa11y on a DigitalOcean Droplet

·470 words·3 mins
Author
Alessandro Ferrini

Installing Pa11y on a virtual machine turned out to be more challenging than I expected, and since I couldn’t find many guides online I decided to write one. If you’re looking for a quick solution, I’ve prepared a script to install everything.

What Is Pa11y?
#

Pa11y as described by its team is an automated accessibility testing pal. In other words, it helps identify accessibility issues on websites. Keep in mind that the European Accessibility Act will go into effect on June 28, 2025, and all existing websites must comply with these regulations by June 28, 2027.

Further Reading: For a detailed overview, check out Martijn Hols’s excellent article: The European Accessibility Act for websites and apps.

For a personal project, I need an API to scan a website and return a JSON response with all accessibility errors. Fortunately, Pa11y can output results in JSON. For instance, running:

pa11y https://www.alessandroferrini.com -r json

produces a JSON-formatted list of accessibility issues. Perfect!

The Problem
#

Installing Pa11y on my local machine was simple: npm install -g pa11y. However, when I tried to deploy my application to a virtual machine, everything stopped working. My stack is straightforward FastAPI for an API endpoint and Redis for caching, but on the VM, I’ve got so many cryptic errors that was really hard to determine the root cause.

Installing Pa11y on DigitalOcean
#

For my tests I’ve used a 4$ Droplet (with 512MB of Memory) from DigitalOcean with Ubuntu 24.10.

  1. Configure a VM:
    I bought a Droplet on DigitalOcean and created a new user. If you’re not sure how to do this, consult their official guide: How to Add and Delete Users on Ubuntu.

  2. Install Pa11y and Chrome via Puppeteer:
    In my case, I installed a specific version of Chrome (127.0.6533.88) because the newer versions had issues (if I find a fix, I’ll update this article).

    sudo npm install -g pa11y
    npx puppeteer browsers install chrome@127.0.6533.88
    
  3. Adjust Ownership and Permissions for the Chrome Sandbox:
    After installing, you need to grant the chrome_sandbox binary the correct ownership and setuid bit:

    sudo chown root:root $HOME/.cache/puppeteer/chrome/linux-127.0.6533.88/chrome-linux64/chrome_sandbox
    sudo chmod 4775 $HOME/.cache/puppeteer/chrome/linux-127.0.6533.88/chrome-linux64/chrome_sandbox
    
  4. Set Environment Variables:
    Next, export the CHROME_DEVEL_SANDBOX variable and ensure that XDG_RUNTIME_DIR and DBUS_SESSION_BUS_ADDRESS point to the correct $UID:

    export CHROME_DEVEL_SANDBOX="$HOME/.cache/puppeteer/chrome/linux-$TARGET_CHROME_VERSION/chrome-linux64/chrome_sandbox"
    export XDG_RUNTIME_DIR="/run/user/$UID"
    export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$UID/bus"
    
  5. Allow Memory Overcommitment:
    Finally, you may need to tweak kernel memory settings for Chrome to allocate memory effectively—especially on lower-memory Droplets:

    sudo sysctl -w vm.overcommit_memory=1
    

With these steps, Pa11y should run successfully on your Droplet. Congratulations!

TL;DR
#

Since I frequently test these setups, I wrote a small script that handles installation automatically:

Caution: Always review any script from the internet before running it.

wget -qO- https://raw.githubusercontent.com/Alurith/pa11y-digital-ocean/refs/heads/main/install.sh | bash

If you find any problem open and issue on Github

If you want to support more tests this is my referral link to DigitalOcean, thanks!