Magento installation services powered by Nginx

Alex KondratievAlex Kondratiev

8 min read

Find out how to install an NginX-powered Magento store on the Ubuntu server for outstanding performance.


Overview

This guide has been written for a competent developer or server administrator to set up the Magento e-commerce website. The installation instructions assume you have a fully qualified and recent Ubuntu server with root access. In addition to the tips described in this post, ITsyndicate's system team have elaborated on the on the automated installation of Magento websites. Please contact us to find out more details about automated Magento installation services.

Installation

Prepare a VPS

One of the first things to do before installing any server software on an Ubuntu server, or any other Linux server, is to ensure that the operating system itself is up to date. Run the necessary updates by running the apt-get update and apt-get dist-upgrade commands. The former will update the local cache of the list of software available, and the latter will actually trigger the upgrade of the system.

shell

1apt-get --yes update && apt-get --yes upgrade

After a successful upgrade/update cycle, you might need to reboot the server to make sure everything is set up. For example, many recent Debian releases include kernel or bootloader updates, and those would only take effect after a reboot.

However, they might not be relevant to the upcoming Magento installation with Nginx web server, but were good for the health of the server generally.

Install Magento

We chose Nginx web server, which is very popular among the web server markets. When we provide management services, we use Nginx, because it gives an opportunity to speed up the work of the application, it's flexible in configuration, and easily allows coping with load in high-load projects.

Percona Server provides a replacement for MySQL with added features (for more information on Percona please check their documentation under www.percona.com.

Let's get out hands dirty:

shell

1apt-key adv --keyserver keys.gnupg.net --recv-keys 1C4CBDCDCD2EFD2A
2
3apt-get --yes --purge remove mysql-server mysql-client mysql-common && apt-get --yes autoremove
4
5
6cat <<EOF >> /etc/apt/sources.list
7
8# Percona update sources
9deb http://repo.percona.com/apt "$(lsb_release -sc)" main
10deb-src http://repo.percona.com/apt "$(lsb_release -sc)" main
11EOF
12
13cat <<EOF > /etc/apt/preferences.d/00percona.pref
14Package: *
15Pin: release o=Percona Development Team
16Pin-Priority: 1001
17EOF

After the source list has been updated, you need to update the local APT cache again, by running the update command and then installing the Percona Server:

shell

1apt-get --yes update && apt-get install percona-server-server

During the installation of Percona Server, you will need to respond to the wizard questions, such as setting up the password.
The next step is to install the prerequisites for Magento installation, which are PHP and related modules. We will also install the Nginx web server, along with the database web management interface:

shell

1sudo apt-get update
2sudo apt-get --yes install \
3 php7.4 php7.4-cli php7.4-fpm php7.4-mysql php7.4-curl php7.4-gd php7.4-mbstring php7.4-xml \
4 nginx \
5 php-apcu \
6 memcached \
7 ntp \
8 phpmyadmin
Note! For the production installation, ensure that the PHPMyAdmin component is properly secured.

After the installation, run the MySQL utility to ensure that the basic security mechanisms are set in place, such as disabling root login: mysql_secure_installation

The MySQL wizard will ask you some questions to set up the environment accordingly.

Once your database is running, note that the Percona Server uses the same syntax and commands as MySQL. You can create the database using the following standard SQL commands:

shell

1mysql -u root -p
2create database magento;
3GRANT USAGE ON *.* TO magento@localhost IDENTIFIED BY 'magento';
4GRANT ALL ON magento.* TO magento@localhost;

This will essentially create the database, and grant permissions for a local user with a naive password, to access that database.

Note! For secure installations, one should choose a secure password instead of a simple one.

As a next step, you need to create a directory under /var/www/ with the name of the domain you want to use. For example, for the domain.com run the command:

shell

1mkdir -p /var/www/domain.com/public_html

After the directory has been created, cd into it:

shell

1cd /var/www/domain.com/public_html

Download and extract the Magento package:

shell

1wget http://www.magentocommerce.com/downloads/assets/1.9.0.1/magento-1.9.0.1.tar.gz
2tar xzvf magento-1.9.0.1.tar.gz
3rm magento-1.9.0.1.tar.gz
4mv magento/* .
5rm -rf magento

Now let's move to the Nginx configuration. Remove the default configuration file:

typescript

1unlink /etc/nginx/sites-enabled/default

Note that you are actually removing a symbolic link from the sites-enabled directory, and the original default config will stay in the sites-available directory.

Now, create the main Nginx configuration file /etc/nginx/nginx.conf:

nginx

1user www-data;
2worker_processes 4;
3pid /var/run/nginx.pid;
4
5events {
6 worker_connections 10000;
7 multi_accept on;
8 use epoll;
9}
10
11http {
12 sendfile on;
13 tcp_nopush on;
14 tcp_nodelay on;
15 keepalive_timeout 65;
16 types_hash_max_size 2048;
17
18 # server_tokens off;
19 # server_names_hash_bucket_size 64;
20 # server_name_in_redirect off;
21
22 include /etc/nginx/mime.types;
23 default_type application/octet-stream;
24
25 log_format loadtime '$remote_addr - $remote_user [$time_local] '
26 '$request_time "$request" $status $body_bytes_sent '
27 '"$http_referer" "$http_user_agent" ';
28
29 access_log off;
30 error_log /var/log/nginx/error.log;
31
32 gzip on;
33 gzip_disable "MSIE [1-6]\.(?!.*SV1)";
34 gzip_vary on;
35 gzip_proxied any;
36 gzip_comp_level 6;
37 gzip_buffers 16 8k;
38 gzip_http_version 1.1;
39 gzip_types
40 text/plain
41 text/css
42 application/json
43 application/x-javascript
44 text/xml
45 application/xml
46 application/xml+rss
47 text/javascript
48 application/javascript;
49
50 client_max_body_size 100m;
51 autoindex off;
52
53 # Detect when HTTPS is used
54 map $scheme $fastcgi_https {
55 default off;
56 https on;
57 }
58
59 include /etc/nginx/sites-enabled/*;
60}
61

Then you need to set up the domain-specific configuration for Magento in the sites-available directory and symlink it to the sites-enabled directory.

This is a handy and standard layout scheme in many of the Linux distributions, because the administrator can enable one domain without losing the original configuration file (as each site is only enabled by the symbolic link).

To set up the domain-specific configuration file, you can use the same approach as before, either your favorite text editor, like nano or vim, on the server, or locally notepad and transfer the file to the server.

Note! Choose the appropriate domain name for your particular installation situation. In this example we use domain.com, but obviously, for any production installation, the actual domain name should be used.

For the production installation, please note that an additional configuration should be created to enable SSL for the Magento installation. This example will only set up a plain-text HTTP version, which would leave the use of user credentials vulnerable and should not be used in a production environment.

Edit the configuration file for your Magento domain:

nginx

1server {
2 listen 80;
3 server_name DOMAIN.com;
4
5 ## Forcibly prepend a www
6 rewrite / $scheme://www.$host$request_uri permanent;
7}
8
9server {
10 listen 80 default;
11 ## SSL directives might go here
12 server_name www.DOMAIN.com *.DOMAIN.com; ## Domain is here twice so server_name_in_redirect will favour the www
13 root /var/www/vhosts/DOMAIN.com;
14
15 location / {
16 index index.html index.php; ## Allow a static html file to be shown first
17 try_files $uri $uri/ @handler; ## If missing, pass the URI to Magento's front handler
18 expires 30d; ## Assume all files are cachable
19 }
20
21 ## These locations would be hidden by .htaccess normally
22 location ^~ /app/ { deny all; }
23 location ^~ /includes/ { deny all; }
24 location ^~ /lib/ { deny all; }
25 location ^~ /media/downloadable/ { deny all; }
26 location ^~ /pkginfo/ { deny all; }
27 location ^~ /report/config.xml { deny all; }
28 location ^~ /var/ { deny all; }
29
30 location /var/export/ { ## Allow admins only to view export folder
31 auth_basic "Restricted"; ## Message shown in login window
32 auth_basic_user_file htpasswd; ## See /etc/nginx/htpassword
33 autoindex on;
34 }
35
36 location /. { ## Disable .htaccess and other hidden files
37 return 404;
38 }
39
40 location @handler { ## Magento uses a common front handler
41 rewrite / /index.php;
42 }
43
44 location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler
45 rewrite ^(.*.php)/ $1 last;
46 }
47
48 location ~ .php$ { ## Execute PHP scripts
49 if (!-e $request_filename) {
50 rewrite / /index.php last; ## Catch 404s that try_files miss
51 }
52 expires off; ## Do not cache dynamic content
53 fastcgi_pass 127.0.0.1:9000;
54 fastcgi_param HTTPS $fastcgi_https;
55 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
56 fastcgi_param MAGE_RUN_CODE default; ## Store code is defined in Admin > Configuration > Manage Stores
57 fastcgi_param MAGE_RUN_TYPE store;
58 include fastcgi_params; ## See /etc/nginx/fastcgi_params
59 }
60}
61

Then, back on the shell, build the symbolic link to the sites-enabed directory, to let Nginx include it in the main configuration upon launch of the web server.

shell

1ln -s /etc/nginx/sites-available/domain.com /etc/nginx/sites-enabled/
2service nginx restart

After the web server has been restarted, fine-tuning of the PHP execution environment is still required. PHP-FPM is a custom enhancement for the PHP application execution environment. It enforces the FastCGI execution environment to bring up features related to process control. It has been chosen by Magento to improve the stability and reliability of the Magento instances.

The module requires a specific operating system-level user to be created. Please choose here your favourite username, instead of just a username, like phpfpmuser or alike, so that you can identify it later on.

Note! Brand new user should have nologin attribute for security reasons.

Additionally, some configurations might not want to create a separate user to run with, but use the existing web user www-data instead. Please ensure that you understand the specifics of the chosen username to run FPM under, as outlined in the FPM documentation and system architecture plan.

shell

1useradd username -d /var/www/domain.com -s /bin/bash
2passwd username

Now that the user has been created, the FPM configuration needs to be stored. Again, you may use either your favourite text editor locally or remotely, or write the file via a shell script cat command, like in this example.

shell

1ln -s /etc/nginx/sites-available/domain.com /etc/nginx/sites-enabled/
2service nginx restart

shell

1cat <&LTEOF > /etc/php5/fpm/pool.d/www.conf
2[www-username]
3user = username
4group = username
5listen = 127.0.0.1:9000
6pm = ondemand
7pm.max_children = 100
8pm.start_servers = 4
9pm.min_spare_servers = 2
10pm.max_spare_servers = 6
11pm.max_requests = 500
12pm.status_path = /status
13chdir = /
14php_flag[display_errors] = on
15php_admin_value[error_log] = /var/log/fpm-php.www.log
16;php_admin_flag[log_errors] = on
17php_admin_value[memory_limit] = 1024M
18EOF

Restart the PHP-FPM:

shell

1service php5-fpm restart

Finalizing the permissions and setting up the cron job

To ensure that the web root has proper permissions, you could run the following commands. In essence, that will change the permissions of all the directories to 755 and all the files to 644. As a reminder, 755 means user-writable, group-readable, and executable (browseable), and 644 for files, the same without the execution flag.

shell

1cd /var/www/domain.com
2find . -type d -exec chmod 755 {} \;
3find . -type f -exec chmod 644 {} \;
Note! Some server instances might come with SELinux pre-installed and running in enforcing mode. The SELinux will introduce another layer of permissions on top, or beneath, the traditional user/group/others combination. In that case, you might need to ensure that the proper SELInux context has been assigned for the files and that web server is running under a compatible security policy.

Finally, you would set up the cron job to periodically clean up internal Magento session information. That is defined in the cron scheduled file, to be created in a similar manner to the creation of all the other files in this guide, either using the text editor or directly via the cat command:

shell

1cat <<LTEOF > /etc/cron.d/phpsessclean
224 3 * * * root find /var/www/*/public_html/var/session/ -type f -name 'sess_*' -mtime +7 | xargs rm -rf > /dev/null
3EOF

In the end, you should check that Magento is up and running as expected, execute its database initialization, and other application-specific wizards. This guide has been written using Ubuntu 22.04 running on the VPS server.


If you have any questions or comments, please drop us a line.

Alex Kondratiev

Alex Kondratiev

Founder of ITsyndicate. DevOps Enthusiast with 15+ years of experience in cloud, Infrastructure as Code, Kubernetes, and automation. Specialized in architecting secure, scalable, and resilient systems.

Plan the present.
Build the future.