This document outlines the configuration of a systemd unit designed to run the Playwright MCP server. The setup is opinionated, adhering to the Filesystem Hierarchy Standard (FHS) and the curated SELinux policies found in Fedora and Red Hat Enterprise Linux distributions.
This systemd unit runs the Playwright MCP container in "rootful" mode, meaning the container is managed by a podman process running as the root user. This is in contrast to Podman's default and more secure "rootless" mode, which allows non-privileged users to run containers. Running as root is a deliberate choice in this configuration, often necessitated by requirements like binding to privileged ports below 1024.
For seamless container communication, a dedicated container network named br-container is created using the command:
sudo podman network create br-containerWhen containers are connected to this user-defined bridge network, Podman provides automatic DNS-based service discovery. This functionality is handled by aardvark-dns, an authoritative DNS server that serves DNS records for containers within Podman-managed networks. This allows containers on the same network to resolve each other's IP addresses by their container names.
When using Podman on a system with SELinux in enforcing mode, it is crucial to manage the security contexts of volumes mounted into containers.
The systemd unit file specifies the volume mount as --volume /srv/containers/%N/data:/data:Z. The :Z suffix instructs Podman to relabel the host directory (/srv/containers/playwright-mcp-server/data) with a private, unshared SELinux label (container_file_t). This makes the directory accessible only to the processes within that specific container.
The specified host path, /srv/containers/, is intentionally chosen because standard SELinux policies on Fedora and RHEL-based systems are pre-configured to handle files in this directory. As shown below, files and directories created under /srv/containers/ will automatically inherit the container_file_t context, which is necessary for container runtimes like Podman to access them.
berstuk ~ » sudo semanage fcontext -l | grep \/srv\/container
/srv/containers(/.*)? all files system_u:object_r:container_file_t:s0
/var/srv/containers(/.*)? all files system_u:object_r:container_file_t:s0 This pre-configured policy simplifies volume management, as you do not need to manually change the SELinux context of the host directory.
sudo mkdir -p /srv/containers/playwright/{conf,data}
# Setting ownership to match the uidnumber/gidnumber used in the playwright container
sudo chown -R 1000:1000 /srv/containers/playwright
sudo chmod -R g+rwX /srv/containers/playwrightWhile this systemd unit is designed for Podman, it can be adapted for Docker. However, there are some key differences to be aware of:
- Architecture: The most significant difference is that Docker uses a client-server architecture with a long-running daemon (
dockerd) that manages all containers. Podman, on the other hand, is daemonless and launches containers as child processes of the user that starts them. - Systemd Integration: Podman offers superior integration with systemd. It includes tools like
podman generate systemdto automatically create systemd unit files for containers, simplifying the process of managing containers as system services. - Security: Podman is generally considered more secure due to its default rootless operation. While Docker has a rootless mode, it is not the default and has some limitations.
- CLI Compatibility: For most common commands, Podman is a drop-in replacement for Docker, meaning you can often alias
dockertopodman(alias docker=podman) with minimal issues. - Image Building: Docker has built-in image building capabilities (
docker build). Podman often relies on a separate tool called Buildah for more advanced image creation, though basicpodman buildfunctionality exists.
To adapt this unit file for Docker, you would primarily need to replace the podman commands with their docker equivalents. For example, using sed 's/podman/docker/g'. However, be mindful that Docker's interaction with systemd and SELinux may require different configurations.
-
Create the systemd Unit File: Save the provided unit file content to
/etc/systemd/system/playwright-mcp-server.service. This location is the standard directory for system-wide services managed by systemd. -
Create the Container Data Directory: The service expects a directory on the host system to mount as a volume inside the container. Create the necessary directory structure:
sudo mkdir -p /srv/containers/playwright-mcp-server/data
On SELinux-enforcing systems like Fedora or RHEL, the correct
container_file_tsecurity context will be automatically applied to this directory based on existing file context rules. -
Create the Podman Network: For automatic DNS resolution between containers, create the specified Podman network:
sudo podman network create br-container
This only needs to be done once. Any subsequent containers can be attached to this same network.
-
Reload the systemd Daemon: After creating a new unit file, you must inform systemd to scan for new or changed units:
sudo systemctl daemon-reload
Once the unit file is installed, you can manage the Playwright MCP server using standard systemctl commands.
-
Enabling the Service: To have the service start automatically at boot, you need to enable it:
sudo systemctl enable playwright-mcp-server.serviceThis creates a symbolic link from the system's service startup directory to the unit file.
-
Starting and Stopping the Service: You can manually control the service with the following commands:
- To start the service:
sudo systemctl start playwright-mcp-server.service
- To stop the service:
sudo systemctl stop playwright-mcp-server.service
- To start the service:
-
Restarting the Service: If you make changes to the container image or need to restart the service for any reason:
sudo systemctl restart playwright-mcp-server.service
-
Checking the Service Status: To view the current status of the service, including whether it is active, and to see the latest log entries, use:
sudo systemctl status playwright-mcp-server.service
This will provide a snapshot of the service's state, including process IDs and recent log output.
-
Viewing Logs: For more detailed and historical logs, use the
journalctlcommand. To follow the logs in real-time, which is useful for debugging:sudo journalctl -u playwright-mcp-server.service -f
This shows the logs specifically for this unit. Since the container is configured to use the
conmonsdnotify mechanism, container logs will be directly ingested into the systemd journal. -
Troubleshooting: If the service fails to start, begin by checking the status and logs:
- Run
sudo systemctl status playwright-mcp-server.serviceto see if there are immediate error messages. - Use
sudo journalctl -u playwright-mcp-server.serviceto get a more complete picture of what might have gone wrong during the startup process. Common issues could include networking problems, SELinux permission errors, or issues with the container image itself. - You can also inspect the running containers using
sudo podman ps -ato see if the container is being created and what its exit status is.
- Run