Learn how to set up and automate a full LAMP stack on Ubuntu 24.04 using Ansible. This step-by-step tutorial covers Apache, MySQL, and PHP with best practices.
Introduction:
Setting up a LAMP stack (Linux, Apache, MySQL/MariaDB, PHP) is still one of the most common starting points for web applications. Instead of installing everything manually, we can automate the entire process with Ansible. Automation ensures consistency, saves time, and makes scaling our infrastructure much easier.
When we automate a LAMP stack, a flat single-file playbook is fine for learning. But in real-world projects, that approach quickly becomes unmaintainable. The professional way is to use roles, each role dedicated to a component like Apache, MySQL, or PHP. This keeps our playbooks modular, reusable, and easier to extend.
In this section, we’ll learn how to organize an Ansible project with roles, and then deploy Apache, MySQL, and PHP on Ubuntu 24.04 with clarity and reliability.
Ansible LAMP Stack Deployment on Ubuntu
Step 1: Prepare Our Environment
Start with a fresh Ubuntu 24.04 server. Make sure it’s updated:
sudo apt update && sudo apt upgrade -y
Install Ansible on our control machine (this could be our local system or a separate management server):
sudo apt install ansible -y
Verify installation:
ansible --version
Step 2: Configure SSH Access
Ansible communicates over SSH. We need key-based authentication:
Generate SSH keys (on control machine):
ssh-keygen -t ed25519
Copy the public key to the target Ubuntu server:
ssh-copy-id user@server-ip
Now we can test the connection:
ansible all -i server-ip, -m ping -u user
If it returns pong, we are ready.
Step 3: Create Ansible Project Structure
Create a project folder:
mkdir lamp-ansible && cd lamp-ansible
touch inventory playbook.yml
Initialize the standard Ansible layout:
ansible-galaxy init roles/apache
ansible-galaxy init roles/mysql
ansible-galaxy init roles/php
Now we have:
lamp-ansible/
├── inventory
├── playbook.yml
└── roles/
├── apache/
├── mysql/
└── php/
Edit inventory file and add servers:
nano inventory
Add following content:
[lamp_servers]
server1 ansible_host=server-ip ansible_user=user
Note: Add all the servers you want to install LAMP.
Step 4: Apache Role
Edit roles/apache/tasks/main.yml
:
nano roles/apache/tasks/main.yml
Add following content:
---
- name: Install Apache
apt:
name: apache2
state: present
update_cache: yes
- name: Ensure Apache is enabled and running
service:
name: apache2
state: started
enabled: true
- name: Allow HTTP and HTTPS through UFW
community.general.ufw:
rule: allow
port: "{{ item }}"
proto: tcp
loop:
- 80
- 443
- name: Deploy PHP info page for testing
copy:
dest: /var/www/html/info.php
content: "<?php phpinfo(); ?>"
owner: www-data
group: www-data
mode: '0644'
notify: Restart Apache
Save and exit the file.
Add a handler roles/apache/handlers/main.yml
:
nano roles/apache/handlers/main.yml
Add following content:
---
- name: Restart Apache
service:
name: apache2
state: restarted
Save and exit the file.
Step 5: MySQL Role
Edit roles/mysql/tasks/main.yml
:
nano roles/mysql/tasks/main.yml
Add following content:
---
- name: Install MySQL server and dependencies
apt:
name:
- mysql-server
- python3-mysqldb
state: present
update_cache: yes
- name: Ensure MySQL is enabled and started
service:
name: mysql
state: started
enabled: true
- name: Secure MySQL root user
community.mysql.mysql_user:
name: root
host: localhost
password: "{{ mysql_root_password }}"
priv: "*.*:ALL,GRANT"
login_unix_socket: /var/run/mysqld/mysqld.sock
state: present
- name: Remove anonymous MySQL users
community.mysql.mysql_user:
name: ''
host_all: true
state: absent
login_unix_socket: /var/run/mysqld/mysqld.sock
- name: Drop test database
community.mysql.mysql_db:
name: test
state: absent
login_unix_socket: /var/run/mysqld/mysqld.sock
Save and exit the file.
Step 6: PHP Role
Edit roles/php/tasks/main.yml
:
nano roles/php/tasks/main.yml
Add following content:
---
- name: Install PHP and required extensions
apt:
name:
- php
- libapache2-mod-php
- php-mysql
state: present
update_cache: yes
notify: Restart Apache
Save and exit the file.
Step 7: Main Playbook
Finally, tie everything together in playbook.yml:
nano playbook.yml
Add following content:
---
- hosts: lamp_servers
become: true
roles:
- apache
- mysql
- php
Save and exit the file.
Step 8: Run the Playbook
Execute:
ansible-galaxy collection install community.mysql community.general
ansible-playbook -i inventory playbook.yml
Step 9: Verify Deployment
Login into host server and check Apache status:
systemctl status apache2
Check PHP:
Visit http://server-ip/info.php
and confirm PHP info page loads.
Check MySQL root login:
mysql
Final Thoughts
By automating the LAMP stack installation with Ansible on Ubuntu 24.04, we replace repetitive manual work with a clean, repeatable process. This approach ensures our web applications are deployed consistently and can easily scale across multiple servers.
Automation is not just a time-saver; it is a professional habit that makes our infrastructure more reliable and secure.
With this role-based Ansible setup, we not only automate a LAMP stack on Ubuntu 24.04 but also follow best practices for structure and maintainability. This is the same method teams use in production environments where clarity, repeatability, and modularity are non-negotiable.
Check out robust instant dedicated servers, Instant KVM VPS, premium shared hosting and data center services in New Zealand