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.
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.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
Adjust Ownership and Permissions for the Chrome Sandbox:
After installing, you need to grant thechrome_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
Set Environment Variables:
Next, export theCHROME_DEVEL_SANDBOX
variable and ensure thatXDG_RUNTIME_DIR
andDBUS_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"
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!