LAMP stack is an acronym for Linux, Apache, MySQL/MariaDB, and PHP stack. This forms a powerful stack that powers many websites and web applications on the internet. LAMP stack is a combination of the four open-source projects that when put together will give you a complete solution. In this guide, we shall discuss how to set up a LAMP stack on Ubuntu/Debian using Ansible.
LAMP Stack comprises the following open-source software applications.
- Linux – This is the operating system hosting the Applications.
- Apache – Apache HTTP is a free and open-source cross-platform web server.
- MySQL/MariaDB – Open Source relational database management system.
- PHP – Programming/Scripting Language used for developing Web applications.
We shall discuss all that is needed to set up the stack, including how to prepare your environment for this.
Ansible is an open-source configuration management and orchestration tool that is widely used for automating tasks and operations for system administrators and cloud users.
Setup Pre-requisites
Before we can get started, make sure you have the below minimum requirements.
- Ubuntu 20.04 or Debian 10/11 hosts
- A remote user with sudo privileges
- SSH key authentication set up for remote execution
- Ansible installed on your control node
1) Environment Preparations
In this guide, we shall be making use of Ansible playbooks and roles. These are some of the modules that make Ansible much easy to use.
If you don’t have Ansible installed on your machine (your workstation), you can install it with the commands below. Remember, this shouldn’t be done on the servers we intend to deploy the LAMP stack, but rather the machine you will use to run the ansible commands.
For Ubuntu/Debian:
sudo apt install ansible -y
For RPM-based OS:
sudo yum install ansible -y
Configure SSH key authentication to the remote server:
ssh-copy-id username@remote-server
Create a directory on your workstation that will be used as the working directory for this setup.
mkdir ansible_playbook && cd $_
2) Configure Ansible Playbook and Roles.
As discussed before, we shall configure Ansible playbooks and roles to perform the tasks below:
- Install Aptitude, prefreded package manager for Ansible
- Will install Apache, MariaDB-server and PHP
- Create and enable a VirtualHost for Apache
- Disable the default VirtualHost for Apache
- Configure the root password for MariaDB
- Configure PHP test file
- Allow HTTP traffic through the firewall.
We will create an ansible role for Apache and PHP installation and another one for MariaDB installation.
Create Default Variables
Create the default variables file that will contain information such as the domain name, MariaDB root password, etc.
In our working directory, create a sub-directory named vars and add a variables configuration file.
mkdir vars && cd vars
vim default.yml
In the default.yml file, add the information below, replacing the variables with your details.
---
mysql_root_password: "P@ssw0rd"
app_user: "apache"
http_host: "lamp.example.com"
http_conf: "lamp.example.com.conf"
http_port: "80"
disable_default: true
Create a hosts inventory file in the default working directory. Here, we add the IP of the remote server that we intend to set up LAMP stack.
vim hosts
....
[lampstack]
192.168.100.227
Create Apache Role
Create a roles sub-directory from the working directory and another sub-directory for Apache.
mkdir -p roles/apache
Here, we need to create the role for Apache and PHP, which shall contain all the required steps, modules, and templates for Apache service.
Create Apache & PHP task
Create the main execution task for Apache and PHP, inside the Apache directory
mkdir tasks && cd tasks
vim main.yml
Add the content below in the main.yml file:
---
- name: Install prerequisites
apt: name={{ item }} update_cache=yes state=latest force_apt_get=yes
loop: [ 'aptitude' ]
#Apache Configuration
- name: Install Apache and PHP Packages
apt: name={{ item }} update_cache=yes state=latest
loop: [ 'apache2', 'php', 'php-mysql', 'libapache2-mod-php' ]
- name: Create document root
file:
path: "/var/www/{{ http_host }}"
state: directory
owner: "{{ app_user }}"
mode: '0755'
- name: Set up Apache virtualhost
template:
src: "files/apache.conf.j2"
dest: "/etc/apache2/sites-available/{{ http_conf }}"
- name: Enable new site
shell: /usr/sbin/a2ensite {{ http_conf }}
- name: Disable default Apache site
shell: /usr/sbin/a2dissite 000-default.conf
when: disable_default
notify: Reload Apache
# UFW Configuration
- name: "UFW - Allow HTTP on port {{ http_port }}"
ufw:
rule: allow
port: "{{ http_port }}"
proto: tcp
# PHP Info Page
- name: Sets Up PHP Info Page
template:
src: "files/info.php.j2"
dest: "/var/www/{{ http_host }}/info.php"
- name: Reload Apache
service:
name: apache2
state: reloaded
- name: Restart Apache
service:
name: apache2
state: restarted
Create Apache Handlers
Add the Handlers for Apache. This should be done under the Apache role directory:
mkdir handlers && cd handlers
vim main.yml
Add the following content for the Apache handlers
---
- name: Reload Apache
service:
name: apache2
state: reloaded
- name: Restart Apache
service:
name: apache2
state: restarted
Add Apache Files
Create the files that will be used for the generation of the VirtualHost and the info.php index file. This is also done in the Apache role directory
mkdir files && cd files
Create the VirtualHost file
vim apache.conf.j2
<VirtualHost *:{{ http_port }}>
ServerAdmin webmaster@localhost
ServerName {{ http_host }}
ServerAlias www.{{ http_host }}
DocumentRoot /var/www/{{ http_host }}
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<Directory /var/www/{{ http_host }}>
Options -Indexes
</Directory>
<IfModule mod_dir.c>
DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm
</IfModule>
</VirtualHost>
Create the PHP test file
$ vim info.php.j2
<?php
phpinfo();
Ensure your Directory tree looks like this:
../apache$ tree
├── files
│ ├── apache.conf.j2
│ └── info.php.j2
├── handlers
│ └── main.yml
└── tasks
└── main.yml
3 directories, 4 files
Create MariaDB Role
Create a role for MariaDB. Create a directory for the MariaDB task, in the roles directory.
mkdir -p mariadb/tasks && cd mariadb/tasks
Create a configuration file for MariaDB task:
vim main.yml
---
- name: Install prerequisites
apt: name={{ item }} update_cache=yes state=latest force_apt_get=yes
loop: [ 'aptitude' ]
#Install MariaDB server
- name: Install MariaDB Packages
apt: name={{ item }} update_cache=yes state=latest
loop: [ 'mariadb-server', 'python3-pymysql' ]
# Start MariaDB Service
- name: Start MariaDB service
service:
name: mariadb
state: started
become: true
# MariaDB Configuration
- name: Sets the root password
mysql_user:
name: root
password: "{{ mysql_root_password }}"
login_unix_socket: /var/run/mysqld/mysqld.sock
- name: Removes all anonymous user accounts
mysql_user:
name: ''
host_all: yes
state: absent
login_user: root
login_password: "{{ mysql_root_password }}"
- name: Removes the MySQL test database
mysql_db:
name: test
state: absent
login_user: root
login_password: "{{ mysql_root_password }}"
Confirm that your structure for the Ansible roles looks like this:
../roles$ tree
.
├── apache
│ ├── files
│ │ ├── apache.conf.j2
│ │ └── info.php.j2
│ ├── handlers
│ │ └── main.yml
│ └── tasks
│ └── main.yml
└── mariadb
└── tasks
└── main.yml
6 directories, 5 files
Create the Ansible Playbook
Create a playbook in the parent working directory which makes use of the roles we just created above.
$ vim lampstack.yml
---
- name: configure lamp
hosts: lampstack
become: yes
become_method: sudo
vars_files:
- vars/default.yml
roles:
- apache
- mariadb
The entire configuration tree from the working directory should conform to this:
../ansible_playbook$ tree
.
├── hosts
├── lampstack.yml
├── roles
│ ├── apache
│ │ ├── files
│ │ │ ├── apache.conf.j2
│ │ │ └── info.php.j2
│ │ ├── handlers
│ │ │ └── main.yml
│ │ └── tasks
│ │ └── main.yml
│ └── mariadb
│ └── tasks
│ └── main.yml
└── vars
└── default.yml
8 directories, 8 files
30 Run Ansible Playbook to install LAMP Stack on Ubuntu / Debian
With our environment ready, we will need to run the playbook to install LAMP stack on Debian/Ubuntu
$ ansible-playbook -i hosts lampstack.yml -u <remote-user>
Replace the <remote-user> option with the user you configured for SSH.
The configuration should start. Upon successful execution, you should get an output such as this below:
Our installation was successful. We can now check if we can reach the server from the browser.
Navigate to http://server-IP/info.php
Conclusion
We have successfully set up LAMP stack on Debian/Ubuntu with Ansible. As you can see, it is easier to configure your LAMP stack with Ansible. We can also reuse the playbook we created to configure more LAMP stack instances on-demand. Cheers!
More guides on Ansible topics:
- Manage SELinux Status, Context, Ports and Booleans Using Ansible
- Generate OpenSSL Self-Signed Certificates with Ansible
- Install Ansible AWX on CentOS 8 / Rocky Linux 8
- Manage Users and Groups on Linux using Ansible