Deploy Node.js App: PM2 and Nginx Guide
Complete guide to deploying Node.js applications on a VPS. Node.js installation with nvm, PM2 process manager, Nginx reverse proxy, SSL certificate, and environment variables management.
Complete guide to deploying PHP applications on a VPS. LAMP vs LEMP comparison, Apache/Nginx + PHP-FPM + MySQL setup, virtual host configuration, and PHP version management.
PHP is one of the cornerstones of web development, powering millions of websites worldwide. This guide compares LAMP (Linux + Apache + MySQL + PHP) and LEMP (Linux + Nginx + MySQL + PHP) stacks, covers installation steps, and walks through deploying your PHP application.
| Feature | LAMP | LEMP |
|---|---|---|
| Web Server | Apache | Nginx |
| Performance | Medium-high | High |
| Memory Usage | More | Less |
| .htaccess | Supported | Not supported |
| PHP Integration | mod_php or PHP-FPM | PHP-FPM (required) |
| Static Files | Good | Excellent |
| Configuration | Easier | Slightly more complex |
LEMP stack offers better performance for PHP applications like WordPress and Laravel. LAMP may be preferred for legacy applications that require .htaccess.
# Update package list
sudo apt update && sudo apt upgrade -y
# Install Nginx
sudo apt install nginx -y
# Start and enable service
sudo systemctl start nginx
sudo systemctl enable nginx
# Install MariaDB (MySQL alternative, faster)
sudo apt install mariadb-server mariadb-client -y
# Start service
sudo systemctl start mariadb
sudo systemctl enable mariadb
# Security configuration
sudo mysql_secure_installation
# Create database and user
sudo mysql -u root -p
CREATE DATABASE myapp_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'myapp_user'@'localhost' IDENTIFIED BY 'strong-password';
GRANT ALL PRIVILEGES ON myapp_db.* TO 'myapp_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
# Add PHP repository (for Ubuntu)
sudo apt install software-properties-common -y
sudo add-apt-repository ppa:ondrej/php -y
sudo apt update
# Install PHP 8.2 and common extensions
sudo apt install php8.2 php8.2-fpm php8.2-mysql php8.2-xml php8.2-curl \
php8.2-mbstring php8.2-zip php8.2-gd php8.2-bcmath php8.2-intl \
php8.2-redis php8.2-imagick -y
# Start PHP-FPM service
sudo systemctl start php8.2-fpm
sudo systemctl enable php8.2-fpm
# Check PHP version
php --version
# Edit PHP.ini
sudo nano /etc/php/8.2/fpm/php.ini
Important settings:
; Memory limit
memory_limit = 256M
; Maximum upload size
upload_max_filesize = 64M
post_max_size = 64M
; Maximum execution time
max_execution_time = 300
; Error display (should be off in production)
display_errors = Off
log_errors = On
error_log = /var/log/php/error.log
; OPcache (for performance)
opcache.enable = 1
opcache.memory_consumption = 128
opcache.max_accelerated_files = 10000
opcache.revalidate_freq = 2
# Restart PHP-FPM
sudo systemctl restart php8.2-fpm
# Create application directory
sudo mkdir -p /var/www/myapp/public
sudo chown -R www-data:www-data /var/www/myapp
# Virtual host configuration
sudo nano /etc/nginx/sites-available/myapp
server {
listen 80;
server_name example.com www.example.com;
root /var/www/myapp/public;
index index.php index.html;
# URL rewriting for Laravel/Symfony
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# Process PHP files with PHP-FPM
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
# Block access to hidden files
location ~ /\.(?!well-known).* {
deny all;
}
# Cache for static files
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
client_max_body_size 64M;
}
# Enable the site
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Multiple PHP versions can run on the same server:
# Install multiple PHP versions
sudo apt install php7.4 php7.4-fpm php8.1 php8.1-fpm php8.2 php8.2-fpm -y
# Change default PHP version for CLI
sudo update-alternatives --config php
# Use different PHP version for different sites in Nginx
# Replace php8.2-fpm.sock with php7.4-fpm.sock
# Clone the repo
cd /var/www
git clone https://github.com/user/myapp.git
cd myapp
# Install Composer dependencies
composer install --no-dev --optimize-autoloader
# Create .env file
cp .env.example .env
nano .env
# Generate application key
php artisan key:generate
# Database migration
php artisan migrate --force
# Generate caches
php artisan config:cache
php artisan route:cache
php artisan view:cache
# Set file permissions
sudo chown -R www-data:www-data /var/www/myapp
sudo chmod -R 755 /var/www/myapp
sudo chmod -R 775 /var/www/myapp/storage
sudo chmod -R 775 /var/www/myapp/bootstrap/cache
# Install Certbot
sudo apt install certbot python3-certbot-nginx -y
# Obtain SSL certificate
sudo certbot --nginx -d example.com -d www.example.com
# Test automatic renewal
sudo certbot renew --dry-run
On REXE servers, make sure ports 80 and 443 are open via Path Panel. Keep MySQL port 3306 closed to the outside.
Your PHP application is now running on a LEMP or LAMP stack. The Nginx + PHP-FPM combination delivers high performance, while OPcache caches your PHP code for much faster execution. Keep your application up to date with regular security updates and PHP version management.
LEMP (Nginx + PHP-FPM) is recommended for new projects; it uses less memory and offers higher performance. However, LAMP (Apache) is easier to configure for legacy PHP applications or WordPress that use .htaccess. Both stacks are suitable for production environments.
PHP-FPM (FastCGI Process Manager) runs PHP as a separate process, managed independently from the web server. Compared to mod_php, it uses less memory, offers better performance, and makes it possible to use different PHP versions for different sites.
Multiple PHP versions can be installed via the Ondrej PPA repository. A separate PHP-FPM service runs for each version (php7.4-fpm, php8.1-fpm, php8.2-fpm). In Nginx, different PHP versions can be assigned to different sites by using different PHP-FPM sockets.
Enable OPcache (opcache.enable=1), increase PHP-FPM worker count, add cache headers for static files in Nginx. For Laravel/Symfony, run 'php artisan config:cache' and 'php artisan route:cache'. Optimize session and cache management with Redis.
Complete guide to deploying Node.js applications on a VPS. Node.js installation with nvm, PM2 process manager, Nginx reverse proxy, SSL certificate, and environment variables management.
Guide to installing and optimizing WordPress on a VPS. LEMP stack setup, wp-config.php settings, file permissions, SSL, OPcache performance optimization, and security hardening.
Guide to deploying Python/Django applications on a VPS. Virtualenv setup, Django production settings, Gunicorn WSGI server, Nginx reverse proxy, systemd service, and static file management.