Get LAMP Stack Up and Running on Your Server in Less than 90 Seconds using Cloud-Init

Building software today consists of many different technologies including programming languages, frameworks, databases and other tools. All of this combined is what you call a “company’s tech stack”. For example, a popular one is the MERN stack which stands for MongoDB, Express, React and Node. But today, let’s take a look at LAMP stack as it’s one of the most influential and popular ones.

Table of Contents

What is LAMP Stack?

LAMP stands for Linux, Apache, MySQL and PHP and has been around since 1998 as a free and open-source alternative to commercial software to build websites. Since then, many companies and tools have adopted this tech stack and it’s widely used until today.

Isn’t LAMP dead?

There are many other tech stacks gaining more and more popularity and web-development isn’t as complex anymore as it was 20 years ago. Despite this, LAMP is still widely used and tools like WordPress powering 43% of the web are doing a great job at keeping LAMP alive.

Here are just a few examples of big companies or tools using LAMP stack:

  1. WordPress
  2. Wikipedia
  3. Slack
  4. Facebook

By the way, this blog also runs on WordPress and thus uses the LAMP tech stack.

Setting up LAMP Stack

So now you know what we’re talking about, let’s get to work and set up a website with the LAMP stack. The goal is to have an Apache web server running with PHP and MySQL and we can achieve this with a simple installation using the apt (Advanced Packaging Tool) on Linux. But besides this manual installation method, there are actually other ways to get the LAMP stack ready on our machine.
Although in Contabo it’s possible to set up a new instance with LAMP stack preinstalled on a VPS or VDS when creating a new instance or using the reinstallation panel, sometimes it’s necessary to tweak some settings and thus a manual installation may be the better way to go.

To get a complete understanding of the cloud-init config file, we’ll start with the manual installation first as the config is mostly based on the steps we’re doing in the manual guide.

Manual Installation

To get started, all you need is a Linux server and root access to it so we can install and configure the required packages. We’ll be using Debian 11 on a Contabo Cloud VPS in this guide.

Before installing new packages, make sure the system is up-to-date by updating and upgrading the packages:

apt update && apt upgrade -y

Next we add a few packages required for the installation and also apache2:

apt-get install software-properties-common wget curl apache2 -y

In order to install the PHP packages, we first need to add the PHP repository:

curl -sSL https://packages.sury.org/php/README.txt | sudo bash -x

Now we can install the PHP packages:

apt-get install php8.1 php8.1-cli php8.1-common php8.1-curl php8.1-gd php8.1-intl php8.1-mbstring php8.1-mysql php8.1-opcache php8.1-readline php8.1-xml php8.1-xsl php8.1-zip php8.1-bz2 libapache2-mod-php8.1 -y

If you don’t need the extensions above, you can also install PHP without all the additional packages:

apt-get install php8.1 php8.1-cli libapache2-mod-php8.1 -y

Let’s restart the apache2 web server with service apache2 restart and if you visit your server’s IP address, you should be able to see the apache2 default page:

apache2_default_page

To have a full LAMP stack installed, all there’s left is MySQL. We can install it pretty easily with a simple command:

apt install mariadb-server mariadb-client -y && mysql_secure_installation

This will install MariaDB (MySQL) and automatically start the installer. In the installation process you’ll be asked to set a new root password. To access your database, you can do so with “root” as username and the password you just set.

Congrats, you successfully installed the LAMP stack on your system. But we can be way more efficient, so let’s head over to cloud-init and automate what we’ve just done manually.

Installation using Cloud-Init

In a previous article, we already explained the benefits of cloud-init and why it’s awesome. Generally, cloud-init is a tool to set a cloud instance up using a predefined config file as blueprint. This not only automates the setup process but also helps when it comes to disaster recovery and clusters.

With the manual installation guide in mind, we can now create the cloud-init config to automate the process and replicate it on many machines.

To indicate that it’s a cloud-init config, the first line looks like this:

#cloud-config

Cloud-init provides two simple options to control whether the packages should be updated and upgraded initially. To make sure we’re working with the latest and greatest, we set them to true:

package_update: true
package_upgrade: true

The apache2 web server and a few other required packages can be installed right away and we can tell cloud-init to install them with the packages module:

packages:
  - software-properties-common
  - wget
  - curl
  - apache2

The rest of the installation will be done in the runcmd module. It’s a simple list of commands that will be executed in the cloud-init “config” stage. In order to install PHP, we can use the same commands as we did in the manual installation:

runcmd:
  - curl -sSL https://packages.sury.org/php/README.txt | sudo bash -x
  - sudo apt-get install php8.1 php8.1-cli php8.1-common php8.1-curl php8.1-gd php8.1-intl php8.1-mbstring php8.1-mysql php8.1-opcache php8.1-readline php8.1-xml php8.1-xsl php8.1-zip php8.1-bz2 libapache2-mod-php8.1 -y
  - service apache2 restart

Setting up MySQL / MariaDB is a bit different. First we need to install it:

apt install mariadb-server mariadb-client -y

Because we can’t use the mysql_secure_installation installer in this case, we have to set the password using the cloud-init config. We don’t want a password to be stored in this file, so let’s just create a random one and save it to a file on the server (/home/mysql_access.txt) so we can access it using SSH:

pw=$(openssl rand -base64 18); echo "mysql_password=$pw" >> /home/mysql_access.txt

To actually change the password, use the mysqladmin command:

pw=$(openssl rand -base64 18); mysqladmin -u root -h localhost password "$pw"; echo "mysql_password=$pw" >> /home/mysql_access.txt

Now let’s reload the grant tables to make sure the changes are effective:

mysqladmin reload

If we now combine all these configurations, we get a complete cloud-init config that can be used to create new instances with the LAMP stack installed and configured:

#cloud-config
package_update: true
package_upgrade: true
packages:
  - software-properties-common
  - wget
  - curl
  - apache2
runcmd:
  - curl -sSL https://packages.sury.org/php/README.txt | sudo bash -x
  - sudo apt-get install php8.1 php8.1-cli php8.1-common php8.1-curl php8.1-gd php8.1-intl php8.1-mbstring php8.1-mysql php8.1-opcache php8.1-readline php8.1-xml php8.1-xsl php8.1-zip php8.1-bz2 libapache2-mod-php8.1 -y
  - service apache2 restart
  - apt install mariadb-server mariadb-client -y
  - pw=$(openssl rand -base64 18); mysqladmin -u root -h localhost password "$pw"; echo "mysql_password=$pw" >> /home/mysql_access.txt
  - mysqladmin reload

The Benefits of Using Cloud-Init

With this configuration file, you have created a single file that can be used to replicate this setup on multiple instances.

Do you need another website built on top of LAMP? Simply spin up a new machine and you’re ready to deploy your new project.

Something bad happened and an instance went down? No problem, with this Cloud-Init config you can create a new instance quickly with all your configuration already applied to it.

It’s about replication and disaster recovery: You no longer need to install new instances manually, because with this config you’ve created a blueprint that can be used when creating new instances – this means less work for you and a much more efficient workflow.