Install PHP 8.5 from Remi on RHEL, AlmaLinux, or Rocky Linux
Enable EPEL, CRB or CodeReady Builder, and the official Remi repository; switch the system PHP module to 8.5; install FPM and verify the exact runtime.
Obtain a maintained PHP 8.5 system runtime when the base Enterprise Linux repositories provide an older branch, without mixing arbitrary RPM sources.
- RHEL 8, 9, 10
- AlmaLinux / Rocky Linux 8, 9, 10
- PHP 8.5
- Supported host and recovery access Use a supported distribution, keep an independent root-capable session, and record the current package repositories before changing the PHP runtime.
cat /etc/os-release && uname -m - Application compatibility Confirm the application, framework, extensions, and deployment tooling explicitly support the target PHP branch.
- Configuration backup Archive the active PHP, web-server, and application configuration before packages, pools, or handlers change.
OneLiners never runs these steps or stores secrets. Review placeholders, versions, current state, and change-control requirements before using a command.
Full guide
What you will build
- A PHP 8.5 system runtime on a supported RHEL, AlmaLinux, or Rocky Linux 8–10 host using Fedora EPEL, the distribution's CodeReady Builder/CRB repository, and the official Remi release package and module stream.
- A reviewed package transaction that moves the system PHP family together, installs only an explicit baseline of CLI, FPM, OPcache and application-required extensions, and preserves a configuration/package inventory for rollback.
- An enabled but not yet publicly connected `php-fpm` service with exact version, configuration-file, syntax, service, extension and package-repository provenance evidence.
- The platform gate reports a supported distribution major and x86_64/aarch64 architecture; EPEL, CodeReady Builder/CRB and Remi repositories are enabled through their official packages or tools.
- `php -v` reports 8.5.x, `php-fpm -t` succeeds, the systemd service is active, required modules are visible, and DNF identifies the installed PHP packages as coming from the intended Remi stream.
- The application compatibility decision, pre-change configuration/archive/package list, transaction review, rollback stream, handler cutover and post-install security work are documented rather than hidden inside a blind package install.
Architecture
How the parts fit together
Enterprise Linux supplies BaseOS/AppStream and a builder repository. Fedora EPEL and Remi add dependencies and the PHP 8.5 packages. Installing `remi-release-<major>.rpm` adds signed repository definitions; selecting `php:remi-8.5/common` tells DNF modular dependency solving to treat Remi's PHP family as the active system stream. Unprefixed packages such as `php-cli` and `php-fpm` then replace or upgrade the system PHP branch together. The CLI reads `/etc/php.ini` plus `/etc/php.d`, while `php-fpm` runs as a separate systemd service and pool configuration. This guide stops before Apache/nginx traffic is connected because handler selection, pool identity, application configuration and deployment verification are separate production boundaries.
- The operator proves distribution, major version and architecture before constructing any repository URL.
- Current PHP packages, stream, extensions, repositories and configuration are archived as rollback evidence.
- Official EPEL plus builder repositories satisfy dependencies; the official Remi release package adds Remi metadata and signing configuration.
- DNF previews and then switches the PHP family to `remi-8.5`, resolving a coherent transaction instead of mixing individual RPM files.
- The required runtime/extension baseline is installed, FPM is validated and started, and version/configuration/repository evidence is captured before any web handler changes.
Assumptions
- The host is RHEL, AlmaLinux, or Rocky Linux major 8, 9, or 10 on x86_64/aarch64, has working trusted DNS/TLS/time, and its lifecycle and support policy permit EPEL plus Remi packages.
- RHEL is registered with a valid entitlement when `subscription-manager` is required. Clone hosts provide the EPEL `crb` helper or an equivalent documented CRB repository.
- Application owners have confirmed PHP 8.5 support for the framework, Composer dependencies, extensions, encoders/agents and deployment tooling using a clone or staging environment.
- An independent root-capable session, maintenance window, host/application backup and tested rollback are available. This is a system-stream replacement, not a side-by-side installation.
- The web server is not automatically pointed at the new FPM service by this guide; pool identity, socket permissions, handler scope and real application acceptance are completed separately.
Key concepts
- system stream
- A selected modular package family whose unprefixed names replace the distribution PHP branch system-wide; it affects CLI, FPM and extension dependencies together.
- Remi SCL
- A separate prefixed package layout such as `php85-php-*` under `/opt/remi`; use the parallel-install guide when the system PHP must remain unchanged.
- EPEL
- Fedora's Extra Packages for Enterprise Linux repository, used here only through its official release package for the detected major version.
- CodeReady Builder / CRB
- A repository with additional build/runtime dependencies. RHEL calls it CodeReady Builder; compatible distributions commonly expose CRB.
- module switch-to
- A DNF operation that changes an enabled module stream and synchronizes installed packages with the target stream rather than enabling a name only.
- package provenance
- Evidence of which repository supplied an installed NEVRA package, checked with DNF rather than inferred from a binary version string.
- PHP-FPM
- A long-running FastCGI process manager used by web servers; installing and starting it does not safely configure a site handler by itself.
Security and production boundaries
- Adding EPEL and Remi expands the software supply chain. Use only HTTPS official release packages, retain RPM signature checking, inspect repository files/keys, and never disable `gpgcheck` to bypass a failure.
- PHP 8.5 compatibility must include native extensions, monitoring/security agents and Composer dependencies. An extension missing from the target repository is a stop condition, not a reason to download an arbitrary RPM.
- Do not expose a `phpinfo()` page or point all virtual hosts at the new default FPM pool. Build a dedicated pool/handler and a minimal authenticated health check, then remove test scripts.
- A successful CLI version does not prove FPM configuration, web-handler isolation, SELinux access, socket permissions, application migrations, or rollback safety.
- Third-party repository packages may change the vendor support boundary for the host. Record the decision and lifecycle owner before production installation.
Stop before continuing if
- Stop if the distribution/major/architecture is unsupported, RHEL is unregistered, repository TLS/signature checks fail, official repository IDs cannot be identified, or the host has mixed/conflicting RPM sources.
- Do not switch streams until application/extension compatibility, transaction preview, configuration backup, package inventory, maintenance ownership and rollback stream are documented.
- Stop if DNF proposes removing unrelated applications, critical extensions have no PHP 8.5 build, dependency resolution requires disabling GPG checks, or available disk/inode capacity is insufficient.
- Do not connect production traffic until FPM syntax/service, dedicated pool/handler, SELinux/socket permissions, application health, logs and rollback are verified.
instruction
Identify the exact Enterprise Linux release
Choose repository URLs and the builder repository for the detected major version; stop unless the host is RHEL, AlmaLinux, or Rocky Linux 8–10 on an architecture published by Remi.
Why this step matters
Repository URLs and dependency repositories are major-version and architecture specific, so a hard platform gate prevents a plausible-looking command from installing the wrong release package.
What to understand
Source `/etc/os-release`, derive the numeric major without trusting free-form display text, and print architecture explicitly.
The case statement accepts only RHEL, AlmaLinux and Rocky Linux 8–10 on Remi-published x86_64/aarch64. It exits before any network or package mutation on other systems.
Cloud images and compatible derivatives can differ in repository management; they need their own reviewed guide rather than weakening this guard.
System changes
- No persistent change; reads operating-system identity and machine architecture and exits nonzero for unsupported combinations.
Syntax explained
. /etc/os-release- Loads distribution-maintained identity variables into the current shell.
${VERSION_ID%%.*}- Removes the first dot and everything after it to derive the major release.
uname -m- Reports kernel machine architecture used to select published packages.
case ... exit 1- Fails closed when the exact distribution-major-architecture tuple is outside scope.
. /etc/os-release; EL_MAJOR="${VERSION_ID%%.*}"; ARCH="$(uname -m)"; printf 'id=%s major=%s version=%s arch=%s\n' "$ID" "$EL_MAJOR" "$VERSION_ID" "$ARCH"; case "$ID:$EL_MAJOR:$ARCH" in rhel:[89]:x86_64|rhel:10:x86_64|rhel:[89]:aarch64|rhel:10:aarch64|almalinux:[89]:x86_64|almalinux:10:x86_64|almalinux:[89]:aarch64|almalinux:10:aarch64|rocky:[89]:x86_64|rocky:10:x86_64|rocky:[89]:aarch64|rocky:10:aarch64) ;; *) printf 'Unsupported platform for this guide\n' >&2; exit 1;; esacid=almalinux major=10 version=10.0 arch=x86_64
Checkpoint: Checkpoint: inspect platform
Continue whenThe output shows one supported ID, major 8–10, full version, and x86_64 or aarch64; unsupported hosts stop before repository work.
Stop whenID, major or architecture is unexpected, the host is an in-place-upgrade hybrid, or lifecycle/support ownership is unclear.
If this step fails
A seemingly compatible Enterprise Linux derivative is rejected.
Likely causeThis guide deliberately supports only tested IDs and repository-management paths.
cat /etc/os-releaserpm -E %rheluname -m
ResolutionUse that distribution's official instructions and a separately validated procedure; do not edit the guard blindly.
Security notes
- Failing closed prevents an attacker-controlled or mistaken URL/version substitution from changing the host supply chain.
Alternatives
- Use Remi's official configuration wizard manually for another explicitly supported distribution and record a separate reviewed runbook.
Stop conditions
- ID, major or architecture is unexpected, the host is an in-place-upgrade hybrid, or lifecycle/support ownership is unclear.
instruction
Inventory the current PHP runtime and repositories
Capture the current package, module stream, extensions, and enabled repositories so rollback does not depend on memory.
Why this step matters
The installed binary, module selection, package set and enabled repositories are all needed to assess blast radius and construct a rollback; `php -v` alone omits most of that state.
What to understand
A missing `php` binary is acceptable and printed as such, but the module/repository inventory must still succeed.
Record installed `php*` NEVRAs and provenance separately before the mutation even though the quick command displays the human-oriented stream/repository state.
Identify web handlers and services before installation so starting a new FPM unit cannot accidentally compete for a socket.
System changes
- No persistent change; reads current PHP version, module streams, enabled repositories, packages and service context.
Syntax explained
php -v 2>/dev/null || true- Records a current CLI when present without failing a clean host.
dnf module list php- Displays available, enabled and installed PHP module streams.
dnf repolist --enabled- Lists repositories currently allowed to satisfy transactions.
php -v 2>/dev/null || true; sudo dnf module list php; sudo dnf repolist --enabledThe installed branch, active stream, and repository IDs are recorded.
Checkpoint: Checkpoint: inventory runtime
Continue whenThe current branch/absence, selected stream, installed package family, handlers and all enabled repository IDs are saved as pre-change evidence.
Stop whenPackages come from unknown/mixed repositories, DNF reports damage, current handler/socket ownership is unknown, or rollback stream cannot be identified.
If this step fails
DNF shows modular filtering or duplicate PHP packages from several repositories.
Likely causeA prior third-party repository, manual RPM or incomplete stream change already mixed the runtime.
sudo dnf checkdnf repoquery --installed --qf '%{name} %{evr} %{repoid}' 'php*' | sort
ResolutionRepair and document the existing package state before introducing Remi; do not stack another repository over unresolved damage.
Security notes
- Repository inventory is supply-chain evidence; store it with the change record and flag any disabled signature checking.
Alternatives
- Collect the same NEVRA, stream, repo, service, socket and config evidence through signed configuration-management inventory.
Stop conditions
- Packages come from unknown/mixed repositories, DNF reports damage, current handler/socket ownership is unknown, or rollback stream cannot be identified.
instruction
Back up PHP and web-server configuration
Preserve configuration and package inventory before changing the system module stream.
Why this step matters
Module switching can replace default configuration and make old directives incompatible, so both files and exact package inventory are required for a controlled return to the prior runtime.
What to understand
Archive only existing PHP/web-server configuration paths, inspect the archive, store its checksum, and protect it root-only. A suppressed missing-path warning is not proof of a good backup.
The RPM list records extensions whose names may not be obvious from application configuration. Add application releases, database state and secrets through their established backup system.
Test restore on a clone or snapshot. A tarball on the same failing disk is rollback convenience, not a disaster-recovery backup.
System changes
- Creates a timestamped root-only configuration archive and `/root/php-packages-before.txt`; it does not change installed packages or running services.
Syntax explained
tar -C / -czf- Creates a compressed archive with filesystem-root-relative paths.
2>/dev/null || true- Allows optional absent web-server paths but requires the operator to inspect the resulting archive explicitly.
rpm -qa 'php*' | sort- Records the complete installed PHP package-name/version set.
tee /root/php-packages-before.txt- Stores deterministic rollback inventory under root control.
sudo tar -C / -czf /root/php-before-remi-$(date +%F-%H%M).tgz etc/php.ini etc/php.d etc/php-fpm.d etc/httpd etc/nginx 2>/dev/null || true; rpm -qa 'php*' | sort | sudo tee /root/php-packages-before.txt/root/php-before-remi-2026-07-25-1200.tgz
Checkpoint: Checkpoint: backup config
Continue whenA non-empty protected archive lists all existing relevant configuration, its checksum is retained, and the package inventory has the exact prior extension set.
Stop whenArchive is missing/empty, required configuration is absent from it, application/database backup is untested, or no independent recovery session exists.
If this step fails
The archive command prints a filename but required configuration is missing.
Likely causeOptional-path suppression hid absent directories, configuration lives elsewhere, or the current runtime is a parallel/custom build.
php --inisudo tar -tvzf /root/php-before-remi-*.tgz | lessrpm -ql php-common | grep /etc
ResolutionDiscover the real configuration paths, rebuild and verify the archive, and document the runtime layout before package changes.
Security notes
- Configuration archives may contain database credentials, TLS keys or environment values; store mode 0600 and never attach them unredacted.
Alternatives
- Use an application-consistent VM snapshot plus versioned configuration/package manifests when its restore has been rehearsed and retention is protected.
Stop conditions
- Archive is missing/empty, required configuration is absent from it, application/database backup is untested, or no independent recovery session exists.
command
Enable EPEL and the distribution builder repository
Install the Fedora EPEL release package for the detected major version, then enable CodeReady Builder on registered RHEL or use the CRB helper on compatible clones because Remi dependencies may come from it.
Why this step matters
Remi packages rely on dependencies outside the minimal base; configuring official EPEL and the distribution's builder repository first makes the dependency graph explicit and reviewable.
What to understand
The EPEL release URL is constructed only after the platform gate and points to Fedora infrastructure for the exact EL major.
Registered RHEL uses `subscription-manager` and an architecture-specific CodeReady Builder ID. AlmaLinux/Rocky follow Remi's current `crb install` helper path.
List enabled repository IDs after mutation. Repository availability is not permission to install arbitrary packages from them.
System changes
- Installs the EPEL repository-release package and enables CodeReady Builder/CRB, changing DNF repository configuration and trusted package sources.
Syntax explained
epel-release-latest-${EL_MAJOR}.noarch.rpm- Selects Fedora's EPEL repository definition for the detected major independent of CPU architecture.
subscription-manager repos --enable- Enables entitled CodeReady Builder content on RHEL.
crb install- Uses the current Remi-documented helper path to configure CRB on supported compatible distributions.
dnf repolist --enabled- Provides concrete post-change repository evidence.
. /etc/os-release; EL_MAJOR="${VERSION_ID%%.*}"; sudo dnf install -y "https://dl.fedoraproject.org/pub/epel/epel-release-latest-${EL_MAJOR}.noarch.rpm"; if [ "$ID" = rhel ]; then sudo subscription-manager repos --enable "codeready-builder-for-rhel-${EL_MAJOR}-$(arch)-rpms"; else sudo crb install; fi; sudo dnf repolist --enabled | grep -Ei 'epel|codeready|crb'codeready-builder-for-rhel-10-x86_64-rpms epel
Checkpoint: Checkpoint: enable prerepositories
Continue whenOfficial EPEL and the matching CodeReady Builder/CRB repository IDs are enabled alongside the expected base repositories.
Stop whenTLS/signature verification fails, RHEL entitlement is absent, helper/repository ID is unknown, or enabling the repository would violate support policy.
If this step fails
CodeReady Builder/CRB cannot be enabled.
Likely causeRHEL is unregistered, architecture/major ID is wrong, EPEL helper is unavailable, or the clone names its repository differently.
subscription-manager status 2>/dev/null || truesudo dnf repolist all | grep -Ei 'codeready|crb'rpm -q epel-release
ResolutionUse the official distribution repository-management path for the detected host and confirm the exact enabled ID; do not substitute an unrelated mirror.
Security notes
- Never use `--nogpgcheck`, HTTP mirrors, copied `.repo` files, or a broad third-party bootstrap script to bypass a repository failure.
Alternatives
- Use the distribution-supported PHP stream or a pre-approved internally mirrored/signed repository when external EPEL/Remi access is prohibited.
Stop conditions
- TLS/signature verification fails, RHEL entitlement is absent, helper/repository ID is unknown, or enabling the repository would violate support policy.
command
Install the Remi release package for the detected major version
Use the official rpms.remirepo.net release package and inspect repository state immediately afterward.
Why this step matters
The official Remi release RPM adds repository definitions and signing material for one EL major; installing it as a package makes the supply-chain change visible, versioned and removable.
What to understand
`rpm -E %rhel` is evaluated by the RPM stack after the OS gate and determines the release-package URL. Inspect the downloaded package signature/repository files where policy requires approval.
Listing all `remi` IDs shows safe, modular and versioned channels, but does not prove the desired stream is selected.
Keep default GPG verification. If metadata or signatures fail, repair trust/time/proxy rather than weakening verification.
System changes
- Installs `remi-release-<major>` and adds `/etc/yum.repos.d/remi*.repo` plus trusted signing configuration; it does not yet switch PHP.
Syntax explained
rpm -E %rhel- Uses the RPM macro for the Enterprise Linux major.
https://rpms.remirepo.net/enterprise/- Uses Remi's official repository host.
dnf repolist all- Displays enabled and disabled Remi repository definitions after installation.
EL_MAJOR="$(rpm -E %rhel)"; sudo dnf install -y "https://rpms.remirepo.net/enterprise/remi-release-${EL_MAJOR}.rpm"; sudo dnf repolist all | grep -E '^remi'remi-safe and versioned Remi repositories are listed.
Checkpoint: Checkpoint: install remi
Continue whenThe installed release package matches the host major, signature verification succeeds, and expected Remi repository IDs are visible without unknown duplicates.
Stop whenThe URL redirects outside approved infrastructure, signature validation fails, release major differs, repository files disable GPG checks, or conflicting Remi definitions already exist.
If this step fails
The Remi release RPM conflicts with an existing repository package.
Likely causeA previous/manual Remi configuration or another vendor package owns the same paths.
rpm -q remi-releaserpm -V remi-releasesudo grep -R -nE '^(\[remi|gpgcheck|baseurl|mirrorlist)' /etc/yum.repos.d
ResolutionReconcile the existing official package/configuration and verify ownership; do not force-overwrite repository files.
Security notes
- A repository release package changes future software trust and update behavior; treat its files, keys and lifecycle as production configuration.
Alternatives
- Use a security-reviewed internal mirror that preserves Remi signatures, metadata and update cadence.
Stop conditions
- The URL redirects outside approved infrastructure, signature validation fails, release major differs, repository files disable GPG checks, or conflicting Remi definitions already exist.
command
Switch the system PHP module to Remi 8.5
Use DNF module switching so dependencies move together; review the transaction before accepting it on production.
Why this step matters
The system runtime must move as a coherent package family. `switch-to` synchronizes installed PHP packages with the selected 8.5 stream instead of mixing individual versions and ABIs.
What to understand
First run the same command with `--assumeno` and capture removals, upgrades, downgrades, repository sources, download size and extension compatibility.
The quick path's `-y` is appropriate only after that review and an approved maintenance window. Open sessions/processes keep old code until restarted.
A missing extension or unrelated removal is a hard stop. The parallel SCL guide is safer when one application alone needs PHP 8.5.
System changes
- Changes the enabled PHP module stream and synchronizes installed unprefixed PHP packages with `php:remi-8.5/common`.
Syntax explained
dnf module switch-to- Selects the target stream and performs a package synchronization transaction.
php:remi-8.5/common- Names Remi's PHP 8.5 stream and common profile.
--assumeno- Safer preview that resolves and prints the transaction without accepting it.
-y- Accepts the reviewed transaction non-interactively; never use it before preview.
sudo dnf module switch-to -y php:remi-8.5/commonThe transaction selects the php:remi-8.5 stream.
Checkpoint: Checkpoint: switch stream
Continue whenOnly the reviewed PHP family and required dependencies change, no critical extension/unrelated package is removed, and the enabled stream becomes remi-8.5.
Stop whenPreview removes unrelated software, a required extension lacks a build, transaction source is unexpected, downgrade/conflict is unexplained, or rollback stream/package set is unavailable.
If this step fails
DNF reports conflicts or proposes erasing an extension.
Likely causeThe extension is incompatible with PHP 8.5, repository metadata is incomplete, or another repository pins an ABI.
sudo dnf module switch-to php:remi-8.5/common --assumenodnf repoquery --installed --qf '%{name} %{evr} %{repoid}' 'php*' | sort
ResolutionCancel, keep the prior stream, and resolve compatibility in staging or choose a parallel runtime; never use `--allowerasing` blindly.
Security notes
- Do not weaken dependency or signature checks to force a language-runtime upgrade; inconsistent native modules can crash or expose applications.
Alternatives
- Install prefixed php85 SCL packages or deploy a pinned container while the system stream remains unchanged.
Stop conditions
- Preview removes unrelated software, a required extension lacks a build, transaction source is unexpected, downgrade/conflict is unexplained, or rollback stream/package set is unavailable.
command
Install the runtime, FPM, and common production extensions
Install only extensions required by the application; this baseline covers database, XML, internationalization, ZIP, and process control.
Why this step matters
An explicit extension allowlist keeps the attack surface and future patch obligations visible; copying a generic mega-list often installs unused interpreters and native code.
What to understand
The baseline includes CLI, FPM, OPcache, database drivers, XML, multibyte, internationalization, ZIP and process functions. Remove packages the application does not require.
Use Composer platform requirements and staging traces to identify additional extensions. Match the FPM and CLI branches and inspect repository provenance.
Installing packages does not securely configure php.ini, pool identity, upload limits, sessions, error display, socket access, SELinux or the web handler.
System changes
- Installs or upgrades the selected PHP CLI/FPM/OPcache and explicit extension RPMs from the active stream.
Syntax explained
php / php-cli- Provides common configuration and the command-line interface.
php-fpm- Provides the system FastCGI process manager service.
php-opcache- Provides shared bytecode caching that still requires production sizing/invalidation policy.
php-mysqlnd / php-pgsql- Provides database-specific native drivers; install only those used.
php-xml/mbstring/intl/zip/process- Adds common application capabilities and corresponding patch surface.
sudo dnf install -y php php-cli php-fpm php-opcache php-mysqlnd php-pgsql php-xml php-mbstring php-intl php-zip php-processPHP 8.5 packages are installed from a Remi repository.
Checkpoint: Checkpoint: install runtime
Continue whenThe reviewed package set installs from the intended stream, every required extension is present, unused packages are excluded, and DNF completes without unresolved transactions.
Stop whenAny package comes from an unexpected repository, critical extension is absent, disk/inodes are low, transaction scripts fail, or production traffic still depends on untested old processes.
If this step fails
The application reports a missing extension after installation.
Likely causeIts package was not identified, config scans a different directory, or no compatible Remi build exists.
php --iniphp -m | sortdnf search 'php-*'
ResolutionMap the exact extension to an official compatible package and test it in staging; do not install an arbitrary binary or assume CLI and FPM load the same configuration.
Security notes
- Every native extension executes in the application process; minimize the set and keep its Remi/PHP lifecycle monitored.
Alternatives
- Start with the smallest CLI/FPM baseline and add one evidence-backed extension at a time during staging acceptance.
Stop conditions
- Any package comes from an unexpected repository, critical extension is absent, disk/inodes are low, transaction scripts fail, or production traffic still depends on untested old processes.
verification
Start FPM and prove package provenance
Enable FPM, verify syntax, exact version, loaded configuration, and RPM vendor before connecting a web server.
Why this step matters
Starting the service only after FPM syntax, version and provenance checks prevents an unverified runtime from silently becoming a web handler; package success is not an end-to-end acceptance test.
What to understand
`php -v` and `php --ini` prove the CLI branch and scanned files. `php-fpm -t` validates FPM's own configuration, which can differ.
`dnf info --installed` supplies the `From repo` field that `rpm -qi` does not. Record the exact NEVRA and stream as change evidence.
Enable/start FPM without changing Apache/nginx. Inspect the socket/listener, pool identity and SELinux context before a canary handler references it.
System changes
- Enables and starts `php-fpm` at boot, creates its runtime socket/log state, and records version/configuration/package provenance evidence.
Syntax explained
systemctl enable --now- Starts the unit immediately and creates the boot-time enablement link.
php --ini- Lists the loaded CLI configuration and scanned fragment directory.
php-fpm -t- Tests FPM configuration syntax without serving application traffic.
dnf info --installed- Reports installed package metadata including `From repo` provenance.
sudo systemctl enable --now php-fpm; php -v; php --ini; sudo php-fpm -t; dnf info --installed php php-fpm | grep -E '^(Name|Version|Release|From repo)'PHP 8.5.x is reported, FPM configuration is successful, and From repo identifies remi-modular.
Checkpoint: Checkpoint: start and prove
Continue whenCLI reports PHP 8.5.x, FPM syntax succeeds and service is active, configuration paths are intentional, and PHP/FPM packages report the Remi repository.
Stop whenFPM syntax/start fails, version branches differ, config paths are unexpected, package source is not Remi, socket conflicts, or an existing web handler is changed implicitly.
If this step fails
php-fpm fails while php -v succeeds.
Likely causeFPM reads a different/old pool directive, an extension fails in service context, socket/user paths conflict, or SELinux denies access.
sudo php-fpm -ttsystemctl status php-fpm --no-pagersudo journalctl -u php-fpm --since '-15 min' --no-pager -n 150sudo ss -lxnp | grep php
ResolutionLeave web traffic on the prior handler, correct the exact configuration or policy failure, rerun syntax, and start only when evidence is clean.
Security notes
- Do not publish phpinfo or use the default broad pool as proof. Connect a dedicated least-privilege pool through one reviewed canary site.
Alternatives
- Keep FPM disabled after package verification and configure/test the dedicated pool offline before the first service start.
Stop conditions
- FPM syntax/start fails, version branches differ, config paths are unexpected, package source is not Remi, socket conflicts, or an existing web handler is changed implicitly.
Finish line
Verification checklist
php -r 'printf("%s %d-bit\n", PHP_VERSION, PHP_INT_SIZE * 8);' && systemctl is-active php-fpmPHP reports 8.5.x with the expected word size and php-fpm is active.dnf repoquery --installed --qf '%{name} %{evr} %{repoid}' 'php*' | sort; php -m | sortPHP packages resolve to the intended Remi stream and required extensions are present.Recovery guidance
Common problems and safe checks
EPEL or Remi release-package installation fails signature or TLS verification.
Likely causeSystem time/CA trust is wrong, a proxy intercepts TLS, URL/major is incorrect, cached metadata is corrupt, or the package is not from the official host.
timedatectl statuscurl -I https://rpms.remirepo.net/enterprise/remi-release-10.rpmrpm -q epel-release remi-releasesudo dnf clean expire-cache
ResolutionCorrect time, trust path, proxy and detected major; use only official release URLs and valid signatures. Never add `--nogpgcheck` as a repair.
DNF cannot resolve `php:remi-8.5` or reports modular filtering conflicts.
Likely causeRequired repositories are disabled, metadata is stale, another stream/repository pins packages, or EL/DNF generation differs from the expected path.
sudo dnf repolist --enabledsudo dnf module list phpsudo dnf repoquery --installed --qf '%{name} %{evr} %{repoid}' 'php*' | sortsudo dnf check
ResolutionRestore complete official BaseOS/AppStream, builder, EPEL and Remi metadata, remove only documented conflicting repository policy, preview the switch again, and stop if it remains incoherent.
The stream transaction wants to remove a required PHP extension or application package.
Likely causeThat extension has no PHP 8.5-compatible build, a third-party package constrains the old ABI, or the application depends on an obsolete component.
rpm -qa 'php*' | sortsudo dnf repoquery --whatrequires php-commonsudo dnf module switch-to php:remi-8.5/common --assumeno
ResolutionKeep the current runtime or move the application to a tested parallel/container environment until every required extension has a trusted compatible build.
PHP CLI reports 8.5 but php-fpm fails its configuration test or start.
Likely causeAn old directive or extension is incompatible, multiple pool names/sockets conflict, the service reads different configuration, or SELinux/filesystem permissions block paths.
sudo php-fpm -ttphp --inisystemctl status php-fpm --no-pagersudo journalctl -u php-fpm --since '-15 min' --no-pager -n 150sudo ss -lxnp | grep php
ResolutionUse the exact failing file/line from `-tt` or the journal, restore/port that configuration in staging, revalidate, and leave the web handler on the prior runtime until FPM is healthy.
Reference
Frequently asked questions
Why not download individual PHP RPM files?
The runtime, FPM and extensions share an ABI and dependencies. A repository plus coherent stream lets DNF resolve and update the package family together.
Does this preserve the old system PHP?
No. Unprefixed Remi packages replace/switch the system stream. Use the separate prefixed `php85` SCL guide for side-by-side operation.
Can I skip EPEL or CRB if installation appears to work?
Do not design around an accidental cache or partial dependency set. Configure the official prerequisites documented by Remi for the detected Enterprise Linux release.
Why stop before configuring nginx or Apache?
Package installation and request routing are separate risk boundaries. A site-specific FPM pool and handler require their own ownership, socket, SELinux, rollback and application tests.
Recovery
Rollback
Restore the previous DNF module stream and configuration during a controlled maintenance window.
- Stop php-fpm and restore the archived PHP and web-server configuration.
- Use dnf module switch-to with the recorded previous stream, then distro-sync the PHP packages.
- Reinstall the exact recorded extension set and validate the older runtime before restoring traffic.
- Do not remove repository packages until dependency resolution and application rollback are proven.
Evidence