Skip to main content
  1. Posts/

Running Playwright on Rocky Linux 10 for Robotmk Synthetic Monitoring

I wanted a real browser-based synthetic monitoring check (Checkmk’s Robotmk1, which drives Robot Framework2’s Browser library3 - built on Playwright) running from a small dedicated Rocky Linux 10 host. It works, but three things about Playwright and RCC4 on a RHEL-family distro are not documented anywhere obvious, and each one silently produces a “successful” build that then fails at test time. Here’s what actually happens and how to fix it.

Checkmk Checkmk

Playwright doesn’t officially support RHEL
#

Playwright’s own system requirements5 list Debian and Ubuntu only for Linux. Rocky, Fedora, and RHEL aren’t mentioned at all. In practice this means: the browser binary downloads and installs fine, but launching it fails with something like this:

Error: browserType.launch:
Host system is missing dependencies to run browsers.
Please install them with the following command:

    npx playwright install-deps

Alternatively, use apt:
    apt-get install libnss3 libnspr4 libatk1.0-0 ...

install-deps shells out to apt-get, which doesn’t exist on Rocky, so that suggested fix is a dead end on this OS.

Mapping the dependencies to RHEL package names
#

The Debian package names don’t map 1:1 to RHEL ones. This list (Chromium only, no Firefox/WebKit) is what actually resolves on Rocky Linux 10 - credit to the community mapping in the playwright-fedora6 project, which this is drawn from:

sudo dnf install -y \
  alsa-lib atk at-spi2-atk cups-libs libdrm \
  libXcomposite libXdamage libXrandr mesa-libgbm pango cairo \
  libxkbcommon libXfixes nspr nss \
  xorg-x11-fonts-Type1 xorg-x11-fonts-misc

Everything above resolves from Rocky’s baseos/appstream repos - no EPEL needed. zlib isn’t on the list because RHEL 10 ships zlib-ng-compat instead, which already provides the same libz.so and is installed by default.

NOTE: this is an unofficial mapping, not something Playwright tests or supports. It works today against robotframework-browser 19.1.0 / Playwright’s bundled Chromium as of 2026-09-18 - a future Chromium bump could need an additional package or two. If the browser fails to launch again after an update, re-run the test with verbose output and read the new missing-library list; it’s usually one or two additions, not a different problem.

RCC’s conda.yaml post-install hook
#

Installing robotframework-browser via pip is only half the setup - the library needs a separate step to actually download the browser binary:

rfbrowser init

If you only add this to robot.yaml’s tasks: section, it never runs in production: Robotmk calls Robot Framework directly and doesn’t use robot.yaml’s task definitions1 at all (RCC still requires the file to exist, it just ignores that part of it under Robotmk).

The hook belongs in conda.yaml, under the key rccPostInstall:

channels:
  - conda-forge
dependencies:
  - python=3.11.9
  - nodejs=20.9.0
  - pip=24.0
  - pip:
    - robotframework==7.1.1
    - robotframework-browser==19.1.0
rccPostInstall:
  - rfbrowser init

NOTE: get the key name wrong (postInstall, post-install, anything but exactly rccPostInstall) and RCC won’t error - it silently drops the unrecognized key from what it calls the “unified conda environment descriptor” and reports a normal successful build. If your browser test fails with a missing-dependencies error despite the hook being in place, check the build log for Post install scripts phase skipped -- no scripts - that line means the key wasn’t recognized.

The holotree caching trap
#

Getting the key right isn’t quite enough. RCC caches built environments in a content-addressed store called the holotree, and the hash it uses is computed only from the dependencies: block - not from rccPostInstall. Change only the post-install hook and RCC will happily report “Environment building succeeded” in a couple of seconds, reusing the exact same cached environment as before, hook and all silently skipped (Post install scripts phase skipped -- no scripts in the build log if you look).

If you’re iterating on the hook itself, you have to force a clean rebuild by clearing the cache directories RCC was configured to use (these are the Robotmk scheduler’s own settings, so the exact paths depend on your ROBOCORP_HOME/conda base directory config):

sudo systemctl stop robotmk-scheduler-daemon
sudo rm -rf /opt/robotmk/rcc_home/* /opt/robotmk/conda/*
sudo systemctl start robotmk-scheduler-daemon

Watch the scheduler’s log for Environment building succeeded - a genuine rebuild takes tens of seconds (dependency resolution, pip install, the post-install hook), not two.

Verifying it actually works
#

Don’t use rcc task run to test this - it invokes robot.yaml’s tasks: shell command, which (as above) isn’t what Robotmk actually runs in production, and the shell: field isn’t passed through a shell anyway (no && support), so it’s an easy way to chase a second, unrelated bug.

The documented way to test a suite in isolation is rcc task shell7, which drops you into the built environment, followed by running Robot Framework directly - exactly what Robotmk does in production:

cd /path/to/your/suite
sudo rcc task shell --robot robot.yaml --controller robotmk --space my-space
# now inside the environment:
robot tests.robot

With the RHEL dependency packages installed and rccPostInstall correctly in place:

==============================================================================
Tests
==============================================================================
Website Is Reachable                                                  | PASS |
------------------------------------------------------------------------------
Tests                                                                 | PASS |
1 test, 1 passed, 0 failed

A minimal tests.robot that exercises this whole chain:

*** Settings ***
Library    Browser
Suite Teardown    Close Browser    ALL

*** Test Cases ***
Website Is Reachable
    New Browser    chromium    headless=True
    New Page    https://example.com
    Get Title    ==    Example Domain

For the Checkmk side of this - Managed Robots, the scheduler bakery rule, and the deployment gotcha it throws if the agent runs as root - see the companion post8.

Resources
#

Author
Andreas Müller
Platform Engineer at B&W Handelsgesellschaft mbH focusing on infrastructure management, container orchestration, and developer enablement. Mostly living in the terminal. Tech stack: Ansible, Kubernetes, IaC, and CheckMK for observability.