Installing LAMP Stack on Ubuntu 22.04 — A Step-by-Step Guide for Beginners

Ubuntu tutorial - IT technology blog
Ubuntu tutorial - IT technology blog

What Is LAMP Stack and When Do You Need It?

If you’re just getting started with backend web development or you’ve been handed a task to deploy a PHP application to a server, chances are you’ll need LAMP Stack. It’s the classic combination of Linux + Apache + MySQL + PHP — the foundation that powers WordPress, Laravel, Drupal, and hundreds of other PHP applications. Apache alone holds around 30% of the global web server market share, so knowing how to set up LAMP is a genuinely practical skill.

I’ve used LAMP on our company’s staging environment (Ubuntu 22.04) to test configurations before pushing to production. The hard-learned lesson: install in the right order and configure correctly from the start. Do it backwards and you’ll spend an entire afternoon debugging things that never should have been a problem.

This guide uses Apache instead of Nginx because many legacy PHP projects still depend on mod_rewrite and .htaccess. If you’re looking for a Nginx setup, there’s a separate post on the blog for that.

Installing Each Component

1. Update the System

Before installing anything, always update the package list — skipping this step is a common source of version conflicts down the road:

sudo apt update && sudo apt upgrade -y

2. Install Apache

sudo apt install apache2 -y

Once that’s done, start the service and enable it to run on boot:

sudo systemctl start apache2
sudo systemctl enable apache2

If you’re using UFW, open port 80:

sudo ufw allow 'Apache'
sudo ufw reload

Navigate to http://<your-server-IP> in a browser. If you see the “Apache2 Ubuntu Default Page”, you’re good to go.

3. Install MySQL

sudo apt install mysql-server -y

Run the security script — this step is important, don’t skip it:

sudo mysql_secure_installation

The script will walk you through a series of prompts. For production environments, here’s how I always answer:

  • VALIDATE PASSWORD component: Y (enable password strength checking)
  • Remove anonymous users: Y
  • Disallow root login remotely: Y
  • Remove test database: Y
  • Reload privilege tables: Y

Log in to MySQL to confirm everything is working:

sudo mysql -u root -p

4. Install PHP

Ubuntu 22.04 ships PHP 8.1 in its default repositories. Install it along with the commonly needed extensions:

sudo apt install php libapache2-mod-php php-mysql php-cli php-curl php-gd php-mbstring php-xml php-zip -y

Here’s a quick breakdown of why each extension matters:

  • php-mysql — connects PHP to MySQL/MariaDB
  • php-mbstring — handles multibyte string processing (required for Japanese, Vietnamese, etc.)
  • php-xml — handles XML parsing; many PHP frameworks won’t run without this
  • php-zip — used by WordPress when installing or updating plugins

Verify the installed version:

php -v

Detailed Configuration

Creating a Virtual Host for Your Application

Dropping everything into the default /var/www/html directory is fine for a quick test, but no more than that. I always create a dedicated Virtual Host for each project — it lets you run multiple websites on the same server without them interfering with each other.

Create the project directory and set ownership:

sudo mkdir -p /var/www/myapp/public
sudo chown -R $USER:$USER /var/www/myapp/public
sudo chmod -R 755 /var/www/myapp

Open a new Virtual Host config file:

sudo nano /etc/apache2/sites-available/myapp.conf

Paste in the following:

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ServerName myapp.local
    DocumentRoot /var/www/myapp/public

    <Directory /var/www/myapp/public>
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/myapp-error.log
    CustomLog ${APACHE_LOG_DIR}/myapp-access.log combined
</VirtualHost>

Enable the site and the mod_rewrite module — both Laravel and WordPress require it:

sudo a2ensite myapp.conf
sudo a2enmod rewrite
sudo systemctl restart apache2

Creating a MySQL Database and User for Your Application

Never connect to your database as root from your application — always create a dedicated user with the minimum necessary privileges:

sudo mysql -u root -p

CREATE DATABASE myapp_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'myapp_user'@'localhost' IDENTIFIED BY 'StrongPassword123!';
GRANT ALL PRIVILEGES ON myapp_db.* TO 'myapp_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Note: Use utf8mb4 instead of utf8 to ensure full Unicode support, including emoji. WordPress had a well-known bug where emoji would get corrupted on save — all because the utf8 charset only supports 3 bytes per character, while emoji require 4.

Tuning PHP Configuration for Production

The PHP config file for Apache lives at /etc/php/8.1/apache2/php.ini. These are the settings I adjust immediately after a fresh install:

sudo nano /etc/php/8.1/apache2/php.ini

Use Ctrl+W in nano to search for each setting, then update them as follows:

; File upload size limit (adjust to your needs)
upload_max_filesize = 64M
post_max_size = 64M

; Increase memory limit for heavier applications
memory_limit = 256M

; Maximum script execution time (seconds)
max_execution_time = 60

; Disable error display on production (enable during development)
display_errors = Off
log_errors = On
error_log = /var/log/php_errors.log

Save the file, then restart Apache to apply the changes:

sudo systemctl restart apache2

Testing and Monitoring

Verify PHP Is Working Correctly

Create a phpinfo.php file to test:

sudo nano /var/www/myapp/public/phpinfo.php
<?php
phpinfo();
?>

Visit http://<your-server-IP>/phpinfo.php — you’ll see the full PHP information page. Check that the extensions you installed (mysql, mbstring, xml, etc.) are listed.

Delete this file immediately after you’re done — leaving it publicly accessible is a serious security vulnerability. It exposes your entire server configuration to anyone who visits the URL:

sudo rm /var/www/myapp/public/phpinfo.php

Test the PHP → MySQL Connection

Create a database connection test file:

<?php
$conn = new mysqli('localhost', 'myapp_user', 'StrongPassword123!', 'myapp_db');

if ($conn->connect_error) {
    die('Connection error: ' . $conn->connect_error);
}

echo 'MySQL connection successful! Server version: ' . $conn->server_info;
$conn->close();
?>

If you see “MySQL connection successful”, your LAMP Stack is working end-to-end. Remember to delete this test file once you’ve confirmed everything is working.

Three Service Check Commands Worth Bookmarking

Before announcing “deployment complete” to the team, I always do a quick run through these:

# Check Apache status
sudo systemctl status apache2

# Check MySQL status
sudo systemctl status mysql

# Watch Apache error log in real time
sudo tail -f /var/log/apache2/error.log

# Watch MySQL error log
sudo tail -f /var/log/mysql/error.log

Or use this cleaner one-liner:

for svc in apache2 mysql; do
  echo -n "$svc: "
  systemctl is-active $svc
done

Both should print active.

Check Which Ports Are Listening

sudo ss -tlnp | grep -E '(:80|:443|:3306)'

Apache should be on port 80, MySQL on 3306. Note that MySQL only binds to 127.0.0.1 by default — this is the correct secure configuration and means it’s not exposed to the internet.

Common Issues and Fixes

  • Apache won’t start: Run sudo apachectl configtest first. The most common culprit is a config syntax error — a missing bracket or angle bracket — or port 80 already being in use by another process.
  • PHP extension won’t load: Check /etc/php/8.1/apache2/conf.d/ — each extension has its own .ini file there. Quickly verify with php -m | grep mysql.
  • MySQL refuses connection: This is a common gotcha — 'user'@'localhost' and 'user'@'127.0.0.1' are treated as two different users in MySQL. Double-check the host you specified when creating the user.

Share: