{"id":3780,"date":"2019-08-09T20:33:45","date_gmt":"2019-08-09T08:33:45","guid":{"rendered":"http:\/\/www.zoyinc.com\/?p=3780"},"modified":"2019-09-18T19:13:58","modified_gmt":"2019-09-18T07:13:58","slug":"centos-7-php-7-2-python-3-6-apache-2-4","status":"publish","type":"post","link":"http:\/\/www.zoyinc.com\/?p=3780","title":{"rendered":"CentOS 7 + PHP 7.2 + Python 3.6 + Apache 2.4"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3805\" src=\"http:\/\/www.zoyinc.com\/wp-content\/uploads\/2019\/08\/CentOS7SCLHttpd24_03.jpg\" alt=\"\" width=\"1709\" height=\"727\" srcset=\"http:\/\/www.zoyinc.com\/wp-content\/uploads\/2019\/08\/CentOS7SCLHttpd24_03.jpg 1709w, http:\/\/www.zoyinc.com\/wp-content\/uploads\/2019\/08\/CentOS7SCLHttpd24_03-150x64.jpg 150w, http:\/\/www.zoyinc.com\/wp-content\/uploads\/2019\/08\/CentOS7SCLHttpd24_03-300x128.jpg 300w, http:\/\/www.zoyinc.com\/wp-content\/uploads\/2019\/08\/CentOS7SCLHttpd24_03-768x327.jpg 768w, http:\/\/www.zoyinc.com\/wp-content\/uploads\/2019\/08\/CentOS7SCLHttpd24_03-500x213.jpg 500w\" sizes=\"auto, (max-width: 1709px) 100vw, 1709px\" \/><\/p>\n<p>I am setting up a new CentOS 7 server, in 2019, because I want a long life public facing WordPress host that I can update easily. For example when the &#8220;Heartbleed&#8221; security bug, in the OpenSSL cryptography library, was discovered you needed to update your SSL install. This proved to be a major problem for me because my O\/S was Fedora and quite old so updating was difficult.<\/p>\n<p>The problem for me in setting up a WordPress install on CentOS 7 is that like RedHat 7 it comes with PHP 5 and Python 2. Both quite dated. In addition it was not made easy to update to PHP 7 and Python 3.<\/p>\n<p>The &#8220;correct&#8221; and &#8220;official&#8221; way to resolve this is via RedHat&#8217;s &#8220;Software Collections&#8221;:<\/p>\n<p style=\"padding-left: 30px;\"><a  href=\"https:\/\/www.softwarecollections.org\/\">https:\/\/www.softwarecollections.org\/<\/a><\/p>\n<p>Looking around for how to run CentOS\/RHEL 7 with Apache httpd 2.4, PHP 7.x and Python 3.x I found a multitude of solutions, but mostly mixes of using scl and downloading modules from other repos. It became a minefield and it was really looking like not the right way to do it.<\/p>\n<p>I have come to the conclusion the answer is to run all of Apache, PHP and Python via scl. The problem seems to be how to run all of these things together. In particular if Apache is running from scl how do you get PHP installed within that particular.<\/p>\n<h2>Software collections<\/h2>\n<p>To quote the Software Collections site:<\/p>\n<blockquote><p>Software Collections give you the power to build and concurrently install multiple versions of the same components on your system, without affecting the system versions of the packages installed from your distribution.<\/p>\n<p>The intent of SoftwareCollections.org is to give projects and third parties the ability to:<\/p>\n<ul>\n<li>Create and distribute multiple versions of software for major RPM-based Linux distributions.<\/li>\n<li>Package software that may not be easy to distribute in upstream distributions.<\/li>\n<li>Allow projects to move at a different pace than the upstream distribution release cycle.<\/li>\n<li>Give users more flexibility and choice in software selection for their chosen distributions.<\/li>\n<li>Provide a flexible format for admins and users to package their own software.<\/li>\n<\/ul>\n<\/blockquote>\n<h1>Steps<\/h1>\n<p>To stop any confusion and ensure we are using the right versions first ensure you don&#8217;t have either Apache httpd or PHP isntalled:<\/p>\n<p style=\"padding-left: 30px;\">rpm -qa | grep http<br \/>\nrpm -qa | grep php<br \/>\nrpm -qa | grep python<\/p>\n<p>Python should return a bunch of bunch of RPM but they should be mostly v2. So now run:<\/p>\n<p style=\"padding-left: 30px;\">php<\/p>\n<p>This should return:<\/p>\n<p style=\"padding-left: 30px;\">php: command not found&#8230;<\/p>\n<p>Then run<\/p>\n<p style=\"padding-left: 30px;\">python &#8211;version<\/p>\n<p>Which should return:<\/p>\n<p style=\"padding-left: 30px;\">Python 2.7.5<\/p>\n<p>So we should be all and ready to begin.<\/p>\n<h2>Repos<\/h2>\n<p>You should probably install the REmi and EPEL repos. Run the following:<\/p>\n<p style=\"padding-left: 30px;\">wget -q http:\/\/rpms.remirepo.net\/enterprise\/remi-release-7.rpm<br \/>\nwget -q https:\/\/dl.fedoraproject.org\/pub\/epel\/epel-release-latest-7.noarch.rpm<br \/>\nrpm -i remi-release-7.rpm epel-release-latest-7.noarch.rpm<\/p>\n<h2>Enable software collections<\/h2>\n<p>To enable software collections run:<\/p>\n<p style=\"padding-left: 30px;\">yum update<br \/>\nyum install centos-release-scl<br \/>\nyum install scl-utils-build<\/p>\n<h2>Apache http<\/h2>\n<p>Now install the scl httpd24 package and all http24 modules. One thing that got me about this is it is simply called &#8220;httpd24&#8221; not something like &#8220;rh-httpd24&#8221;:<\/p>\n<p style=\"padding-left: 30px;\">sudo yum install httpd24 httpd24-httpd-devel httpd24-mod\\*<\/p>\n<p>This includes httpd24-httpd-devel which is required when we install mod_wsgi for Python<\/p>\n<p>Now enable the http24 collection, enable the service:<\/p>\n<p style=\"padding-left: 30px;\">scl enable httpd24 bash<br \/>\nsystemctl enable httpd24-httpd.service<br \/>\nsystemctl restart httpd24-httpd<\/p>\n<p>The thing with software collections is that it moves everything from a folder perspective. So the config folders for http are no longer under &#8220;\/etc\/http&#8221; but are now buried much deeper in:<\/p>\n<p style=\"padding-left: 30px;\">\/opt\/rh\/httpd24\/root\/etc\/httpd<\/p>\n<p>Additionally the document root has moved and is now:<\/p>\n<p style=\"padding-left: 30px;\">\/opt\/rh\/httpd24\/root\/var\/www\/html<\/p>\n<p>So now create a test file:<\/p>\n<p style=\"padding-left: 30px;\">echo &#8220;&lt;?php phpinfo(); ?&gt;&#8221; &gt; \/opt\/rh\/httpd24\/root\/var\/www\/html\/test.php<\/p>\n<p>So if you try to get to this page, <a  href=\"http:\/\/centos7-base\/test.php\">http:\/\/centos7-base\/test.php<\/a>\u00a0 it won&#8217;t work and most likely you will see a blank page. This is because PHP is still not enabled in Apache, neither is it installed on the VM. In fact if you &#8220;View page source&#8221; it will just show &#8220;&lt;?php phpinfo(); ?&gt;&#8221;.<\/p>\n<h2>PHP 7.2<\/h2>\n<p>If you are still in the bash shell from starting httpd then exit. You need to install PHP, install the following:<\/p>\n<p style=\"padding-left: 30px;\">systemctl stop httpd24-httpd.service<br \/>\nyum install rh-php72 rh-php72-php rh-php72-php-mysqlnd<br \/>\nservice httpd24-httpd restart<\/p>\n<p>You should now find when you go to\u00a0<a  href=\"http:\/\/centos7-base\/test.php\">http:\/\/centos7-base\/test.php<\/a>\u00a0 this should now bring back the full PHP info:<\/p>\n<p><a  href=\"http:\/\/www.zoyinc.com\/wp-content\/uploads\/2019\/08\/CentOS7SCLHttpd24_01.jpg\" class=\"thickbox no_icon\" title=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-3793\" src=\"http:\/\/www.zoyinc.com\/wp-content\/uploads\/2019\/08\/CentOS7SCLHttpd24_01.jpg\" alt=\"\" width=\"463\" height=\"394\" srcset=\"http:\/\/www.zoyinc.com\/wp-content\/uploads\/2019\/08\/CentOS7SCLHttpd24_01-150x127.jpg 150w, http:\/\/www.zoyinc.com\/wp-content\/uploads\/2019\/08\/CentOS7SCLHttpd24_01-300x254.jpg 300w, http:\/\/www.zoyinc.com\/wp-content\/uploads\/2019\/08\/CentOS7SCLHttpd24_01-354x300.jpg 354w\" sizes=\"auto, (max-width: 463px) 100vw, 463px\" \/><\/a>The lesson I learned was that installing &#8220;rh-php72&#8221;, while necessary wasn&#8217;t the one that made it work, it was &#8220;rh-php72-php&#8221; that did the magic. Listing the contents of &#8220;rh-php72-php&#8221; shows:<\/p>\n<pre class=\"crayon:false;\">[root@centos7-base \/]# repoquery -l rh-php72-php\r\n<span style=\"background-color: #ffff00;\">\/opt\/rh\/httpd24\/root\/etc\/httpd\/conf.d\/rh-php72-php.conf<\/span>\r\n<span style=\"background-color: #ffff00;\">\/opt\/rh\/httpd24\/root\/etc\/httpd\/conf.modules.d\/15-rh-php72-php.conf<\/span>\r\n<span style=\"background-color: #ffff00;\">\/opt\/rh\/httpd24\/root\/usr\/lib64\/httpd\/modules\/librh-php72-php7.so<\/span>\r\n<span style=\"background-color: #ffff00;\">\/opt\/rh\/httpd24\/root\/usr\/share\/httpd\/icons\/rh-php72-php.gif<\/span>\r\n\/opt\/rh\/rh-php72\/register.content\/var\/opt\/rh\/rh-php72\/lib\/php\/session\r\n\/opt\/rh\/rh-php72\/register.content\/var\/opt\/rh\/rh-php72\/lib\/php\/wsdlcache\r\n\/var\/opt\/rh\/rh-php72\/lib\/php\/opcache\r\n\/var\/opt\/rh\/rh-php72\/lib\/php\/session\r\n\/var\/opt\/rh\/rh-php72\/lib\/php\/wsdlcache<\/pre>\n<p>To finish of PHP lets install some more useful packages and restart:<\/p>\n<p style=\"padding-left: 30px;\">yum install rh-php72-php-gd rh-php72-php-mbstring rh-php72-php-intl rh-php72-php-pecl-apcu<br \/>\nservice httpd24-httpd restart<\/p>\n<p>You can optionally restart the host to prove Apache auto starts &#8211; probably a good idea.<\/p>\n<h2>Python 3.6<\/h2>\n<p>Before you start run &#8220;python &#8211;version&#8221; which should show you are running Python 2.7.<\/p>\n<p>Now install Python 3.6:<\/p>\n<p style=\"padding-left: 30px;\">sudo yum install rh-python36<\/p>\n<p>Test by running<\/p>\n<p style=\"padding-left: 30px;\">scl enable rh-python36 bash<br \/>\npython &#8211;version<br \/>\nexit<\/p>\n<p>Need to:<\/p>\n<ul>\n<li>Enable httpd24 and python36 together<\/li>\n<li>Upgrade pip<\/li>\n<li>Install mod-wsgi<\/li>\n<\/ul>\n<p style=\"padding-left: 30px;\">scl enable rh-python36 httpd24 bash<br \/>\npip install &#8211;upgrade pip<br \/>\npip install mod-wsgi<\/p>\n<p>If pip installs mod-wsgi successfully you will see:<\/p>\n<pre class=\"crayon:false;\">[root@centos7-base ~]# [root@centos7-base ~]# pip install mod-wsgi\r\nCollecting mod-wsgi\r\n  Using cached https:\/\/files.pythonhosted.org\/packages\/26\/03\/a3ed5abc2e66c82c40b0735c2f819c898d136879b00be4f5537126b6a4a4\/mod_wsgi-4.6.7.tar.gz\r\nInstalling collected packages: mod-wsgi\r\n  Running setup.py install for mod-wsgi ... done\r\nSuccessfully installed mod-wsgi-4.6.7<\/pre>\n<p>When trying to install &#8220;mod-wsgi&#8221; you will get the following error if you have not installed &#8220;httpd24-httpd-devel&#8221;:<\/p>\n<p style=\"padding-left: 30px;\">RuntimeError: The &#8216;apxs&#8217; command appears not to be installed or is not executable.<\/p>\n<p>To put the new mod_wsgi module into the Apache httpd modules folder run:<\/p>\n<p style=\"padding-left: 30px;\">mod_wsgi-express install-module<\/p>\n<p>To check it is there run:<\/p>\n<p style=\"padding-left: 30px;\">cd \/opt\/rh\/httpd24\/root\/etc\/httpd\/modules<br \/>\nls -la<\/p>\n<p>You should see the mod_wsgi listed as:<\/p>\n<p style=\"padding-left: 30px;\">mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so<\/p>\n<p>Add the following into the apache config along with the other modules by creating a one line conf file:<\/p>\n<p style=\"padding-left: 30px;\">echo &#8220;LoadModule wsgi_module modules\/<span style=\"background-color: #ffff00;\">mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so<\/span>&#8221; &gt; \/opt\/rh\/httpd24\/root\/etc\/httpd\/conf.modules.d\/16-mod-wsgi.conf<\/p>\n<p>Ensure the highlighted bit matches the name of the module that you listed earlier in the Apache httpd &#8220;\/modules&#8221; folder. In our case &#8220;mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so&#8221;.<\/p>\n<p>Create a file called &#8220;mod_wsgi-py36.conf&#8221;:<\/p>\n<p style=\"padding-left: 30px;\">echo &#8220;WSGIScriptAlias \/wsgi\/ \/opt\/rh\/httpd24\/root\/var\/www\/wsgi-scripts\/&#8221; &gt; \/opt\/rh\/httpd24\/root\/etc\/httpd\/conf.d\/mod_wsgi-py36.conf<\/p>\n<p>Yes need the trailing forward slashes &#8220;\/&#8221;.<\/p>\n<p>Restart Apache:<\/p>\n<p style=\"padding-left: 30px;\">systemctl restart httpd24-httpd.service<\/p>\n<p>Logs folder is: \/opt\/rh\/httpd24\/root\/etc\/httpd\/logs<\/p>\n<p>Create the folder for the scripts and cd to it:<\/p>\n<p style=\"padding-left: 30px;\">mkdir -p \/opt\/rh\/httpd24\/root\/var\/www\/wsgi-scripts\/<\/p>\n<p>Create a test php file in this folder called &#8220;test.wsgi&#8221; and put the following in it:<\/p>\n<pre class=\"lang:python decode:true \">#\r\n# Sample WSGI Python script from Zoyinc\r\n#\r\nimport datetime\r\nimport sys\r\n\r\ndef application(environ, start_response):\r\n    status = '200 OK'\r\n    currDateTime  = datetime.datetime.now().strftime(\"%b %d %Y %H:%M:%S\")\r\n    outputStr = '''\r\n&lt;html&gt;\r\n   &lt;head&gt;&lt;title&gt;Test Python Script from Apache&lt;\/title&gt;&lt;\/head&gt;\r\n   &lt;body&gt;\r\n      &lt;\/br&gt;\r\n      &lt;h2&gt;Today is: ''' + currDateTime + '''&lt;\/h2&gt;\r\n      &lt;\/br&gt;\r\nThis is a test page generated by Python based on instructions from &lt;a href='http:\/\/www.zoyinc.com'&gt;Zoyinc&lt;\/a&gt;&lt;\/br&gt;\r\nPython version is ''' + str(sys.version) + '''\r\n   &lt;\/body&gt;\r\n&lt;\/html&gt;\r\n    '''\r\n\r\n    response_headers = [('Content-type', 'text\/html'),\r\n                        ('Content-Length', str(len(outputStr)))]\r\n    start_response(status, response_headers)\r\n    return [bytes(outputStr, encoding= 'utf-8')]<\/pre>\n<p>There are a number of important points to this script.<\/p>\n<ul>\n<li>By the fact that it outputs the time we know it is via Python and not a static page<\/li>\n<li>WSGI has been hard coded to use &#8216;application as the entry point, so unless you change the WSGI build you need to use &#8216;def application()&#8217;<\/li>\n<li>The &#8216;status&#8217; is the response sent back to the browser<\/li>\n<li>WSGI expects a byte string with the correct encoding this is why we use &#8216;bytes()&#8217; and also &#8220;encoding=&#8217;utf-8&#8242;&#8221;<\/li>\n<li>If you don&#8217;t set the header to be &#8216;text\/html&#8217; then in a browser it will be just text not html<\/li>\n<li>If it&#8217;s not working tail the &#8220;error_log&#8221; file in &#8220;\/opt\/rh\/httpd24\/root\/etc\/httpd\/logs&#8221;<\/li>\n<\/ul>\n<p>To get to the page use: http:\/\/centos7-base\/wsgi\/test.wsgi<\/p>\n<p>You should see:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3798\" src=\"http:\/\/www.zoyinc.com\/wp-content\/uploads\/2019\/08\/CentOS7SCLHttpd24_02.jpg\" alt=\"\" width=\"496\" height=\"289\" srcset=\"http:\/\/www.zoyinc.com\/wp-content\/uploads\/2019\/08\/CentOS7SCLHttpd24_02.jpg 496w, http:\/\/www.zoyinc.com\/wp-content\/uploads\/2019\/08\/CentOS7SCLHttpd24_02-150x87.jpg 150w, http:\/\/www.zoyinc.com\/wp-content\/uploads\/2019\/08\/CentOS7SCLHttpd24_02-300x175.jpg 300w\" sizes=\"auto, (max-width: 496px) 100vw, 496px\" \/><\/p>\n<h2>Final check<\/h2>\n<p>As it has been a bit of a log journey I would restart the host and then go to both the php and python pages. That way you know Apache auto start and also that both PHP and Python are working at the correct versions after restart:<\/p>\n<p style=\"padding-left: 30px;\">http:\/\/centos7-base\/test2.php<br \/>\nhttp:\/\/centos7-base\/wsgi\/test.wsgi<\/p>\n<h2>Resources<\/h2>\n<p>Read the docs: mod_wsgi documentation<br \/>\n<a  href=\"https:\/\/modwsgi.readthedocs.io\/en\/develop\/index.html\">https:\/\/modwsgi.readthedocs.io\/en\/develop\/index.html<\/a><\/p>\n<p>Python Package Index: mod-wsgi<br \/>\n<a  href=\"https:\/\/pypi.org\/project\/mod-wsgi\/\">https:\/\/pypi.org\/project\/mod-wsgi\/<\/a><\/p>\n<p>Software Collections<br \/>\n<a  href=\"https:\/\/www.softwarecollections.org\/en\/\">https:\/\/www.softwarecollections.org\/en\/<\/a><\/p>\n<p>Red Hat Developers Blog: Software Collections on Red Hat Enterprise Linux<br \/>\n<a  href=\"https:\/\/developers.redhat.com\/blog\/2013\/01\/28\/software-collections-on-red-hat-enterprise-linux\/\">https:\/\/developers.redhat.com\/blog\/2013\/01\/28\/software-collections-on-red-hat-enterprise-linux\/<\/a><br \/>\nExcellent explanation from 2013, by Marcela Maslanova, about when it was created and why it was created. Gives great insight to motivations and history.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I am setting up a new CentOS 7 server, in 2019, because I want a long life public facing WordPress host that I can update easily. For example when the &#8220;Heartbleed&#8221; security bug, in the OpenSSL cryptography library, was discovered you needed to update your SSL install. This proved to be a major problem for [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":3807,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[553,559,433,552],"tags":[565,555,562,558,564,251,430,554,6,561,563,94,560,372,308],"class_list":["post-3780","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-centos","category-php","category-python","category-redhat","tag-565","tag-centos","tag-host","tag-install","tag-linuxhttpd7","tag-php","tag-python","tag-red-hat","tag-redhat","tag-scl","tag-server","tag-setup","tag-software-collections","tag-vm","tag-vmware"],"_links":{"self":[{"href":"http:\/\/www.zoyinc.com\/index.php?rest_route=\/wp\/v2\/posts\/3780","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.zoyinc.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.zoyinc.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.zoyinc.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.zoyinc.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3780"}],"version-history":[{"count":23,"href":"http:\/\/www.zoyinc.com\/index.php?rest_route=\/wp\/v2\/posts\/3780\/revisions"}],"predecessor-version":[{"id":3808,"href":"http:\/\/www.zoyinc.com\/index.php?rest_route=\/wp\/v2\/posts\/3780\/revisions\/3808"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/www.zoyinc.com\/index.php?rest_route=\/wp\/v2\/media\/3807"}],"wp:attachment":[{"href":"http:\/\/www.zoyinc.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3780"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.zoyinc.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3780"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.zoyinc.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3780"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}