Posted on

Custom Dockerfile for PHP 5.6 / Apache / WPCLI

I wanted to get my old wordpress 3.4 websites running again, so I had to build a couple docker images, and a docker compose file. This starts with Ubuntu 16, as I thought I would be able to get PHP5 on there. But in reality this container comes with PHP7 hooked up in the apt sources. So I ended up compiling PHP 5.6.40 in the container.

Base Image

# Use an Ubuntu base image
FROM ubuntu:16.04

# Set environment variables
ENV DEBIAN_FRONTEND=noninteractive
ENV PHP_VERSION=5.6.40

# Install dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential \
    apache2 \
    apache2-dev \
    libxml2-dev \
    libcurl4-openssl-dev \
    libssl-dev \
    libmysqlclient-dev \
    libreadline-dev \
    libzip-dev \
    libbz2-dev \
    libjpeg-dev \
    libpng-dev \
    libxpm-dev \
    libfreetype6-dev \
    libmcrypt-dev \
    libicu-dev \
    zlib1g-dev \
    libxslt-dev \
    libsodium-dev \
    libmagickwand-dev \
    libpcre3-dev \
    curl \
    wget \
    re2c \
    bison \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Download and extract PHP source
RUN wget --no-check-certificate https://www.php.net/distributions/php-${PHP_VERSION}.tar.gz && \
    tar -xvf php-${PHP_VERSION}.tar.gz && \
    rm php-${PHP_VERSION}.tar.gz

# Change directory to PHP source
WORKDIR php-${PHP_VERSION}

# Install MySQL development libraries for the mysql extension
RUN apt-get update && apt-get install -y --no-install-recommends libmysqlclient-dev && \
    apt-get clean && rm -rf /var/lib/apt/lists/*

# Reconfigure and build PHP to include the MySQL extension
RUN ./configure \
    --prefix=/usr/local/php5.6 \
    --with-apxs2=/usr/bin/apxs \
    --enable-maintainer-zts \
    --with-mysql \
    --with-mysqli \
    --with-pdo-mysql \
    --enable-mbstring \
    --enable-calendar \
    --enable-ctype \
    --with-curl \
    --enable-exif \
    --enable-ffi \
    --enable-fileinfo \
    --enable-filter \
    --enable-ftp \
    --with-gd \
    --with-gettext \
    --with-iconv \
    --with-imagick \
    --with-libdir=/usr/lib/x86_64-linux-gnu \
    --enable-json \
    --with-libxml-dir=/usr \
    --enable-mbstring \
    --with-mysqli=mysqlnd \
    --with-openssl \
    --enable-pcntl \
    --with-pcre-dir=/usr \
    --enable-pdo \
    --enable-phar \
    --enable-posix \
    --with-readline \
    --enable-session \
    --enable-shmop \
    --enable-simplexml \
    --enable-sockets \
    --with-sodium \
    --enable-sysvmsg \
    --enable-sysvsem \
    --enable-sysvshm \
    --enable-tokenizer \
    --enable-xml \
    --enable-xmlreader \
    --enable-xmlwriter \
    --with-xsl \
    --enable-opcache \
    --enable-zip \
    --with-zlib && \
    make -j$(nproc) && \
    make install

# Create a symlink for PHP to /bin
RUN ln -s /usr/local/php5.6/bin/php /bin/php

# Enable mod_rewrite module and configure Apache to allow .htaccess files
RUN a2enmod rewrite

# Configure Apache for PHP
RUN echo "LoadModule php5_module /usr/local/php5.6/lib/php/extensions/no-debug-non-zts-20131226/libphp5.so" >> /etc/apache2/apache2.conf && \
    echo "AddType application/x-httpd-php .php" >> /etc/apache2/apache2.conf && \
    echo "DirectoryIndex index.php" >> /etc/apache2/apache2.conf

# Allow overrides for .htaccess files in the Apache configuration
RUN echo "<Directory /var/www/html>" >> /etc/apache2/apache2.conf && \
    echo "    AllowOverride All" >> /etc/apache2/apache2.conf && \
    echo "</Directory>" >> /etc/apache2/apache2.conf

# Switch Apache to prefork MPM if needed (threaded MPM requires threadsafe PHP)
RUN a2dismod mpm_event mpm_worker && a2enmod mpm_prefork

# Copy test PHP file
RUN echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php

# Expose HTTP port
EXPOSE 80

# Start Apache
CMD ["apachectl", "-D", "FOREGROUND"]

The next step was adding WPCLI

# Use your custom PHP image as the base
FROM php56:latest


# Install dependencies for WP-CLI
RUN apt-get update && apt-get install -y \
    curl \
    ca-certificates \
    && rm -rf /var/lib/apt/lists/*

# Ensure PHP is linked to /usr/local/bin/php (change path based on where PHP was compiled)
ENV PATH="/usr/local/bin:/usr/local/php5.6/bin:$PATH"
RUN ln -s /usr/local/php-5.6.40/bin/php /usr/local/bin/php

# Install WP-CLI
RUN curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && \
    php wp-cli.phar --info && \
    chmod +x wp-cli.phar && \
    mv wp-cli.phar /usr/local/bin/wp

# Verify WP-CLI installation
RUN wp --info

# Expose port 80 (optional)
EXPOSE 80

# Start Apache (or your desired service)
CMD ["apache2ctl", "-D", "FOREGROUND"]

And then using docker compose to bring up Apache / PHP / MYSQL services online:

version: '3.7'
services:
  mysql:
    image: mysql/mysql-server:5.7.37
    environment:
     MYSQL_DATABASE: webdesign
     MYSQL_USER: ROOT
     MYSQL_PASSWORD: PASSWORD
    restart: always
    volumes:
     - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    ports:
     - "3307:3306"
  legacy-php:
    depends_on:
     - mysql
    image: php5.6-apache-wpcli
    volumes:
     - .:/var/www/html
    ports:
     - "80:80"

Over writing the WordPress 3.4 files with 3.7 allowed me to export an XML.

Posted on

Update Ubuntu server system time

Yesterday I setup a rotating backup for my wordpress sites that I am self hosting on an ubuntu server.

Had to update the system time on my server to make sure my cron jobs actually execute when I expect them to. I ran the following commands:

sudo timedatectl set-timezone America/Los_Angeles
sudo hwclock –systohc
sudo timedatectl set-ntp true
sudo systemctl restart cron
sudo systemctl restart rsyslog

this updated the cron daemon and the syslog daemon to use the new timesettings, which I set to Los Angeles time, and also made sure they are synced with an NTP server.

I also edit the logging system configuration by running

vi /etc/rsyslog.d/50-default.conf

Then uncommenting the line

cron.* /var/log/cron.log

This allows me to follow the tail of the log file and make sure that my cron job is executed at the expected time without any errors

tail -f /var/log/cron.log

Posted on

Rotating backup my self hosted wordpress sites with a bash script and a cron job

Getting hacked sucks! I have never been able to recover from the last hack that I suffered.
So Disaster Recovery is a priority. The last couple of days I’ve rebuild my blog on my own Linux server with NGINX, PHPFPM, and MySQL.
Today I went ahead and created 4 folders, one for each week of the month, assuming 4 weeks per month.

I wrote a quick backup.sh script, and setup a cron job with :

cd “$(dirname “$0″)”
value=$(cat count)
value=$(($value%4 + 1))
echo $”tar -czf /opt/backups/week$value/www.tgz /var/www”
tar -czf /opt/backups/week$value/www.tgz /var/www
echo $”mysqldump –all-databases | gzip > /opt/backups/week$value/data.gz”
mysqldump –all-databases -u root -p $MYSQL_PASSWORD | gzip > /opt/backups/week$value/data.gz
echo $value > count

This script reads from a file, in order to keep count of which week it currently is. So you will need that in the same directory.

Then I used this command to install the cron job

crontab -e

And used this to make it run every Thursday at 2 am.

# m h dom mon dow command
0 2 * * 4 /opt/backups/backup.sh

Next step is actually testing DR process by simulating a disaster and recovery.

Here is a video if you need more information:

Posted on

How to get free SSL certificates quickly installed on your Linux / NGINX server.

If you’re not aware of the letsencrypt project, let me teach you!
This wonderful organization is basically handing out free money, in the form of SSL certificates.
So if you’re savvy enough to self host your sites, you should be able to do this pretty quickly also.

If you’re like me and you have snap package manager and nginx installed all you have to do is:

  1. SSH into your server
  2. Run these commands
      sudo snap install --classic certbot
      sudo ln -s /snap/bin/certbot /usr/bin/certbot
      sudo certbot --nginx

This will install CERTBOT, create a symlink to it, and execute it for nginx. It really is that simple! I did make a quick video on it if you want to see more in depth explanation on how it worked for me.

Posted on

Dell Suffering: A Scanner Darkly

lol. Okay that’s a dirty trick that should get me some traffic. 🙂

Anyways. The printer is finally up on the network and working great. I couldn’t be happier with that right now.
But I am stuck at a new problem. I can’t configure the scanner to ‘Scan to PC’ or to ‘Scan to FTP’ correctly.
Oh sure, there is a drop down in the printer’s web interface and tool box software.
But the drop down only gives you the choice of which do you wish to use, SMB / FTP, changing the selection doesn’t make input boxes appear or anything.
You would think the printer is not psychic, and needs to have host, username, and password information entered somewhere.

But alas, I am left in a Death Cap Daze, staring at the printer, my senses and cognitive abilities distorted, and like Keanu Reeves, all I can do is utter a: ‘Woohh.’

Posted on

Dell Suffering

Yes, I know.

I complain A LOT.

But when you waste like an hour trying to get your 1355cnw printer on the wireless network, what else are you going to do!
First, the printer itself:

I can’t make heads or tails of the experience / display / setup process. Its horrid. I feel like I’m using an interface from the 80’s.
Not just in design of the external panel, or buttons, or other hardware components. But the over experience itself. The constant restarts, the non responsive menu.
This is poor product design from the soul to the heart of the printer and even the external support for the product, the dell website, has a horrible user experience.

So second poor product from dell, their website:

I believe the dell team should realize that the first page result for the search query “1355cnw drivers” results as the product detail / buy page being the first result.
You would think that a product’s detail page would contain on it, all pertinent links to the product. Such as the drivers. The word drivers is no where easily found above the fold, but it does exist in the footer.

So having not found a direct link to the specific drivers, I clicked back, and went on to the second result.

But this was the download page for the Mac version. At least I am assuming its the mac version because it has ‘_Mac’ in the name. No where does it say for which type platform or version or processor type on the download page.

Wait, it gets worse!

So having to go to the driver downloads home, I try to search for the printer. I choose  ‘Select product from my products’ or a link to that says something to that effect.  The resulting page is a login form. I am thinking that once I login into dell, they will know what printer I bought. But the list is empty, even after I click on it, and login. I am stuck staring at a page with almost nothing on it. So I go back and select ‘Choose from product list’ and begin to refine the search down.

Finally I arrive at my product download page, select three items to download, which is also a f*king confusing page as list multiple drivers with confusing labeling system, and get prompted with an ‘INSTALL OUR DOWDNLOADER  ON YOUR SYSTEM’ prompt.

G*d Dang it.  Oh, man, I am just trying to scan a check so I can start my contract with KForce, and a routine printer installation has become a nightmare.

I have to download, before I can download. Dell, KISS my shiny metal a**.