LAMP Stack on Alibaba Cloud ECS: From Fresh Instance to Production-Ready Web Server
Chen Kai BOSS

Turning a fresh Alibaba Cloud ECS instance from "I can SSH in" to "public visitors can access my site reliably" involves three common stumbling blocks: network access (security groups + firewall rules), service coordination (Apache – PHP – MySQL request pipeline), and permission/version mismatches (directory ownership, PHP extensions, MySQL authentication). This guide first clarifies the LAMP architecture with diagrams, then walks through security group configuration, environment installation with verification steps, Apache/MySQL/PHP installation with key configurations, and finally a complete Discuz deployment plus source-compile installation workflow (including cleanup, dependency preparation, service auto-start, and common troubleshooting scenarios). By the end, you'll have a traditional Web stack running on the cloud from 0 to 1.

Why LAMP Still Matters in 2025

LAMP (Linux + Apache + MySQL + PHP) is often dismissed as "legacy" compared to containerized microservices, but for small to mid-sized content sites, CMS platforms (WordPress, Discuz, Drupal), and many SaaS backends, LAMP remains the most cost-effective, well-documented, and maintenance-friendly solution.

Key advantages:

  • Mature ecosystem: Decades of plugins, tutorials, stack overflow answers
  • Shared hosting compatibility: Easy to migrate from/to managed hosting
  • Predictable performance: No orchestration overhead, direct request path
  • Lower barrier: One server, three services — easier to reason about than Kubernetes

When NOT to use LAMP:

  • High concurrency APIs (consider Nginx + Node/Go/Rust)
  • Microservices architecture (use Docker + orchestration)
  • Real-time features (WebSocket-heavy apps prefer event-driven stacks)

LAMP Architecture: The Request Flow

Understanding how a request travels through the stack is critical for debugging.

The four-layer model

  1. User → Apache (Web Server)
    Browser sends HTTP request to port 80/443. Apache parses the URL and determines which file to serve.

  2. Apache → PHP (Application Runtime)
    If the requested file is .php, Apache invokes PHP via mod_php or FastCGI to execute the script.

  3. PHP → MySQL (Database)
    PHP script queries MySQL via mysqli/PDO extensions to fetch/store data.

  4. MySQL → PHP → Apache → User
    Data flows back through the same pipeline, rendered as HTML and returned to the browser.

Critical interfaces to verify:

  • Apache can read .php files (file permissions)
  • Apache can invoke PHP (module loaded)
  • PHP can connect to MySQL (extension installed, credentials correct)

Part I: Alibaba Cloud ECS Networking Setup

Before installing any software, you must open ports at two layers: cloud security group (virtual firewall) and OS-level firewall (iptables/firewalld).

1. Assigning a Public IP

In the ECS console:

  • Select your instance → NetworkingPublic IP.
  • If no public IP is assigned, bind one from your available IP pool.
  • Record the IP (e.g., 8.134.207.88) for testing later.

2. Configuring Security Group Rules

Navigate to Security GroupsManage RulesInbound. Add:

Protocol Port Source CIDR Purpose
TCP 22 0.0.0.0/0 SSH login
TCP 80 0.0.0.0/0 HTTP traffic
TCP 443 0.0.0.0/0 HTTPS traffic
TCP 3306 Your IP only MySQL remote access (optional, risky if opened to all)

Security tip: Never expose MySQL (3306) to 0.0.0.0/0 in production. Use SSH tunneling instead:

1
ssh -L 3306:localhost:3306 user@8.134.207.88

3. OS-level Firewall (iptables/firewalld)

On CentOS/RHEL (firewalld):

1
2
3
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

On Ubuntu/Debian (ufw):

1
2
3
4
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

Verification:

1
curl http://YOUR_PUBLIC_IP
If you see "Connection refused," check security group. If you see "No route to host," check OS firewall.


Part II: Installing LAMP Components (Ubuntu Example)

Prerequisites: Disable conflicting services

Before installing, stop any existing web servers or databases:

1
2
3
4
5
6
# Check for running services
sudo systemctl status apache2 httpd nginx mysql mariadb

# Stop if found
sudo systemctl stop apache2 httpd nginx mysql mariadb
sudo systemctl disable apache2 httpd nginx mysql mariadb

1. Apache Web Server

Installation

1
2
sudo apt update
sudo apt install -y apache2

Start and enable

1
2
sudo systemctl start apache2
sudo systemctl enable apache2

Verify

Visit http://YOUR_PUBLIC_IP/. You should see the Apache2 Ubuntu Default Page.

If you see "Unable to connect": 1. Check security group (port 80 open?) 2. Check firewall: sudo ufw status 3. Check Apache is running: sudo systemctl status apache2

Key directories

  • Config: /etc/apache2/apache2.conf
  • Virtual hosts: /etc/apache2/sites-available/
  • Document root: /var/www/html/ (default landing page)
  • Logs: /var/log/apache2/access.log, /var/log/apache2/error.log

2. MySQL Database

Installation (Ubuntu uses MySQL, CentOS often uses MariaDB)

1
sudo apt install -y mysql-server

Run security wizard

1
sudo mysql_secure_installation

Follow the prompts:

  • Set root password (strong, at least 12 chars)
  • Remove anonymous users: Yes
  • Disallow root login remotely: Yes (use SSH tunnel instead)
  • Remove test database: Yes

Verify

1
2
sudo systemctl status mysql
sudo mysql -u root -p

Inside MySQL:

1
2
3
SHOW DATABASES;
CREATE DATABASE test_lamp;
EXIT;

Common pitfall: Authentication plugin mismatch

MySQL 8.0+ uses caching_sha2_password by default, but many PHP apps expect mysql_native_password. Fix:

1
2
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'yourpassword';
FLUSH PRIVILEGES;

3. PHP and Extensions

Installation

1
sudo apt install -y php libapache2-mod-php php-mysql

Verify PHP integration with Apache

1
echo "<?php phpinfo(); ?>" | sudo tee /var/www/html/info.php

Visit http://YOUR_PUBLIC_IP/info.php. You should see a PHP information page listing:

  • PHP version (e.g., 7.4 or 8.1)
  • Loaded extensions (check for mysqli, pdo_mysql)

If you see the source code instead of the PHP info page:

  • Apache is not processing .php files. Check: sudo a2enmod php7.4 (replace with your version).
  • Restart Apache: sudo systemctl restart apache2.

Install additional extensions (commonly needed)

1
2
sudo apt install -y php-curl php-gd php-mbstring php-xml php-zip
sudo systemctl restart apache2

Part III: Deploying a Real Application (Discuz! Forum)

Discuz! is a popular PHP forum software. Deploying it reveals the most common LAMP pitfalls: file permissions, MySQL user creation, and PHP extension requirements.

1. Download and extract Discuz!

1
2
3
4
5
6
cd /var/www/html
sudo wget https://download.comsenz.com/DiscuzX/3.4/Discuz_X3.4_SC_UTF8.zip
sudo apt install -y unzip
sudo unzip Discuz_X3.4_SC_UTF8.zip
sudo mv upload/* .
sudo rm -rf upload Discuz_X3.4_SC_UTF8.zip

2. Set directory permissions

Apache runs as user www-data (Ubuntu) or apache (CentOS). It must be able to read/write certain directories:

1
2
sudo chown -R www-data:www-data /var/www/html
sudo chmod -R 755 /var/www/html

For Discuz-specific directories (the installer checks these):

1
2
3
4
sudo chmod -R 777 /var/www/html/data
sudo chmod -R 777 /var/www/html/config
sudo chmod -R 777 /var/www/html/uc_server/data
sudo chmod -R 777 /var/www/html/uc_client/data

Security note: chmod 777 is convenient but risky. After installation, tighten to 755 or 750.

3. Create MySQL database and user

1
sudo mysql -u root -p

Inside MySQL:

1
2
3
4
5
CREATE DATABASE discuz CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER 'discuz_user'@'localhost' IDENTIFIED BY 'StrongPassword123!';
GRANT ALL PRIVILEGES ON discuz.* TO 'discuz_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;

4. Run the web installer

Visit http://YOUR_PUBLIC_IP/install/. The installer will: 1. Check environment (PHP version, extensions) 2. Check permissions (can it write to data/, config/?) 3. Ask for database credentials

Fill in:

  • Database host: localhost
  • Database name: discuz
  • Database user: discuz_user
  • Database password: StrongPassword123!

If the installer complains about missing extensions, install them:

1
2
sudo apt install -y php-mysqli php-gd
sudo systemctl restart apache2

5. Post-installation cleanup

After installation succeeds, delete the installer:

1
sudo rm -rf /var/www/html/install


Part IV: Troubleshooting Checklist

Problem 1: "Connection refused" when accessing site

Cause: Port blocked or service not running

Debug steps: 1. Check Apache is running: sudo systemctl status apache2 2. Check listening ports: sudo ss -tuln | grep 80 3. Check security group (port 80 open?) 4. Check OS firewall: sudo ufw status or sudo firewall-cmd --list-all

Solution:

1
2
sudo systemctl start apache2
sudo ufw allow 80/tcp

Problem 2: "403 Forbidden" when accessing a directory

Cause: Missing index.php/index.html or directory permissions

Debug steps: 1. Check if file exists: ls -l /var/www/html/ 2. Check Apache can read it: sudo -u www-data cat /var/www/html/index.php 3. Check DirectoryIndex directive in Apache config

Solution:

1
2
3
4
5
# Fix ownership
sudo chown -R www-data:www-data /var/www/html

# Or temporarily test with permissive permissions
sudo chmod -R 755 /var/www/html

Problem 3: PHP shows as plain text (source code visible)

Cause: Apache is not processing .php files

Debug steps: 1. Check if PHP module is loaded: apache2ctl -M | grep php 2. Check .htaccess or virtual host config

Solution:

1
2
3
4
5
# Enable PHP module (Ubuntu/Debian)
sudo a2enmod php7.4 # Replace with your PHP version
sudo systemctl restart apache2

# Verify: curl http://localhost/info.php (should see PHP output, not source)

Problem 4: "Can't connect to MySQL server on 'localhost'"

Cause: MySQL service not running or connection credentials wrong

Debug steps: 1. Check MySQL is running: sudo systemctl status mysql 2. Test connection: mysql -u discuz_user -p -h localhost 3. Check bind-address in /etc/mysql/mysql.conf.d/mysqld.cnf (should be 127.0.0.1 for localhost)

Solution:

1
2
3
sudo systemctl start mysql
# If still failing, check MySQL error log:
sudo tail -f /var/log/mysql/error.log

Problem 5: Discuz installer says "Directory not writable"

Cause: Apache cannot write to required directories

Solution:

1
2
sudo chown -R www-data:www-data /var/www/html
sudo chmod -R 777 /var/www/html/data /var/www/html/config /var/www/html/uc_server/data /var/www/html/uc_client/data

After installation, tighten permissions:

1
sudo chmod -R 755 /var/www/html/data


Part V: Best Practices for Production LAMP

1. Never run as root

Always run services as dedicated users:

  • Apache: www-data (Ubuntu) or apache (CentOS)
  • MySQL: mysql

2. Use virtual hosts for multiple sites

Instead of dumping everything in /var/www/html/, create virtual hosts:

1
2
3
4
5
6
7
8
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/example.com
<Directory /var/www/example.com>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>

Save to /etc/apache2/sites-available/example.com.conf, then:

1
2
sudo a2ensite example.com
sudo systemctl reload apache2

3. Enable HTTPS

Use Encrypt for free certificates:

1
2
sudo apt install -y certbot python3-certbot-apache
sudo certbot --apache -d example.com -d www.example.com

4. Harden MySQL

  • Disable remote root login
  • Use strong passwords (12+ chars, mixed case, symbols)
  • Create per-app database users (never reuse root)

5. Monitor logs

Set up log rotation and monitoring:

1
2
3
4
5
6
# Apache logs
tail -f /var/log/apache2/access.log
tail -f /var/log/apache2/error.log

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

6. Automate backups

1
2
3
4
5
6
# Database backup script
mysqldump -u root -p discuz > /backups/discuz_$(date +%F).sql

# Schedule daily backups
crontab -e
0 2 * * * mysqldump -u root -pYourPassword discuz > /backups/discuz_$(date +\%F).sql

Part VI: Source Compilation (Advanced)

If you need a specific version not available in repos, or want maximum optimization, compile from source.

Why compile from source?

Pros:

  • Control over build flags (enable/disable features)
  • Latest version (repos lag behind)
  • Custom patches

Cons:

  • Time-consuming (hours for MySQL)
  • Manual dependency resolution
  • No automatic security updates

Compiling MySQL 5.6 from source

Prerequisites

1
sudo yum install -y gcc gcc-c++ cmake bison libaio-devel ncurses-devel zlib-devel openssl-devel

Download and extract

1
2
3
4
5
cd /usr/local
sudo mkdir software-mysql && cd software-mysql
sudo wget https://repo.huaweicloud.com/mysql/Downloads/MySQL-5.6/mysql-5.6.49.tar.gz
sudo tar -xzvf mysql-5.6.49.tar.gz
cd mysql-5.6.49

Configure

1
2
3
4
5
6
7
8
9
10
cmake . \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DMYSQL_DATADIR=/usr/local/mysql/data \
-DENABLE_LOCAL_INFILE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DMYSQL_TCP_PORT=3306 \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DWITH_EXTRA_CHARSETS=all \
-DMYSQL_USER=mysql

Compile (expect 1-3 hours)

1
2
make -j$(nproc)
sudo make install

Initialize

1
2
3
4
sudo useradd -r -s /sbin/nologin mysql
sudo chown -R mysql:mysql /usr/local/mysql
cd /usr/local/mysql
sudo ./scripts/mysql_install_db --user=mysql

Create systemd service

1
2
3
sudo cp support-files/mysql.server /etc/init.d/mysql
sudo systemctl enable mysql
sudo systemctl start mysql

Part VII: Real-World Case Studies

Case 1: Migrating from shared hosting

Scenario: Moving a WordPress site from GoDaddy to Alibaba Cloud ECS.

Steps: 1. Export database: mysqldump from old host 2. Copy files via SFTP to /var/www/html 3. Import database on new host 4. Update wp-config.php with new DB credentials 5. Update DNS A record to new public IP

Pitfall: File permissions. On shared hosting, everything is owned by your user. On ECS, Apache runs as www-data. Fix: sudo chown -R www-data:www-data /var/www/html.

Case 2: Running multiple sites (virtual hosts)

Scenario: Host blog.example.com and forum.example.com on one instance.

Solution: Create two virtual hosts:

1
2
3
4
5
6
7
8
9
10
11
# /etc/apache2/sites-available/blog.conf
<VirtualHost *:80>
ServerName blog.example.com
DocumentRoot /var/www/blog
</VirtualHost>

# /etc/apache2/sites-available/forum.conf
<VirtualHost *:80>
ServerName forum.example.com
DocumentRoot /var/www/forum
</VirtualHost>

Enable:

1
2
sudo a2ensite blog forum
sudo systemctl reload apache2

Case 3: Handling PHP version conflicts

Scenario: Old app requires PHP 5.6, new app requires PHP 7.4.

Solution: Use php-fpm with different versions:

1
2
3
4
5
6
7
8
9
10
# Install both versions
sudo apt install -y php5.6-fpm php7.4-fpm

# Configure virtual host to use specific version
<VirtualHost *:80>
ServerName oldapp.example.com
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php5.6-fpm.sock|fcgi://localhost"
</FilesMatch>
</VirtualHost>


Summary: LAMP in 5 Steps

  1. Open ports (security group + OS firewall)
  2. Install services (Apache, MySQL, PHP)
  3. Verify each layer (Apache serves HTML → PHP runs → MySQL connects)
  4. Set permissions (Apache user can read/write)
  5. Deploy app (Discuz, WordPress, etc.)

Next steps:

  • Enable HTTPS with Encrypt
  • Set up automated backups
  • Monitor with Zabbix or Prometheus
  • Explore Nginx as an Apache alternative

Further reading:

  • Apache docs: https://httpd.apache.org/docs/
  • MySQL reference: https://dev.mysql.com/doc/
  • PHP manual: https://www.php.net/manual/en/
  • Post title:LAMP Stack on Alibaba Cloud ECS: From Fresh Instance to Production-Ready Web Server
  • Post author:Chen Kai
  • Create time:2023-01-07 00:00:00
  • Post link:https://www.chenk.top/en/lamp-on-ecs/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.
 Comments