Setting Up a LAMP Stack on a VPS: Secure, Fast, and Production-Ready
LAMP on a VPS: What you will build and why it matters
A LAMP stack—Linux, Apache, MariaDB/MySQL, and PHP—is still the foundation of choice for dynamic web sites and APIs. On a VPS, you have root access, predictable performance, and the ability to harden security for your needs—unlike noisy neighbors on entry-level shared hosting. If you're still deciding between environments, read up with our primer What is VPS Hosting and Why It Might Be the Right Hosting for You.
Goal: Provision a production-grade LAMP server on an Ubuntu (22.04/24.04) VPS, including a firewall, a hardened database server, latest PHP 8.x, a virtual host for your domain, and free HTTPS using Let's Encrypt.
Prep work and an architecture sketch
- A fresh VPS (1–2 vCPU, 1–2 GB RAM minimum for small WordPress/Joomla sites; more for dynamic sites).
- Ubuntu 22.04 LTS or 24.04 LTS with SSH access (root or sudo user).
- A domain name pointing at an IPv4/IPv6 of your server (A/AAAA).
- Some familiarity with the shell, e.g., SSH, editing config files, restarting services.
| Component | Role | Notes |
|---|---|---|
| Linux (Ubuntu) | Base OS | Stable LTS, large package ecosystem |
| Apache | Web server | Modules, .htaccess, virtual hosts |
| MariaDB/MySQL | Database | SQL storage, users, backups |
| PHP 8.x | Runtime | Fast, actively maintained, FPM preferred |
Production note: Prefer php-fpm over the legacy Apache libapache2-mod-php. FPM provides better performance and resource isolation.
Server hardening and updates—part 1
Log in via SSH as a sudo user; don't log in as root daily. Update packages and set hostname/timezone.
# connect
ssh ubuntu@your_server_ip
# update & basic tools
sudo apt update && sudo apt -y upgrade
sudo apt -y install curl vim ufw htop unzip
# optional: set timezone
sudo timedatectl set-timezone UTC
Set up a basic firewall with UFW (allow SSH first, then allow web traffic).
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status
Why now? Enabling the firewall early reduces the risk during the stack installation.
Install Apache and activate useful modules
Apache is mature, stable, and easy to extend. Install it and enable the modules you'll need for rewrites, and FPM.
sudo apt -y install apache2
sudo a2enmod rewrite headers ssl proxy_fcgi setenvif
# FPM integration module is enabled later with PHP packages
sudo systemctl enable --now apache2
sudo systemctl status apache2
Confirm that the default page is served up by loading http://your domain or http://your_server_ip. If you get the Apache default page, you're good to go.
Install MariaDB (or MySQL) and run the secure installation
MariaDB is a binary-compatible replacement for MySQL, which works great for most PHP apps.
sudo apt -y install mariadb-server
sudo systemctl enable --now mariadb
sudo mariadb-secure-installation
- Set a strong root password (or swap to Unix socket auth as suggested).
- Remove anonymous users and the test DB.
- Disallow remote root login if using in production.
Create an application DB and user (sub in values below):
sudo mariadb -e "CREATE DATABASE appdb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
sudo mariadb -e "CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'STRONG_PASSWORD_HERE';"
sudo mariadb -e "GRANT ALL PRIVILEGES ON appdb.* TO 'appuser'@'localhost'; FLUSH PRIVILEGES;"
Charset note: Prefer utf8mb4 over utf8 to fully support emojis and multibyte characters.
Install PHP 8.x with FPM and commonly used extensions
Install PHP-FPM and useful modules for popular CMS/framework:
sudo apt -y install php8.3-fpm php8.3-cli php8.3-mysql php8.3-curl php8.3-xml \
php8.3-mbstring php8.3-zip php8.3-gd php8.3-intl php8.3-bcmath
# enable Apache <-> PHP-FPM integration
sudo a2enconf php8.3-fpm
sudo systemctl reload apache2
Verify:
php -v
php -m | grep -E "mysql|curl|xml|mbstring|zip|gd|intl|bcmath"
systemctl status php8.3-fpm
Performance tuning: For small VPS plans, tune pm.max_children in /etc/php/8.3/fpm/pool.d/www.conf (e.g., 5-10) to avoid memory exhaustion for slowloris-type attacks.
Create a virtual host for your domain
Organize your site files under /var/www/yourdomain and create a dedicated vhost that proxies PHP requests to FPM.
sudo mkdir -p /var/www/yourdomain/public
sudo chown -R www-data:www-data /var/www/yourdomain
sudo chmod -R 755 /var/www/yourdomain
# sample PHP probe
echo "" | sudo tee /var/www/yourdomain/public/info.php > /dev/null
Virtual host config (sub in yourdomain.com):
sudo nano /etc/apache2/sites-available/yourdomain.conf
# Paste:
ServerName yourdomain.com
ServerAlias www.yourdomain.com
DocumentRoot /var/www/yourdomain/public
AllowOverride All
Require all granted
<FilesMatch "\.php$">
SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost/"
ErrorLog ${APACHE_LOG_DIR}/yourdomain_error.log
CustomLog ${APACHE_LOG_DIR}/yourdomain_access.log combined
Enable the site and reload Apache:
sudo a2dissite 000-default.conf
sudo a2ensite yourdomain.conf
sudo systemctl reload apache2
Rewrites & permalinks: AllowOverride All lets CMS apps (WP, Joomla, etc.) use .htaccess for clean URLs. For stricter security
Step 3: Setting Up Apache, MySQL, and PHP
Now that we have installed all the necessary components, it is time to configure them to interact correctly with one another. Apache will be the one to serve your web pages, MySQL will store your application data, and PHP will be the middleware that connects Apache and MySQL.
1. Configure Apache
To create a virtual host file for your project to keep your settings organized:
sudo nano/etc/apache2/sites-available/myproject.conf
Then enter the following configuration:
<VirtualHost *:80>
ServerAdmin This email address is being protected from spambots. You need JavaScript enabled to view it.
ServerName myproject.com
DocumentRoot /var/www/myproject
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Save the file, and enable your virtual host:
sudo a2ensite myproject.conf
sudo systemctl reload apache2
2. Secure and Configure MySQL
After installation, you should secure your MySQL server:
sudo mysql_secure_installation
Set a root password, remove anonymous users, disable remote root logins, and delete test databases for better security.
Create a new database and user:
CREATE DATABASE myproject;
CREATE USER 'myuser'@'localhost' IDENTIFIED BY 'strongpassword';
GRANT ALL PRIVILEGES ON myproject.* TO 'myuser'@'localhost';
FLUSH PRIVILEGES;
3. Test PHP Integration
Verify that PHP is correctly integrated with Apache:
sudo nano /var/www/html/info.php
Add the following code:
<?php
phpinfo();
?>
Visit http://your-server-ip/info.php in your web browser. You should see the PHP information page, indicating everything is working properly.
For more information regarding hosting environments and alternatives to a VPS, check out our article on Hosting vs. VPS: Key Differences Explained.
At this point, you should have a working LAMP stack running on your VPS server. The last step is to optimize its performance and secure things a little more.
Step 4: Optimize and Secure Your LAMP Stack
Now that you have your LAMP stack installed and running, it is important to optimize its performance and secure your server from potential threats. A well-optimized stack not only performs better but also protects itself from attacks.
1. Activate a Firewall
Begin by enabling UFW (Uncomplicated Firewall) to manage your server's incoming and outgoing traffic:
sudo ufw allow OpenSSH
sudo ufw allow in "Apache Full"
sudo ufw enable
This setting will allow SSH connections and HTTP/HTTPS traffic while rejecting everything else.
2. Secure Apache
- Disable directory listing with
Options -Indexesin your virtual host configuration. - Mask the Apache version and OS name by editing
/etc/apache2/conf-available/security.confand adding:
ServerTokens Prod
ServerSignature Off
- Use HTTPS by installing a free SSL certificate using Let’s Encrypt:
sudo apt install certbot python3-certbot-apache
sudo certbot --apache
3. Optimize MySQL
Open the configuration file with:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
Adjust parameters such as innodb_buffer_pool_size and query_cache_size, based on your server's amount of RAM, to improve database queries. Continuously check performance with:
mysqltuner
4. Harden PHP
- Disable potentially dangerous functions by editing
/etc/php/*/apache2/php.ini:
disable_functions = exec,passthru,shell_exec,system
- Turn off PHP error display when in production:
display_errors = Off
- Keep PHP regularly updated in case of vulnerabilities.
By following these procedures, you have a fully-featured, optimized, and secured LAMP stack of your own VPS at your disposal. This setup is ideal for hosting websites, applications, or even for experimentation with custom projects. For further insight into web hosting setups, you can read our guide about Shared Hosting Explained.
Now that your LAMP stack is all set up, you can confidently deploy applications such as WordPress, Laravel, or even any custom-built platform.