CREATE ACCOUNT
Create an account first before you click checkout and contact admin for your queries
Ubuntu 22.04 64-bit LAMP Stack — Production Documentation

Ubuntu 22.04 64-bit LAMP Stack

Production-oriented installation, configuration, security, deployment, backup, monitoring and troubleshooting documentation.
Apache + PHP 8.1 + MySQL + Ubuntu 22.04 LTS
1

System Preparation

Update Ubuntu and verify that the server is running the expected 64-bit architecture.

sudo apt update
sudo apt upgrade -y
sudo apt full-upgrade -y
sudo apt autoremove -y

Check the operating system and CPU architecture:

uname -m
dpkg --print-architecture
lsb_release -a
cat /etc/os-release

Check server resources:

free -h
df -h
lsblk
lscpu
2

Basic Server Security

Create a dedicated administrative user:

sudo adduser adminuser
sudo usermod -aG sudo adminuser

Install useful administration tools:

sudo apt install -y curl wget vim nano unzip zip git htop tree net-tools lsof ca-certificates gnupg software-properties-common apt-transport-https

Install and configure UFW:

sudo apt install -y ufw
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

Do not expose MySQL port 3306 publicly unless it is specifically required and protected by network restrictions.

3

Install Apache

sudo apt update
sudo apt install -y apache2

Enable and start Apache:

sudo systemctl enable --now apache2

Check Apache:

systemctl status apache2
apache2 -v

Test configuration:

sudo apache2ctl configtest

Default web root: /var/www/html

Test Apache locally:

curl http://localhost

Apache service commands:

sudo systemctl start apache2
sudo systemctl stop apache2
sudo systemctl restart apache2
sudo systemctl reload apache2
sudo systemctl enable apache2
sudo systemctl disable apache2

Apache logs:

sudo tail -f /var/log/apache2/access.log
sudo tail -f /var/log/apache2/error.log
4

Apache Modules

List loaded modules:

apache2ctl -M

Enable common modules:

sudo a2enmod rewrite
sudo a2enmod headers
sudo a2enmod ssl
sudo a2enmod expires
sudo a2enmod http2
sudo systemctl reload apache2

Disable a module:

sudo a2dismod MODULE_NAME
5

Install PHP

Ubuntu 22.04 LTS provides PHP 8.1 as its standard PHP release.

sudo apt update
sudo apt install -y php libapache2-mod-php php-cli php-common php-mysql php-curl php-gd php-mbstring php-xml php-zip php-intl php-bcmath php-soap php-opcache

Verify PHP:

php -v

List PHP modules:

php -m

Check PHP configuration:

php --ini

Create a temporary PHP information page:

sudo nano /var/www/html/info.php
<?php
phpinfo();
?>

Open /info.php in a browser, then remove it immediately after testing.

sudo rm /var/www/html/info.php
6

PHP Configuration

Edit the Apache PHP configuration:

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

Important settings include:

memory_limit
upload_max_filesize
post_max_size
max_execution_time
max_input_time
max_input_vars
max_file_uploads
date.timezone
display_errors
log_errors
error_log

Production example:

display_errors = Off
log_errors = On
date.timezone = Asia/Manila
memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 60

Restart Apache after changes:

sudo systemctl restart apache2
7

PHP OPcache

OPcache improves PHP performance by caching compiled PHP bytecode.

sudo apt install -y php8.1-opcache
php -i | grep -i opcache

Tune OPcache according to the application's workload and available memory rather than blindly copying settings from another server.

8

Install MySQL

sudo apt update
sudo apt install -y mysql-server
sudo systemctl enable --now mysql

Check MySQL:

sudo systemctl status mysql
mysql --version

Run the security configuration:

sudo mysql_secure_installation

Open the MySQL administration shell:

sudo mysql
9

MySQL Database Administration

Create a database:

CREATE DATABASE appdb
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;

Create a restricted application user:

CREATE USER 'appuser'@'localhost'
IDENTIFIED BY 'CHANGE_THIS_TO_A_STRONG_PASSWORD';

GRANT ALL PRIVILEGES ON appdb.*
TO 'appuser'@'localhost';

FLUSH PRIVILEGES;

Test the application account:

mysql -u appuser -p appdb

Useful SQL commands:

SHOW DATABASES;
USE appdb;
SHOW TABLES;
SELECT USER, HOST FROM mysql.user;
SHOW GRANTS FOR 'appuser'@'localhost';
EXIT;

Example table:

CREATE TABLE users (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  email VARCHAR(255) NOT NULL UNIQUE,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
10

MySQL Backup and Restore

Back up one database:

mysqldump -u appuser -p appdb > appdb.sql

Back up all databases:

sudo mysqldump --all-databases > all-databases.sql

Compressed backup:

mysqldump -u appuser -p appdb | gzip > appdb.sql.gz

Restore:

mysql -u appuser -p appdb < appdb.sql

Restore compressed backup:

gunzip -c appdb.sql.gz | mysql -u appuser -p appdb

A backup is not proven until it has been successfully restored. Maintain multiple copies, preferably including off-server storage.

11

Apache Virtual Hosts

Create the website directory:

sudo mkdir -p /var/www/example.com/public_html

Set ownership:

sudo chown -R $USER:www-data /var/www/example.com

Set basic permissions:

sudo chmod -R 755 /var/www/example.com

Create the virtual host:

sudo nano /etc/apache2/sites-available/example.com.conf
<VirtualHost *:80>

    ServerName example.com
    ServerAlias www.example.com

    DocumentRoot /var/www/example.com/public_html

    <Directory /var/www/example.com/public_html>
        Options FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
    CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined

</VirtualHost>

Enable the website:

sudo a2ensite example.com.conf

Optionally disable the default site:

sudo a2dissite 000-default.conf

Test and reload:

sudo apache2ctl configtest
sudo systemctl reload apache2
12

.htaccess and mod_rewrite

Enable rewrite:

sudo a2enmod rewrite
sudo systemctl reload apache2

Example front-controller .htaccess:

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
13

HTTPS with Let's Encrypt

Install Certbot:

sudo apt update
sudo apt install -y certbot python3-certbot-apache

Request and configure the certificate:

sudo certbot --apache -d example.com -d www.example.com

Test automatic renewal:

sudo certbot renew --dry-run

List certificates:

sudo certbot certificates
14

SSL Verification

Enable SSL:

sudo a2enmod ssl
sudo systemctl reload apache2

Check listening ports:

sudo ss -lntp | grep -E ':80|:443'

Inspect Apache virtual hosts:

sudo apache2ctl -S
15

File and Directory Permissions

Inspect files:

ls -lah /var/www/example.com/

Set ownership:

sudo chown -R USER:www-data /var/www/example.com

Set directory permissions:

sudo find /var/www/example.com -type d -exec chmod 755 {} \;

Set file permissions:

sudo find /var/www/example.com -type f -exec chmod 644 {} \;

Avoid using chmod 777 as a general solution. Application-specific writable directories should be configured individually.

16

Apache Security Headers

Enable the headers module:

sudo a2enmod headers
sudo systemctl reload apache2

Example headers:

Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"

Content-Security-Policy and HSTS should be designed and tested specifically for the application.

17

PHP Application Deployment

Example application structure:

/var/www/example.com/
    app/
    config/
    storage/
    vendor/
    public/

When a framework provides a dedicated public directory, use that directory as Apache's DocumentRoot.

Example Composer deployment:

cd /var/www/example.com
composer install --no-dev --optimize-autoloader
18

Git Deployment

Install Git:

sudo apt install -y git

Example clone:

cd /var/www
sudo git clone REPOSITORY_URL example.com

Production deployments should use controlled credentials, protected secrets, reproducible builds, dependency pinning, and a rollback procedure.

19

MySQL Remote Access

Avoid remote MySQL access unless it is required.

If remote access is required:

  • Restrict the source IP/network.
  • Use encrypted connections.
  • Use a dedicated database account.
  • Grant only required privileges.
  • Restrict firewall access.
  • Monitor authentication and network activity.

Never expose port 3306 to the entire Internet without a strong, deliberate security architecture.

20

Service and Process Troubleshooting

Check services:

systemctl status apache2
systemctl status mysql

Check failed services:

systemctl --failed

View logs:

journalctl -u apache2 -n 100 --no-pager
journalctl -u mysql -n 100 --no-pager

Check processes:

ps aux
top
htop

Check ports:

sudo ss -lntup
21

Apache Troubleshooting

Configuration error:

sudo apache2ctl configtest

Recent Apache logs:

sudo journalctl -u apache2 -n 100 --no-pager
sudo tail -n 100 /var/log/apache2/error.log

Virtual hosts:

sudo apache2ctl -S

Enabled sites:

ls -lah /etc/apache2/sites-enabled/

Enabled modules:

apache2ctl -M

For HTTP 403 errors, inspect directory permissions and Apache access rules.

namei -l /var/www/example.com/public_html/index.php
22

PHP Troubleshooting

php -v
php -m
php --ini

Check common database extensions:

php -m | grep mysqli
php -m | grep pdo_mysql

Inspect PHP configuration:

php -i | less

Restart Apache after configuration changes:

sudo systemctl restart apache2
23

MySQL Troubleshooting

sudo systemctl status mysql
sudo journalctl -u mysql -n 100 --no-pager
mysql -u appuser -p
sudo mysql -e "SHOW DATABASES;"
sudo mysql -e "SELECT User,Host FROM mysql.user;"
sudo mysql -e "SHOW GRANTS FOR 'appuser'@'localhost';"
24

Performance Monitoring

CPU and memory:

htop
free -h
uptime

Disk:

df -h
df -i

Network:

ss -s
ip -s link

MySQL processes:

sudo mysql -e "SHOW PROCESSLIST;"

Tune production systems from measured workload data instead of arbitrary configuration values.

25

Log Rotation

Inspect logrotate configuration:

ls /etc/logrotate.d/
cat /etc/logrotate.d/apache2

Test the configuration:

sudo logrotate -d /etc/logrotate.conf

Force rotation only when required:

sudo logrotate -f /etc/logrotate.conf
26

Automatic Security Updates

Install unattended-upgrades:

sudo apt install -y unattended-upgrades

Check service status:

sudo systemctl status unattended-upgrades

Production systems should have a tested patch-management process, maintenance windows where appropriate, and monitoring for failed updates.

27

Web Application Backup

Example site backup:

sudo tar -czf example-site-$(date +%F).tar.gz \
/var/www/example.com

A production backup strategy should consider:

  • Application files
  • Database dumps
  • User uploads
  • Configuration
  • Secrets and certificates where appropriate
  • Deployment configuration
  • Off-server/off-site copies
  • Encryption
  • Retention policies
  • Regular restore tests
28

Cron Jobs

Edit the current user's crontab:

crontab -e

List cron jobs:

crontab -l

System cron locations:

/etc/crontab
/etc/cron.d/
/etc/cron.daily/
/etc/cron.weekly/
/etc/cron.monthly/

Example PHP scheduled task:

*/5 * * * * /usr/bin/php /var/www/example.com/artisan schedule:run >> /var/log/app-cron.log 2>&1
29

Environment Variables and Secrets

Never hard-code production passwords, API keys, private keys or other secrets into PHP source code or Git repositories.

For a protected .env file:

chmod 600 .env

Prefer keeping sensitive files outside the public web root when the application architecture allows it.

30

Common Apache Commands

sudo a2ensite example.com.conf
sudo a2dissite example.com.conf
sudo a2enmod rewrite
sudo a2dismod rewrite
sudo apache2ctl configtest
sudo apache2ctl -S
sudo systemctl reload apache2
sudo systemctl restart apache2
31

Useful Ubuntu Network Commands

ip addr
ip route
resolvectl status
dig example.com
curl -I http://example.com
curl -I https://example.com
sudo ss -lntup
ping -c 4 example.com
32

MySQL Database Maintenance

Check database sizes:

sudo mysql -e "
SELECT table_schema AS db,
ROUND(SUM(data_length+index_length)/1024/1024,2) AS MB
FROM information_schema.tables
GROUP BY table_schema
ORDER BY MB DESC;"

Connect to a database:

mysql -u appuser -p appdb

Inspect tables:

SHOW TABLES;
DESCRIBE users;
33

Common HTTP Status Codes

200  OK
301  Permanent redirect
302  Temporary redirect
304  Not modified
400  Bad request
401  Authentication required
403  Forbidden
404  Not found
405  Method not allowed
408  Request timeout
429  Too many requests
500  Internal server error
502  Bad gateway
503  Service unavailable
504  Gateway timeout
34

Security Checklist

  • Ubuntu packages are current.
  • SSH keys are configured and tested.
  • Direct root SSH login is disabled where appropriate.
  • Firewall is enabled.
  • Only required ports are exposed.
  • Apache is current.
  • PHP is current for the supported application/runtime.
  • MySQL is current.
  • Database users use least privilege.
  • MySQL is not unnecessarily exposed to the Internet.
  • HTTPS is enabled for production websites.
  • Certificate renewal has been tested.
  • Sensitive files are not web-accessible.
  • File permissions are restrictive.
  • Secrets are not stored in Git.
  • Backups are automated.
  • Backups are stored separately.
  • Restore tests are performed.
  • Logs are monitored.
  • Disk usage is monitored.
  • Security updates are managed.
  • A rollback procedure exists.
35

Quick LAMP Installation

Basic installation sequence for Ubuntu 22.04:

sudo apt update
sudo apt upgrade -y

sudo apt install -y apache2
sudo systemctl enable --now apache2

sudo apt install -y php libapache2-mod-php php-mysql php-curl \
php-gd php-mbstring php-xml php-zip php-intl php-bcmath php-opcache

sudo apt install -y mysql-server
sudo systemctl enable --now mysql

sudo a2enmod rewrite headers ssl

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

sudo apache2ctl configtest
sudo systemctl reload apache2

Then:

  1. Create a database and restricted application user.
  2. Create an Apache virtual host.
  3. Point DNS to the server.
  4. Configure HTTPS.
  5. Deploy the application.
  6. Configure backups.
  7. Configure monitoring.
  8. Remove test files.
  9. Verify permissions.
36

Recommended Production Architecture

Internet
   |
   | HTTPS :443
   v
Apache
   |
   +--> PHP application
   |
   +--> Static files/uploads
   |
   v
MySQL
(local/private network)

Operational components:

  • UFW firewall
  • SSH keys
  • Security updates
  • Log rotation
  • Backups
  • Monitoring and alerts
  • HTTPS certificate renewal
37

Disaster Recovery

Document:

  • Server hostnames and IP addresses
  • DNS records
  • Domain names
  • Application deployment procedure
  • Database names and users
  • Backup locations
  • Backup recovery credentials
  • SSL renewal process
  • Required PHP extensions
  • Required system packages
  • Cron jobs
  • Firewall rules
  • External dependencies

Recovery sequence:

  1. Provision a clean supported Ubuntu server.
  2. Apply security updates.
  3. Configure administrative access.
  4. Configure firewall.
  5. Install Apache, PHP and database software.
  6. Restore application files.
  7. Restore database.
  8. Restore configuration and secrets securely.
  9. Configure DNS and HTTPS.
  10. Test the application.
  11. Verify backups.
  12. Monitor the recovered system.
38

Version Notes

Ubuntu package versions change through security and maintenance updates. Do not assume that the exact package revision on one server will match another.

Before production deployment verify:

  • Ubuntu 22.04 security status
  • PHP version required by the application
  • MySQL/MariaDB support requirements
  • Apache package status
  • Application/framework compatibility
  • Third-party repository trust and maintenance
39

Final Verification Commands

Operating system:

lsb_release -a
uname -m

Apache:

apache2 -v
sudo apache2ctl configtest
sudo apache2ctl -S
systemctl is-active apache2

PHP:

php -v
php -m

MySQL:

mysql --version
systemctl is-active mysql

Network:

sudo ss -lntup
sudo ufw status verbose

Disk and memory:

df -h
free -h

Logs:

sudo tail -n 50 /var/log/apache2/error.log
sudo journalctl -u mysql -n 50 --no-pager

HTTPS:

curl -I https://example.com
40

Production Best Practices

  1. Keep Ubuntu and all packages patched.
  2. Use least privilege.
  3. Protect SSH.
  4. Do not expose MySQL unnecessarily.
  5. Use HTTPS.
  6. Do not use chmod 777 as a general fix.
  7. Keep secrets out of source control.
  8. Back up both files and databases.
  9. Test backup restoration.
  10. Monitor logs, disk, CPU and memory.
  11. Test configuration changes before reloading services.
  12. Maintain a documented rollback plan.
  13. Use application-compatible PHP extensions.
  14. Keep production and development credentials separate.
  15. Use reproducible deployment procedures.
  16. Remove diagnostic files such as phpinfo() from production.
  17. Do not blindly copy tuning settings from unrelated servers.
  18. Maintain a recovery path before making access-related changes.
Production note: Review every command for your environment before execution. Keep credentials and private keys out of documentation and source control. Test backups by restoring them.