roadrunner Documentation

High-performance PHP application server, process manager written in Go and powered with plugins

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy roadrunner on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name roadrunner --restart always roadrunner-server/roadrunner:latest

1. Project Overview & Quickstart (roadrunner-server/roadrunner)

File: README.md

RoadRunner is an open-source (MIT licensed) high-performance PHP application server, process manager written in Go and powered with plugins โค๏ธ.
It supports running as a service with the ability to extend its functionality on a per-project basis with plugins.

Features

RoadRunner features a range of plugins, including HTTP(S)/2/3 and fCGI servers that are compatible with PSR-7/PSR-17 standards. This is just one of its many capabilities. It serves as an effective alternative to the traditional Nginx+FPM setup, providing improved performance and more flexibility. Its extensive plugin options go far beyond just HTTP(S)/2/3 and fCGI servers, offering a broad range of functionalities:

  • Queue drivers: RabbitMQ, Kafka, SQS, Beanstalk, NATS, In-Memory.
  • KV drivers: Redis, Memcached, BoltDB, In-Memory.
  • OpenTelemetry protocol support (gRPC, http, jaeger).
  • Workflow engine via Temporal.
  • gRPC server. For increased speed, the protobuf extension can be used.
  • HTTP(S)/2/3 and fCGI servers features automatic TLS management, 103 Early Hints support and middleware like: Static, Headers, gzip, prometheus (metrics), send (x-sendfile), OTEL, proxy_ip_parser, etc.
  • Embedded distribute lock plugin which manages access to shared resources.
  • Metrics server (you might easily expose your own).
  • WebSockets and Broadcast via Centrifugo server.
  • Systemd-like services manager with auto-restarts, execution time limiter, etc.
  • Production-ready.
  • And more ๐Ÿ˜‰

Installation

The easiest way to get the latest RoadRunner version is to use one of the pre-built release binaries, which are available for
OSX, Linux, FreeBSD, and Windows. Instructions for using these binaries are on the GitHub releases page.

Docker:

To get the roadrunner binary file you can use our docker image: ghcr.io/roadrunner-server/roadrunner:2025.X.X (more information about
image and tags can be found here).

dockerfile
FROM ghcr.io/roadrunner-server/roadrunner:2025.X.X AS roadrunner
FROM php:8.3-cli

COPY --from=roadrunner /usr/bin/rr /usr/local/bin/rr

# USE THE RR

Configuration located in the .rr.yaml file (full sample):

Installation via Composer

You can also install RoadRunner automatically using the command shipped with the composer package, run:

bash
composer require spiral/roadrunner-cli
./vendor/bin/rr get-binary

Server binary will be available at the root of your project.

Note

PHP's extensions php-curl and php-zip are required to download RoadRunner automatically.
PHP's extensions php-sockets need to be installed to run roadrunner.
Check with php --modules your installed extensions.

Installation option for the Debian-derivatives (Ubuntu, Mint, MX, etc)

bash
wget https://github.com/roadrunner-server/roadrunner/releases/download/v2025.X.X/roadrunner-2025.X.X-linux-amd64.deb
sudo dpkg -i roadrunner-2025.X.X-linux-amd64.deb

Download the latest release via curl:

bash
curl --proto '=https' --tlsv1.2 -sSf  https://raw.githubusercontent.com/roadrunner-server/roadrunner/master/download-latest.sh | sh

MacOS using [Homebrew](https://brew.sh/):

bash
brew install roadrunner

Windows using [Chocolatey](https://community.chocolatey.org/):

bash
choco install roadrunner

Configuration can be located in .rr.yaml file (full sample):

yaml
version: '3'

rpc:
  listen: tcp://127.0.0.1:6001

server:
  command: "php worker.php"

http:
  address: "0.0.0.0:8080"

logs:
  level: error

Read more in Documentation.

Example Worker:

php
<?php

use Spiral\RoadRunner;
use Nyholm\Psr7;

include "vendor/autoload.php";

$worker = RoadRunner\Worker::create();
$psrFactory = new Psr7\Factory\Psr17Factory();

$worker = new RoadRunner\Http\PSR7Worker($worker, $psrFactory, $psrFactory, $psrFactory);

while ($req = $worker->waitRequest()) {
    try {
        $rsp = new Psr7\Response();
        $rsp->getBody()->write('Hello world!');

        $worker->respond($rsp);
    } catch (\Throwable $e) {
        $worker->getWorker()->error((string)$e);
    }
}

[!IMPORTANT]
If you see the EOF error, check that you have installed the PHP packages from this step.
If this does not help, try to execute the command php worker.php directly and check the output.


Run:

To run application server:

text
$ ./rr serve -c .rr.yaml

License:

The MIT License (MIT). Please see LICENSE for more information. Maintained
by Spiral Scout.

Contributors

Thanks to all the people who already contributed!


File: schemas/readme.md

Schemas

This directory contains public schemas for the most important parts of application.

Do not rename or remove this directory or any file or directory inside.

  • You can validate existing config file using the following command from the project root.
bash
docker run --rm -v "$(pwd):/src" -w "/src" node:22-alpine sh -c \
    "cd schemas && npm install && node test.js"

2. Official Technical Reference & Guides (roadrunner-server/roadrunner-docs)

File: README.md

RoadRunner is an open-source (MIT licensed) high-performance PHP application server, load balancer, and process manager.
It supports running as a service with the ability to extend its functionality on a per-project basis.

Contributors

Thanks to all the people who already contributed!


File: docs/en/lab/dashboards/dashboards.md

RoadRunner Dashboards

Grafana's dashboards for the RR (including temporal) installations. More info about the available metrics is here: link

gRPC dashboard

This dashboard contains gRPC plugin metrics: link

HTTP dashboard

This dashboard contains http plugin metrics: link

JOBS dashboard

This dashboard contains jobs plugin metrics: link

Temporal dashboard

This dashboard contains temporal (RR part) plugin metrics.
Official repo with the temporal metrics available here: https://github.com/temporalio/dashboards


File: docs/en/lab/dashboards/grpc.md

text
/* Detailed source-code truncated for AI context efficiency. */

File: docs/en/lab/dashboards/http.md

text
/* Detailed source-code truncated for AI context efficiency. */

File: docs/en/lab/dashboards/jobs.md

text
/* Detailed source-code truncated for AI context efficiency. */

File: docs/en/lab/dashboards/temporal.md

text
/* Detailed source-code truncated for AI context efficiency. */

File: docs/en/lab/access-logs.md

Logging โ€” HTTP Access logs

RoadRunner has the HTTP access logs support, which provides detailed information about incoming HTTP requests and
responses.

Note
This feature is disabled by default, but it can be easily enabled by configuring the HTTP server.

Enabling HTTP Access Logs

To enable HTTP access logs in RoadRunner, you need to modify the configuration file of the HTTP server.

Here's an example configuration file:

yaml .rr.yaml
version: "3"

http:
  address: 127.0.0.1:8000
  access_logs: true
  # ...

Once enabled, RoadRunner will log the following information for each incoming HTTP request:

  • method - HTTP method of the request
  • remote_addr - Remote address of the client
  • bytes_sent - Content length of the response
  • http_host - Host name of the server
  • request - Query string of the request
  • time_local - Local time of the server in Common Log Format
  • request_length - Request body size including headers in bytes (content-len + size of all headers) in bytes. Max allowed headers
    size for the RR is 1MB.
  • request_time - Request processing time in seconds with a milliseconds' resolution
  • status - HTTP response status
  • http_user_agent - HTTP user agent string of the client
  • http_referer - HTTP referer string of the client

File: docs/en/lab/applogger.md

Logging โ€” Application logger

The RoadRunner server has a useful app-logger plugin that allows users to send logs from their applications to the
RoadRunner server using an RPC interface. This plugin is enabled by default and does not require any additional
configurations. It can be used to observe all application and server logs in one place. This is especially useful when
debugging and monitoring applications.

Note
It will send raw messages to the RoadRunner STDERR

Configuration

The logs section in the RoadRunner configuration file allows you to configure logging behavior for their application.

yaml .rr.yaml
rpc:
  listen: tcp://127.0.0.1:6001

logs:
  channels:
    app:
      level: info

Warning
To interact with the RoadRunner app-logger plugin, you will need to have the RPC defined in the rpc configuration
section. You can refer to the documentation page here to learn more about the configuration.

The level key is used to specify the logging level for this channel. This means that only log messages with a severity
level of info or higher will be sent to this channel.

Note
Read more about logging in the Logging โ€” Logger section.

PHP client

The RoadRunner app-logger plugin comes with a convenient PHP package that simplifies the process of integrating the
plugin with your PHP application.

Installation

To get started, you can install the package via Composer using the following command:

terminal
composer require roadrunner-php/app-logger

Usage

After the installation, you can create an instance of the RoadRunner\Logger\Logger class, which will allow you to use
the available class methods.

Here is an example:

php
use Spiral\Goridge\RPC\RPC;
use RoadRunner\Logger\Logger;

$rpc = RPC::create('tcp://127.0.0.1:6001');

$logger = new Logger($rpc);

$logger->info('Hello, RoadRunner!');
$logger->warning('Something might be wrong...');
$logger->error('Houston, we have a problem!');

Note
You can refer to the documentation page here to learn more about creating the RPC connection.

Available methods

  • debug(string): void: Sends a debug log message to the server
  • error(string): void: Sends an error log message to the server
  • info(string): void: Sends an info log message to the server
  • warning(string): void: Sends a warning log message to the server
  • log(string): void: Sends a log message directly to the STDERR of the server

API

RPC API

RoadRunner provides an RPC API, which allows you to manage app-logger in your applications using remote
procedure calls. The RPC API provides a set of methods that map to the available methods of
the RoadRunner\Logger\Loggerclass in PHP.

Note
All methods accept a string (which will be log message) as a first argument and a bool placeholder for the second
arg.

Error

Method sends an error log message with the specified message to the RoadRunner server.

go
func (r *RPC) Error(in string, _ *bool) error {}

Info

Method sends an info log message with the specified message to the RoadRunner server.

go
func (r *RPC) Info(in string, _ *bool) error {}

Warning

Method sends a warning log message with the specified message to the RoadRunner server.

go
func (r *RPC) Warning(in string, _ *bool) error {}

Debug

Method sends a debug log message with the specified message to the RoadRunner server.

go
func (r *RPC) Debug(in string, _ *bool) error {}

Log

Method sends a log message with the specified message directly to the STDERR of the RoadRunner server.

go
func (r *RPC) Log(in string, _ *bool) error {}

File: docs/en/lab/health.md

Observability โ€” Health and Readiness checks

The RoadRunner Status Plugin provides a healthcheck status for various plugins such
as http, grpc, temporal, jobs and centrifuge. This plugin provides an easy way to check the condition of the
workers and ensure that they are ready to serve requests.

Activation of the Status Plugin

To activate the health/readiness checks endpoint, include a status section in your configuration file.

Here is an example:

yaml .rr.yaml
version: "3"

status:
  address: 127.0.0.1:2114

The above configuration sets the address to 127.0.0.1:2114. This is the address that the plugin will listen to. You
can change the address to any IP address and port number of your choice.

To access the health check, you need to use the following URL: http://127.0.0.1:2114/health?plugin=http. This URL will
return the health status of the http plugin.

Note
You can specify multiple plugins by separating them with a comma. For example, to check the health status of both the
http and grpc plugins, you can use the following URL: http://127.0.0.1:2114/health?plugin=http&plugin=grpc.

The health check endpoint will return HTTP 200 if there is at least one worker ready to serve requests. If there are
no workers ready to service requests, the endpoint will return HTTP 500. If there are any other errors, the endpoint
will also return HTTP 500.

The readiness check endpoint will return HTTP 200 if there is at least one worker ready to take the request (i.e., not
currently busy with another request). If there is no worker ready or all workers are busy, the endpoint will return
HTTP 500 status code (you can override this too).

Customizing the Not-Ready Status Code

By default, Status Plugin uses a 500 status code. However, you can replace this status code with a custom one.

To achieve this, utilize the unavailable_status_code option:

yaml .rr.yaml
version: "3"

status:
  address: 127.0.0.1:2114
  unavailable_status_code: 501

Jobs plugin pipelines check

In addition to checking the health status of the workers, you can also examine the pipelines in the Jobs plugin using
the following URL: http://127.0.0.1:2114/jobs

This URL will return the status of the pipelines in the Jobs plugin. The output will be in the following format:

text
plugin: jobs: pipeline: test-1 | priority: 13 | ready: true | queue: test-1 | active: 0 | delayed: 0 | reserved: 0 | driver: memory | error:

Use cases

The health check endpoint serves the following purposes:

Kubernetes Readiness and Liveness Probes

In Kubernetes, you can use readiness and liveness probes to check the health of your application. It can be used as a
readiness or liveness probe to ensure that your application is ready to serve requests. You can configure Kubernetes to
check the health check endpoint and take appropriate action if the endpoint returns an error.

Read more here

AWS Target Group Health Checks

If you are using AWS Elastic Load Balancer, you can use it as a health check for your target group. You can configure
the target group to check the health check endpoint and take appropriate action if the endpoint returns an error.

Read more here

GCE Load Balancing Health Checks

If you are using Google Cloud Platform, you can use it as a health check for your load balancer. You can configure the
load balancer to check the health check endpoint and take appropriate action if the endpoint returns an error.

Read more here


File: docs/en/lab/logger.md

Logging โ€” Logger

Logger Plugin is responsible for collecting logs from server plugins and PHP application workers' STDERR and
displaying them in the RoadRunner STDERR/STDOUT. It comes with a variety of options that allow you to customize the
way your application logs are collected and displayed.

Configuration

Modes

yaml
logs:
  mode: production

There are three available modes:

  1. production - This mode uses logger settings that are optimized for production usage.
  2. development - This mode is enabled by default and is designed for use during application development. In
    development mode, DPanicLevel logs panic, console colors are used, and logs are written to standard error. Sampling
    is disabled, and stack traces are automatically included on logs of WarnLevel and above.
  3. raw - This mode displays messages as raw output without any formatting. This mode is useful in production
    environments where you need to parse logs programmatically.

Note
Use production mode in production environments. It is optimized for production usage.

Encoding

Logger supports two types of encoding, console and json. By default, console encoding is used, which outputs logs
in a friendly format. JSON encoding, on the other hand, returns messages in a JSON Structured logging format. This
format presents log messages as JSON objects with key-value pairs representing each log message field, making them more
machine-readable and easier to process programmatically. JSON encoding is also better suited for production usage.

yaml
logs:
  encoding: console

Level

The level is used to specify the logging level. This means that only log messages with a severity level will be sent to
this channel. Available levels include panic, error, warn, info, and debug.

yaml
logs:
  level: info

Note
The default level is debug.

Output

By default, RoadRunner sends logs to STDERR. However, you can configure RoadRunner to send logs to STDOUT by using
the output key.

yaml
logs:
  output: stdout

Line Endings

It allows configuring custom line endings for the logger. By default, the plugin uses \n as the line ending. Note that the \n is a forced default. This means that if the value is empty, RoadRunner will still use \n. So no empty line endings are allowed.

yaml
logs:
  line_ending: "\r\n"

Channels

In addition, you can configure each plugin log messages individually using the channels section. It allows you to
customize the logger settings for each plugin independently. You can disable logging for a particular plugin or change
its log mode and output destination.

yaml
version: "3"

logs:
  encoding: console # default value
  level: info
  mode: none # disable server logging. Also `off` can be used.
  channels:
    http:
      mode: production
      output: http.log

File Logger

It is possible to redirect channels or the entire log output to a file. To use the file logger, you need to set
the file_logger_options.log_output option to the filename where you want to write the logs.

Entire log

yaml
logs:
  mode: development
  file_logger_options:
    log_output: "test.log"
    max_size: 10
    max_age: 24
    max_backups: 10
    compress: true

Channel

You can also redirect a specific channel to a file. To do this, you need to specify the channel name in the channels

yaml
logs:
  mode: development
  level: debug
  channels:
    http:
      file_logger_options:
        log_output: "test.log"
        max_size: 10
        max_age: 24
        max_backups: 10
        compress: true

Available options

  1. log_output: Filename is the file to write logs to in the same directory. It uses processname-lumberjack.log in
    os.TempDir() if empty.
  2. max_size: is the maximum size in megabytes of the log file before it gets rotated. It defaults to 100 megabytes.
  3. max_age: is the maximum number of days to retain old log files based on the timestamp encoded in their filename.
    Note that a day is defined as 24 hours and may not exactly correspond to calendar days due to daylight savings, leap
    seconds, etc. The default is not to remove old log files based on age.
  4. max_backups: is the maximum number of old log files to retain. The default is to retain all old log files (though
    MaxAge may still cause them to get deleted.)
  5. compress: determines if the rotated log files should be compressed using gzip. The default is not to perform
    compression.
  6. log_ending: line ending to use in the logger. Default is new line - \n.

ZapLogger

Feel free to register your own ZapLogger extensions.