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.)
127.0.0.1:9200
, as can be shown with:
sudo ss -lnpt | grep 9200
Sample output:
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
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.
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
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
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.
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
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.
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
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 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/
).
- Back Up and Restore MariaDB Databases From the Command line
- Use Duplicati to Back Up Files on Debian, Ubuntu (Automated Encrypted Backup)
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)
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
If this error still persists, then you need to disable maintenance mode as described below.
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
Still no success? Try rebooting the server.
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
No Space Left on Disk?
If your server runs out of disk space, then MySQL/MariaDB and Elasticsearch would fail. You can use the ncdu
command-line utility to find out which directories is using up the most disk space
sudo apt install ncdu
Once you removed unneeded files and directories to reclaim disk space, restart MySQL/MariaDB and Elasticsearch.
sudo systemctl restart mysql elasticsearch
SQLSTATE[HY000] [2002] Connection timed out
This error indicates Magento code can’t log into MySQL database. Check the SQL login credential in the /var/www/magento/app/etc/env.php
file. Make sure it’s correct. If you forgot the SQL user password, use the following command at the SQL console to reset it.
ALTER USER 'magento'@'localhost' IDENTIFIED BY 'magento_password';
404 Not Found for Admin URL
Change your admin URI
sudo -u www-data php8.1 /var/www/magento/bin/magento setup:config:set --backend-frontname="admin_path"
Enable production mode
sudo -u www-data php8.1 /var/www/magento/bin/magento deploy:mode:set production
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
If you configured Varnish cache for Magento, you also need to restart Varnish.
sudo systemctl restart varnish
Accepting Bitcoin Payment From Customers
You can set up BTCPAY Server, so you can accept Bitcoin payments from customers. BTCPAY Server can be easily integreated with Magento with a plugin. It can also automatically genereate invoice and integrate with QuickBooks Online to make accounting a breeze.
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 🙂
Very nice tutorial indeed but I am still getting a 502 Bad Gateway” Nginx Error. I am trying to fix the error but no help from the internet at all.
I will reinstall and see what happens !!!
One of the best overall.
Thank you for all the tutorials but it is a shame that I just discovered your site today.
If you get a 502 bad gateway error, check if the following services are running.
Try to restart them.
Note: This article didn’t show how to enable Varnish cache. I list its command just in case.
Thank you. This is the best tutorial I encountered so far on the net. Works perfectly. Would really recommend to anybody who like me struggled to have a working Magento deployment. Thanks again!!!!!!!
Hi. Really nice guide, thanks! Is it at all possible to use my own already existing SMTP server instead of using Sendinblue as per your steps?
Great tutorial. Thank you.
I think that people get 502 bad gateway because:
server unix:/var/run/php/php8.1-fpm.sock;
in the below block:upstream fastcgi_backend {
server unix:/var/run/php/php8.1-fpm.sock;
}
Should be changed to
server unix:/run/php/php8.1-fpm.sock;
. VAR has to be removed.Hi,
Thanks for this tutorial. but i am getting this error. can you help:
array_merge(): Argument #2 must be of type array, string given#0 /var/www/html/setup/src/Magento/Setup/Model/ConfigModel.php(157): array_merge()
thanks