Building an eCommerce Site with Drupal Commerce

Colin Bitterfield
7 min readDec 12, 2019

I started this journey because the eCommerce site we built with OpenCart 3 was too slow and we needed a better alternative. These are my experiences.

In the world of Agile, we need to level-set and define the problem upfront. I tried the quickstart package and it was too old, I tried the basic install and it was too complicated, finally, I am trying the demo project.

Security Advisory: On a production system, the operating system should be hardened to CIS Level 1 and require at least 2FA (google-authenticator). If you store any privacy or customer data, the system needs to be TLS 1.2 only, secure headers, and have data at rest encryption. I would also recommend automatic security updates for the operating system.

To create our development platform, I chose Oracle’s Virtualbox and Ubuntu 18.04 LTS. The LTS version of the support is Long Term Supported. This is the recommended version for any production application.

Due to the fact that we are creating a virtual machine, we will need to add the guest additions at the end of the standard installation.

Virtual Hardware Config:

CPU = 4
RAM = 4096
HDD = 100G (dynamically sized)
VIDEO = VBoxSVGA
NETWORK = Bridged (so you can ssh/sftp to it)
Shared Folders: I share my downloads folder for easy access to software. It is optional. Set to automount

Installation Notes:

Only MySQL 5.7 is supported by Drupal 8. Only the old password style is supported. Drupal uses MySQL PDO driver (because PDO unlike MySQLi supports both PostgreSQL and MySQL).I prefer Percono mySQL for performance.

Guest Additions

After the basic installation, we need to add the guest add-ons and update the patches. I have also found that VirtualBox can fail if you insert the guest’s cd additions. For best results attach the ISO before starting the VM.

sudo apt update
sudo apt upgrade -y
sudo apt install zip unzip curl wget -y
sudo mount -t iso9660 /dev/sr0 /mnt
sudo apt install -y gcc make perl linux-headers-generic
sudo sh /mnt/VBoxLinuxAdditions.run
"VirtualBox Guest Additions: Running kernel modules will not be replaced until the system is restarted"reboot

Apache Installation

apt install apache2 -y

We will configure apache after all of the software is installed.

PHP: Installation

At this time, Ubuntu 18.04.03 LTS distribution contains PHP 7.2.

Drupal 8 Requirements can be found here.

apt installphp -y
apt install php7.2-bcmathphp7.2-bz2 php7.2-bz2 php7.2-cgi \
php7.2-cli php7.2-common php7.2-curl php7.2-dev php7.2-enchant \
php7.2-fpm php7.2-gd php7.2-json php7.2-mbstring php7.2-opcache \
php7.2-mysql php7.2-pspell php7.2-readline php7.2-tidy php7.2-xml \
php7.2-zip -y

MySQL (Percona Installation)

I prefer the Percona version. However, any MySQL 5.7 distribution will work the same.

wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.debsudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.debpercona-release setup ps57
apt install percona-server-server

Create a user and a database for the project

mysql -u root -pMySecurePasswordcreate database commerce;CREATE USER 'app_commerce'@'localhost' IDENTIFIED  BY 'mysql -';CREATE USER 'app_commerce'@'%' IDENTIFIED  BY '4Ht#RQz5jDNt';
flush privileges;
exit

Composer Installation

Note: Do not use the “apt install composer” it is old and does not upgrade well.

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"php -r "if (hash_file('sha384', 'composer-setup.php') === 'a5c698ffe4b8e849a443b120cd5ba38043260d5c4023dbf93e1558871f1f07f58274fc6f4c93bcfd858c6bd0775cd8d1') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"php composer-setup.php --install-dir=/usr/local/bin --filename=composerphp -r "unlink('composer-setup.php');"

Results of these commands

root@drupal-demo-project:~# php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
root@drupal-demo-project:~# php -r "if (hash_file('sha384', 'composer-setup.php') === 'a5c698ffe4b8e849a443b120cd5ba38043260d5c4023dbf93e1558871f1f07f58274fc6f4c93bcfd858c6bd0775cd8d1') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
Installer verified
root@drupal-demo-project:~# php composer-setup.php --install-dir=/usr/local/bin --filename=composer
All settings correct for using Composer
Downloading...
Composer (version 1.9.1) successfully installed to: /usr/local/bin/composer
Use it: php /usr/local/bin/composer
root@drupal-demo-project:~# php -r "unlink('composer-setup.php');"

Project Setup

Create a working folder for the project. I like using a root folder “/data” with a subdirectory “./commerce”. If I tie a specific user to the project, I set the home directory of that user to/data/commerce.

mkdir /data
mkdir /data/commerce
cd /data/

Setup permissions for the directories:

Note my default user is “commerce”

groupadd -g 1500 commerce-site
usermod -a -G commerce-site www-data
usermod -a -G commerce-site commerce
chown -R commerce:commerce-site /data
chmod -R 775 /data

Results:

root@drupal-demo-project:/data# ls -la
total 12
drwxrwxr-x 3 commerce commerce-site 4096 Dec 10 19:46 .
drwxr-xr-x 26 root root 4096 Dec 10 19:46 ..
drwxrwxr-x 2 commerce commerce-site 4096 Dec 10 19:46 commerce

Drupal Commerce

Now add the Drupal demo-project

su - commerce
cd /data
composer create-project drupalcommerce/demo-project commerce --stability dev --no-interaction

Added Note:

After I completed this article and installation, I found that I need some NPM modules. Add the following after the above command.

composer require bower-asset/jquery-simple-color bower-asset/spectrum

Results

> DrupalProject\composer\ScriptHandler::createRequiredFiles
Created a sites/default/settings.php file with chmod 0666
Created a sites/default/files directory with chmod 0777

Additional Useful Modules: Seckit and Feeds.

~/commerce$ composer require drupal/seckit
~/commerce$ composer require drupal/feeds

Apache Configuration:

Because this is a local installation and we want to use a named server, we need to add an entry in the host machine /etc/hosts and the guest machine /etc/hosts

guest machine IP: 192.168.200.136

On the guest (Ubuntu)

echo -e "127.0.0.1\tcommerce.local" >> /etc/hosts

On my Mac (Host Machine)

echo -e "192.168.200.136\tcommerce.local" >> /etc/hosts

Now I can configure the apache server for the project. We need to create a named virtual server for the directory “/data/commerce/web”. Create the following file in “/etc/apache2/sites-available”.

# Filename 001-commerce-local.conf
<VirtualHost *:80>
ServerName commerce.local
ServerAdmin webmaster@localhost
DocumentRoot /data/commerce/web
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<Directory /data/commerce/web>
Options All -Indexes -ExecCGI +Includes +MultiViews
<IfModule mod_dav.c>
DAV Off
</IfModule>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
#Fix Clean URLS
root@drupal-demo-project:/etc/apache2/sites-enabled# a2enmod rewrite
Enabling module rewrite.
To activate the new configuration, you need to run:
systemctl restart apache2
root@drupal-demo-project:/etc/apache2/sites-enabled# systemctl restart apache2

Database Configuration

I change localhost to the IP address, this fixes odd issues with mysql.sock permission issues.

Don’t be surprised if you get this message the first time:

Error Connecting to the Database

The first step is to test if the mysql command works.

Now we need to check the socket

commerce@drupal-demo-project:~$ php -ini | grep mysqld.sock
pdo_mysql.default_socket => /var/run/mysqld/mysqld.sock => /var/run/mysqld/mysqld.sock

This tells us where PHP is looking for the socket. Now we need to see where the socket is.

commerce@drupal-demo-project:/etc/mysql$ mysqladmin -p -u app_commerce  variables | grep sock
Enter password:
| performance_schema_max_socket_classes | 10 |
| performance_schema_max_socket_instances | 322 |
| socket | /var/run/mysqld/mysqld.sock

After some troubleshooting on mysql, the issue was the grant option wasn’t applied properly. Logging in as root (mysql -u root -p )and running this command. Fixed the issue

GRANT ALL PRIVILEGES ON commerce. * TO 'app_commerce'@'localhost';

A little time passes

Setup Screen

Final Configuration

Post Installation Notes:

  1. If you get an “Access Denied admin” type message, use incognito and reset your webserver.
  2. There were 2 errors and 3 warnings in the admin panel.

Remove write permissions from the configuration directory and settings

# Fix for configuration files
cd ./commerce/web/sites
chmod -222 default
chmod -222 default/settings.php

Add the following lines for your domain into the settings.php file.

$settings['trusted_host_patterns'] = [
'^www\.example\.com$',
'^example\.com$'
];

--

--

Colin Bitterfield

NIST certified Security Professional | 10+ years experience in infrastructure security and compliance | Experienced in creating security programs.