Compile from source and install Apache HTTP Server 2.4 and PHP 7 on Linux

A how-to guide to build localhost (“virtual host”) PHP 7 sites on the latest Apache HTTP server

I am using a nearly decade-old version of Ubuntu as my main OS. As it runs Gnome 2 and Firestarter, I will be sticking with it until rapture time. However, I did not want the old Apache and PHP from the “Old Releases” Ubuntu repository. Apache HTTP Server 2.4 was released in March this year. I couldn’t care for the new features. The old Apache would have worked just fine but new was new. So, I decided to install the latest Apache HTTP server and PHP 7 by building them from source. There aren’t any tutorials on building Apache 2.4 and PHP 7 from source, particularly from the requirement of a development machine. Besides that many of the configuration files, executables (a2ensite) and directories seem to be missing after the compilation/installation process was complete. It required a bit of thinking and RTFM. So, I decided to put it all down here in one place.

Apache HTTP Server 2.4 (httpd) compilation, installation and configuration

First, download the source files.

cd ~/Build
wget -c url-of-pcre-archive
wget -c url-of-apache-httpd-archive 
wget -c url-of-apr-util
wget -c url-of-apr

Extract the source files of PCRE and httpd in a directory named Build. The source files of the Apache Runtime need to be extracted inside the srclib directory of the httpd directory.

cd ~/Build
tar -xf pcre*
tar -xjf http*.bz*

cd http*
cd srclib
tar -xf ../../apr-1*
tar -xf ../../apr-util-1*
ln -s apr-1* apr
ln -s apr-util-1* apr-util

Next, compile and install PCRE to some directory (/usr/local/pcre).

cd ~/Build
cd pcre*
./configure --prefix=/usr/local/pcre
sudo make install # Installs PCRE to directory /usr/local/pcre

Finally, compile Apache httpd to some directory (/opt/httpd) with specified PCRE and Apache Runtime directories.

cd ~/Build
cd http*
./configure --prefix=/opt/httpd --with-included-apr --with-pcre=/usr/local/pcre
sudo make install # Install Apache httpd to directory /opt/httpd

The Apache HTTP Server has been installed. Now, it is time to start it and check it in a browser.

sudo /opt/httpd/bin/apachectl -k start # Start server
firefox http://localhost  # Serves /opt/httpd/htdocs/index.html

The configuration files of Apache httpd 2.4 seem to be different from the ones from the Apache installed from the old Ubuntu repositories. The main configuration file will be at /opt/httpd/conf/httpd.conf

PHP7 compilation, installation and configuration

Next, compile and install PHP 7 to some directory (/opt/php-7). When executing the configure statement, you need to specify the location of the Apache Extension Tool (/opt/httpd/bin/apxs).

sudo /opt/httpd/bin/apachectl -k stop # Stop Apache HTTP Server
cd ~/Build
cd php-7*
./configure --help | more
read -p "Press enter to continue" oNothing 
./configure -with-apxs2=/opt/httpd/bin/apxs  --prefix=/opt/php/php-7/arch-all --exec-prefix=/opt/php/php-7/arch
make test # This step is optional 
sudo make install # Install PHP to directory /opt/php/php-7
sudo libtool --finish ~/Build/php-7/libs # Adds PHP 7 module loader to httpd.conf

This completes the PHP 7 installation. Please note that the libtool statement writes the following line to Apache server’s httpd.conf file.

LoadModule php7_module        modules/

After PHP 7 has been installed, add a PHP file extension handler to Apache server’s httpd.conf file.

# The following is a multi-line statement. Copy all of them.
echo '
  <FilesMatch \.php>; 
    SetHandler application/x-httpd-php 
  </FilesMatch>' | sudo tee -a /opt/httpd/conf/httpd.conf 

Copy the development php.ini in the Build directory to /opt/php/php-7/arch/lib directory.

cd ~/Build/php-7*
sudo cp php.ini-development /opt/php/php-7/arch/lib/php.ini

Modify this file appropriately for your developmental setup. For production, you will have to use modify and use php.ini-production as the php.ini file. This completes the PHP installation and configuration.

Now, it is time to test .it. Create a sample PHP file in the Apache server’s htdocs directory and request it in a browser.

echo '<? phpinfo(); ?>' > php-test.php
sudo mv ./php-test.php /opt/httpd/htdocs/php-test.php
sudo /opt/httpd/bin/apachectl -k start # Start Apache HTTP Server
firefox http://localhost/php-test.php

This will prove that your HTTPd server can handle PHP. However, to develop websites on your local development machine, some more changes need to be made. You can delete the /opt/httpd/htdocs/php-test.php file.

Apache HTTP Server reconfiguration for virtual hosts

First, append a line in your /etc/hosts file so that browser requests to your test site (say are routed to your local installation of the httpd server.

echo "" | sudo tee -a /etc/hosts

Next, clean up httpd.conf by removing the PHP file handler and the PHP loadmodule statement. Instead, append the following lines to httpd.conf.

# Added by me
Include conf/me-websites.conf 

Now, httpd.conf is mostly in its original state, save for the line that tells httpd to load the new me-websites.conf configuration file. Then, create the file me-websites.conf file and put all your virtual hosts configurations in it. Copy this file to /opt/httpd/conf directory. This will ensure that PHP scripting is limited to your “virtual host” sites.

Listen 8080

<VirtualHost *:8080>
  DocumentRoot "/home/account-name/Websites/PHP/me-website/htdocs"
  ErrorLog "/home/account-name/Websites/PHP/me-website/logs/"
  TransferLog "/home/account-name/Websites/PHP/me-website/logs/"
  LoadModule rewrite_module modules/
  LoadModule php7_module        modules/

  <FilesMatch \.php$>
    SetHandler application/x-httpd-php
  <Directory "/home/account-name/Websites/PHP/me-website/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted


Next, add your account to the user group www-data. Your account can be the owner of the directory /home/account-name/Websites/PHP/me-website/htdocs but you need to give read, write and execute permissions to www-data. Now, you can put your PHP scripts in /home/account-name/Websites/PHP/me-website/htdocs and start coding. You can test the site in a browser at

If you would like to test it on port 80, then remove the “Listen 80” in httpd.conf and replace 8080 in inside the VirtualHost directive in me-websites.conf. Then, you can simply test your sites at or

Fix for autogenerate bug in Eclipse PHP run configuration

I have already published how to modify the Eclipse source files to fix the autogenerate bug in the Run configuration of Eclipse PHP. If that is too much for you, then you can simply let Apache HTTP Server’s rewrite module fix it for you. Create a .htaccess file in your home folder. This will remove the your Eclipse PHP project name for the run configuration.

RewriteEngine On
Redirect "/me-website" "/"

Interestingly, the propriety IDE (derived from the same open-source project) sold by the creator of PHP does not suffer from this PDT “bug”.

Posted in software | Tagged , , , , , | Leave a comment

Greasemonkey JavaScript-based YouTube adblocker and annoyances remover

Watching YouTube online is still impossible for me – the Net connection is still flaky and there are disturbances in the electricity supply. Downloading the videos and playing them offline is still the only option for me. Even then, the YouTube comes with a great deal of annoyances – ads (text and video), autoplay, “Recommended for you” video list, lack of RSS feeds, half-hidden description, YouTube-curated (or censored) “Top Comments”.

I have created several Greasemonkey scripts to deal with YouTube. Recently, I added a few more. Here they are:

The last one is new. It does several things – disables video ads, hides text ads, disables autoplay, deletes “recommended for you” ads.

Disabling video ads was tricky. The current implementation opens the same video URL in another tab and closes the current tab. This is repeated until YouTube relents and loads the original video. This can range anywhere from 2 to 10 reloads, probably. The code also finds the mute button and mutes the ad.

// ==UserScript==
// @name        YouTube Ads Disabler
// @namespace
// @description Disables ads, swithces off autoplay, adds RSS link, deletes "recommended for you" videos, unhides description, displays latest comments first
// @include*
// @version     1
// @grant       none
// ==/UserScript==

document.addEventListener("DOMContentLoaded", fixYouTubeAnnoyances, false);

  function() {

function fixYouTubeAnnoyances() {
  console.log("YAD: Here");
  var sAdStyle = " { visibility: none!important; display: none!important; }";
  try {
    window.setTimeout(closeVideoAds, 1*1000);
    window.setTimeout(showDescription, 2*1000);
    window.setTimeout(removeRecommendedForYouAds, 3*1000);  
    window.setTimeout(disableAndHideAdContainers, 4*1000);  
    window.setTimeout(disableAutoPlay, 5*1000);
  } catch (e) {
    console.error("YAD Error: " + e);

function closeVideoAds() {
  console.log("YAD: Detecting video ads...");        
  if ((document.getElementsByClassName("videoAdUiTopButtons").length > 0) || (document.getElementsByClassName("videoAdUi").length > 0)) {
    console.log("YAD: Video ad found"); , '_blank');
    //, '_self').close();

    if (document.getElementsByClassName("ytp-mute-button").length > 0) {
      console.log("YAD: Video ad mute button found");        
      if (document.getElementsByClassName("ytp-volume-panel").length > 0) {
        if (document.getElementsByClassName("ytp-volume-panel")[0].getAttribute("aria-volumetext") != "100% volume muted") {
          console.log("YAD: Video ad muted");

  } else {
    console.log("YAD: No video ad");

function disableAutoPlay() {
  console.log("YAD: Disabling autoplay...");
  if ((document.getElementById("autoplay-checkbox") != null) && (document.getElementById("autoplay-checkbox").checked)) {
    console.log("YAD: Autoplay button found");
    console.log("YAD: Autoplay disabled");

function showDescription() {
  console.log("YAD: Finding description...");
  if (document.getElementById("action-panel-details") != null) {
    document.getElementById("action-panel-details").className = "action-panel-content yt-uix-expander yt-card yt-card-has-padding";
  console.log("YAD: Description unhidden.");

function removeRecommendedForYouAds() {
  console.log("YAD: Removing recommended videos");
  var oRelatedColumn = document.getElementById("watch-related");
  if (oRelatedColumn != null) {
    var arRelatedVids = oRelatedColumn.getElementsByTagName("li");
    var j = 0;
    if (arRelatedVids.length > 0) {
      for (var i = arRelatedVids.length-1; i > -1; i--) {        
        if (arRelatedVids[i].textContent.indexOf("Recommended for you") != -1) {
          //console.log("YAD: Removing " + arRelatedVids[i].textContent);
    console.log("YAD: Removed " + j  + " recommended videos");      

function disableAndHideAdContainers() {
  // Not published to protect YouTube content creators' interest

NOTE: I use an old version of Firefox and I spoof a newer but still old version in it. YouTube and other Google sites serve different styles of pages for different browser versions. The above code works with Firefox 42. To make the code work, you can spoof version 42 using the UserAgent Switcher add-on with this UA string.

Mozilla/5.0 (Windows NT 6.2; rv:42) Gecko/20100101 Firefox/42.0

Of course, I will not be publishing the ad-blocking code. YouTube apocalypse is on now. Ad agencies have done to YouTube what they had been doing for decades to newspaper and TV journalism – interfering in content. After CNN decided to launch a crusade against Alex Jones’ YouTube channels, ad agencies are now telling YouTube that their ads should not be playing on “controversial” content. The bottomline now is that videos from big music labels and stars can have all kind of crude/vulgar/unsuitable content but ordinary folk stepping out of the line will have to be immediately “demonetized.” I found one retired nurse, who publishes makeup tutorials, complaining that she never said a bad word or anything controversial but all her videos were demonetized.

Until the said apocalypse, YouTube content creators seem to have been generously paid. When the times were good, YouTube went all over the world asking people to make videos and make tons of money. Now, YouTube’s revenues are down and the first victims are the small and independent content creators who took YouTube’s bait. A million page views earns the creators very little. It is only with off-YouTube marketing deals and paid-promotion that YouTube content creators can make money. I am surprised that that many seemingly intelligent people left their day jobs and became “Youtubers” full time. Even more sad are the legion of retired folks whose savings have been destroyed by Bush and Obama’s zero-interest monetary regime and free-trade policies, and Wall Street’s looting of pension funds and local government funds. There can be no economy without local manufacturing. Selfies and cat videos are not what an advanced economy runs on.

Anyway, I can tolerate text ads. The videos ads are horrible. The “recommended for you” videos are downright creepy. Why are they recommended for me?

Posted in news, technology | Tagged , , | Leave a comment

An easy “Joule Thief” inverter circuit to power an electric torch with two LEDs using only one 1.2 or 1.5 volt (dead) battery

My handmade torch with a Joule Thief inverter design. The missing piece of the ferrite core can be found at the top of the battery. That’s the coil. The rubber band is used to hold down a momentary switch on the plastic tubing so that this photo could be taken.

These days, electric torches (flashlights) use LED bulbs. An LED bulb typically requires a minimum 1.85 volts to power on. Usually, a battery of two 1.5 volt cells (providing 3 volts) is used in torches to power them. If the voltage supplied by the cells in the battery falls below 1.85 volts, the LED will not light up. The “dead” cells in the battery will have to be replaced even though they still have considerable energy in them.

A “Joule thief” can be used to power an LED bulb using just one 1.5 (non-rechargeable) or 1.2 (rechargeable) cell. A “Joule thief” is so named because it can use just one cell. It can also power an LED with a cell that is deemed dead. The Joule thief circuit accomplishes this by using a coil to store energy and then generating spikes of voltages to turn the LED on and off several times a second. For human eyes, the LED appears to be lit up.

A Fritzing version of a Joule thief circuit

There are many videos on the Internet on how to build one. There are a number of misleading ideas of what is required to make it work. No need a circular ferrite core. I used a broken piece of ferrite core piece from a transformer salvaged from a failed phone charger. The number of windings on the coil does not increase the voltage. Instead, it affects the frequency of the voltage spikes. The voltage output is determined by the base voltage supplied by the battery and saturation level of the ferrite core. The windings need not be evenly spaced or anything like that. However, they need to be close to the ferrite core.

Parts required:

  • Two white LEDs
  • One non-polarized 0.1 uF capacitor
  • NPN transistor
  • 220 ohm resistor
  • jumper wire
  • ferrite core piece
  • winding (enameled) wire or any insulated wire


  1. Take two strands of equal-length enameled wire and wind it around a piece of ferrite core, say 20 to 40 times. Remove the enamel from the four ends of the coil. Twist/solder two ends of different wires. Use a multimeter continuity test to ensure that you are not tying the ends of the same wire. You can also use a LED+button cell combo to do the continuity test. Connect this tied end to the battery’s positive terminal.
  2. Now, you have two ends of coil that are free. Connect one end to a resistor and the other end to the collector of the transistor.
  3. Connect the other end of the resistor to the base of the transistor.
  4. Connect the LEDs and capacitor parallel to the emitter and collector of the transistor. The emitter is on the negative side.
  5. Connect the negative lead from the emitter of the transistor to the negative terminal of the cell.

Posted in electronics, how to | Tagged , , | Leave a comment

Greasemonkey script to display newer comments on YouTube – bypass censorship

Changes comments filter to “Newest first” from “Top comments”

YouTube has been raining on the parade of its content creators with demonetization, censorship and unexplained notifications disablement. Youtube comments are also being censored. The default filter is not “Newest first” or “Oldest first” but “Top comments”. Trolls will eventually game the system. I would rather see unfiltered comments. So, here it is:

// ==UserScript==
// @name        Show newer YouTube comments
// @namespace
// @description Automatically changes YouTube comments filter off
// @include*
// @exclude     %exclude%
// @version     1
// @grant       none
// ==/UserScript==

document.addEventListener("DOMContentLoaded", startItDelayed, false);
function startItDelayed() {
  window.setTimeout(switchCommentsList, 10*1000);
function switchCommentsList() { 
  console.log("Showing newer comments");
  var arButtons = document.getElementsByTagName("button");
  var bFound = false;
  for (var i = 0; i < arButtons.length; i++) {
    if (arButtons[i].textContent.trim() == "Top comments") {
      bFound = true;
  if (bFound) {
    //console.log("Menu found--------------");
    var arButtons = document.getElementsByTagName("button");
    for (var i = 0; i < arButtons.length; i++) {
      if (arButtons[i].textContent.trim() == "Newest first") {
        bFound = true;

Posted in software | Tagged , , | Leave a comment

Solution to OpenJDK’s “Connection error PKIX path building failed: unable to find valid certification path to requested target” error

Today, I downloaded Open JDK 10 to test it against my NetCheck JAR file. It did not work. I got this error:

Connection error PKIX path building failed: unable to find valid certification path to requested target

It seems that the certificat store bundled with the open-source project does not have information on all CAs. So, I copied the certificate store files (cacerts and blacklisted.certs) from Oracle Java JRE directory and the problem got resolved.

Copy the cacert and blacklisted.certs files from Oracle Java.

Posted in news | Leave a comment

A GreaseMonkey script to generate RSS feed links for YouTube channels

Many people use RSS feeds as the primary means to access news and information. RSS is anonymous and does not require you to log in.

Though YouTube generates RSS feeds for its channels, it does not display them (to human visitors) or advertise them (to browser software). If you prefer to subscribe to YouTube videos via RSS, then you have to manually construct the the feed URL for each channel.

I decided to automate the task using this Greasemonkey script. A few seconds after a YouTube video page gets loaded, the Greasemonkey Javascript adds an RSS icon image next to the channel name. The script links the image to the RSS feed of the YouTube channel. (This RSS icon image works seamlessly as it is from Google and is used in its “News” pages.) The Greasemonkey script also adds an RSS link tag to the HTML HEAD section so that browser applications can activate their RSS feed toolbar button.

// ==UserScript==
// @name        YouTube RSS feed generator
// @namespace
// @description Adds a RSS feed button to YouTube channels
// @include*
// @version     1
// @grant       none
// ==/UserScript==

document.addEventListener("DOMContentLoaded", startItDelayed, false);
function startItDelayed() {
  if (document.getElementById("YT_RSS_Feed") == null) {
    window.setTimeout(addRssButton, 6*1000);    

function addRssButton() { 
  console.log("Executing YouTube RSS feed generator")
  var oDivs = document.getElementsByTagName("div");
  if ((oDivs != null) && (oDivs.length > 0)) {
    for (var i = 0; i < oDivs.length; i++) { if (oDivs[i].className == "yt-user-info") { 
      //console.log("YRFG Error: Here"); 

      var oAnchors = oDivs[i].getElementsByTagName("a"); if ((oAnchors != null) && (oDivs.length>1)) {
          var bFound = false;
          for (var j = 0; j < oAnchors.length; j++) {
            //console.log("YRFG Error: " + oAnchors[j].href.substring(0, "".length));

            if (oAnchors[j].href.substring(0, "".length) == "") {
              var sChannelId = oAnchors[j].href.substring("".length);
              var oRssElement = document.createElement("a");
     = "YT_RSS_Feed";
              oRssElement.href = "" + sChannelId;
              oRssElement.innerHTML = "<img src=\"\" style=\"margin: auto 1em; \" />";
              var oLinkElement = document.createElement("link");
              oLinkElement.setAttribute("rel", "alternate");
              oLinkElement.setAttribute("title", oAnchors[j].textContent);
              oLinkElement.setAttribute("type", "application/rss+xml");
              oLinkElement.setAttribute("href", "" + sChannelId);
              bFound = true;
          if (bFound) { break; }

A YouTube channel listing in the Bamboo RSS feed reader (a Firefox add-on or extension).

RSS provides an easier way to check Youtube channels. All that matters to YouTube is that people see their ads. RSS does not block ads and so no problem. Viewers who rely on subscriptions are likely to miss new but not so fresh videos if they don’t log in regularly. (Such videos get folded/wrapped/hidden as newer videos are published.) YouTube RSS feeds can ensure that viewers are more likely to get to know about the existence of a new video.

And, to use this script, you will need the Greasemonkey add-on in the browser. It can be installed from the Firefox/Seamonkey browser add-on search page (Tools – Add-ons from the main menu).

This article has been submitted to .

Posted in software | Tagged , , | Leave a comment

Sound-activated LED lights using NPN transistor

What is wrong with the multi-colored LED light? Is it real?

I have started experimenting with transistors. The amplified AC sound signal forked from the speaker (connected to the base) is enough to turn the transistor on.  The supply voltage is connected to the LED onwards to the collector and a resistor  is connected to emitter (connected to ground).

I had some strange clear transparent LEDs. They turned on when on of the signal was connected to the collector but they did not react to the speaker signal. Stragely, one of the LEDs started glowing in all sorts of colors.

UPDATE: The clear LEDs are RGB LEDs. They follow their own (color) switching rhythm and are unsuitable for being sound-reactive.

Posted in electronics | Tagged , | Leave a comment