This readme is for using FreePBX 17 on a RHEL 9 server and its various clones. FreePBX 17 supports PHP 8, which ships with EL9 and its clones. In general, the FreePBX 17 development targets Debian, not RHEL. This makes using FreePBX on EL9 clones an even more adventurous journey, but it works.

Anyway anyhow, if you want to use FPBX on your EL9 box, you have to find a way to have PHP 7.4 on your EL9 machine. A popular and effective solution is to use the PHP versions provided by Remi. It also has a convenient Wizard page: https://rpms.remirepo.net/wizard/ . that page also explains a way to make different PHP versions coexist on the same machine, in case you want to have both 7.4 for FreePBX and 8.x for other more up-to-date software.

The default Apache/PHP shipped with EL9 derivatives makes use of PHP-FPM, while mod_php was phased out. If you want to continue with mod_php, a popular and effective solution is to use the PHP versions provided by Remi. It also has a convenient Wizard page: https://rpms.remirepo.net/wizard/ . That page also explains a way to make different PHP versions coexist on the same machine.

But Remi versions still support mod_php so if you use them, this can still be an option. So you have to chhose how to handle your PHP scripts: or use php-fpm (see APACHE_PHP-FPM.txt) or make use of the old beloved mod_php , provided you use PHP packages which have it enabled, like Remi's do. Note that there are other options too, for example, a method I appreciated in the past: running an instance of Lighttpd to handle FreePBX as the asterisk user. It can be done even today and indeed, it would probably lead to resource saving. Also NgiNX is reported to work, and I have no doubt about it.

As explained before in the other readme files, I don't like to swhich my whole apache install to run as asterisk:asterisk, since I may well have other web services running on my server, and I want them to be unaffected by the freepbx/asterisk installation. So I find it convenient to run my FreePBX VirtualHost on dedicated ports (usually 81 and 444/https) to be able to run only this virtual host under the asterisk user.
This involves that the session files will be owned by the asterisk user, and that they have to be kept in a directory writable from that user. So I will change it in the virtual host config below. This also has a minor consequence on the FreePBX tools which are run run from the CLI, if they have to deal with the session directory. I explain this a note in the dedicated NOTES readme file.

I use the mpm-itk Apache MPM to switch from apache to asterisk user when Apache has to serve FreePBX Virtual Host requests. This has the advantage of not modifying the whole Apache configuration along with other virtual hosts you can have on your system. In the past, I used mod_ruid2 for this. It's only a question of personal taste.

So on. Install mod_itk and php, which indeed is mod_php:
dnf install httpd-itk php


Edit /etc/httpd/conf.modules.d/00-mpm.conf . Comment out any LoadModule line except for mpm-prefork. In the current config shipped with EL9 "clones" this is commenting the line which loads mod_mpm_event.so and decommenting the one with mod_mpm_prefork.so. In fact mpm_prefork is required for mod_itk. In case you want to stick with mod_mpm_event, another way will be required for running the FreePBX Virtual host (for ex. the Lightttpd solution I mentioned earlier, or I read about using a reverse proxy, etc).

Then edit /etc/httpd/conf.modules.d/01-mpm-itk.conf to load the module. Uncomment the last line so it looks like this:
LoadModule mpm_itk_module modules/mod_mpm_itk.so


If you're using SELinux, the following command is required by mpm-itk:
setsebool -P httpd_graceful_shutdown 1


Now crete the sessions directory for the * user referenced previously:
cp -rp /var/lib/php/session /var/lib/php/asterisksession
chgrp asterisk /var/lib/php/asterisksession


Then create the file /etc/httpd/conf.d/freepbx.conf with the following content:
Listen 81
Listen 444

<VirtualHost *:81>
        ServerName pbx.domain.com
        ServerAlias freepbx

        ServerAdmin webmaster@domain.com

        DocumentRoot /usr/share/freepbx

        <Directory "/usr/share/freepbx">
                Options Indexes FollowSymLinks

                ExpiresActive on
                ExpiresByType image/png "access plus 1 year"
                ExpiresByType image/gif "access plus 1 year"
                ExpiresByType image/jpg "access plus 1 year"
                ExpiresByType css/text "access plus 1 year"

                AllowOverride All

                <IfModule mod_authz_core.c>
                        Require all granted
                </IfModule>
        </Directory>

        <IfModule mpm_itk_module>
                AssignUserId asterisk asterisk
        </IfModule>

        #<IfModule !mod_php.c>
        #       <FilesMatch \.(php|phar)$>
        #               SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://php-fpm"
        #       </FilesMatch>
        #</IfModule>

        <IfModule mod_php.c>
                php_value session.save_handler "files"
                php_value session.save_path    "/var/lib/php/asterisksession"
        </IfModule>

        ErrorLog logs/freepbx-error_log
        CustomLog logs/freepbx-access_log common
</VirtualHost>

<VirtualHost *:444>
        ServerName pbx.domain.com
        ServerAlias freepbx

        ServerAdmin webmaster@domain.com

        DocumentRoot /usr/share/freepbx

        <Directory "/usr/share/freepbx">
                Options Indexes FollowSymLinks

                ExpiresActive on
                ExpiresByType image/png "access plus 1 year"
                ExpiresByType image/gif "access plus 1 year"
                ExpiresByType image/jpg "access plus 1 year"
                ExpiresByType css/text "access plus 1 year"

                AllowOverride All

                <IfModule mod_authz_core.c>
                        Require all granted
                </IfModule>
        </Directory>

        <IfModule mpm_itk_module>
                AssignUserId asterisk asterisk
        </IfModule>

        #<IfModule !mod_php.c>
        #       <FilesMatch \.(php|phar)$>
        #               SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://php-fpm"
        #       </FilesMatch>
        #</IfModule>

        <IfModule mod_php.c>
                php_value session.save_handler "files"
                php_value session.save_path    "/var/lib/php/asterisksession"
        </IfModule>

        ErrorLog logs/freepbx-ssl-error_log
        CustomLog logs/freepbx-ssl-access_log common

        SSLEngine on
        SSLCertificateFile /etc/pki/tls/certs/localhost.crt
        SSLCertificateKeyFile /etc/pki/tls/private/localhost.key

        <Files ~ "\.(cgi|shtml)$">
                SSLOptions +StdEnvVars
        </Files>
        <Directory "/var/www/cgi-bin">
                SSLOptions +StdEnvVars
        </Directory>
        SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
</VirtualHost>


If you dare using SELinux (port 81 is already there on C8, don't know for what):
semanage port -a -t http_port_t -p tcp 444
setsebool -P domain_can_mmap_files 1
setsebool -P daemons_enable_cluster_mode 1
setsebool -P httpd_mod_auth_pam 1
setsebool -P httpd_execmem 1
setsebool -P httpd_run_stickshift 1

Finally
systemctl restart httpd

And if using firewalld:
firewall-cmd --add-port=81/tcp
firewall-cmd --add-port=444/tcp
firewall-cmd --runtime-to-permanent
