Skip to content

Installation ​

Each Linux or macOS package or tarball contains the rapira binary and its libphp interpreter library. The server loads this library into its process. These packages and tarballs do not contain the php command, php-fpm, or an ini directory. Rapira does not require a system PHP installation. For Windows ZIP files, see Windows.

What is libphp, and how does it differ from the PHP command?

PHP builds several interfaces to its engine. These interfaces are Server Application Programming Interfaces, or SAPIs. Each uses the Zend engine and extensions, but it has a different program interface:

SAPIWhat it producesWho is in charge
CLIthe php commandPHP: it starts, runs a script, exits.
FPMphp-fpmPHP: it listens on the socket and keeps a worker pool.
embedlibphp.soThe host program: it calls the interpreter like any other library.

Rapira includes the embed SAPI because the server controls requests. The php command uses a different SAPI, so artifacts do not contain it.

Why does Rapira include its own libphp?

PHP must use --enable-embed=shared to create libphp.so. Few distributions provide this build. Fedora and RHEL provide php-embedded, and Arch provides php-embed. Deb.sury.org provides libphpX.Y-embed for Debian and Ubuntu.

These packages have fixed PHP versions and extension sets. Homebrew PHP does not include the embed SAPI. Thus, each Rapira release builds libphp from an official PHP source archive and includes it with the binary.

What does "PHP runs inside the Rapira process" mean?

During initialization, the rapira process loads libphp into its address space. Rapira calls PHP functions in the same process. It does not use a socket, FastCGI, or request serialization. The library remains a separate file next to the binary. Thus, do not move the binary without the library. See Tarballs on Linux and macOS.

Choosing a PHP version ​

Each download name contains php8.4 or php8.5. This text identifies the PHP minor version of its libphp. Select 8.5 unless an application dependency requires 8.4.

Rapira does not use or change an existing system PHP, php-fpm pool, or Homebrew PHP. Composer, bin/console, and artisan continue to use the system PHP CLI.

Why does each PHP version get its own Rapira build?

The artifact libphp is part of the build and is not interchangeable. The rapira binary links to one specific library. The PHP ABI changes between minor versions. Thus, one Rapira build supports one PHP minor version. The file name identifies this version. You do not need to install PHP or configure php-config.

How do I switch from 8.4 to 8.5?

Install the package for the other PHP version. The package manager replaces the installed Rapira package. Both packages use the same paths. They declare provides, conflicts, and replaces, or obsoletes for RPM. Tarball installations use separate directories and can exist at the same time. Start each version from its own path.

Release artifacts ​

The Rapira releases page contains Linux and macOS release files. The Rapira Windows releases page contains Windows release files. Use the download page to select the operating system, architecture, PHP version, and package format. It also shows the SHA-256 value. Each php8.5 artifact has a corresponding php8.4 artifact.

On Linux, use a package for standard file locations and automatic library dependencies. Use a tarball for a single directory, container image, deployment artifact, or installation without root access. The Linux tarball also requires system libraries. See Tarballs on Linux and macOS for the list.

Check the file with rapira-v0.9.0-SHA256SUMS.txt before installation. See Verifying checksums.

Why must I verify the checksum before installation?

.deb and .rpm packages run installation scripts as root. A changed package could execute unwanted code with root permission. Checksum verification detects a changed package before installation.

Debian and Ubuntu ​

Download the .deb file. Install it through apt with its path:

bash
curl -LO https://github.com/rapira-rs/rapira/releases/download/v0.9.0/rapira-php8.5_0.9.0-1_amd64.deb
sudo apt install ./rapira-php8.5_0.9.0-1_amd64.deb
rapira --version

The package installs the server without a service unit, configuration file, or ini directory. See Running in production to configure systemd.

The packages require glibc 2.34 or newer. The minimum supported versions are Debian 12 and Ubuntu 22.04.

Why does the file path start with ./?

The leading ./ tells apt to use a local file instead of a repository package name.

Which files does the package install?

The package installs /usr/bin/rapira, /usr/lib/rapira/libphp.so, and ICU libraries under /usr/lib/rapira/. On PHP 8.4, it also installs /usr/lib/rapira/opcache.so. It installs the license and README under /usr/share/doc/rapira/.

RHEL, Rocky and Fedora ​

Install the RPM through dnf:

bash
curl -LO https://github.com/rapira-rs/rapira/releases/download/v0.9.0/rapira-php8.5-0.9.0-1.x86_64.rpm
sudo dnf install ./rapira-php8.5-0.9.0-1.x86_64.rpm
rapira --version

The RPM requires glibc 2.34 or newer. RHEL 9, Rocky 9, AlmaLinux 9, and current Fedora versions meet this requirement.

Tarballs on Linux and macOS ​

A tarball unpacks into a single directory that holds the whole server:

text
rapira-v0.9.0-php8.5-linux-x86_64/
├── bin/rapira
├── lib/rapira/
├── share/php/PHP_VERSION.txt
├── README.md
└── LICENSE

On Linux, lib/rapira contains libphp.so and the required ICU libraries. On PHP 8.4, lib/rapira also contains opcache.so on Linux and macOS.

Move the directory to its permanent location. Add a symbolic link to the binary on PATH:

bash
curl -LO https://github.com/rapira-rs/rapira/releases/download/v0.9.0/rapira-v0.9.0-php8.5-linux-x86_64.tar.gz
tar xzf rapira-v0.9.0-php8.5-linux-x86_64.tar.gz
sudo mv rapira-v0.9.0-php8.5-linux-x86_64 /opt/rapira
sudo ln -s /opt/rapira/bin/rapira /usr/local/bin/rapira
rapira --version
bash
curl -LO https://github.com/rapira-rs/rapira/releases/download/v0.9.0/rapira-v0.9.0-php8.5-macos-aarch64.tar.gz
tar xzf rapira-v0.9.0-php8.5-macos-aarch64.tar.gz
sudo mv rapira-v0.9.0-php8.5-macos-aarch64 /opt/rapira
sudo ln -s /opt/rapira/bin/rapira /usr/local/bin/rapira
rapira --version

Installation without root access ​

For an installation without root access, keep the complete directory in your home directory. Create a symbolic link in ~/.local/bin:

bash
mkdir -p "$HOME/.local/opt" "$HOME/.local/bin"
mv rapira-v0.9.0-php8.5-linux-x86_64 "$HOME/.local/opt/rapira"
ln -s "$HOME/.local/opt/rapira/bin/rapira" "$HOME/.local/bin/rapira"
"$HOME/.local/bin/rapira" --version

On macOS, replace the source directory name with the extracted macOS directory name. Add $HOME/.local/bin to PATH if the shell does not include it.

The binary uses a relative path to find its interpreter. Move the complete directory together. Do not copy only bin/rapira to /usr/local/bin/. Use a symbolic link as shown above.

Why does a symlink work when a copy of the binary does not?

The binary contains a relative rpath to the interpreter. Linux uses $ORIGIN/../lib/rapira, and macOS uses @loader_path/../lib/rapira. The loader resolves a symbolic link before it resolves the rpath. Thus, the rpath starts from the actual binary location. A copy in /usr/local/bin has no adjacent lib/rapira directory and cannot find the interpreter.

Which system libraries does the tarball need?

On macOS, lib/rapira contains libphp.dylib and all required non-system libraries. The directory is self-contained.

On Linux, lib/rapira contains libphp.so and the ICU libraries from its build. The system must provide OpenSSL 3, libcurl, libxml2, SQLite, Oniguruma, zlib, libpq, and libstdc++. The deb and RPM packages declare these libraries, glibc, and libgcc as dependencies.

Verifying checksums ​

Each Linux and macOS release has one checksum file for all release files. Verify only the downloaded file. On Linux, use --ignore-missing. On macOS, use grep to pass the selected line to shasum:

bash
curl -LO https://github.com/rapira-rs/rapira/releases/download/v0.9.0/rapira-v0.9.0-SHA256SUMS.txt
sha256sum -c --ignore-missing rapira-v0.9.0-SHA256SUMS.txt
bash
curl -LO https://github.com/rapira-rs/rapira/releases/download/v0.9.0/rapira-v0.9.0-SHA256SUMS.txt
grep rapira-v0.9.0-php8.5-macos-aarch64.tar.gz rapira-v0.9.0-SHA256SUMS.txt | shasum -a 256 -c

Docker ​

The ghcr.io/rapira-rs/rapira container image contains the rapira binary and its libphp.so. The image uses FROM scratch and has no base system, shell, or entry point. It cannot run by itself. Copy its files into an application image:

dockerfile
FROM php:8.5-cli-trixie
COPY --from=ghcr.io/rapira-rs/rapira:php8.5 / /
RUN apt-get update \
    && xargs -r apt-get install -y --no-install-recommends < /usr/local/share/rapira/debian-packages.txt \
    && rm -rf /var/lib/apt/lists/*
COPY . /app
CMD ["rapira", "serve", "/app/rapira.toml"]

The application directory holds a rapira.toml:

toml
[http]
listen = ":8000"

[http.pool]
entrypoint = "/app/public/index.php"
mode = "classic"

The image contains /usr/local/bin/rapira, /usr/local/lib/libphp.so, and OPcache. For PHP 8.4, OPcache is a separate opcache.so with an ini file. For PHP 8.5, it is part of libphp.so.

The image also includes bcmath, intl, pdo_pgsql, pgsql, igbinary, and redis as shared modules with INI files that enable them. Redis supports igbinary serialization.

The /usr/local/share/rapira directory contains two more files. PHP_VERSION.txt contains the bundled PHP patch version. debian-packages.txt lists the runtime packages for libphp and its shared extensions. Install these packages in the application image, including when the base image contains PHP.

The image build uses libphp.so from php:8.4-cli-trixie or php:8.5-cli-trixie. It adds the six shared extensions listed above. Add other extensions in the application base image. On a PHP base image, docker-php-ext-install compiles against the same libphp.so.

Each tag identifies its PHP minor version. These tags support amd64 and arm64:

TagWhat it points at
X.Y.Z-php8.4, X.Y.Z-php8.5One release build. The tag never moves.
X.Y-php8.4, X.Y-php8.5The newest stable release with that X.Y version.
php8.4, php8.5The newest stable release.
nightly-php8.4, nightly-php8.5The newest nightly build.

The registry also contains architecture-specific tags such as X.Y.Z-php8.5-amd64 and X.Y.Z-php8.5-arm64.

There is no latest tag. Each Rapira build uses the headers of one PHP minor version. Rapira does not start with a libphp.so from another PHP minor version. Thus, every tag names the PHP minor version that it contains.

Why is the image built FROM scratch?

A scratch image contains only files that the build copies into it. Thus, COPY --from=ghcr.io/rapira-rs/rapira:php8.5 / / copies only Rapira files. You select the application base image.

What does a nightly tag point at?

Each successful CI run on main builds images from that commit. The build gets an immutable X.Y.Z-nightly.<short-sha>-php8.5 tag. X.Y.Z is the repository version. <short-sha> is the first seven characters of the commit identifier. The nightly-php8.5 tag points to that build. The registry keeps the ten newest nightly builds.

The libphp build ​

Linux and macOS release packages and tarballs use libphp built with --disable-all and this fixed set of extensions:

  • Runtime basics: session, filter, mbstring, iconv, ctype, tokenizer, fileinfo, phar, posix.
  • OPcache and PCRE with JIT enabled. On PHP 8.4, OPcache is a separate opcache.so file. See php.ini.
  • Networking and compression: openssl, curl, zlib, sockets, ftp.
  • XML: libxml, dom, xml, simplexml, xmlreader, xmlwriter.
  • Databases: PDO with pdo_sqlite and pdo_pgsql, plus sqlite3 and pgsql.
  • Decimal arithmetic and internationalization: bcmath and intl.
  • Serialization and caching: igbinary and redis, with igbinary serialization enabled for Redis.
  • Shared memory and System V IPC: shmop, sysvmsg, sysvsem, sysvshm.
  • Dates, image metadata and translations: calendar, exif, gettext.
  • Foreign function interface: ffi.
  • Required PHP components: Core, standard, SPL, date, json, hash, random, Reflection.

For other extensions, such as pdo_mysql, APCu, or Imagick, build libphp with the required options. Then compile Rapira against that library. See Build from source.

Each artifact uses the latest available patch release in its PHP 8.4 or PHP 8.5 series. In a tarball, share/php/PHP_VERSION.txt contains the exact version. On a running server, PHP_VERSION and phpinfo() report it. When [observability.metrics] is set, the php_version label of the rapira_build_info metric also reports it. See Metrics and health checks. rapira --version shows only the Rapira version.

Why does PHP_SAPI return fastcgi on PHP 8.4?

On PHP 8.4, OPcache starts only for a fixed list of SAPI names. Rapira registers the SAPI as fastcgi to enable OPcache. PHP 8.5 removed this list, so PHP_SAPI and php_sapi_name() return rapira. The Server API line in phpinfo() shows Rapira for both versions. Code that checks PHP_SAPI must accept both values.

php.ini ​

Linux and macOS packages and tarballs do not contain php.ini, and Rapira does not create one. Without this file, PHP uses its built-in defaults. Rapira changes two of them: it sets display_errors=0 and log_errors=1. A value in php.ini overrides these two settings. See Logging. Set PHPRC to a file or search directory:

bash
PHPRC=/etc/rapira/php.ini rapira serve /etc/rapira/rapira.toml

On PHP 8.4, OPcache is a separate opcache.so file in lib/rapira. PHP does not load this file automatically. Add its absolute path to php.ini:

ini
; deb or RPM package
zend_extension=/usr/lib/rapira/opcache.so
; tarball in /opt/rapira
;zend_extension=/opt/rapira/lib/rapira/opcache.so

On PHP 8.5, OPcache is part of libphp. This line is not necessary.

Where does PHP look for php.ini on its own?

PHP first checks PHPRC. Then it checks the default path set during the PHP build. That build path usually does not exist on the target system. Rapira does not read php.ini from the current directory.

Why is the file called php.ini and not php-rapira.ini?

PHP first checks php-<sapi-name>.ini and then php.ini. The SAPI name is fastcgi on 8.4 and rapira on 8.5. A plain php.ini supports both versions.

Distribution ​

GitHub Releases contains tarballs, packages, and checksum files. ghcr.io/rapira-rs/rapira contains container images. No apt or yum repository is available yet. To update a package, download and install the new version. The package manager replaces the installed version.

To update a tarball, extract the new directory next to the old directory. Then change the symbolic link. Keep the previous directory if you must restore it.

Each successful CI run on main uploads tarballs and a checksum file to the nightly prerelease on GitHub Releases. Release commits skip this upload. The prerelease does not contain .deb or .rpm packages. A nightly build is not a release. For nightly container tags, see Docker. The download page contains a link to the nightly builds.

The macOS build supports Apple Silicon and macOS 14 or newer. It uses an ad hoc signature without a Developer ID or notarization. macOS can request confirmation before the first run. There is no Intel build.

Windows ​

rapira-rs/rapira-windows provides Windows builds for local development. Use Linux or macOS for production. The latest stable Windows release is v0.8.0. Follow its release README for its configuration and extension set.

The x64 build supports Windows 10, Windows 11, and Windows Server. The ARM64 build supports Windows 11. Install the Microsoft Visual C++ Redistributable for the selected architecture. Extract the complete ZIP into one directory. Keep rapira.exe, the matching ZTS PHP runtime, extension DLLs, and php.ini together.

Windows v0.8.0 serves HTTP only. Its configuration uses a top-level [pool] table. Run it from the extracted directory:

powershell
.\rapira.exe serve --config C:\app\rapira.toml

This release does not support the v0.9 quickstart configuration or gRPC. Its PHP profile excludes OpenSSL, cURL, SQLite, XML, and iconv. Each Windows release has one rapira-v<VERSION>-windows-<x86_64|arm64>-SHA256SUMS.txt file for each architecture.

The current Windows source implements the v0.9 plugin configuration and gRPC. It uses rapira serve CONFIG and a separate interpreter thread pool for each plugin. It rejects [observability], grpc.interceptors, and [grpc.auth]. These source features are not in the stable v0.8.0 download.

Quickstart explains how to serve the first request after you install the binary.