<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: KE DUNG BUI</title>
    <description>The latest articles on DEV Community by KE DUNG BUI (@ke_dungbui_71ef44811958b).</description>
    <link>https://dev.to/ke_dungbui_71ef44811958b</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3243263%2Fffdd34b8-5fff-4ea4-8b58-0797be13ff5e.jpg</url>
      <title>DEV Community: KE DUNG BUI</title>
      <link>https://dev.to/ke_dungbui_71ef44811958b</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ke_dungbui_71ef44811958b"/>
    <language>en</language>
    <item>
      <title>How a “dnf update” Broke My PHP Environment (AlmaLinux 9 + Remi) and How I’m Fixing It</title>
      <dc:creator>KE DUNG BUI</dc:creator>
      <pubDate>Thu, 21 Aug 2025 08:57:24 +0000</pubDate>
      <link>https://dev.to/ke_dungbui_71ef44811958b/how-a-dnf-update-broke-my-php-environment-almalinux-9-remi-and-how-im-fixing-it-34k5</link>
      <guid>https://dev.to/ke_dungbui_71ef44811958b/how-a-dnf-update-broke-my-php-environment-almalinux-9-remi-and-how-im-fixing-it-34k5</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;Hi everyone!&lt;br&gt;&lt;br&gt;
I recently ran into a critical issue while managing a staging environment on &lt;strong&gt;AlmaLinux 9&lt;/strong&gt;, running PHP via the &lt;strong&gt;Remi repository&lt;/strong&gt; and &lt;strong&gt;served by Apache&lt;/strong&gt;. After a routine &lt;code&gt;dnf update&lt;/code&gt;, all my CLI-based PHP scripts broke. Miraculously, my web server didn’t go down, but this experience taught me some important lessons about package management in RedHat-based systems.&lt;/p&gt;

&lt;p&gt;Here’s the story of what happened, why it happened, and my ongoing steps to recovery.&lt;/p&gt;


&lt;h3&gt;
  
  
  Background
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OS:&lt;/strong&gt; AlmaLinux 9 (RHEL-compatible)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web server:&lt;/strong&gt; Apache&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PHP:&lt;/strong&gt; Installed from the Remi repository – not AlmaLinux’s built-in version&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usage:&lt;/strong&gt; Both web (served by Apache) and CLI batch jobs use PHP extensively&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  The Incident
&lt;/h3&gt;

&lt;p&gt;All my PHP-based batch jobs suddenly failed with cryptic errors such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Call to undefined function pg_connect()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Class PDO not found&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The lucky part:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;The web server (Apache) kept running and serving PHP just fine.&lt;/strong&gt; If Apache had been restarted, it likely would’ve been affected too, but I dodged that bullet—for now.&lt;/p&gt;


&lt;h3&gt;
  
  
  Initial Troubleshooting
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Check the PHP CLI&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php &lt;span class="nt"&gt;--version&lt;/span&gt;
php &lt;span class="nt"&gt;-m&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;pgsql
php &lt;span class="nt"&gt;-i&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;PDO
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Result:&lt;/em&gt;&lt;br&gt;&lt;br&gt;
CLI PHP was missing all key extensions I rely on, including &lt;code&gt;pdo&lt;/code&gt; and &lt;code&gt;pgsql&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Check which PHP binary is active&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It turned out that &lt;code&gt;/usr/bin/php&lt;/code&gt; was now the default AlmaLinux PHP, installed from the official repository—with hardly any extensions.&lt;/p&gt;

&lt;p&gt;But &lt;code&gt;/opt/remi/php81/root/bin/php&lt;/code&gt; (Remi’s version) was still present and contained all the required extensions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Double-check recent changes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Reviewing automation and update logs, I discovered:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ansible had executed a &lt;code&gt;dnf update&lt;/code&gt; (full system upgrade).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means all system packages—including PHP—got upgraded, with AlmaLinux’s official repositories often “winning” over Remi, replacing the carefully configured PHP stack.&lt;/p&gt;


&lt;h3&gt;
  
  
  What Was (and Wasn’t) Broken
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;All CLI-based PHP scripts were dead&lt;/strong&gt; due to missing extensions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apache kept serving PHP pages&lt;/strong&gt;. The web wasn’t affected (yet) since Apache hadn’t been restarted and still used the loaded Remi PHP module.&lt;/li&gt;
&lt;li&gt;Other possible dependency issues could appear, depending on what else was touched by &lt;code&gt;dnf update&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Steps Toward Recovery
&lt;/h3&gt;
&lt;h4&gt;
  
  
  1. Locate and test the Remi PHP binary
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/opt/remi/php81/root/bin/php &lt;span class="nt"&gt;--version&lt;/span&gt;
/opt/remi/php81/root/bin/php &lt;span class="nt"&gt;-m&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;pgsql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Confirmed: everything is still in place with Remi’s PHP.&lt;/p&gt;
&lt;h4&gt;
  
  
  2. Restore the system PHP symlink
&lt;/h4&gt;

&lt;p&gt;Point the system’s &lt;code&gt;php&lt;/code&gt; command (e.g., &lt;code&gt;/usr/bin/php&lt;/code&gt;) back to Remi’s PHP for CLI use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-sf&lt;/span&gt; /opt/remi/php81/root/bin/php /usr/bin/php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check with &lt;code&gt;which php&lt;/code&gt; that the change is effective.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Now, CLI PHP is mostly working again—as a temporary workaround!&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Proper Clean-up (A Work in Progress)
&lt;/h4&gt;

&lt;p&gt;At the time of writing, I am still working through the full clean-up process.&lt;br&gt;&lt;br&gt;
Here’s the plan I’m following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Remove any official AlmaLinux PHP packages&lt;/strong&gt; that were installed by &lt;code&gt;dnf update&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;dnf remove php php-cli php-common  &lt;span class="c"&gt;# ...and any others that don't belong&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Reinstall Remi PHP core and all required extensions:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;dnf &lt;span class="nb"&gt;install &lt;/span&gt;php81 php81-php-cli php81-php-pgsql php81-php-pdo  &lt;span class="c"&gt;# and whatever else you require&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Verify that Apache is configured to use Remi’s PHP module&lt;/strong&gt;, and restart Apache only after the above is done.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Double-check all settings and run tests&lt;/strong&gt; to ensure CLI and web parity.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;I’ll update this post with final steps and results once the proper fix is fully in place!&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Why Did This Happen? (And How to Prevent It)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On AlmaLinux and other RHEL derivatives, &lt;code&gt;dnf update&lt;/code&gt; upgrades ALL packages from ALL enabled repositories.&lt;/li&gt;
&lt;li&gt;This is &lt;strong&gt;not like &lt;code&gt;apt update&lt;/code&gt;&lt;/strong&gt; on Debian/Ubuntu, which &lt;em&gt;only&lt;/em&gt; updates package lists (and requires &lt;code&gt;apt upgrade&lt;/code&gt; to actually change any package versions).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distro default repositories can override custom builds&lt;/strong&gt; (like Remi) if you’re not careful.&lt;/li&gt;
&lt;li&gt;If possible, add a &lt;code&gt;exclude=php*&lt;/code&gt; line to your &lt;code&gt;dnf.conf&lt;/code&gt; or explicitly scope which packages to upgrade.&lt;/li&gt;
&lt;li&gt;With automation (Ansible, CI, etc.), &lt;strong&gt;never blindly run a global &lt;code&gt;dnf update&lt;/code&gt;&lt;/strong&gt;—always specify only the packages you want managed.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Conclusion &amp;amp; Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;dnf update&lt;/code&gt; is powerful and dangerous in custom environments—use with extreme caution.&lt;/li&gt;
&lt;li&gt;Apache might survive—&lt;em&gt;for a while&lt;/em&gt;—but system-level PHP (CLI) can break immediately if binary paths change.&lt;/li&gt;
&lt;li&gt;Restoring the correct symlink is only a temporary fix; the real solution is to remove conflicting packages and ensure everything is installed from the intended repo.&lt;/li&gt;
&lt;li&gt;Regularly check which &lt;code&gt;php&lt;/code&gt; you’re running (&lt;code&gt;which php&lt;/code&gt;) and what extensions are available (&lt;code&gt;php -m&lt;/code&gt;), especially after any updates.&lt;/li&gt;
&lt;li&gt;Update your automation and deployment playbooks to avoid this mess in the future.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If this happens to you:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Symlink back to Remi’s PHP, clean up conflicting packages, and don’t use &lt;code&gt;dnf update&lt;/code&gt; like you’d use &lt;code&gt;apt update&lt;/code&gt;!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>php</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
