📰

magento2

35 notes  •  WordPress & CMS

Set Up Magento 2 with Redis, Varnish, and Nginx SSL Termination

This guide covers installing and configuring Magento 2 on Ubuntu with MariaDB, PHP-FPM, Redis for caching, Varnish as a full-page cache, and Nginx handling SSL termination as a reverse proxy in front of Varnish.

Prerequisites

  • Ubuntu server with sudo access
  • Domain name pointed at your server IP
  • Magento Marketplace account with access keys

Steps

1. Update System and Install Utilities

sudo apt-get update && sudo apt-get -y upgrade
sudo apt-get -y install curl nano git

2. Install MariaDB and Create Database

sudo apt-get install -y mariadb-server
mysql_secure_installation
mysql -uroot -p
CREATE DATABASE magento;
GRANT ALL PRIVILEGES ON magento.* TO 'magento'@'localhost' IDENTIFIED BY 'StrongPass123';
FLUSH PRIVILEGES;
\q

3. Install PHP 7.x and Required Extensions

sudo apt-get -y install php-fpm php-cli php-gd php-imagick php-mysql php-mcrypt   php-pear php-curl php-intl php-xsl php-zip php-mbstring

Tune PHP settings:

sudo sed -i "s/memory_limit = .*/memory_limit = 256M/" /etc/php/7.0/fpm/php.ini
sudo sed -i "s/upload_max_filesize = .*/upload_max_filesize = 128M/" /etc/php/7.0/fpm/php.ini
sudo sed -i "s/zlib.output_compression = .*/zlib.output_compression = on/" /etc/php/7.0/fpm/php.ini
sudo sed -i "s/max_execution_time = .*/max_execution_time = 18000/" /etc/php/7.0/fpm/php.ini

4. Install Composer

curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer

5. Install Magento 2 from GitHub

sudo git clone https://github.com/magento/magento2.git /var/www/myMagentoSite.com
cd /var/www/myMagentoSite.com
sudo git checkout $(git describe --tags $(git rev-list --tags --max-count=1))
sudo composer install

6. Run Magento Installer

sudo bin/magento setup:install   --base-url=http://myMagentoSite.com/   --db-host=localhost   --db-name=magento   --db-user=magento   --db-password=StrongPass123   --admin-firstname=First   --admin-lastname=Last   --admin-email=user@myMagentoSite.com   --admin-user=admin   --admin-password=AdminPass123   --language=en_US   --currency=USD   --timezone=America/Chicago   --use-rewrites=1

7. Set Up Cron

crontab -u www-data -e
# Add:
* * * * * /usr/bin/php /var/www/myMagentoSite.com/bin/magento cron:run 2>&1

8. Configure Redis

sudo apt-get install -y redis-server
# Configure Magento to use Redis for sessions and cache via bin/magento commands or env.php

9. Install and Configure Varnish

Generate the Magento VCL and apply it to Varnish, then configure Nginx to listen on 443 and proxy to Varnish on port 80 (or 6081).

bin/magento varnish:vcl:generate --export-version=6 > /etc/varnish/default.vcl
systemctl restart varnish

10. Configure Nginx as SSL Terminator

server {
    listen 443 ssl http2;
    server_name myMagentoSite.com;
    ssl_certificate     /etc/ssl/myMagentoSite.com.crt;
    ssl_certificate_key /etc/ssl/myMagentoSite.com.key;

    location / {
        proxy_pass http://127.0.0.1:6081;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-Port 443;
        proxy_set_header Ssl-Offloaded "1";
    }
}

Verify

  • Browse to your store URL over HTTPS
  • Check Varnish is caching: varnishstat or varnishlog
  • Confirm Redis sessions: redis-cli keys '*'

Notes

  • In Magento Admin, go to Stores > Configuration > Advanced > System > Full Page Cache and set caching application to Varnish.
  • Run bin/magento cache:flush after configuration changes.

Install Magento 2 on Ubuntu 16 with Nginx

This guide walks through installing Magento 2 on Ubuntu 16.04 using Nginx as the web server, PHP-FPM, and MySQL.

Prerequisites

  • Ubuntu 16.04 server with root or sudo access
  • Domain name pointed at the server
  • Magento 2 archive or access to GitHub repository
  • Magento Marketplace authentication keys

Steps

1. Install Nginx

apt-get -y install nginx

2. Install and Configure PHP-FPM

apt-get -y install php7.0-fpm php7.0-cli

Edit both /etc/php/7.0/fpm/php.ini and /etc/php/7.0/cli/php.ini to set:

memory_limit = 2G
max_execution_time = 1800
zlib.output_compression = On
systemctl restart php7.0-fpm

3. Install and Configure MySQL

sudo apt install -y mysql-server mysql-client
sudo mysql_secure_installation
mysql -u root -p

Increase max packet size — edit /etc/mysql/mysql.cnf and set max_allowed_packet = 64M, then restart:

service mysql restart

4. Download and Set Up Magento 2

cd /var/www/html
wget https://github.com/magento/magento2/archive/2.0.tar.gz
tar -xzvf 2.0.tar.gz
mv magento2-2.0/ magento2/

Set ownership and permissions:

cd /var/www/html/magento2
find var vendor pub/static pub/media app/etc -type f -exec chmod g+w {} \;
find var vendor pub/static pub/media app/etc -type d -exec chmod g+ws {} \;
chown -R :www-data .
chmod u+x bin/magento

5. Install Composer and Dependencies

curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/bin --filename=composer
cd /var/www/html/magento2
composer install -v

6. Run Magento Installer

cd /var/www/html/magento2/bin
./magento setup:install   --base-url=http://www.example.com/   --db-host=localhost   --db-name=magento   --db-user=magento   --db-password=StrongPass123   --admin-firstname=Admin   --admin-lastname=User   --admin-email=admin@example.com   --admin-user=admin   --admin-password=Admin123   --language=en_US   --currency=USD   --timezone=America/Chicago   --use-rewrites=1

7. Set Developer Mode

cd /var/www/html/magento2/bin
./magento deploy:mode:set developer

Verify

  • Browse to http://your-domain/ — storefront should load
  • Browse to http://your-domain/admin — admin panel should be accessible
  • Check var/log/system.log for errors

Notes

  • Copy the Nginx sample config: cp /var/www/html/magento2/nginx.conf.sample /etc/nginx/conf.d/magento.conf and adjust the root and server_name directives.
  • After installation, switch to production mode: ./magento deploy:mode:set production

Fix Magento 2 / Varnish 5 Error 503 Backend Fetch Failed

Varnish returns "503 Backend Fetch Failed" when a health check URL or PHP entry point is not reachable. This is a known bug in certain Magento 2 + Varnish 5.x configurations where the health check path and the Nginx PHP handler do not match.

Prerequisites

  • Magento 2 with Varnish 4.x or 5.x and Nginx
  • Root or sudo access to edit Varnish VCL and Nginx config

Steps

1. Fix the Varnish VCL Health Check Path

Edit /etc/varnish/default.vcl and locate the health check probe URL. Change:

.url = "/pub/health_check.php";

To:

.url = "/health_check.php";

2. Add health_check to the Nginx PHP Handler

In the Magento Nginx config (typically nginx.conf.sample inside the Magento root), find the PHP entry point location block and add health_check to the pattern.

Before:

location ~ (index|get|static|report|404|503)\.php$ {

After:

location ~ (index|get|static|report|404|503|health_check)\.php$ {

3. Restart Services

systemctl restart varnish
systemctl restart nginx
systemctl restart php7.1-fpm

Verify

curl -I http://localhost/health_check.php

Expect HTTP 200. Then test the store URL through Varnish — 503 errors should be gone.

Notes

  • This issue is a known Magento bug tracked on GitHub affecting PHP 7.1 + Varnish 5.x.
  • If the problem persists, check varnishlog for the backend error detail: varnishlog -g request -q "RespStatus == 503"

Fix Magento 2 Varnish 503 Backend Fetch Failed

After moving product attributes in Magento 2.10 with Varnish, Redis, and PHP 7, you may encounter repeated "503 Backend Fetch Failed" errors. The root cause is a bug in the clean_cache_by_tags function when using PHP 7 with Magento 2.

Prerequisites

  • Magento 2.x with Varnish, Redis, and Nginx
  • PHP 7.x (issue is specific to PHP 7)
  • Admin access to Magento backend

Steps

Option A: Disable block_html Cache (Quick Fix)

Log in to the Magento Admin panel and navigate to:

System > Cache Management

Disable the Blocks HTML output cache type. This stops the cache tag clearing from triggering the bug.

Option B: Downgrade PHP to 5.6

If disabling the cache is not acceptable for performance, consider running PHP 5.6 until the Magento bug is resolved in a patch release.

# On Ubuntu — switch PHP version via update-alternatives or php5.6-fpm
systemctl stop php7.0-fpm
systemctl start php5.6-fpm

Option C: Apply the Magento Patch

Check the official Magento GitHub issue tracker for a patch targeting the clean_cache_by_tags method and apply via Composer:

composer update magento/module-page-cache

Verify

curl -I http://your-store.com/
# Expect: HTTP/1.1 200 OK (or 301/302 for redirects, not 503)

Notes

  • The bug affects Magento 2.x with PHP 7.x and manifests when cache invalidation by tags is triggered.
  • PHP 5.6 is end-of-life; treat Option B as a temporary measure only.

Fix Invalid Apache Directive Errors in Magento

After a cPanel or Apache upgrade, Magento may fail to load and the Apache error log shows an "Invalid command" error. This is caused by the mod_version Apache module not being loaded, which Magento's .htaccess requires.

Prerequisites

  • Magento running on Apache (cPanel or bare server)
  • Root or sudo access to enable Apache modules

Steps

1. Check the Apache Error Log

tail -f /var/log/apache2/error.log
# or on cPanel/CentOS:
tail -f /usr/local/apache/logs/error_log

Confirm the error mentions an invalid directive (typically in a <IfVersion> block).

2. Enable mod_version

On Debian/Ubuntu:

a2enmod version
systemctl restart apache2

On CentOS/RHEL — add to /etc/httpd/conf.modules.d/ or httpd.conf:

LoadModule version_module modules/mod_version.so
systemctl restart httpd

On cPanel, enable the module through WHM:

WHM > Apache Configuration > Global Configuration — ensure mod_version is checked, then rebuild the config.

3. Upgrade Magento if Needed

If you were prompted to upgrade Magento during cPanel maintenance, complete the upgrade:

cd /path/to/magento
bin/magento setup:upgrade

Verify

apache2ctl -M | grep version
# or: httpd -M | grep version
# Expect: version_module (shared)

Browse to the Magento store and admin — both should load without errors.

Notes

  • Magento's .htaccess uses <IfVersion> blocks, which require mod_version.
  • This issue commonly appears after automated cPanel updates that reset or rebuild the Apache module list.

Set Magento 2 File and Folder Permissions

Magento 2 requires specific file and directory permissions to function correctly and securely. Incorrect permissions cause installation failures, front-end errors, and admin issues.

Prerequisites

  • SSH access to the server as root or a sudo user
  • Magento 2 installed under a dedicated system user (e.g., magento)
  • Web server user known (e.g., www-data on Ubuntu, nginx on CentOS)

Steps

Recommended Permission Scheme

  • Directories: 770 (owner and group full, no world access)
  • Files: 660 (owner and group read/write, no world access)
  • Writable directories (var, pub/media, pub/static, app/etc): 777 or web-server-writable

Apply Permissions

find . -type f -exec chmod 644 {} \;
find . -type d -exec chmod 755 {} \;
find ./var -type d -exec chmod 777 {} \;
find ./pub/media -type d -exec chmod 777 {} \;
find ./pub/static -type d -exec chmod 777 {} \;
chmod 777 ./app/etc
chmod 644 ./app/etc/*.xml

Set Ownership

Replace magento and www-data with your Magento owner user and web server group:

chown -R magento:www-data /var/www/magento2
chmod u+x bin/magento

Verify

ls -la /var/www/magento2/var/
ls -la /var/www/magento2/app/etc/

Confirm var/ and pub/media/ are writable by the web server. Run the Magento readiness check in the installer or admin to confirm no file system errors.

Notes

  • For dedicated servers: set the web server user as the Magento file owner with 500 (dirs) and 400 (files) for maximum security, and 700/600 for var/ and pub/media/.
  • Never set permissions to 777 on non-writable directories in production.
  • Re-run permission commands after every deployment or Magento upgrade.

Nginx Configuration for Magento 2

Magento 2 supports Nginx 1.8 and later. This guide covers installing Nginx and PHP-FPM for Magento 2 on Ubuntu 16/18 and CentOS 7, including the required php.ini settings.

Prerequisites

  • Ubuntu 16/18 or CentOS 7 server
  • Root or sudo access
  • Magento 2 codebase already downloaded

Steps

Ubuntu: Install Nginx

apt-get -y install nginx

Ubuntu: Install and Configure PHP-FPM

apt-get -y install php7.2-fpm php7.2-cli

Edit both /etc/php/7.2/fpm/php.ini and /etc/php/7.2/cli/php.ini:

memory_limit = 2G
max_execution_time = 1800
zlib.output_compression = On
date.timezone = UTC
systemctl restart php7.2-fpm

CentOS 7: Install Nginx and PHP-FPM

yum install -y nginx php72-php-fpm php72-php-cli

Configure the Nginx Virtual Host

Copy the Magento-provided sample config and adjust for your environment:

cp /var/www/magento2/nginx.conf.sample /etc/nginx/conf.d/magento.conf

Minimum virtual host block:

upstream fastcgi_backend {
    server unix:/run/php/php7.2-fpm.sock;
}

server {
    listen 80;
    server_name example.com;
    set $MAGE_ROOT /var/www/magento2;
    set $MAGE_MODE developer;
    include /var/www/magento2/nginx.conf.sample;
    access_log /var/log/nginx/magento-access.log;
    error_log  /var/log/nginx/magento-error.log;
}

Test and Reload Nginx

nginx -t
systemctl reload nginx

Verify

curl -I http://example.com/
# Expect HTTP 200 or a Magento redirect

Notes

  • Always use Nginx with PHP-FPM (not mod_php) for Magento 2.
  • The nginx.conf.sample included in the Magento root handles all Magento-specific routing rules — do not remove the include.
  • For production, set $MAGE_MODE to production and run bin/magento deploy:mode:set production.

Fix HTTP 500 Error in Magento 2 on RHEL/CentOS

When Magento 2 returns an HTTP 500 error on CentOS/RHEL with Nginx and no error appears in /var/log/nginx/error.log, the actual error is typically in the PHP-FPM log or is blocked by SELinux.

Steps

1. Check the PHP-FPM Error Log

tail -f /var/log/php-fpm/www-error.log

PHP errors that are suppressed (display_errors = Off) result in a 500 response from Nginx. The actual error message appears in the PHP-FPM log.

2. Temporarily Enable PHP Error Display

Edit /etc/php.ini:

display_errors = On
systemctl restart php-fpm

Reload the page — the real PHP error will now be visible. Once resolved, set display_errors = Off again.

3. Check SELinux Status

sestatus

If SELinux is in enforcing mode it may be blocking PHP-FPM from reading Magento files, causing 500 errors with no PHP log entry.

Put SELinux in Permissive Mode Temporarily

setenforce 0

Reload the page. If it works now, SELinux is the culprit. Apply proper file contexts instead of leaving SELinux disabled:

semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/magento2/var(/.*)?'
semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/magento2/pub/media(/.*)?'
semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/magento2/pub/static(/.*)?'
semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/magento2/app/etc(/.*)?'
restorecon -Rv /var/www/magento2/
setenforce 1

Verify

curl -I http://your-store.com/
# Expect HTTP 200 or 301 (not 500)

Notes

  • If PHP pages render as plain text (no HTML), SELinux is blocking Nginx from executing PHP — the fcontext fix above resolves this.
  • To permanently disable SELinux (not recommended for production), edit /etc/selinux/config and set SELINUX=disabled, then reboot.

Install Magento 2 on CentOS 7

This guide covers a full Magento 2 installation on CentOS 7 with Nginx, PHP 7.1, MySQL, Composer, and Let's Encrypt SSL.

Prerequisites

  • CentOS 7 with at least 2 GB RAM
  • Sudo privileges
  • Domain name pointing to the server
  • Nginx, MySQL/MariaDB, and PHP 7.1 (LEMP stack) already installed
  • Let's Encrypt SSL certificate (optional but recommended)
  • Magento Marketplace account with access keys

Steps

1. Create the MySQL Database

mysql -u root -p
CREATE DATABASE magento;
GRANT ALL ON magento.* TO magento@localhost IDENTIFIED BY 'StrongPass123';
EXIT;

2. Install Required PHP Extensions

sudo yum install php-mysql php-opcache php-xml php-mcrypt php-gd php-soap   php-redis php-bcmath php-intl php-mbstring php-json php-iconv php-fpm php-zip

Tune PHP settings:

sudo sed -i "s/memory_limit = .*/memory_limit = 756M/" /etc/php.ini
sudo sed -i "s/upload_max_filesize = .*/upload_max_filesize = 256M/" /etc/php.ini
sudo sed -i "s/zlib.output_compression = .*/zlib.output_compression = on/" /etc/php.ini
sudo sed -i "s/max_execution_time = .*/max_execution_time = 18000/" /etc/php.ini
sudo sed -i "s/;date.timezone.*/date.timezone = UTC/" /etc/php.ini
sudo sed -i "s/;opcache.save_comments.*/opcache.save_comments = 1/" /etc/php.d/10-opcache.ini

3. Install Composer

curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer

4. Create a Dedicated Magento System User

sudo useradd -m -U -r -d /opt/magento magento
sudo usermod -a -G magento nginx
sudo chmod 750 /opt/magento

5. Download Magento via Composer

sudo su - magento
composer create-project --repository=https://repo.magento.com/   magento/project-community-edition /opt/magento/public_html
# Enter your Magento Marketplace public key as username and private key as password

6. Run the Magento Installer

cd /opt/magento/public_html
bin/magento setup:install   --base-url=https://example.com/   --db-host=localhost   --db-name=magento   --db-user=magento   --db-password=StrongPass123   --admin-firstname=Admin   --admin-lastname=User   --admin-email=admin@example.com   --admin-user=admin   --admin-password=Admin123@   --language=en_US   --currency=USD   --timezone=America/Chicago   --use-rewrites=1   --search-engine=elasticsearch7   --elasticsearch-host=localhost

7. Configure Nginx

sudo nano /etc/nginx/conf.d/magento.conf

Add a server block pointing root to /opt/magento/public_html and include the Magento nginx sample config.

8. Set Up Cron

crontab -u magento -e
# Add:
* * * * * /usr/bin/php /opt/magento/public_html/bin/magento cron:run 2>&1

Verify

bin/magento setup:di:compile
bin/magento deploy:mode:set production
curl -I https://example.com/

Notes

  • If running Magento 2.4+, Elasticsearch is required as the search engine.
  • Run bin/magento setup:upgrade after installing extensions.
  • Use bin/magento maintenance:enable before major updates.

Magento 2 Installation Steps on CentOS 7 with Nginx

Quick-reference installation sequence for Magento 2 on CentOS 7 with Nginx, Let's Encrypt SSL, and PHP-FPM.

Prerequisites

  • CentOS 7 server with root access
  • Domain name pointing to the server
  • Magento archive or Composer access keys

Steps

1. Create MySQL Database and User

mysql -u root -p
CREATE DATABASE magentoDB;
GRANT ALL ON magentoDB.* TO 'magentouser'@'localhost' IDENTIFIED BY 'StrongPass123';
FLUSH PRIVILEGES;
EXIT;

2. Install Nginx

rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
yum install -y nginx
systemctl enable nginx
systemctl start nginx

3. Install Certbot and Generate SSL Certificate

yum install -y certbot
openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
mkdir -p /var/lib/letsencrypt/.well-known
chgrp nginx /var/lib/letsencrypt
chmod g+s /var/lib/letsencrypt

4. Create Nginx SSL Snippets

mkdir /etc/nginx/snippets

Create /etc/nginx/snippets/letsencrypt.conf:

location ^~ /.well-known/acme-challenge/ {
    allow all;
    root /var/lib/letsencrypt/;
    default_type "text/plain";
    try_files $uri =404;
}

Create /etc/nginx/snippets/ssl.conf:

ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 30s;
add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;

5. Create Magento Nginx Virtual Host

Create /etc/nginx/conf.d/magento.conf:

upstream fastcgi_backend {
    server unix:/run/php-fpm/www.sock;
}

server {
    listen 80;
    server_name example.com www.example.com;
    include snippets/letsencrypt.conf;
    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;
    set $MAGE_ROOT /var/www/magento2;
    set $MAGE_MODE production;
    include snippets/ssl.conf;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /var/www/magento2/nginx.conf.sample;
    access_log /var/log/nginx/magento-access.log;
    error_log  /var/log/nginx/magento-error.log;
}

6. Obtain Let's Encrypt Certificate

nginx -t && systemctl reload nginx
certbot certonly --webroot -w /var/lib/letsencrypt/ -d example.com -d www.example.com

7. Reload Nginx

nginx -t && systemctl reload nginx

Verify

curl -I https://example.com/
# Expect: HTTP/2 200

Notes

  • Auto-renew certs: echo "0 */12 * * * root certbot renew --quiet" >> /etc/crontab
  • Install PHP extensions before running the Magento installer — see the CentOS PHP extension guide.

Magento 2 Nginx Config with Let's Encrypt SSL

A complete Nginx configuration for Magento 2 using Let's Encrypt SSL with PHP-FPM as the FastCGI backend and HTTPS redirect for HTTP traffic.

Prerequisites

  • Nginx installed and running
  • PHP-FPM running (socket or TCP)
  • Let's Encrypt certificate already issued (e.g., via Certbot)
  • Magento 2 installed with its nginx.conf.sample present in the document root

Configuration

Create or edit /etc/nginx/conf.d/magento.conf:

upstream fastcgi_backend {
    server unix:/run/php/php7.0-fpm.sock;
}

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

# HTTPS — Magento application
server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    set $MAGE_ROOT /var/www/magento2;
    set $MAGE_MODE production;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    access_log /var/log/nginx/magento-access.log;
    error_log  /var/log/nginx/magento-error.log;

    include /var/www/magento2/nginx.conf.sample;
}

If Using Varnish Behind Nginx (SSL Termination)

server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://127.0.0.1:6081;
        proxy_set_header Host              $http_host;
        proxy_set_header X-Forwarded-Host  $http_host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-Port  443;
        proxy_set_header Ssl-Offloaded     "1";
    }
}

Apply and Reload

nginx -t
systemctl reload nginx

Verify

curl -I https://example.com/
# Expect HTTP/2 200

Notes

  • Always replace example.com with your actual domain and adjust $MAGE_ROOT to the Magento installation path.
  • The include /var/www/magento2/nginx.conf.sample; line handles all Magento-specific routing — do not duplicate those rules manually.

Configure SELinux for Magento 2

On CentOS/RHEL systems with SELinux enforcing, Magento 2 requires specific file context labels to allow Nginx and PHP-FPM to read and write the necessary directories. Without these labels, Magento returns 500 errors or PHP pages render as plain text.

Prerequisites

  • CentOS 7 / RHEL 7 or later with SELinux enforcing
  • Magento 2 installed (adjust the path below to match your installation)
  • policycoreutils-python installed for semanage
yum install -y policycoreutils-python

Steps

1. Apply Writable File Contexts to Magento Directories

semanage fcontext -a -t httpd_sys_rw_content_t '/usr/share/nginx/html/app/etc(/.*)?'
semanage fcontext -a -t httpd_sys_rw_content_t '/usr/share/nginx/html/var(/.*)?'
semanage fcontext -a -t httpd_sys_rw_content_t '/usr/share/nginx/html/pub/media(/.*)?'
semanage fcontext -a -t httpd_sys_rw_content_t '/usr/share/nginx/html/pub/static(/.*)?'

If Magento is installed elsewhere (e.g., /var/www/magento2), adjust paths accordingly:

semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/magento2/app/etc(/.*)?'
semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/magento2/var(/.*)?'
semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/magento2/pub/media(/.*)?'
semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/magento2/pub/static(/.*)?'

2. Apply the Contexts

restorecon -Rv /usr/share/nginx/html/

Verify

ls -Z /var/www/magento2/var/
# Expect: httpd_sys_rw_content_t on the listed files and directories

Reload the Magento store in a browser. If it previously rendered as plain text or returned 500, it should now work correctly with SELinux still enforcing.

Notes

  • Diagnostic: if PHP pages show as text and there are no PHP errors, SELinux is blocking execution. Temporarily check with setenforce 0 and re-test.
  • Never leave SELinux permanently disabled in production. Apply the correct contexts instead.
  • After a Magento upgrade or fresh setup:static-content:deploy, re-run restorecon on affected directories.

Magento 2 Base Nginx Config Reference

This is a reference Nginx configuration for Magento 2 with PHP-FPM as the FastCGI backend and HTTPS handled by an SSL termination layer (Nginx listening on 443 and proxying to Magento on port 80).

Configuration

Create /etc/nginx/conf.d/magento.conf:

upstream fastcgi_backend {
    # Use TCP if php-fpm listens on a port:
    server 127.0.0.1:9000;
    # Or use a Unix socket (comment out above and uncomment below):
    # server unix:/run/php/php-fpm.sock;
}

# HTTP — plain Magento (or backend for Varnish)
server {
    listen 80;
    server_name _;

    set $MAGE_ROOT /opt/magento;
    include /opt/magento/nginx.conf.sample;

    access_log /opt/magento/var/log/nginx-access.log main;
    error_log  /opt/magento/var/log/nginx-error.log;
}

# HTTPS — SSL termination, proxy to HTTP backend
server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate     /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         'AES128+EECDH:AES128+EDH:!aNULL';
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 24h;
    keepalive_timeout   300s;

    location / {
        proxy_pass http://127.0.0.1;
        proxy_set_header Host              $http_host;
        proxy_set_header X-Forwarded-Host  $http_host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-Port  443;
        proxy_set_header Ssl-Offloaded     "1";
    }
}

Apply and Reload

nginx -t
systemctl reload nginx

Verify

curl -I http://localhost/
curl -I https://example.com/

Notes

  • Adjust $MAGE_ROOT to your actual Magento installation directory.
  • The include /opt/magento/nginx.conf.sample; directive is required and handles all Magento URL routing rules.
  • If using Varnish on port 6081, change proxy_pass http://127.0.0.1; to proxy_pass http://127.0.0.1:6081;.

Install the Magento Data Migration Tool

The Magento Data Migration Tool migrates data from Magento 1.x to Magento 2.x. It is installed as a Composer package into the Magento 2 root.

Prerequisites

  • Magento 2 already installed (from Composer or GitHub)
  • Composer available in PATH
  • Access to the Magento 2 root directory as the Magento file system owner

Steps

Option A: Install via Composer (Recommended)

cd /path/to/magento2
composer require magento/data-migration-tool:2.3.1

Replace 2.3.1 with the version that matches your Magento 2 installation. Version mismatch will cause errors.

Option B: Install from GitHub (if Magento 2 was cloned from GitHub)

cd /path/to/magento2
composer config repositories.data-migration-tool   git https://github.com/magento/data-migration-tool
composer require magento/data-migration-tool:2.3.1

Check Installed Version

cd /path/to/magento2/vendor/magento/data-migration-tool
cat composer.json | grep '"version"'

Verify

php bin/magento migrate:check --help
# Should display migration tool usage without errors

Notes

  • The Data Migration Tool version must exactly match the Magento 2 version. For example, Magento 2.3.1 requires tool version 2.3.1.
  • After installation, configure etc/config.xml inside the tool directory with your Magento 1 database credentials before running a migration.
  • If using Plesk with a bundled PHP, specify the full PHP binary path: /opt/plesk/php/7.2/bin/php /usr/lib64/plesk-9.0/composer.phar require ...

Reset Magento Admin Password

If you are locked out of the Magento admin panel, you can reset the admin password directly in the database using a MySQL query.

Prerequisites

  • Access to the Magento database via MySQL CLI or phpMyAdmin
  • Knowledge of the admin username

Steps

1. Find the Database Name

The database name is in the Magento config file:

  • Magento 1.x: app/etc/local.xml — look for <dbname>
  • Magento 2.x: app/etc/env.php — look for 'dbname'

2. Reset the Password — Magento 1.x

mysql -u root -p magento_db_name

UPDATE admin_user
SET password = MD5('YOUR_NEW_PASSWORD'), is_active = 1
WHERE username = 'YOUR_ADMIN_USERNAME';

3. Reset the Password — Magento 2.x

Magento 2 uses a salted SHA256 hash. Replace the xxxxxxxx placeholders with any 8-character random string (the salt):

mysql -u root -p magento_db_name

UPDATE admin_user
SET password = CONCAT(SHA2('xxxxxxxxYOUR_NEW_PASSWORD', 256), ':xxxxxxxx:1')
WHERE username = 'YOUR_ADMIN_USERNAME';

Alternative: Use Magento CLI (Magento 2 only)

cd /path/to/magento2
bin/magento admin:user:create   --admin-user=admin   --admin-password=NewPass123@   --admin-email=admin@example.com   --admin-firstname=Admin   --admin-lastname=User

Or unlock an existing user and set a new password using the customer:change-password equivalent approach via a custom script if the CLI user creation conflicts.

Verify

Browse to https://your-store.com/admin and log in with the new password.

Notes

  • If the admin_user table has a prefix (e.g., mg_admin_user), adjust the table name in the query.
  • After a successful login, flush the Magento cache: bin/magento cache:flush
  • For Magento 2, prefer the CLI method over direct database edits when possible.

Install Required PHP Extensions for Magento on CentOS 7

Magento 2 requires a specific set of PHP extensions. This guide covers installing them on CentOS 7 using the Remi repository for PHP 7.x.

Prerequisites

  • CentOS 7 with root or sudo access
  • Remi PHP repository enabled (for PHP 7.x packages)

Steps

1. Enable the Remi Repository

yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum install -y yum-utils
yum-config-manager --enable remi-php74

2. Install Required PHP Extensions

yum install -y php php-fpm php-cli php-mysql php-opcache php-xml   php-mcrypt php-gd php-soap php-redis php-bcmath php-intl   php-mbstring php-json php-iconv php-zip php-pdo

3. Tune PHP Settings for Magento

sudo sed -i "s/memory_limit = .*/memory_limit = 756M/" /etc/php.ini
sudo sed -i "s/upload_max_filesize = .*/upload_max_filesize = 256M/" /etc/php.ini
sudo sed -i "s/max_execution_time = .*/max_execution_time = 18000/" /etc/php.ini
sudo sed -i "s/zlib.output_compression = .*/zlib.output_compression = on/" /etc/php.ini
sudo sed -i "s/;date.timezone.*/date.timezone = UTC/" /etc/php.ini
sudo sed -i "s/;opcache.save_comments.*/opcache.save_comments = 1/" /etc/php.d/10-opcache.ini

4. Start and Enable PHP-FPM

systemctl enable php-fpm
systemctl start php-fpm

Verify

php -m | grep -E 'gd|intl|mbstring|opcache|pdo|soap|xml|zip'
# All listed extensions should appear in the output
php -i | grep memory_limit
# Expect: memory_limit => 756M

Notes

  • Magento 2.4+ requires PHP 7.4 or 8.1 — adjust the Remi repo enable step accordingly.
  • The php-redis extension is needed only if using Redis for sessions/cache.
  • After changing php.ini, restart PHP-FPM: systemctl restart php-fpm

How to Transfer/Migrate a Magento Installation

This guide covers moving a Magento installation to a new server or hosting provider, including file transfer, database migration, and configuration updates.

Prerequisites

  • SSH access to both the old and new servers
  • MySQL credentials on both servers
  • Sufficient disk space at the destination

Steps

1. Archive Magento Files on the Source Server

cd /path/to/magento
tar -czf /tmp/magento-backup.tar.gz .

2. Transfer the Archive to the New Server

scp /tmp/magento-backup.tar.gz user@new-server:/var/www/magento/

Or download it locally and upload via SFTP.

3. Extract on the New Server

cd /var/www/magento
tar -xzf magento-backup.tar.gz

4. Export the Database from the Source

mysqldump -u root -p magento_db > /tmp/magento_db.sql

5. Import the Database on the New Server

mysql -u root -p
CREATE DATABASE magento_db;
GRANT ALL ON magento_db.* TO 'magento'@'localhost' IDENTIFIED BY 'StrongPass123';
EXIT;

mysql -u root -p magento_db < /tmp/magento_db.sql

6. Update the Magento Configuration

Magento 1.x — edit app/etc/local.xml and update the database connection:

<host><![CDATA[localhost]]></host>
<username><![CDATA[magento]]></username>
<password><![CDATA[StrongPass123]]></password>
<dbname><![CDATA[magento_db]]></dbname>

Magento 2.x — edit app/etc/env.php and update the db section.

7. Update Site URLs in the Database (Magento 1.x)

mysql -u root -p magento_db
UPDATE core_config_data SET value='https://new-domain.com/' WHERE path='web/unsecure/base_url';
UPDATE core_config_data SET value='https://new-domain.com/' WHERE path='web/secure/base_url';

8. Fix Permissions and Clear Cache

find /var/www/magento -type d -exec chmod 755 {} \;
find /var/www/magento -type f -exec chmod 644 {} \;
chmod -R 777 /var/www/magento/var /var/www/magento/pub/media /var/www/magento/pub/static

# Magento 2
cd /var/www/magento
bin/magento cache:flush
bin/magento setup:upgrade

Verify

  • Browse to the new server URL — storefront and admin should load
  • Check var/log/system.log for errors
  • Test checkout and payment flows

Notes

  • If the new server uses a different PHP version, run bin/magento setup:di:compile after the move.
  • Always back up both the database and files before beginning the transfer.
  • Update DNS only after verifying the new server is fully functional.

Magento Reindex Commands

Magento maintains several indexes to improve storefront performance. When indexes become stale, products may not appear in search results or category pages. This reference covers reindexing via the command line for both Magento 1 and Magento 2.

Magento 2 — bin/magento CLI

Reindex All Indexes

bin/magento indexer:reindex

Reindex a Specific Index

bin/magento indexer:reindex catalog_product_price
bin/magento indexer:reindex catalogsearch_fulltext
bin/magento indexer:reindex catalog_product_attribute
bin/magento indexer:reindex catalog_category_product

Check Index Status

bin/magento indexer:status

List Available Index IDs

bin/magento indexer:info

Magento 1 — Shell Indexer Script

Reindex All (Background)

php /var/www/html/shell/indexer.php reindexall &

Check Status

php /var/www/html/shell/indexer.php --status

List Index Keys

php /var/www/html/shell/indexer.php --info

Reindex a Specific Index

php /var/www/html/shell/indexer.php --reindex catalog_product_price

Notes

  • For Magento 2, run commands from the Magento root as the Magento file system owner.
  • For large catalogs, run reindexing during off-peak hours or use schedule mode: bin/magento indexer:set-mode schedule
  • After reindexing, flush the cache: bin/magento cache:flush

Change the Magento Admin URL Path

Changing the Magento admin URL from the default /admin to a custom path reduces exposure to automated attacks. The change must be made via configuration file, not through the Magento Admin web UI.

Prerequisites

  • SSH or FTP access to the Magento installation
  • Ability to clear the Magento cache

Magento 2 (Recommended Method — CLI)

cd /path/to/magento2
bin/magento setup:config:set --backend-frontname=my_custom_admin

Then flush the cache:

bin/magento cache:flush

Magento 1.x — Edit local.xml

Step 1: Change the Admin Path

Open app/etc/local.xml and locate the admin frontname entry:

<frontName><![CDATA[admin]]></frontName>

Replace admin with your custom path (letters and numbers only, no special characters):

<frontName><![CDATA[my_custom_admin]]></frontName>

Step 2: Clear the Cache

rm -rf /path/to/magento/var/cache/*

Step 3: Access the New Admin URL

Log in at: https://your-domain.com/my_custom_admin

Verify

  • The new admin URL should display the login form
  • The old /admin URL should return a 404 error

Notes

  • Do not use the Magento Admin web interface to change the admin URL — this is known to cause redirect loops and broken admin access.
  • For Magento 2, the path is stored in app/etc/env.php under backend > frontName after running the CLI command.
  • Choose a path that is hard to guess (e.g., store_admin_2024) to reduce brute-force risk.

Magento CSV Import/Export Tips

Common pitfalls when importing products or categories into Magento via CSV files, and how to avoid data errors.

Category Fields

  • Category values must be specified as text names, not numeric IDs. For example: Men > Shirts, not 12.
  • Nested categories use a forward slash or greater-than separator depending on Magento version.

Special Characters in Category Names

  • Avoid apostrophes and other special characters in category names. For example, use Mens instead of Men's when preparing CSV data.
  • If the category name must contain an apostrophe, ensure the CSV field is properly quoted.

General CSV Import Tips

  • Always use UTF-8 encoding without BOM when saving CSV files.
  • Use comma as the field delimiter and double-quote as the string enclosure.
  • Required fields for product import: sku, store_view_code, attribute_set_code, product_type, name, price.
  • Test with a small batch (10–20 rows) before importing the full catalog.

Running an Import

In Magento Admin: System > Data Transfer > Import

Or via CLI (Magento 2):

bin/magento import:run   --entity=catalog_product   --behavior=append   --validation-strategy=stop-on-errors   /path/to/import.csv

Notes

  • Always back up the database before running large imports.
  • After a large import, reindex and flush the cache: bin/magento indexer:reindex && bin/magento cache:flush

Magento Image Import and Export

Magento allows bulk import and export of product images alongside the CSV product data. Images must be placed in the correct import directory before running the CSV import.

Prerequisites

  • Magento 2 admin access or CLI access
  • Product images ready in a supported format (JPEG, PNG, GIF)

Image Import Directory

Upload images to the Magento import directory before running the import:

/path/to/magento2/pub/media/import/

CSV Image Columns

In the product CSV, the image columns reference the filename relative to the import directory:

sku,base_image,small_image,thumbnail_image,additional_images
my-product,/my-product.jpg,/my-product.jpg,/my-product.jpg,"/extra1.jpg,/extra2.jpg"

Running the Image Import

In Magento Admin: System > Data Transfer > Import

  1. Set Entity Type to Products
  2. Set Import Behavior to Add/Update
  3. Enable Images File Directory if images are in a subdirectory of pub/media/import/
  4. Upload the CSV and click Check Data, then Import

Exporting Product Images

In Magento Admin: System > Data Transfer > Export

  1. Set Entity Type to Products
  2. Optionally filter by attribute set or SKU range
  3. Click Continue — a CSV file is generated and downloaded

Exported image paths in the CSV reference files under pub/media/catalog/product/.

Notes

  • After import, reindex and flush cache: bin/magento indexer:reindex && bin/magento cache:flush
  • Images are not included in the CSV export archive — copy pub/media/catalog/product/ separately when migrating.

Magento local.xml Configuration Reference

The app/etc/local.xml file is the primary configuration file for Magento 1.x, containing database credentials, cache settings, and session configuration. In Magento 2 this is replaced by app/etc/env.php.

Standard local.xml Structure

<?xml version="1.0"?>
<config>
    <global>
        <install>
            <date><![CDATA[Mon, 01 Jan 2024 00:00:00 +0000]]></date>
        </install>
        <crypt>
            <key><![CDATA[your_encryption_key_here]]></key>
        </crypt>
        <db>
            <table_prefix><![CDATA[]]></table_prefix>
        </db>
        <resources>
            <db>
                <adapter><![CDATA[pdo_mysql]]></adapter>
            </db>
            <default_setup>
                <connection>
                    <host><![CDATA[localhost]]></host>
                    <username><![CDATA[magento]]></username>
                    <password><![CDATA[StrongPass123]]></password>
                    <dbname><![CDATA[magento_db]]></dbname>
                    <initStatements><![CDATA[SET NAMES utf8]]></initStatements>
                    <model><![CDATA[mysql4]]></model>
                    <type><![CDATA[pdo_mysql]]></type>
                    <pdoType><![CDATA[]]></pdoType>
                    <active>1</active>
                </connection>
            </default_setup>
        </resources>
        <session_save><![CDATA[files]]></session_save>
    </global>
    <admin>
        <routers>
            <adminhtml>
                <args>
                    <frontName><![CDATA[admin]]></frontName>
                </args>
            </adminhtml>
        </routers>
    </admin>
</config>

Using Amazon RDS as the Database Host

Replace localhost with the RDS endpoint in the <host> element:

<host><![CDATA[myinstance.abcdefg.us-east-1.rds.amazonaws.com]]></host>

Ensure the RDS security group allows inbound MySQL (port 3306) from the Magento server IP.

Notes

  • Protect this file from web access — Nginx and Apache configs should deny access to app/etc/*.xml.
  • For Magento 2, the equivalent is app/etc/env.php — a PHP array file instead of XML.
  • After editing local.xml, clear the cache: rm -rf var/cache/*

Set Up a Remote MySQL Database Connection for Magento

When running Magento on a separate web node with a dedicated database server, you must configure Magento to connect to MySQL on a remote host and ensure the database server accepts that connection.

Prerequisites

  • MySQL server installed and running on the database host
  • Magento web node can reach the database host on port 3306 (firewall/security group rules)
  • Root MySQL access on the database server

Steps

1. Create the Database and Grant Remote Access

On the database server:

mysql -u root -p

CREATE DATABASE magento;
GRANT ALL PRIVILEGES ON magento.* TO 'magento'@'WEB_NODE_IP' IDENTIFIED BY 'StrongPass123';
FLUSH PRIVILEGES;
EXIT;

Replace WEB_NODE_IP with the IP address of your Magento web server.

2. Allow Remote Connections in MySQL Config

Edit /etc/my.cnf or /etc/mysql/mysql.conf.d/mysqld.cnf on the database server:

bind-address = 0.0.0.0
systemctl restart mysqld

3. Open Firewall Port on the Database Server

# firewalld (CentOS/RHEL)
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="WEB_NODE_IP" port protocol="tcp" port="3306" accept'
firewall-cmd --reload

# ufw (Ubuntu)
ufw allow from WEB_NODE_IP to any port 3306

4. Configure Magento to Use the Remote Database

Magento 2 — during installation:

bin/magento setup:install   --db-host=DB_SERVER_IP   --db-name=magento   --db-user=magento   --db-password=StrongPass123   ...

Or edit app/etc/env.php directly:

'db' => [
    'connection' => [
        'default' => [
            'host' => 'DB_SERVER_IP',
            'dbname' => 'magento',
            'username' => 'magento',
            'password' => 'StrongPass123',
        ],
    ],
],

Magento 1.x — edit app/etc/local.xml:

<host><![CDATA[DB_SERVER_IP]]></host>

Verify

# From the web node, test the connection:
mysql -h DB_SERVER_IP -u magento -p magento
# Should connect without error

Notes

  • For high-availability setups, point db-host to a database load balancer rather than a specific node.
  • If the connection fails, first verify connectivity: ping DB_SERVER_IP and telnet DB_SERVER_IP 3306.
  • Never expose MySQL port 3306 to the public internet — restrict access to specific IP addresses only.

Run Magento Admin on a Separate Server

In load-balanced Magento deployments, you may want to run the Magento admin panel on a dedicated server separate from the front-end cluster to prevent admin activity from affecting storefront performance.

Prerequisites

  • Magento 1.x installed and accessible
  • A separate subdomain or IP for the admin server (e.g., admin.example.com)
  • Admin access to Magento System Configuration

Steps

1. Disable Auto-Redirect to Base URL

In Magento Admin, navigate to:

System > Configuration > Web > URL Options > Auto-redirect to Base URL

Set to No. This prevents Magento from redirecting all admin requests back to the front-end base URL.

2. Set a Custom Admin Base URL

In Magento Admin, navigate to:

System > Configuration > Advanced > Admin > Admin Base URL

  • Set Use Custom Admin URL to Yes
  • Set Custom Admin URL to the admin server URL, e.g., https://admin.example.com/
  • Set Custom Admin Path to the admin frontname (e.g., admin)

3. Configure the Admin Server Nginx/Apache

On the admin server, ensure the Magento document root is served under the admin subdomain and that the admin server can connect to the same database as the front-end cluster.

Verify

  • Browse to https://admin.example.com/admin — admin login should appear
  • Front-end (https://example.com/) should continue to serve the storefront without redirect loops

Notes

  • Both the admin server and front-end nodes must point to the same shared database and shared media/ storage (NFS, S3, or similar).
  • Session storage (Redis or Memcached) must also be shared across all nodes.
  • If you see redirect loops after configuration, clear var/cache/ and browser cookies, then re-test.

Set Category "Is Anchor" to Yes for All Categories in Magento 1.9

In Magento 1.9, the "Is Anchor" category setting controls whether layered navigation (filters) appears on a category page. Setting all categories to "Is Anchor = Yes" in bulk requires a direct database update since there is no bulk UI action.

Prerequisites

  • MySQL access to the Magento database
  • Ability to run indexer commands

Steps

1. Find the is_anchor Attribute ID

mysql -u root -p magento_db

SELECT attribute_id FROM eav_attribute WHERE attribute_code = 'is_anchor';
-- Note the returned attribute_id (commonly 43, but may vary)

2. Update All Categories to Is Anchor = Yes

-- Replace 43 with your actual attribute_id from step 1
UPDATE catalog_category_entity_int
SET value = 1
WHERE attribute_id = 43;

3. Rebuild Affected Indexes

After the database update, rebuild the following indexes:

php /path/to/magento/shell/indexer.php --reindex catalog_category_flat
php /path/to/magento/shell/indexer.php --reindex catalog_product_attribute
php /path/to/magento/shell/indexer.php --reindex catalog_url

Verify

  • Browse to a category page on the storefront — layered navigation filters should now appear on all categories
  • Check in Magento Admin under Catalog > Manage Categories that categories show "Is Anchor: Yes"

Notes

  • The attribute_id for is_anchor differs between Magento installations. Always run the SELECT query first to confirm the correct value before updating.
  • Always back up the database before running bulk UPDATE queries.
  • If the update runs successfully but categories still do not show filters, also flush the Magento cache: rm -rf var/cache/*

Set Up Cron for Specific Magento Indexes

In Magento 1.9, the shell indexer script can be called from a cron job to reindex all or specific indexes on a schedule. This is useful when real-time reindexing is too slow for large catalogs.

Prerequisites

  • Magento 1.9 installed with the shell/indexer.php script
  • Cron configured on the server (crontab access)

Indexer Commands

Reindex All Indexes

php -f /path/to/magento/shell/indexer.php reindexall

List Available Indexes

php -f /path/to/magento/shell/indexer.php info

Reindex Specific Indexes

php /path/to/magento/shell/indexer.php --reindex catalog_product_attribute
php /path/to/magento/shell/indexer.php --reindex catalog_product_price
php /path/to/magento/shell/indexer.php --reindex catalog_url
php /path/to/magento/shell/indexer.php --reindex catalog_product_flat
php /path/to/magento/shell/indexer.php --reindex catalog_category_flat
php /path/to/magento/shell/indexer.php --reindex catalog_category_product
php /path/to/magento/shell/indexer.php --reindex catalogsearch_fulltext
php /path/to/magento/shell/indexer.php --reindex cataloginventory_stock
php /path/to/magento/shell/indexer.php --reindex tag_summary

Setting Up a Cron Job

Reindex All — Every Hour

crontab -e
# Add:
0 * * * * php -f /path/to/magento/shell/indexer.php reindexall

Reindex Specific Indexes — Custom Schedule

# Create a shell script for the indexes you want:
cat > /usr/local/bin/magento-reindex.sh << 'EOF'
#!/bin/bash
php /path/to/magento/shell/indexer.php --reindex catalog_product_price
php /path/to/magento/shell/indexer.php --reindex catalogsearch_fulltext
EOF
chmod +x /usr/local/bin/magento-reindex.sh

# Add to crontab (every 30 minutes):
*/30 * * * * /usr/local/bin/magento-reindex.sh

Notes

  • Run the indexer as the web server user or Magento file owner to avoid permission errors.
  • For Magento 2, use bin/magento indexer:reindex and bin/magento indexer:set-mode schedule instead.
  • Avoid running full reindex during peak traffic hours on large catalogs.

Revert Magento Codebase to a Previous Git Commit

If a Magento deployment introduces a regression, you can roll the codebase back to a previous known-good Git commit. This is a hard reset and discards all commits after the target.

Prerequisites

  • Magento codebase managed in a Git repository
  • SSH access to the server
  • Push access to the remote repository

Steps

1. Identify the Target Commit

git log --oneline -20
# Find the commit hash of the last known-good state

2. Hard Reset to the Target Commit

git reset --hard <commit-hash>
# Example:
git reset --hard a1b2c3d

Or to reset to the previous commit:

git reset --hard HEAD~1

3. Force Push to the Remote (if needed)

git push -f origin main

4. Clear Magento Cache and Recompile

cd /path/to/magento2
bin/magento cache:flush
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f

Verify

git log --oneline -5
# Confirm HEAD is at the intended commit

curl -I https://your-store.com/
# Expect HTTP 200

Notes

  • git reset --hard permanently discards all local changes and commits after the target — ensure you have a backup or have tagged the current state before resetting.
  • Force push (-f) rewrites remote history — coordinate with the team before doing this on a shared branch.
  • Database changes from the reverted deployment are not rolled back by Git — restore a database backup separately if needed.

Stop Running Magento Indexes from the Command Line

Magento indexes can get stuck in a "Running" state due to a crashed process or a deadlock. When this happens the Admin shows indexes as running indefinitely and new reindex jobs are blocked. This guide shows how to identify and reset stuck indexes from the command line.

Prerequisites

  • SSH access to the Magento server
  • MySQL access to the Magento database
  • Magento 1.x with the shell/indexer.php script

Steps

1. Check Index Status

php /path/to/magento/shell/indexer.php status

Indexes showing "Running" when no process is actively running them are stuck.

2. Verify No Indexer Process is Actually Running

ps aux | grep indexer

If no PHP indexer process is listed, the "Running" status is a stale database flag.

3. Reset Stuck Index Statuses in the Database

mysql -u root -p magento_db

-- Reset all indexes to "pending" status
UPDATE index_process SET status = 'pending' WHERE status = 'running';
EXIT;

4. Verify the Reset

php /path/to/magento/shell/indexer.php status

All indexes should now show "Pending" or "Require Reindex".

5. Reindex

php /path/to/magento/shell/indexer.php reindexall

Notes

  • Common causes of stuck indexes: PHP process killed mid-run, MySQL deadlock during price reindex, or server restart during indexing.
  • The catalog_product_price index is particularly prone to causing database deadlocks during checkout — if this index is frequently stuck, switch it to schedule mode.
  • For Magento 2, use bin/magento indexer:reset to reset stuck indexes instead of direct database updates.

Reindex Magento from the Command Line

The Magento command-line indexer allows you to reindex all or specific indexes without using the web interface. This is necessary when the web-based indexer times out or fails on large catalogs.

Prerequisites

  • SSH access to the Magento server
  • Magento 1.x: shell/indexer.php accessible
  • Magento 2.x: bin/magento CLI

Magento 1.x

Check All Index Statuses

php /path/to/magento/shell/indexer.php --status

List Index Keys

php /path/to/magento/shell/indexer.php --info

Returns index keys like:

catalog_product_attribute    Product Attributes
catalog_product_price        Product Prices
cataloginventory_stock       Stock Status
catalog_url                  Catalog URL Rewrites
catalog_product_flat         Product Flat Data
catalog_category_flat        Category Flat Data
catalog_category_product     Category Products
catalogsearch_fulltext       Catalog Search Index
tag_summary                  Tag Aggregation Data

Reindex a Single Index

php /path/to/magento/shell/indexer.php --reindex catalog_product_price

Reindex All Indexes

php /path/to/magento/shell/indexer.php reindexall

Magento 2.x

Check Status

bin/magento indexer:status

Reindex All

bin/magento indexer:reindex

Reindex Specific Index

bin/magento indexer:reindex catalog_product_price
bin/magento indexer:reindex catalogsearch_fulltext

Verify

# Magento 1:
php shell/indexer.php --status
# Expect all indexes to show "Pending" (up to date)

# Magento 2:
bin/magento indexer:status
# Expect all indexes to show "Ready"

Notes

  • For Magento 2, run bin/magento indexer:set-mode schedule to switch to scheduled reindexing instead of manual.
  • Run indexing as the Magento file system owner, not root.
  • After indexing large catalogs, flush the cache: bin/magento cache:flush

Log All Magento SQL Queries

Logging all SQL queries executed by Magento is useful for debugging slow pages, finding N+1 query problems, or auditing database activity. Magento has a built-in query logger in the PDO MySQL adapter.

Prerequisites

  • SSH access to the Magento server
  • Magento 1.x installation (the file-based method below applies to Magento 1)
  • Write permissions to the Magento lib/ directory

Method 1: Enable Magento Built-in SQL Logger (Magento 1.x)

Edit lib/Varien/Db/Adapter/Pdo/Mysql.php and set the following properties to true (around line 103):

/**
 * Write SQL debug data to file
 * @var bool
 */
protected $_debug = true;

/**
 * Minimum query duration time to be logged (seconds)
 * @var float
 */
protected $_logQueryTime = 0.05;

/**
 * Log all queries (ignores minimum query duration)
 * @var bool
 */
protected $_logAllQueries = true;

/**
 * Add call stack data (backtrace) to log
 * @var bool
 */
protected $_logCallStack = true;

Logs are written to:

var/debug/pdo_mysql.log

Example Log Output

## 2024-01-01 12:18:47
## 10258 ## QUERY
SQL: SELECT `adminnotification_inbox`.* FROM `adminnotification_inbox` WHERE ...
TIME: 0.0012

Method 2: Enable MySQL General Query Log

Edit /etc/my.cnf or /etc/mysql/mysql.conf.d/mysqld.cnf:

general_log = 1
general_log_file = /var/log/mysql/general.log
systemctl restart mysqld
tail -f /var/log/mysql/general.log

Verify

tail -f /path/to/magento/var/debug/pdo_mysql.log
# Load a page in the browser — queries should appear in the log

Notes

  • Disable SQL logging in production after debugging — it creates large log files and degrades performance.
  • For Magento 2, use the built-in profiler or Xdebug with a database profiler tool such as Blackfire or New Relic.
  • The MySQL general query log logs all queries server-wide — use it briefly and disable promptly.

Update Site URL in core_config_data After Server Migration

After moving a Magento 1.x store to a new server or changing the domain name, the old URL stored in the core_config_data table must be updated. Failure to do so results in broken CSS, JS, and redirect loops.

Prerequisites

  • Access to the Magento database via MySQL CLI, phpMyAdmin, or MySQL Workbench
  • New domain name or server URL
  • Database backup taken before proceeding

Steps

1. Find the Current URL Rows

SELECT config_id, scope, scope_id, path, value
FROM core_config_data
WHERE path IN ('web/unsecure/base_url', 'web/secure/base_url', 'admin/url/custom');

Note the config_id for each row you need to update.

2. Update Each URL Row

-- Update unsecure base URL (note trailing slash is required)
UPDATE core_config_data
SET value = 'https://new-domain.com/'
WHERE config_id = 261;

-- Update secure base URL
UPDATE core_config_data
SET value = 'https://new-domain.com/'
WHERE config_id = 262;

Alternatively, update by path (if you only have one store view):

UPDATE core_config_data SET value = 'https://new-domain.com/' WHERE path = 'web/unsecure/base_url';
UPDATE core_config_data SET value = 'https://new-domain.com/' WHERE path = 'web/secure/base_url';

3. Clear Magento Cache

rm -rf /path/to/magento/var/cache/*

Verify

SELECT path, value FROM core_config_data
WHERE path IN ('web/unsecure/base_url', 'web/secure/base_url');

Browse to the new domain — storefront should load with correct CSS and JS.

Notes

  • The trailing slash in the URL value is mandatory. Without it, CSS and JS paths break completely.
  • For multi-store setups, each store view may have its own URL row — update all rows, not just the default scope.
  • For Magento 2, use bin/magento setup:store-config:set --base-url="https://new-domain.com/" or update core_config_data using the same approach.
  • Always back up the database before running UPDATE queries on config data.

Set Up Magento on CentOS 7 (Quick Reference)

A condensed quick-reference for setting up Magento on CentOS 7 with Nginx, Let's Encrypt SSL, PHP-FPM, and MySQL.

Prerequisites

  • CentOS 7 server with root access
  • Domain name pointed at the server
  • Magento archive or Composer access

Steps

1. Create Database and User

mysql -u root -p
CREATE DATABASE magentodb;
CREATE USER 'magentouser'@'%' IDENTIFIED BY 'StrongPass123';
GRANT ALL PRIVILEGES ON magentodb.* TO 'magentouser'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
EXIT;

2. Install Nginx

rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
yum install -y nginx
systemctl enable nginx
systemctl start nginx

3. Set Up Let's Encrypt SSL

yum install -y certbot
openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
mkdir -p /var/lib/letsencrypt/.well-known
chgrp nginx /var/lib/letsencrypt
chmod g+s /var/lib/letsencrypt

Create /etc/nginx/snippets/letsencrypt.conf:

location ^~ /.well-known/acme-challenge/ {
    allow all;
    root /var/lib/letsencrypt/;
    default_type "text/plain";
    try_files $uri =404;
}

Create /etc/nginx/snippets/ssl.conf:

ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;

4. Create Nginx Virtual Host

Create /etc/nginx/conf.d/magento.conf:

upstream fastcgi_backend {
    server unix:/run/php-fpm/www.sock;
}

server {
    listen 80;
    server_name example.com www.example.com;
    include snippets/letsencrypt.conf;
    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;
    set $MAGE_ROOT /var/www/magento2;
    set $MAGE_MODE production;
    include snippets/ssl.conf;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /var/www/magento2/nginx.conf.sample;
    access_log /var/log/nginx/magento-access.log;
    error_log  /var/log/nginx/magento-error.log;
}

5. Obtain Let's Encrypt Certificate

nginx -t && systemctl reload nginx
certbot certonly --webroot -w /var/lib/letsencrypt/ -d example.com -d www.example.com
systemctl reload nginx

6. Install Magento and Run Installer

cd /var/www/magento2
bin/magento setup:install   --base-url=https://example.com/   --db-host=localhost   --db-name=magentodb   --db-user=magentouser   --db-password=StrongPass123   --admin-firstname=Admin --admin-lastname=User   --admin-email=admin@example.com   --admin-user=admin --admin-password=Admin123@   --language=en_US --currency=USD   --timezone=America/Chicago --use-rewrites=1

Verify

curl -I https://example.com/
bin/magento indexer:status

Notes

  • Auto-renew SSL: echo "0 */12 * * * root certbot renew --quiet" >> /etc/crontab
  • Configure SELinux contexts for Magento directories if SELinux is enforcing — see the SELinux guide.

Find the Magento 2 Admin Path in the Database

In Magento 2, the admin panel path is not stored in the database by default — it is defined in app/etc/env.php. However, if a custom admin URL was set via the database, it can also appear in core_config_data. This guide covers all methods for finding and changing the admin path.

Method 1: Check env.php (Primary Location)

cat /path/to/magento2/app/etc/env.php | grep -A2 "backend"

Output example:

'backend' => [
    'frontName' => 'admin_1ai8c5',
],

Method 2: Use the Magento CLI

cd /path/to/magento2
bin/magento info:adminuri

Output: /admin_1ai8c5

Method 3: Query core_config_data

mysql -u root -p magento_db

SELECT path, value FROM core_config_data
WHERE path LIKE '%admin%url%';

-- Look for: admin/url/use_custom and admin/url/custom

Change the Admin Path

Using CLI (Recommended)

bin/magento setup:config:set --backend-frontname=newadminpath

If Admin is Inaccessible — Use Database

mysql -u root -p magento_db

INSERT INTO core_config_data (scope, scope_id, path, value)
VALUES ('default', 0, 'admin/url/use_custom', 1);

INSERT INTO core_config_data (scope, scope_id, path, value)
VALUES ('default', 0, 'admin/url/custom', 'https://example.com/newadminpath/');
EXIT;

Then run:

bin/magento setup:config:set --backend-frontname="newadminpath"
bin/magento maintenance:enable
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento maintenance:disable

Verify

bin/magento info:adminuri
# Expect: /newadminpath

Browse to https://example.com/newadminpath — the admin login page should load.

Notes

  • Magento 2 generates a random admin path suffix during installation (e.g., admin_1ai8c5) for security. Do not simplify it to just admin in production.
  • Always use the CLI method when possible — direct env.php or database edits can leave configuration inconsistent.
  • After changing the admin path, flush the cache: bin/magento cache:flush