Install Magento eCommerce Site on Ubuntu 22.04 Server with Nginx

This tutorial is going to show you how to install Magento on Ubuntu 22.04 with Nginx, MySQL, and PHP8.1 (LEMP Stack). Magento is a very popular content management system (CMS) specifically built for e-commerce sellers to set up their own online stores.

Magento Features

  • 100% control of customer data.
  • You can install it on your server and there is no need to worry about your shop being shut down by a third party (like Shopify and Amazon).
  • The built-in page builder provides modern, drag-and-drop tools to quickly create compelling content and shopping experiences without the need for developer support.
  • Single-store mode and multi-store mode.
  • A vast marketplace of extensions.

Step 1: Check Requirements

Here’s what you should prepare before setting up your own Magento e-commerce site.

1. A domain name. You need a domain name, so visitors can use it to access your e-commerce store. I registered my domain name at NameCheap because the price is low and they give whois privacy protection free for life.

2. A server. To run Magento, you need a server with at least 4GB RAM. If you are looking for a virtual private server (VPS), I recommend Kamatera VPS, which features:

  • 30 days free trial.
  • Starts at $4/month (1GB RAM)
  • High-performance KVM-based VPS
  • 9 data centers around the world, including the United States, Canada, UK, Germany, The Netherlands, Hong Kong, and Isreal.

Follow the tutorial linked below to create your Linux VPS server at Kamatera.

3. SMTP Service. You need to use an SMTP server to send emails for account registration and various other notifications to your customers.  You can use a free SMTP relay service.

Once the above requirements are met, follow the steps below to install Magento.

Step 2: Install ElasticSearch on Ubuntu Server

SSH into your Ubuntu 22.04 server and update existing software.

sudo apt update && sudo apt upgrade -y

ElasticSearch is a fast and scalable search and analytics engine. It’s used by Magento as the catalog search solution. We can install Elasticsearch from the official repository with the following commands. (Note: Magento currently isn’t compatible with ElasticSearch 8. We will install ElasticSearch 7.)

Install the apt-transport-https package because the ElasticSearch repository uses HTTPS protocol.

sudo apt-get install -y apt-transport-https

Add the ElasticSearch repository.

echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-7.x.list

Import ElasticSearch GPG public key.

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg

Update repository index and install ElasticSearch.

sudo apt update 

sudo apt install -y elasticsearch default-jre-headless

Then start ElasticSearch

sudo systemctl enable --now elasticsearch

Check the status.

systemctl status elasticsearch

We can see that it’s now enabled and running, and it uses 2.3G RAM. (Hint: If this command doesn’t quit immediately, press Q to make it quit.)

magento elasticsearch ubuntu

By default, it listens on 127.0.0.1:9200, as can be shown with:

sudo ss -lnpt | grep 9200

Sample output:

elasticsearch 7 listen on localhost

You may want to reduce the memory usage of ElasticSearch. To do that, create the /etc/elasticsearch/jvm.options.d/memory.options file.

sudo nano /etc/elasticsearch/jvm.options.d/memory.options

Add the following two lines in this file.

-Xms1g
-Xmx1g

This means the Java virtual machine used by ElasticSearch will use 1G RAM. Note that there should not be any space at the beginning of each line. Restart ElasticSearch for the change to take effect.

sudo systemctl restart elasticsearch

Run the following command to test if ElasticSearch is working.

curl http://localhost:9200

If ElasticSearch is working properly, it will output a message like below.

{
  "name" : "ubuntu",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "uO_sXa_0T9ua-pkUn3aTbQ",
  "version" : {
    "number" : "7.17.4",
    "build_flavor" : "default",
    "build_type" : "deb",
    "build_hash" : "79878662c54c886ae89206c685d9f1051a9d6411",
    "build_date" : "2022-05-18T18:04:20.964345128Z",
    "build_snapshot" : false,
    "lucene_version" : "8.11.1",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

If it’s not working, you will get the reply:

Curl: (52) Empty reply from server

Step 3: Download Magento on Ubuntu Server

Install Composer, which is a PHP dependency manager.

sudo apt install -y composer

Create web root directory for Magento.

sudo mkdir -p /var/www/magento/

Create the .config directory for the www-data user.

sudo mkdir -p /var/www/.config/

Make sure the www-data user can write to this directory.

sudo chown www-data:www-data /var/www/ -R

Install the necessary PHP extensions.

sudo apt install -y php-imagick php8.1-fpm php8.1-mbstring php8.1-soap php8.1-bcmath php8.1-xml php8.1-mysql php8.1-common php8.1-gd php8.1-cli php8.1-curl php8.1-zip php8.1-intl

Change to the /var/www/ directory.

cd /var/www/

Create the Magento project.

sudo -u www-data composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition magento

install magento via composer ubuntu

The repo.magento.com URL requires user authentication. Go to https://marketplace.magento.com/ to create an account, then go to this URL (https://marketplace.magento.com/customer/accessKeys/) to create an access key for Magento 2. Use the Public key as your username and the Private key as your password.

magento access keys

Next, run the following commands to set file permissions.

cd /var/www/magento/

sudo find var generated vendor pub/static pub/media app/etc -type f -exec chmod g+w {} +

sudo find var generated vendor pub/static pub/media app/etc -type d -exec chmod g+ws {} +

sudo chown -R :www-data .

sudo chmod u+x bin/magento

Step 4: Install MySQL Database Server

Magento currently supports: MySQL-8, MySQL-5.7, MariaDB-10.4. MariaDB 10.5 or higher is not supported. Ubuntu 22.04 repository includes MariaDB 10.6, so we will choose MySQL instead of MariaDB.

Run the following command to install MySQL 8.0 from the default Ubuntu repository.

sudo apt install mysql-server-8.0

Once it’s installed, MySQL server will be automatically started, as can be seen with:

sudo systemctl status mysql

ubuntu mysql community server

If it’s not running, you can start with:

sudo systemctl enable --now mysql

Step 5: Create a Database and User for Magento Site

Log into MySQL console as root with the following command.

sudo mysql -u root

Once you are logged in, create a database for Magento using the following command. I named it magento, but you can use whatever name you like such as your site name. (Don’t leave out the semicolon.)

CREATE DATABASE magento;

Then enter the command below to create a database user for Magento. Replace magento_password with your preferred password.

CREATE USER 'magento'@'localhost' IDENTIFIED BY 'magento_password';

Next, grant permissions to this user.

GRANT ALL PRIVILEGES ON magento.* to 'magento'@'localhost';

Flush the privileges table for the changes to take effect and then get out of MySQL console.

FLUSH PRIVILEGES;

EXIT

Ubuntu magento mysql database

Step 6: Install Magento on Ubuntu Server

Make sure you are in the /var/www/magento/ directory.

cd /var/www/magento/

Run the following command to install Magento.

sudo -u www-data bin/magento setup:install --base-url=http://example.com --use-secure=1 --base-url-secure=https://example.com --use-secure-admin=1 --db-host=localhost --db-name=magento --db-user=magento --db-password=magento_password --admin-firstname=super --admin-lastname=admin --admin-email=[email protected] --admin-user=admin --admin-password=admin_password --language=en_US --currency=USD --timezone=America/Chicago --use-rewrites=1 --elasticsearch-host=http://127.0.0.1 --elasticsearch-port=9200 --elasticsearch-enable-auth=0

Replace:

  • example.com with your real domain name.
  • magento_password with the password created in step 5.
  • [email protected] with your preferred admin email address.
  • admin_password with your preferred admin password.

The installation process is pretty fast. As you can see, Magento is installed successfully.

magento installation complete ubuntu server

If you encounter the following error in the installation process, it’s because ElasticSearch isn’t running or you configured it wrong.

 Could not validate a connection to Elasticsearch. No alive nodes found in your cluster

Now create Magento Cron jobs.

sudo -u www-data php8.1 bin/magento cron:install

This will add the cron job in the www-data user’s crontab file. You can check it with:

sudo -u www-data crontab -l

Output:

#~ MAGENTO START d1957f62aa710cc367525c9ec68dd7456d4311756b5aa37d2143c4a98b25318c
* * * * * /usr/bin/php8.1 /var/www/magento/bin/magento cron:run 2>&1 | grep -v "Ran jobs by schedule" >> /var/www/magento/var/log/magento.cron.log
#~ MAGENTO END d1957f62aa710cc367525c9ec68dd7456d4311756b5aa37d2143c4a98b25318c

The Magento installer gives us the admin URI. Each Magento may have a unique admin URI, so you need to remember or bookmark it in your web browser.  Next, we need to set up Nginx web server in order to access the admin panel.

Step 6: Set Up Nginx Virtual Host

Install Nginx web server.

sudo apt install nginx

Remove the default virtual host.

sudo rm /etc/nginx/sites-enabled/default

Magento ships with a sample Nginx config file in /var/www/magento/ directory. Move it to the /etc/nginx/conf.d/ directory.

sudo mv /var/www/magento/nginx.conf.sample /etc/nginx/conf.d/magento.sample

We create a new virtual host file for Magento in the /etc/nginx/conf.d/ directory. The file name must end with .conf.

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

Put the following texts into the file. Replace the red texts with your own domain name. Don’t forget to create DNS A records for your domain name in your DNS zone editor.

upstream fastcgi_backend {
   server unix:/var/run/php/php8.1-fpm.sock;
}

server {
  listen 80;
  listen [::]:80;
  server_name www.example.com example.com;
  set $MAGE_ROOT /var/www/magento/;
  include /etc/nginx/conf.d/magento.sample;
  client_max_body_size 2M;

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

Save and close the file. Then test Nginx configurations.

sudo nginx -t

If the test is successful, reload Nginx.

sudo systemctl reload nginx

Open TCP port 80 and 443 in firewall.

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

Enter your domain name in the browser address bar and the default Magento page will show up.

example.com

magento default home page

Step 7: Enabling HTTPS

To encrypt the HTTP traffic, we can enable HTTPS by installing a free TLS certificate issued from Let’s Encrypt. Run the following command to install Let’s Encrypt client (certbot) on Ubuntu 22.04 server.

sudo apt install certbot python3-certbot-nginx

And run this command to obtain and install TLS certificate.

sudo certbot --nginx --agree-tos --no-eff-email --redirect --hsts --staple-ocsp --email [email protected] -d example.com,www.example.com

Wher

  • --nginx: Use the Nginx plugin.
  • --agree-tos: Agree to terms of service.
  • --no-eff-email: Don’t subscribe to the EFF mailing list.
  • --redirect: Force HTTPS by 301 redirect.
  • --hsts: Add the Strict-Transport-Security header to every HTTP response. Forcing the browser to always use TLS for the domain. Defends against SSL/TLS Stripping.
  • --staple-ocsp: Enables OCSP Stapling. A valid OCSP response is stapled to the certificate that the server offers during TLS.
  • --email: Email used for registration and recovery contact.
  • -d flag is followed by a list of domain names, separated by comma. You can add up to 100 domain names.

The certificate should now be obtained and automatically installed.

magento https certbot

If you reload the Magento home page, you can see that HTTP is automatically redirected to HTTPS connection.

Step 8: Set Up SMTP Relay

Before accessing the Magento admin panel, you need to make sure SMTP is working because the Magento requires it to set up two factor authentication. You won’t be able to log in if you don’t set it up.

Follow the tutorial linked below to set up Postfix SMTP relay. This will also allow Magento to send emails to your customers.

Step 9: Log into Magento Admin Panel

You can now log into Magento admin panel. If you don’t remember your admin URI, run the following command to display it on the command line.

sudo -u www-data php8.1 /var/www/magento/bin/magento info:adminuri

magento admin URI

When logging in with the admin account, you need to use your username, not your admin email address. Upon first login, you need to configure two factor authentication.

magento two factor authentication

Magento admin dashboard

magento admin dashboard

If the admin dashboard displays the following message.

One or more indexers are invalid. Make sure your Magento cron job is running.

You can manually reindex.

sudo -u www-data /usr/bin/php8.1 /var/www/magento/bin/magento indexer:reindex

Create Additional Admin Users

It can be helpful to create multiple admin users when working with a team because an account can be used by only one person at the same time.

sudo -u www-data php8.1 /var/www/magento/bin/magento admin:user:create

Increase Upload File Size Limit

By default, files such as images, PDF files uploaded to the Magento media library can not be larger than 2MB. To increase the upload size limit, edit the PHP configuration file.

sudo nano /etc/php/8.1/fpm/php.ini

Find the following line (line 846).

upload_max_filesize = 2M

Change the value like below:

upload_max_filesize = 20M

Then find the following line (line 694).

post_max_size = 8M

Change the maximum size of POST data that PHP will accept.

post_max_size = 20M

Save and close the file. Alternatively, you can run the following two commands to change the value without manually opening the file.

sudo sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 20M/g' /etc/php/8.1/fpm/php.ini

sudo sed -i 's/post_max_size = 8M/post_max_size = 20M/g' /etc/php/8.1/fpm/php.ini

Then restart PHP-FPM.

sudo systemctl restart php8.1-fpm

Nginx also sets a limit of upload file size. The default maximum upload file size limit set by Nginx is 1MB. To allow uploading large files to your Magento site, edit the Nginx configuration file.

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

We have already set the maximum file size in this file, as indicated by

client_max_body_size 2M;

You can change it if you prefer, like 20M.

client_max_body_size 20M;

Save and close the file. Then reload Nginx for the changes to take effect.

sudo systemctl reload nginx

How to Back Up Magento

You can choose the traditional approach to back up the MySQL database and web files (/var/www/magento/).

Magento Built-in Backups

Alternatively, you can use the Magento built-in functionality to take backups. Enable the backup functionality.

sudo -u www-data php8.1 /var/www/magento/bin/magento config:set system/backup/functionality_enabled 1

Take code and configuration files backup:

sudo -u www-data php8.1 /var/www/magento/bin/magento setup:backup --code

Take media backup:

sudo -u www-data php8.1 /var/www/magento/bin/magento setup:backup --media

Take complete database backup.

sudo -u www-data php8.1 /var/www/magento/bin/magento setup:backup --db

Backups are stored under /var/www/magento/var/backups/.

How to Restore Magento

Roll back the code

sudo -u www-data php8.1 /var/www/magento/bin/magento setup:rollback --code-file=code_filename

Roll back the media

sudo -u www-data php8.1 /var/www/magento/bin/magento setup:rollback --media-file=meida_filename

Roll back the database.

sudo -u www-data php8.1 /var/www/magento/bin/magento setup:rollback --db-file=db_filename

Then flush Magento cache.

sudo -u www-data php8.1 /var/www/magento/bin/magento cache:flush
sudo -u www-data php8.1 /var/www/magento/bin/magento cache:clean

Disable maintenance mode.

sudo -u www-data php8.1 /var/www/magento/bin/magento maintenance:disable

If you encounter the following error during the rollback process, you can ignore them.

Deprecated Functionality: preg_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated in /var/www/magento/vendor/magento/zendframework1/library/Zend/Db/Statement.php on line 222

In Mysql.php line 109:
                                                                                                                                                                            
  SQLSTATE[HY000]: General error: 1100 Table 'queue_lock' was not locked with LOCK TABLES, query was: DELETE FROM `queue_lock` WHERE (created_at <= '2022-06-18 14:09:35')  
                                                                                                                                                                            

In Mysql.php line 90:
                                                                                           
  SQLSTATE[HY000]: General error: 1100 Table 'queue_lock' was not locked with LOCK TABLES  

If the following error occurs,

The rollback can't be executed because not all files are writable.

then you should run the restore as root.

sudo php8.1 /var/www/magento/bin/magento setup:rollback --code-file=code_filename

Once the restore is complete, change the file ownership.

sudo chown www-data:www-data /var/www/magento/ -R

Restore Magento Database via MySQL

A best practice is to create another database like magento_restore, then restore with the .sql file.

CREATE DATABASE magento_restore;

GRANT ALL PRIVILEGES ON magento_restore.* to 'magento'@'localhost';

Enable maintenance mode.

sudo -u www-data php8.1 /var/www/magento/bin/magento maintenance:enable

Then use MySQL command to restore the database like so:

sudo mysql -u root magento_restore < /var/www/magento/var/backups/1655562157_db.sql

Then edit the env.php file.

sudo nano /var/www/magento/app/etc/env.php

Change the database name:

'host' => '127.0.0.1',
'dbname' => 'magento_restore',
'username' => 'magento',
'password' => 'magento_password',

Save the file.  Then flush the cache.

sudo -u www-data php8.1 /var/www/magento/bin/magento cache:flush
sudo -u www-data php8.1 /var/www/magento/bin/magento cache:clean
sudo chown www-data:www-data /var/www/magento/var/cache/ -R

Disable maintenance mode:

sudo -u www-data php8.1 /var/www/magento/bin/magento maintenance:disable

If you encounter the following error, it’s probably because the database details in the env.php file are wrong.

There are no commands defined in the "cache" namespace.

Create Cron Jobs to Automate Backup

Edit the www-data user’s crontab file.

sudo -u www-data crontab -e

Add the following line to this file.

@daily php8.1 /var/www/magento/bin/magento config:set system/backup/functionality_enabled 1 ; php8.1 /var/www/magento/bin/magento setup:backup --code ; php8.1 /var/www/magento/bin/magento setup:backup --media ; php8.1 /var/www/magento/bin/magento setup:backup --db

Save the file and you are done.

How to Upgrade Magento

Upgrade the Magento application, DB data, and schema.

sudo -u www-data php8.1 /var/www/magento/bin/magento setup:upgrade

Troubleshooting tips

You might encounter various problems in Magento in the future, here are some handy tips to fix them 🙂

Check Logs

You can check the Nginx error log /var/log/nginx/magento.error. Magento also has its logs under /var/www/magento/var/log/.

Class doesn’t  exist

If you encounter an error like below.

main.CRITICAL: Class Magento\Framework\Session\Config\ConfigInterface\Proxy does not exist {"exception":"[object] (ReflectionException(code: -1): Class Magento\\Framework\\Session\\Config\\ConfigInterface\\Proxy does not exist at /var/www/magento/vendor/magento/framework/Code/Reader/ClassReader.php:24)"} []

Here’s the solution.

sudo chown www-data:www-data /var/www/magento/ -R
sudo chown www-data:www-data /var/www/magento/var/cache/ -R
sudo -u www-data php8.1 /var/www/magento/bin/magento setup:di:compile

Then flush Magento cache.

sudo -u www-data php8.1 /var/www/magento/bin/magento cache:flush
sudo -u www-data php8.1 /var/www/magento/bin/magento cache:clean

503 Error (Service Unavilable)

magento 503 service temporarily unavailable

503 error means there’s a problem in the Magento application code. Here’s the solution:

sudo chown www-data:www-data /var/www/magento/ -R

sudo chown www-data:www-data /var/www/magento/var/cache/ -R

sudo -u www-data php8.1 /var/www/magento/bin/magento setup:di:compile

Flush Magento cache.

sudo -u www-data php8.1 /var/www/magento/bin/magento cache:flush
sudo -u www-data php8.1 /var/www/magento/bin/magento cache:clean

Enable production mode

sudo -u www-data php8.1 /var/www/magento/bin/magento deploy:mode:set production

Unable to proceed: the maintenance mode is enabled

Show the current mode:

sudo -u www-data php8.1 /var/www/magento/bin/magento maintenance:status

Disable maintenance mode.

sudo -u www-data php8.1 /var/www/magento/bin/magento maintenance:disable

Enable Debugging mode

Sometime, you will see the following error.

An error occurred during application run, see exception log for more details.

But the exception log doesn’t tell anything about this error. In this case, you can enable debugging mode so you will have more clues to find out the cause of problem.

sudo -u www-data php8.1 /var/www/magento/bin/magento deploy:mode:set developer

After debugging is finished, you can enable production mode

sudo -u www-data php8.1 /var/www/magento/bin/magento deploy:mode:set production

Resize catalog images

You can resize all product images for display on your storefront with the following command.

sudo -u www-data php8.1 /var/www/magento/bin/magento catalog:images:resize

By default, this command runs in synchronous mode. If there’s a warning like below, then image resize will stop.

Warning: getimagesize(): corrupt JPEG data: 8723 extraneous bytes before marker

You can run image resize in synchronous mode. This way, all product images will be scheduled for resizing and processed in the background.

sudo -u www-data php8.1 /var/www/magento/bin/magento catalog:images:resize --async

If you run htop command, you will find the following job running.

bin/magento queue:consumer:start media.storage.catalog.image.resize

To list queued tasks, run the following command.

sudo -u www-data php8.1 /var/www/magento/bin/magento queue:consumers:list

Unable to unserialize value

If Magento displays the Unable to unserialize value error, it could be that there’s Redis server running on your system. You should restart redis-server.

sudo systemctl restart redis-server

Wrapping Up

I hope this tutorial helped you install Magento on Ubuntu 22.04 with Nginx, MySQL and PHP8.1 (LEMP stack). As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks. Take care 🙂

Rate this tutorial
[Total: 6 Average: 4.5]

Leave a Comment

  • Comments with links are moderated by admin before published.
  • Your email address will not be published.
  • Use <pre> ... </pre> HTML tag to quote the output from your terminal/console.
  • Please use the community (https://community.linuxbabe.com) for questions unrelated to this article.
  • I don't have time to answer every question. Making a donation would incentivize me to spend more time answering questions.

The maximum upload file size: 2 MB. You can upload: image. Links to YouTube, Facebook, Twitter and other services inserted in the comment text will be automatically embedded. Drop file here