Magento 2 Installation and Optimization
Magento 2 is an enterprise-grade e-commerce platform offering advanced features for complex product catalogs, multi-store operations, and sophisticated customer management. Installation requires careful preparation and understanding of dependencies. This comprehensive guide covers production-ready Magento 2 setup including Composer-based installation, Elasticsearch integration, Redis caching, Varnish reverse proxy caching, PHP-FPM tuning, background job processing with Cron, and production deployment strategies.
Table of Contents
- System Requirements and Prerequisites
- LEMP Stack Installation
- Composer and Magento 2 Installation
- Elasticsearch Configuration
- Redis Caching Setup
- Varnish HTTP Cache
- PHP-FPM and Nginx Optimization
- Cron Jobs and Background Processing
- Production Mode Deployment
- Performance Tuning
- Conclusion
System Requirements and Prerequisites
Magento 2 is resource-intensive and requires modern infrastructure. Minimum VPS specifications should include 8GB RAM, 4 CPU cores, 50GB SSD storage, and modern PHP 8.1+.
Verify system requirements:
# Check PHP version (8.1+ required)
php -v
# Check available memory
free -h
# Check disk space
df -h /
# Verify CPU cores
nproc
Update system packages:
sudo apt update
sudo apt upgrade -y
sudo apt install curl wget git zip unzip vim htop -y
Create a Magento system user:
# Create dedicated user for security
sudo useradd -m -s /bin/bash magento
sudo usermod -aG www-data magento
# Create web root
sudo mkdir -p /var/www/magento
sudo chown -R magento:www-data /var/www/magento
LEMP Stack Installation
Magento 2 requires Linux, Nginx, MySQL/MariaDB, and PHP with specific extensions.
Install Nginx:
sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx
sudo systemctl status nginx
Install MariaDB:
sudo apt install mariadb-server mariadb-client -y
sudo systemctl start mariadb
sudo systemctl enable mariadb
sudo mysql_secure_installation
# Create Magento database
sudo mysql -u root -p << EOF
CREATE DATABASE magento;
CREATE USER 'magento'@'localhost' IDENTIFIED BY 'SecurePassword123!';
GRANT ALL PRIVILEGES ON magento.* TO 'magento'@'localhost';
FLUSH PRIVILEGES;
EXIT;
EOF
Install PHP 8.2 with required extensions:
# Add PHP repository
sudo apt install software-properties-common -y
sudo add-apt-repository ppa:ondrej/php -y
sudo apt update
# Install PHP and extensions
sudo apt install php8.2 php8.2-fpm php8.2-mysql php8.2-json php8.2-intl \
php8.2-xml php8.2-bcmath php8.2-zip php8.2-curl php8.2-gd php8.2-mbstring \
php8.2-opcache php8.2-cli php8.2-common php8.2-sodium -y
# Start PHP-FPM
sudo systemctl start php8.2-fpm
sudo systemctl enable php8.2-fpm
Configure PHP-FPM for Magento:
sudo nano /etc/php/8.2/fpm/pool.d/www.conf
Apply settings optimized for Magento:
[www]
user = www-data
group = www-data
listen = /run/php/php8.2-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 96
pm.start_servers = 24
pm.min_spare_servers = 12
pm.max_spare_servers = 48
pm.max_requests = 5000
request_terminate_timeout = 600
request_slowlog_timeout = 30s
slowlog = /var/log/php8.2-fpm-slow.log
Configure PHP settings for Magento:
sudo nano /etc/php/8.2/fpm/php.ini
Set essential parameters:
memory_limit = 2G
max_execution_time = 600
max_input_time = 600
upload_max_filesize = 256M
post_max_size = 256M
max_input_vars = 10000
; OPcache configuration
opcache.enable = 1
opcache.memory_consumption = 512
opcache.max_accelerated_files = 50000
opcache.validate_timestamps = 0
opcache.revalidate_freq = 0
opcache.interned_strings_buffer = 16
opcache.fast_shutdown = 1
; Realpath cache
realpath_cache_size = 4096K
realpath_cache_ttl = 86400
; Session configuration
session.save_path = "/var/lib/php/sessions"
session.gc_maxlifetime = 28800
Restart PHP-FPM:
sudo systemctl restart php8.2-fpm
Composer and Magento 2 Installation
Composer is the dependency manager for Magento 2 and handles all package installation.
Install Composer:
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
sudo chmod +x /usr/local/bin/composer
# Verify installation
composer --version
Generate Magento authentication keys:
# Log in to https://account.magento.com/
# Navigate to API Portal -> Integrations -> Tokens
# Create a new integration token
# Copy public and private keys
Configure Composer authentication:
sudo -u magento composer config -g http-basic.repo.magento.com {PUBLIC_KEY} {PRIVATE_KEY}
Download Magento 2 via Composer:
cd /var/www/magento
sudo -u magento composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition .
# For enterprise
# sudo -u magento composer create-project --repository-url=https://repo.magento.com/ magento/project-enterprise-edition .
Install Magento 2:
cd /var/www/magento
# Run installation command
sudo -u magento php bin/magento setup:install \
--base-url="https://example.com/" \
--db-host="localhost" \
--db-name="magento" \
--db-user="magento" \
--db-password="SecurePassword123!" \
--admin-firstname="Admin" \
--admin-lastname="User" \
--admin-email="[email protected]" \
--admin-user="admin" \
--admin-password="AdminPassword123!" \
--language="en_US" \
--currency="USD" \
--timezone="America/Chicago" \
--use-rewrites="1" \
--elasticsearch-host="localhost" \
--elasticsearch-port="9200"
Configure file permissions:
# Set ownership
sudo chown -R :www-data /var/www/magento
# Set permissions
sudo find /var/www/magento -type f -exec chmod 644 {} \;
sudo find /var/www/magento -type d -exec chmod 755 {} \;
sudo find /var/www/magento/var -type d -exec chmod 777 {} \;
sudo find /var/www/magento/pub/static -type d -exec chmod 777 {} \;
sudo find /var/www/magento/pub/media -type d -exec chmod 777 {} \;
Elasticsearch Configuration
Magento 2 requires Elasticsearch for catalog search functionality in production environments.
Install Elasticsearch 7.x:
# Add Elasticsearch repository
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
sudo apt-get install apt-transport-https -y
echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-7.x.list
# Install Elasticsearch
sudo apt update
sudo apt install elasticsearch=7.17.0 -y
# Start service
sudo systemctl start elasticsearch
sudo systemctl enable elasticsearch
Configure Elasticsearch:
sudo nano /etc/elasticsearch/elasticsearch.yml
Apply Magento-optimized settings:
cluster.name: magento-cluster
node.name: node-1
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 127.0.0.1
http.port: 9200
discovery.type: single-node
# Performance tuning
indices.memory.index_buffer_size: 30%
thread_pool.bulk.queue_size: 300
thread_pool.bulk.size: 8
Restart Elasticsearch:
sudo systemctl restart elasticsearch
sudo systemctl status elasticsearch
Verify Elasticsearch:
curl -X GET "localhost:9200/"
curl -X GET "localhost:9200/_cluster/health?pretty"
Configure Magento to use Elasticsearch:
cd /var/www/magento
sudo -u magento php bin/magento config:set catalog/search/engine "elasticsearch7"
sudo -u magento php bin/magento config:set catalog/search/elasticsearch7_server_hostname "localhost"
sudo -u magento php bin/magento config:set catalog/search/elasticsearch7_server_port "9200"
# Reindex catalog
sudo -u magento php bin/magento indexer:reindex
Redis Caching Setup
Redis dramatically improves performance by caching configuration, sessions, and temporary data.
Install Redis:
sudo apt install redis-server redis-tools -y
sudo systemctl start redis-server
sudo systemctl enable redis-server
# Verify
redis-cli ping
Configure Redis:
sudo nano /etc/redis/redis.conf
Apply production settings:
bind 127.0.0.1
protected-mode yes
port 6379
timeout 0
tcp-keepalive 300
daemonize no
# Persistence
save 900 1
save 300 10
save 60 10000
appendonly yes
appendfsync everysec
# Memory
maxmemory 2gb
maxmemory-policy allkeys-lru
# Replication
databases 16
Restart Redis:
sudo systemctl restart redis-server
Configure Magento to use Redis:
cd /var/www/magento
# Set cache backend to Redis
sudo -u magento php bin/magento config:set system/full_page_cache/caching_application "2"
sudo -u magento php bin/magento config:set system/full_page_cache/redis/server "127.0.0.1"
sudo -u magento php bin/magento config:set system/full_page_cache/redis/port "6379"
sudo -u magento php bin/magento config:set system/full_page_cache/redis/database "0"
# Set session storage to Redis
sudo -u magento php bin/magento config:set system/redisq/redis/host "127.0.0.1"
sudo -u magento php bin/magento config:set system/redisq/redis/port "6379"
Or configure via app/etc/env.php:
cat >> /var/www/magento/app/etc/env.php << 'EOF'
'cache' => [
'frontend' => [
'default' => [
'backend' => 'Cm_Cache_Backend_Redis',
'backend_options' => [
'server' => '127.0.0.1',
'port' => '6379',
'persistent' => '',
'database' => '0',
]
]
]
],
'session' => [
'save' => 'redis',
'redis' => [
'host' => '127.0.0.1',
'port' => '6379',
'password' => '',
'timeout' => '2.5',
'persistent_identifier' => '',
'database' => '1',
'compression_threshold' => '2048',
'compression_library' => 'gzip',
'log_level' => '3',
'max_concurrency' => '6',
'break_after_frontend' => '5',
'break_after_adminhtml' => '30',
'first_lifetime' => '600',
'bot_first_lifetime' => '60',
'bot_lifetime' => '7200',
'disable_locking' => '0',
'min_lifetime' => '60',
'max_lifetime' => '2592000'
]
],
EOF
Flush caches:
cd /var/www/magento
sudo -u magento php bin/magento cache:flush
Varnish HTTP Cache
Varnish provides HTTP-level caching for unauthenticated requests, significantly reducing server load.
Install Varnish:
curl -L https://packagecloud.io/varnishcache/varnish60lts/gpgkey | sudo apt-key add -
echo "deb https://packagecloud.io/varnishcache/varnish60lts/ubuntu focal main" | sudo tee /etc/apt/sources.list.d/varnishcache_varnish60lts.list
sudo apt update
sudo apt install varnish -y
sudo systemctl start varnish
sudo systemctl enable varnish
Configure Varnish for Magento 2:
sudo nano /etc/varnish/default.vcl
Apply Magento 2 configuration:
vcl 4.1;
import std;
import xkey;
backend default {
.host = "127.0.0.1";
.port = "8080";
.first_byte_timeout = 600s;
.connect_timeout = 600s;
.between_bytes_timeout = 600s;
}
acl purge {
"127.0.0.1";
"localhost";
}
sub vcl_recv {
# Bypass cache for admin and API
if (req.url ~ "^/admin" || req.url ~ "^/api") {
return (pass);
}
# Cache only GET and HEAD requests
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}
# Remove cookies for cacheable requests
if (!(req.url ~ "^/admin") && !(req.url ~ "^/customer") && !(req.url ~ "^/checkout")) {
unset req.http.cookie;
}
# Purge cache on request
if (req.method == "PURGE") {
if (!client.ip ~ purge) {
return (synth(405, "Not allowed"));
}
return (purge);
}
return (hash);
}
sub vcl_backend_response {
# Cache static content for 1 year
if (bereq.url ~ "\.(js|css|png|gif|jpg|jpeg|svg|ico|webp)$") {
set beresp.ttl = 365d;
set beresp.http.Cache-Control = "public, immutable";
}
# Cache HTML for 10 minutes
if (beresp.http.Content-Type ~ "text/html") {
set beresp.ttl = 10m;
set beresp.http.Cache-Control = "public, max-age=600";
}
# Add xkey for smart purging
if (beresp.status == 200) {
set beresp.http.xkey = bereq.url;
}
return (deliver);
}
sub vcl_hash {
hash_data(req.url);
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
return (lookup);
}
sub vcl_deliver {
# Add cache status header
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
set resp.http.X-Cache-Hits = obj.hits;
return (deliver);
}
Update Varnish default port:
sudo nano /etc/varnish/varnish.params
Change to port 6081 (Varnish), Nginx will listen on 8080:
VARNISH_LISTEN_PORT=6081
VARNISH_ADMIN_LISTEN_PORT=6082
VARNISH_BACKEND_PORT=8080
Update Nginx to listen on 8080:
sudo nano /etc/nginx/sites-available/magento.conf
Change listen directive:
listen 8080;
Restart services:
sudo systemctl restart varnish
sudo systemctl restart nginx
Configure Magento to communicate with Varnish:
cd /var/www/magento
sudo -u magento php bin/magento config:set system/full_page_cache/caching_application "2"
sudo -u magento php bin/magento config:set system/full_page_cache/varnish/access_list "127.0.0.1"
sudo -u magento php bin/magento config:set system/full_page_cache/varnish/backend_host "127.0.0.1"
sudo -u magento php bin/magento config:set system/full_page_cache/varnish/backend_port "8080"
# Export configuration
sudo -u magento php bin/magento config:set system/full_page_cache/varnish/param_purge_button "1"
Test Varnish caching:
# Check cache status
curl -I http://localhost:6081/
# Monitor Varnish statistics
sudo varnishstat
# View real-time requests
sudo varnishlog
PHP-FPM and Nginx Optimization
Nginx configuration directly impacts Magento performance by handling requests efficiently.
Create Nginx configuration for Magento:
sudo nano /etc/nginx/sites-available/magento.conf
Apply optimized settings:
upstream fastcgi_backend {
server unix:/run/php/php8.2-fpm.sock;
}
server {
listen 8080;
server_name example.com;
set $MAGE_ROOT /var/www/magento;
access_log /var/log/nginx/magento_access.log;
error_log /var/log/nginx/magento_error.log warn;
root $MAGE_ROOT/pub;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Caching headers
expires 365d;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location /setup {
root $MAGE_ROOT;
location ~ ^/setup/index.php {
fastcgi_pass fastcgi_backend;
fastcgi_param SCRIPT_FILENAME $request_filename;
include fastcgi_params;
}
}
location /pub/static/ {
expires 365d;
add_header Cache-Control "public, immutable";
}
location /pub/media/ {
expires 30d;
add_header Cache-Control "public, proxy-revalidate";
}
location ~ \.php$ {
fastcgi_pass fastcgi_backend;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_index index.php;
}
location ~ /\. {
deny all;
}
}
Enable the Nginx configuration:
sudo ln -s /etc/nginx/sites-available/magento.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Cron Jobs and Background Processing
Magento 2 requires cron jobs for indexing, cache cleaning, and background tasks.
Set up system cron:
# Edit crontab for www-data user
sudo crontab -u www-data -e
Add Magento cron entries:
*/1 * * * * cd /var/www/magento && php bin/magento cron:run | grep -v "Ran jobs" >> var/log/magento.cron.log
*/1 * * * * cd /var/www/magento && php bin/magento queue:consumers:start exportProcessor &
*/1 * * * * cd /var/www/magento && php bin/magento queue:consumers:start productAttributesProcessor &
*/1 * * * * cd /var/www/magento && php bin/magento queue:consumers:start asyncOpRedis &
Verify cron is working:
# Check cron history
tail -f /var/www/magento/var/log/magento.cron.log
# Check scheduled jobs
sudo -u magento php bin/magento cron:run
Production Mode Deployment
Magento 2 requires specific configuration and compilation for production environments.
Set production mode:
cd /var/www/magento
# Generate static files
sudo -u magento php bin/magento setup:static-content:deploy en_US -f
# Compile DI code
sudo -u magento php bin/magento setup:di:compile
# Set mode to production
sudo -u magento php bin/magento deploy:mode:set production
# Verify mode
sudo -u magento php bin/magento deploy:mode:show
Configure environment.php:
cat > /var/www/magento/app/etc/env.php << 'EOF'
<?php
return [
'backend' => [
'frontName' => 'admin_custom_path'
],
'crypt' => [
'key' => 'GeneratedEncryptionKey'
],
'db' => [
'table_prefix' => '',
'connection' => [
'default' => [
'host' => 'localhost',
'dbname' => 'magento',
'username' => 'magento',
'password' => 'SecurePassword123!',
'model' => 'mysql4',
'engine' => 'innodb',
'initStatements' => 'SET NAMES utf8;',
'active' => '1',
]
]
],
'resource' => [
'default_setup' => [
'connection' => 'default'
]
],
'x-frame-options' => 'SAMEORIGIN',
'MAGE_MODE' => 'production',
'session' => [
'save' => 'redis',
'redis' => [
'host' => '127.0.0.1',
'port' => '6379',
'password' => '',
'timeout' => '2.5',
'database' => '1',
'compression_threshold' => '2048',
'compression_library' => 'gzip',
]
],
];
EOF
Verify production deployment:
# Check for errors
cd /var/www/magento && tail -f var/log/system.log
# Monitor performance
iostat -x 1
vmstat 1 10
Performance Tuning
Fine-tune Magento for maximum performance in your specific environment.
Enable HTTP/2 in Nginx:
sudo nano /etc/nginx/sites-available/magento.conf
# Update listen directive
listen 8080 http2;
Optimize MySQL for Magento:
mysql -u root -p << EOF
USE magento;
ANALYZE TABLE catalog_product_entity;
ANALYZE TABLE catalog_product_entity_media_gallery;
ANALYZE TABLE sales_order;
ANALYZE TABLE sales_order_item;
EOF
Monitor real-time performance:
# Install monitoring tools
sudo apt install nethogs iotop -y
# Monitor I/O
sudo iotop
# Monitor network
sudo nethogs
# Check memory usage
ps aux --sort=-%mem | head -20
Conclusion
Magento 2 installation and optimization requires attention to infrastructure, caching layers, and background processing. A properly configured Magento 2 environment includes optimized PHP-FPM, MySQL tuning, Elasticsearch for search, Redis for caching, Varnish for HTTP caching, and proper static file compilation. Implement these technologies in progression, monitoring performance improvements at each step. Regular maintenance including cache clearing, log rotation, and database optimization ensures sustained performance as your store grows and customer traffic increases.


