A LAMP stack (Linux, Apache, MySQL, PHP) is still a common baseline for running PHP applications on a self-managed Ubuntu server — here's a working setup, current as of recent Ubuntu LTS releases.
1. Update package lists
sudo apt update && sudo apt upgrade -y
2. Install Apache
sudo apt install apache2 -y
sudo systemctl enable apache2
sudo systemctl start apache2
3. Install MySQL
sudo apt install mysql-server -y
sudo mysql_secure_installation
mysql_secure_installation walks through setting a root password, removing anonymous users, and disabling remote root login — don't skip this step on anything beyond a throwaway local environment.
4. Install PHP and common extensions
sudo apt install php libapache2-mod-php php-mysql php-mbstring php-xml php-curl -y
The specific extension list depends on what the application needs — a Laravel project typically also needs php-zip, php-bcmath, and php-gd or php-imagick for image handling.
5. Restart Apache to load PHP
sudo systemctl restart apache2
6. Install phpMyAdmin
sudo apt install phpmyadmin -y
During installation, select apache2 when prompted for the web server to configure automatically, and choose whether to let the installer configure the database for phpMyAdmin itself.
The step people miss: enabling the Apache config
If phpMyAdmin was installed separately from Apache, or the automatic prompt was skipped, the Apache config for it needs to be included manually:
sudo ln -s /etc/phpmyadmin/apache.conf /etc/apache2/conf-available/phpmyadmin.conf
sudo a2enconf phpmyadmin
sudo systemctl reload apache2
Without this, /phpmyadmin returns a 404 even though the package installed successfully — a common point of confusion.
Security note for a real server
phpMyAdmin is a high-value administration surface on a public server. For anything beyond local development, restrict access with a real control such as a VPN, firewall/IP allow-list, or an additional authenticated gateway. Moving it to a non-default URL can reduce noise from generic scanners, but obscurity is not an access-control boundary.
Verify the installed PHP version and modules before configuring the app
php -v
php -m
apache2ctl -M | grep php
The Ubuntu repository decides which PHP version the unversioned php packages install. Application requirements should drive whether that repository version is acceptable; do not add a third-party repository merely because a tutorial uses one. After installation, confirm the CLI and Apache are actually using the version and extensions you expect.
Apache needs the right document root for frameworks
A Laravel application's web root is its public/ directory, not the project root. Pointing an Apache virtual host at the whole repository can expose files that should never be web-accessible, including dependency metadata or environment configuration if another server rule is also wrong. A minimal virtual host should set DocumentRoot to the application's public directory and allow the rewrite behavior the framework expects.
Do not test PHP with a permanent phpinfo page
A temporary file containing <?php phpinfo(); is useful for confirming Apache's PHP integration, but remove it immediately after testing. The output reveals loaded modules, filesystem paths, server configuration, and environment details that are useful for debugging and equally useful to an attacker.
MySQL root authentication may not work the way older tutorials expect
Ubuntu's packaged MySQL commonly configures local administrative access around the operating-system account rather than requiring the same password-based root flow shown in older generic guides. If mysql -u root -p behaves differently than expected, inspect the installed authentication configuration before resetting credentials. For applications, create a dedicated database and a least-privileged application user instead of connecting Laravel or plain PHP as MySQL root.