Skip to content
intermediate Phase 97 · Deployment

Linux and Nginx for Magento

Linux server setup and Nginx configuration for Magento including virtual hosts, performance tuning, and security hardening

1h
0 problems
Topic Progress 0%

Linux Server Setup

Server Requirements

# Minimum requirements
RAM: 4GB (8GB+ recommended)
CPU: 2 cores (4+ recommended)
Disk: 80GB SSD (200GB+ recommended)
OS: Ubuntu 22.04 LTS or CentOS 8

Initial Server Setup

# Update system
sudo apt update && sudo apt upgrade -y

# Install essential packages
sudo apt install -y curl wget git unzip software-properties-common

# Create deploy user
sudo adduser deploy
sudo usermod -aG sudo deploy

# Setup SSH key
sudo mkdir -p /home/deploy/.ssh
sudo cp ~/.ssh/authorized_keys /home/deploy/.ssh/
sudo chown -R deploy:deploy /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh
sudo chmod 600 /home/deploy/.ssh/authorized_keys

# Firewall setup
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

Install Nginx

# Install Nginx
sudo apt install -y nginx

# Start and enable
sudo systemctl start nginx
sudo systemctl enable nginx

# Verify
sudo systemctl status nginx
curl http://localhost

Install PHP-FPM

# Install PHP 8.1 and extensions
sudo apt install -y php8.1-fpm php8.1-cli php8.1-mysql \
    php8.1-xml php8.1-mbstring php8.1-intl php8.1-gd \
    php8.1-curl php8.1-zip php8.1-redis php8.1-bcmath

# Start PHP-FPM
sudo systemctl start php8.1-fpm
sudo systemctl enable php8.1-fpm

Install MySQL

# Install MySQL 8
sudo apt install -y mysql-server

# Secure installation
sudo mysql_secure_installation

# Create Magento database
sudo mysql -u root -p
CREATE DATABASE magento_db;
CREATE USER 'magento'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON magento_db.* TO 'magento'@'localhost';
FLUSH PRIVILEGES;

Install Redis

# Install Redis
sudo apt install -y redis-server

# Configure Redis
sudo sed -i 's/maxmemory .*/maxmemory 1GB/' /etc/redis/redis.conf
sudo sed -i 's/maxmemory-policy .*/maxmemory-policy allkeys-lru/' /etc/redis/redis.conf

# Restart
sudo systemctl restart redis-server

Key Takeaway

Linux server setup: update system, install Nginx, PHP-FPM, MySQL, Redis. Create deploy user with SSH access and configure firewall.

Nginx Configuration for Magento

Basic Nginx Configuration

# /etc/nginx/sites-available/magento
server {
    listen 80;
    server_name www.example.com;
    
    root /var/www/magento/pub;
    index index.php;
    
    # Logs
    access_log /var/log/nginx/magento-access.log;
    error_log /var/log/nginx/magento-error.log;
    
    # Max body size for uploads
    client_max_body_size 100M;
    
    # PHP-FPM
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        
        # Timeout settings
        fastcgi_read_timeout 300s;
        fastcgi_send_timeout 300s;
    }
    
    # Static files
    location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }
    
    # Deny access to sensitive files
    location ~ /\. {
        deny all;
    }
}

Magento-Specific Configuration

# /etc/nginx/sites-available/magento
server {
    listen 80;
    server_name www.example.com;
    
    root /var/www/magento/pub;
    index index.php;
    
    # Magento rewrites
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }
    
    # API endpoints
    location /rest/ {
        try_files $uri $uri/ /index.php$is_args$args;
    }
    
    # Static assets
    location /static/ {
        expires 1y;
        add_header Cache-Control "public";
        try_files $uri $uri/ =404;
    }
    
    # Media files
    location /media/ {
        expires 1y;
        add_header Cache-Control "public";
        try_files $uri $uri/ =404;
    }
    
    # PHP processing
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        
        # Magento specific
        fastcgi_param MAGE_MODE production;
    }
    
    # Security headers
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";
    add_header X-XSS-Protection "1; mode=block";
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
}

Enable Site

# Create symlink
sudo ln -s /etc/nginx/sites-available/magento /etc/nginx/sites-enabled/

# Remove default site
sudo rm /etc/nginx/sites-enabled/default

# Test configuration
sudo nginx -t

# Reload Nginx
sudo systemctl reload nginx

Key Takeaway

Nginx configuration for Magento: set root to pub/, configure PHP-FPM, handle rewrites for routing, and add security headers.

Performance Tuning

Nginx Performance

# /etc/nginx/nginx.conf
worker_processes auto;
worker_rlimit_nofile 65535;

events {
    worker_connections 4096;
    multi_accept on;
    use epoll;
}

http {
    # Basic settings
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    
    # Buffering
    client_body_buffer_size 10K;
    client_header_buffer_size 1k;
    client_max_body_size 100m;
    large_client_header_buffers 4 8k;
    
    # Gzip
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml text/javascript \
               application/json application/javascript application/xml+rss \
               application/atom+xml image/svg+xml;
    
    # Open file cache
    open_file_cache max=1000 inactive=20s;
    open_file_cache_valid 30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;
}

Connection Tuning

# Upstream configuration
upstream php-fpm {
    server unix:/var/run/php/php8.1-fpm.sock;
    keepalive 32;
}

# FastCGI tuning
location ~ \.php$ {
    fastcgi_pass php-fpm;
    fastcgi_buffer_size 128k;
    fastcgi_buffers 4 256k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    fastcgi_read_timeout 300s;
    fastcgi_send_timeout 300s;
}

Static File Optimization

# Static files with long cache
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
    expires 1y;
    add_header Cache-Control "public";
    access_log off;
    
    # Enable gzip for static
    gzip_static on;
    
    # Enable brotli if available
    brotli_static on;
}

Rate Limiting

# Rate limiting zones
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;

# API rate limiting
location /rest/ {
    limit_req zone=api burst=20 nodelay;
    try_files $uri $uri/ /index.php$is_args$args;
}

# Login rate limiting
location /customer/account/login/ {
    limit_req zone=login burst=3 nodelay;
    try_files $uri $uri/ /index.php$is_args$args;
}

Key Takeaway

Performance tuning: enable gzip, tune worker connections, configure fastcgi buffering, enable static file caching, and implement rate limiting.

Virtual Hosts and Security

Multiple Sites Virtual Hosts

# Site 1: www.store1.com
server {
    listen 80;
    server_name www.store1.com;
    root /var/www/store1/pub;
    # ... configuration ...
}

# Site 2: www.store2.com
server {
    listen 80;
    server_name www.store2.com;
    root /var/www/store2/pub;
    # ... configuration ...
}

SSL Configuration

server {
    listen 443 ssl http2;
    server_name www.example.com;
    
    ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
    
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;
    
    # HSTS
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}

# Redirect HTTP to HTTPS
server {
    listen 80;
    server_name www.example.com;
    return 301 https://$host$request_uri;
}

Security Hardening

# Hide Nginx version
server_tokens off;

# 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;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self' https: http:" always;

# Deny access to hidden files
location ~ /\. {
    deny all;
    access_log off;
    log_not_found off;
}

# Deny access to sensitive files
location ~* \.(env|htaccess|htpasswd|ini|log|sh|sql)$ {
    deny all;
}

# Block access to app directory
location /app/ {
    deny all;
}

location /app/etc/ {
    deny all;
}

location /lib/ {
    deny all;
}

location /pkginfo/ {
    deny all;
}

location /var/ {
    deny all;
}

location /vendor/ {
    deny all;
}

Enable SSL with Let's Encrypt

# Install Certbot
sudo apt install -y certbot python3-certbot-nginx

# Get certificate
sudo certbot --nginx -d www.example.com

# Auto-renewal
sudo systemctl status certbot.timer

# Test renewal
sudo certbot renew --dry-run

Key Takeaway

Virtual hosts enable multiple sites on one server. SSL with Let's Encrypt provides free certificates. Security hardening hides version, blocks sensitive files, and adds security headers.

Quiz

1. What is the Magento root directory in Nginx?

Question 1 options

2. What does fastcgi_pass do in Nginx?

Question 2 options

3. Why enable gzip in Nginx?

Question 3 options

4. What does server_tokens off do?

Question 4 options

5. Why use worker_processes auto?

Question 5 options

Flashcards

Question

What is the Magento Nginx root?

Answer

/var/www/magento/pub - Magento serves from the pub/ directory

Question

What does fastcgi_pass do?

Answer

Directs PHP requests to PHP-FPM for processing

Question

Why enable gzip?

Answer

Compresses responses to reduce bandwidth and improve load times

Question

What is server_tokens off?

Answer

Hides Nginx version in response headers for security

Question

What does try_files do?

Answer

Checks if files exist, falls back to index.php for Magento routing

Question

Why use keepalive in Nginx?

Answer

Reuses connections to PHP-FPM for better performance

Question

What is rate limiting?

Answer

Limits requests per second from a client to prevent abuse

Question

How to enable SSL with Let's Encrypt?

Answer

certbot --nginx -d domain.com for free SSL certificates

Revision Notes

Key Takeaways

  • 1. Magento root in Nginx is /var/www/magento/pub
  • 2. Use try_files for Magento routing
  • 3. Enable gzip, keepalive, and static file caching
  • 4. Add security headers and hide server version
  • 5. Use Let's Encrypt for free SSL certificates

Interview Tips

  • Explain Nginx configuration for Magento
  • Discuss performance tuning techniques
  • Describe security hardening measures
  • Explain virtual host setup for multiple sites

Cheat Sheet

Nginx for Magento

Root: /var/www/magento/pub
PHP: fastcgi_pass to PHP-FPM socket
Routing: try_files $uri $uri/ /index.php$is_args$args

Performance:

  • gzip on
  • keepalive 32
  • worker_processes auto
  • open_file_cache

Security:

  • server_tokens off
  • Security headers
  • Block /app/, /var/, /vendor/

SSL:
certbot --nginx -d domain.com