Two complete web stacks, side-by-side on VM 105 LinuxServer · sharing one MariaDB. Each command block has a Copy button — click, paste, run, verify.
VM 105's noVNC console doesn't accept paste. Use SSH from the Proxmox web shell instead — it pastes cleanly.
In Safari: https://10.10.10.10:8006 → log in as root → click node tctmachine → top tab >_ Shell.
ssh tct_linuxserver@192.168.0.20
Replace tct_linuxserver with your VM 105 admin username if different. Type yes to accept the host key, then your password.
tct_linuxserver@tctlinuxserver:~$.Wipes any prior Apache, NGINX, MariaDB, or PHP installs so we start from zero. If nothing was installed before, this still runs cleanly.
sudo systemctl stop apache2 nginx mariadb 2>/dev/null sudo apt purge -y 'apache2*' 'nginx*' 'mariadb-*' 'php*' libapache2-mod-php sudo apt autoremove --purge -y sudo rm -rf /etc/apache2 /etc/nginx /etc/mysql /var/lib/mysql /var/www/html /var/www/lamp sudo apt update
Reading package lists... Done. No errors.apt list --installed 2>/dev/null | grep -E "(apache|nginx|php|mariadb)"
Output should be empty (no matching packages installed).
sudo apt update && sudo apt upgrade -y
One database backend serves both stacks.
sudo apt install -y mariadb-server mariadb-client sudo systemctl enable --now mariadb sudo systemctl status mariadb --no-pager | head -5
Active: active (running)sudo mysql_secure_installation
Answer the prompts:
| Prompt | Answer |
|---|---|
| Enter current password for root | (press Enter) |
| Switch to unix_socket authentication? | n |
| Change the root password? | Y → set strong password (write it down) |
| Remove anonymous users? | Y |
| Disallow root login remotely? | Y |
| Remove test database? | Y |
| Reload privilege tables? | Y |
sudo mariadb <<'EOF' CREATE DATABASE capstone_db; CREATE USER 'capuser'@'localhost' IDENTIFIED BY 'CapstonePass2026!'; GRANT ALL PRIVILEGES ON capstone_db.* TO 'capuser'@'localhost'; FLUSH PRIVILEGES; SHOW DATABASES; EOF
capstone_db + information_schema, mysql, performance_schema, sys.sudo apt install -y nginx sudo systemctl enable --now nginx curl -sI http://localhost/ | head -2
HTTP/1.1 200 OK + Server: nginx/1.x.xsudo apt install -y php-fpm php-mysql php-cli php-curl php-mbstring php-xml php-zip php -v | head -1 ls /run/php/
PHP 8.x.x (cli) · ls shows a php8.x-fpm.sock file (note the version)sudo tee /etc/nginx/sites-available/default > /dev/null <<'NGINX_CONF'
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.php index.html index.htm;
server_name _;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:PHP_FPM_SOCK_PLACEHOLDER;
}
location ~ /\.ht {
deny all;
}
}
NGINX_CONF
PHP_FPM_SOCK=$(ls /run/php/php*-fpm.sock 2>/dev/null | head -1)
echo "Using PHP-FPM socket: $PHP_FPM_SOCK"
sudo sed -i "s|PHP_FPM_SOCK_PLACEHOLDER|${PHP_FPM_SOCK}|" /etc/nginx/sites-available/default
sudo nginx -t
sudo systemctl reload nginx
nginx: configuration file /etc/nginx/nginx.conf test is successfulsudo mkdir -p /var/www/html echo "" | sudo tee /var/www/html/info.php curl -s http://localhost/info.php | head -3
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional... — that's PHP rendering.<?php phpinfo(); ?> in the output, FastCGI isn't connected. Re-run the socket sed in 4.3, then sudo systemctl reload nginx.sudo apt install -y apache2 libapache2-mod-php
Single command: rewrites ports.conf for port 8080 and replaces the default vhost so the <Directory> block lives inside the <VirtualHost> (canonical Apache 2.4 placement — avoids "AllowOverride not allowed here" errors).
sudo sed -i 's/^Listen 80$/Listen 8080/' /etc/apache2/ports.conf sudo mkdir -p /var/www/lamp sudo chown -R www-data:www-data /var/www/lamp sudo tee /etc/apache2/sites-available/000-default.conf > /dev/null <<'EOF'ServerAdmin webmaster@localhost DocumentRoot /var/www/lamp EOFOptions Indexes FollowSymLinks AllowOverride None Require all granted ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined
sudo apache2ctl configtest sudo systemctl restart apache2 sudo systemctl status apache2 --no-pager | head -5 sudo ss -tlnp | grep -E ':(80|8080) '
Syntax OK · Active: active (running) · ss shows two lines — nginx on 0.0.0.0:80 and apache2 on 0.0.0.0:8080.sudo journalctl -u apache2 -n 20 — Apache didn't start. Common cause: the sed in 5.2 didn't match (already-modified file). Inspect /etc/apache2/ports.conf — make sure it says Listen 8080, not Listen 80.Distinct welcome pages + identical DB-test pages, so you can demo "same database, different web servers".
sudo tee /var/www/html/index.html > /dev/null <<'EOF'LEMP — NGINX Capstone — LEMP Stack
NGINX + PHP-FPM + MariaDB on Ubuntu Server 26.04 ·
192.168.0.20Test pages
Sister stack: LAMP on port 8080 →
EOFsudo tee /var/www/html/dbtest.php > /dev/null <<'EOF'
connect_error) { die("❌ " . $mysqli->connect_error); }
echo "✅ LEMP — connected via PHP-FPM
";
echo "MariaDB version: " . $mysqli->server_info . "
";
echo "Web server: " . $_SERVER['SERVER_SOFTWARE'] . "
";
echo "Port: " . $_SERVER['SERVER_PORT'] . "
";
$mysqli->close();
?>
EOF
sudo tee /var/www/lamp/index.html > /dev/null <<'EOF'LAMP — Apache Capstone — LAMP Stack
Apache 2 + mod_php + MariaDB on Ubuntu Server 26.04 ·
192.168.0.20:8080Test pages
Sister stack: LEMP on port 80 →
EOFecho "" | sudo tee /var/www/lamp/info.php > /dev/null
sudo tee /var/www/lamp/dbtest.php > /dev/null <<'EOF'
connect_error) { die("❌ " . $mysqli->connect_error); }
echo "✅ LAMP — connected via mod_php
";
echo "MariaDB version: " . $mysqli->server_info . "
";
echo "Web server: " . $_SERVER['SERVER_SOFTWARE'] . "
";
echo "Port: " . $_SERVER['SERVER_PORT'] . "
";
$mysqli->close();
?>
EOF
sudo chown -R www-data:www-data /var/www/lamp /var/www/html
MariaDB stays bound to localhost — no rule for port 3306. Production-shaped.
sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow 22/tcp comment "SSH" sudo ufw allow 80/tcp comment "HTTP NGINX (LEMP)" sudo ufw allow 8080/tcp comment "HTTP Apache (LAMP)" sudo ufw allow 443/tcp comment "HTTPS (future)" sudo ufw --force enable sudo ufw status verbose
Run this single block. The output is your evidence-of-build for the lab report.
echo "=== LAMP + LEMP COEXISTENCE on VM 105 ===" echo echo "--- Hostname / OS ---" hostnamectl | head -3 echo echo "--- NGINX (LEMP, port 80) ---" systemctl is-active nginx nginx -v 2>&1 curl -sI http://localhost/ | head -2 echo echo "--- Apache (LAMP, port 8080) ---" systemctl is-active apache2 apache2 -v | head -1 curl -sI http://localhost:8080/ | head -2 echo echo "--- MariaDB (shared) ---" systemctl is-active mariadb mariadb -V echo echo "--- PHP ---" php -v | head -1 echo "PHP-FPM (LEMP): $(systemctl is-active php*-fpm)" echo "mod_php (LAMP): $(apache2ctl -M 2>/dev/null | grep -c php_module) modules loaded" echo echo "--- Listening ports ---" sudo ss -tlnp | grep -E ':(80|8080|3306) ' echo echo "--- UFW ---" sudo ufw status verbose | head -10
27-linuxserver-lamp-lemp.png. We'll wire it into the verification page as the LAMP+LEMP milestone.Prove the stacks are reachable from your other VMs. Pick whichever method matches the VM you're on.
| URL | Expected |
|---|---|
http://192.168.0.20/ | Green-banner LEMP welcome page |
http://192.168.0.20/dbtest.php | "✅ LEMP — connected via PHP-FPM" + MariaDB version |
http://192.168.0.20:8080/ | Orange-banner LAMP welcome page |
http://192.168.0.20:8080/dbtest.php | "✅ LAMP — connected via mod_php" + MariaDB version |
curl -s http://192.168.0.20/ | head -10 echo "---" curl -s http://192.168.0.20:8080/ | head -10
From Mac Terminal:
ssh -L 8000:192.168.0.20:80 -L 8081:192.168.0.20:8080 root@10.10.10.10
Leave that open. In Safari, browse:
| URL | Stack |
|---|---|
http://localhost:8000/ | LEMP (NGINX → port 80 inside) |
http://localhost:8081/ | LAMP (Apache → port 8080 inside) |
sudo ss -tlnp | grep nginx shows 0.0.0.0:80 not 127.0.0.1:80.DMZ net → LAN_NET ports 80, 8080.info.php leaks PHP version + module list. Remove before the lab demo. Keep dbtest.php (no secrets exposed).
sudo rm /var/www/html/info.php /var/www/lamp/info.php
:80 → green-banner LEMP welcome:8080 → orange-banner LAMP welcomecapstone_db in MariaDBss -tlnp shows nginx:80, apache2:8080, mariadb:3306