Ravi Sagar | Home | Blog

Mastering Drupal

Table of Contents

1 Setup LAMP on Alma Linux

1.1 Make sure system is up to do

sudo dnf clean all
sudo dnf install epel-release
sudo dnf update

1.1.1 Error while updating: GPG check FAILED

sudo dnf update --nogpgcheck

1.2 Add user

adduser username
passwd username

1.3 Add user to the wheel group for sudo privileges

usermod -aG wheel username

1.4 Generate key pair


1.5 Copy your local public key to the server

ssh-copy-id username@SERVER_IP_ADDRESS

1.6 Log off from root and login with the new user

After this you can login to the server using ssh username@SERVER_IP_ADDRESS.

1.7 Secure ssh remote root logins

  • Open the file sudo vi /etc/ssh/sshd_config
  • Change from yes to no: PermitRootLogin no
  • Restart SSH: sudo systemctl restart sshd

1.8 Setup firewall

sudo dnf install firewalld
sudo systemctl start firewalld
sudo systemctl enable firewalld

1.8.1 Error: ERROR: 'python-nftables' failed: internal:0:0-0: Error: Could not process rule: No such file or directory

  • Open the file vi /etc/firewalld/firewalld.conf
  • Change the line to iptables: FirewallBackend=iptables
  • Restart firewalld: systemctl restart firewalld

This also didn't work.

1.9 Install and enable Apache

sudo dnf install httpd httpd-tools
sudo systemctl start httpd
sudo systemctl enable httpd
sudo systemctl status httpd

Main configuration is /etc/httpd/conf/httpd.conf and default DocumentRoot is /var/www/html

1.9.1 Apache modules

We just need to install additional module for php and mysql on Alma Linux.

1.10 Make your pages available to public

sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https 
sudo firewall-cmd --reload

1.11 Install Mariadb

sudo dnf install mariadb-server mariadb
sudo systemctl start mariadb
sudo systemctl enable mariadb
sudo mysql_secure_installation

1.12 Install PHP 8

Check available versions.

sudo dnf module list php
sudo dnf module enable php:8.1
sudo dnf install php php-fpm php-zip php-intl php-opcache php-gd php-mbstring php-gd php-xml php-mysqlnd

1.12.1 PHP modules

Installed above. We just need to install on Alma Linux

1.13 Create vhost

Create a file ~ sudo emacs /etc/httpd/conf.d/vhost.conf~.

Content of this file.

<VirtualHost *:80>
 ServerAdmin admin@sparxsys.com
 ServerName sparxsys.com #localhost for testin
 ServerAlias www.sparxsys.local #localhost for testing
 DocumentRoot "/var/www/html/sparxsys.live/public_html/web"
 ErrorLog "/var/www/html/sparxsys.live/logs/error.log"
 CustomLog "/var/www/html/sparxsys.live/logs/access.log" common
 <Directory "/var/www/html/sparxsys.live/public_html/web">
   Require all granted
   AllowOverride All

Create the directories.

sudo mkdir -p /var/www/html/sparxsys.live/{public_html/web,logs}

Check everything works so far using apachectl configtest

1.14 DocumentRoot and Apache permissions

Create a group and add users to it.

sudo groupadd webadmin
sudo usermod -aG webadmin ravisagar

Change ownership of document root directory.

sudo chown root:webadmin /var/www/html/

This didn't work for me so I had to make myself as the owner.

sudo chown ravisagar:ravisagar /var/www/html/

Change permissions of the document root directory.

sudo chmod 2775 /var/www/html/ -R

1.15 Initial test

Place a file in the following location.

echo "Hello" > /var/www/html/sparxsys.live/public_html/web/index.html

I had to open the file separately to do it.

Also place info.php in this location.

echo "<?php phpinfo(); ?>" > /var/www/html/sparxsys.live/public_html/web/info.php

2 TODO Setup LAMP on Arch for Drupal development on local computer   drupal

The following setup is for local Drupal development. Source: https://wiki.archlinux.org/title/Apache_HTTP_Server

2.1 Install Apache and start it

sudo pacman -S apache
systemctl start httpd.service

Main configuration is /etc/httpd/conf/httpd.conf and default DocumentRoot is /srv/http

Check apache configurations using apachectl configtest command.

2.2 Create user home directory (optional)

mkdir ~/public_html
touch ~/public_html/index.html
echo "Ravi's home" >> ~/public_html/index.html
chmod o+x ~
chmod o+x ~/public_html
chmod -R o+r ~/public_html
systemctl restart httpd.service

Now you can access your personal home page at localhost/~ravisagar

2.3 TLS (not on local computer)

In /etc/httpd/conf/httpd.conf, uncomment the following three lines:

LoadModule ssl_module modules/mod_ssl.so
LoadModule socache_shmcb_module.so modules/mod_socache_shmcb.so
Include conf/extra/httpd-ssl.conf

If using Certbot (certbot –apache), the following line needs to be uncommented as well:

LoadModule rewrite_module modules/mod_rewrite.so

After obtaining a key and certificate, make sure the SSLCertificateFile and SSLCertificateKeyFile lines in /etc/httpd/conf/extra/httpd-ssl.conf point to the key and certificate. If a concatenated chain of CA certificates was also generated, add that filename against SSLCertificateChainFile.

2.4 Virtual hosts

If you want to have more than one host, uncomment the following line in /etc/httpd/conf/httpd.conf

Include conf/extra/httpd-vhosts.conf

Content of the conf/extra/httpd-vhosts.conf If the setup if for local computer then ignore the ssl part.

<VirtualHost *:80>
    ServerAdmin admin@sparxsys.com
    ServerName sparxsys.local
    ServerAlias www.sparxsys.local
    DocumentRoot "/home/ravisagar/projects/sparxsys.local/public_html/web"
    ErrorLog "/home/ravisagar/projects/sparxsys.local/logs/error.log"
    CustomLog "/home/ravisagar/projects/sparxsys.local/logs/access.log" common
    <Directory "/home/ravisagar/projects/sparxsys.local/public_html/web">
        Require all granted
        AllowOverride All
    #RewriteEngine on
    #RewriteCond %{SERVER_NAME} =indiaunveiled.in [OR]
    #RewriteCond %{SERVER_NAME} =www.indiaunveiled.in
    #RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

<VirtualHost *:443>
    ServerAdmin admin@sparxsys.com
    ServerName sparxsys.local
    ServerAlias www.sparxsys.local
    DocumentRoot "/home/ravisagar/projects/sparxsys.local/public_html/web"
    ErrorLog "/home/ravisagar/projects/sparxsys.local/logs/error.log"
    CustomLog "/home/ravisagar/projects/sparxsys.local/logs/access.log" common
    <Directory "/home/ravisagar/projects/sparxsys.local/public_html/web">
        Require all granted
    #RewriteEngine on
    #RewriteCond %{SERVER_NAME} =staging.ravisagar.in [OR]
    #RewriteCond %{SERVER_NAME} =www.staging.ravisagar.in
    #RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
    SSLEngine on
    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLCertificateFile /etc/letsencrypt/live/www.staging.ravisagar.in/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/www.staging.ravisagar.in/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/www.staging.ravisagar.in/chain.pem

2.5 Modify your /etc/hosts and add your virtual hosts sparxsys.local
127.0.01 www.sparxsys.local

That is it, now you can open http://sparxsys.local/ in your browser

2.6 Install php

Just install php7 to be on the safer side.

sudo pacman -S php7 php7-apache php7-gd

For PHP8

sudo pacman -S php php-apache php-gd

In /etc/httpd/conf/httpd.conf, comment the line:

#LoadModule mpm_event_module modules/mod_mpm_event.so

and uncomment the line:

LoadModule mpm_prefork_module modules/mod_mpm_prefork.so

Place this at the end of the LoadModule list:

LoadModule php7_module modules/libphp7.so
AddHandler php-script .php

For PHP8

LoadModule php_module modules/libphp.so
AddHandler php-script .php

Place this at the end of the Include list:

Include conf/extra/php7_module.conf

For PHP8

Include conf/extra/php_module.conf

Check your php.ini file in use using php --ini Modify your /etc/php7/php.ini and uncomment the following line.


upload_max_filesize = 10M
post_max_size = 10M

Switch to php7 (if needed, didn't work properly though)

sudo rm /usr/bin/php
sudo ln -s /usr/bin/php7 /usr/bin/php
sudo rm /usr/bin/php-config
sudo ln -s /usr/bin/php-config7 /usr/bin/php-config
sudo rm /usr/bin/phpize
sudo ln -s /usr/bin/phpize7 /usr/bin/phpize
php -v

2.7 Install mysql

sudo pacman -S mariadb
sudo mysql_install_db --user=mysql --basedir=/usr --datadir=/var/lib/mysql
sudo systemctl start mariadb

Setup mysql

sudo mysql_secure_installation

Make sure you change the root password.

If you are not able to start mariadb then perform these steps.

systemctl stop mariadb
sudo rm -R /var/lib/mysql/*
sudo systemctl start mariadb

Create database

CREATE DATABASE db_ CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

2.8 MySQL performance settings

In the /etc/my.cnf add the following lines.


2.9 Test PHP works

echo "<?php phpinfo(); ?>" > test.php

Now go to http://localhost/~ravisagar/test.php and check whether you see php version.

3 Install Composer

Follow the instructions here: https://getcomposer.org/download/ You may want to install it in ~/Downloads. After following the instructions you will get composer.phar which you can move to your /usr/local/bin.

sudo mv ~/Downloads/composer /usr/local/bin/

On Arch you can also do it easily using.

sudo pacman -S composer

4 Move existing site to drupal-composer/drupal-project

Update: The following steps didn't work because I got error related to old modules. So I decided to install fresh Drupal.

You can move your existing site that you made without composer to drupal-composer.

4.1 Install new drupal site

composer create-project drupal-composer/drupal-project:9.x-dev public_html --no-interaction

Create config/sync directory in composer root, inside publichtml.

Or if you are trying to upgrade from a bit old version of Drupal like for example version 8.6.3 to 9.3.0 then download a specific version of drupal.

Source: https://drupal.stackexchange.com/questions/283212/how-can-i-install-a-specific-core-version

composer create-project drupal-composer/drupal-project:8.x-dev my_site_name_dir --no-interaction --no-install

Then modify your composer.json and mention the drupal version.

"require": {
    "drupal/core": "8.6.*",

4.2 Copy all custom themes, modules, files, and settings to the new project

Copy files

cp -a ~/webfaction-sites/sparxsys/var/www/html/sparxsys.live/public_html/web/sites/default/files/. ~/projects/sparxsys.local/public_html/web/sites/default/files/

Copy settings.php and make sure database settings are correct.

cp ~/webfaction-sites/sparxsys/var/www/html/sparxsys.live/public_html/web/sites/default/settings.php ~/projects/sparxsys.local/public_html/web/sites/default/

Restore your database

mysql -u root -p db_local_sparxsys < ~/webfaction-sites/sparxsys/home/drupal/backup/sparxsys.com/2021-12-17_db.sql

Install modules needed. Check in your existing Drupal installation. Install all the modules previously installed.

composer require drupal/metatag:*
composer require drupal/pathalias:*

Using :* at the end will make sure any installation version compatible with your drupal installation will be installed.

Install theme.

composer require drupal/bootstrap:*

Create directory for custom theme.

mkdir web/themes/custom

Move old subtheme to this directory.

cp -r ~/webfaction-sites/sparxsys/var/www/html/sparxsys.live/public_html/web/themes/ravisagartheme ~/projects/sparxsys.local/public_html/web/themes/custom/

Add the following in your ravisagartheme/ravisagartheme.info.yml

core_version_requirement: ^8 || ^9

Update db and clear cache

vendor/bin/drush updb
vendor/bin/drush cache-rebuild

If you get error related to pathauto missing tables in the error log then create the table. Source: https://www.drupal.org/project/drupal/issues/3099084

CREATE TABLE `path_alias` (
  `revision_id` INT(10) UNSIGNED DEFAULT NULL,
  `alias` VARCHAR(255) DEFAULT NULL,
  `status` TINYINT(4) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `path_alias_field__uuid__value` (`uuid`),
  UNIQUE KEY `path_alias__revision_id` (`revision_id`),
  KEY `path_alias__status` (`status`,`id`),
  KEY `path_alias__alias_langcode_id_status` (`alias`(191),`langcode`,`id`,`status`),
  KEY `path_alias__path_langcode_id_status` (`path`(191),`langcode`,`id`,`status`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='The base table for path_alias entities.';
CREATE TABLE `path_alias_revision` (
  `id` int(10) unsigned NOT NULL,
  `revision_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `langcode` varchar(12) CHARACTER SET ascii NOT NULL,
  `path` varchar(255) DEFAULT NULL,
  `alias` varchar(255) DEFAULT NULL,
  `status` tinyint(4) NOT NULL,
  `revision_default` tinyint(4) DEFAULT NULL,
  PRIMARY KEY (`revision_id`),
  KEY `path_alias__id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='The revision table for path_alias entities.';
CREATE TABLE `redirect` (
  `rid` int(11) NOT NULL AUTO_INCREMENT,
  `type` varchar(255) NOT NULL,
  `uuid` varchar(128) CHARACTER SET ascii NOT NULL,
  `language` varchar(12) CHARACTER SET ascii NOT NULL,
  `hash` varchar(64) DEFAULT NULL,
  `uid` int(10) unsigned DEFAULT NULL COMMENT 'The ID of the target entity.',
  `redirect_source__path` varchar(2048) DEFAULT NULL COMMENT 'The source path',
  `redirect_source__query` longblob COMMENT 'Serialized array of path queries',
  `redirect_redirect__uri` varchar(2048) DEFAULT NULL COMMENT 'The URI of the link.',
  `redirect_redirect__title` varchar(255) DEFAULT NULL COMMENT 'The link text.',
  `redirect_redirect__options` longblob COMMENT 'Serialized array of options for the link.',
  `status_code` int(11) DEFAULT NULL,
  `created` int(11) DEFAULT NULL,
  PRIMARY KEY (`rid`),
  UNIQUE KEY `redirect_field__uuid__value` (`uuid`),
  UNIQUE KEY `hash` (`hash`),
  KEY `redirect_field__uid__target_id` (`uid`),
  KEY `redirect_field__redirect_source__path` (`redirect_source__path`(50)),
  KEY `redirect_field__redirect_redirect__uri` (`redirect_redirect__uri`(30)),
  KEY `source_language` (`redirect_source__path`(191),`language`)
) ENGINE=InnoDB AUTO_INCREMENT=86 DEFAULT CHARSET=utf8mb4 COMMENT='The base table for redirect entities.';

I usually check the sql file to get this database table query.

Update db and clear cache

vendor/bin/drush updb
vendor/bin/drush cache-rebuild

4.3 Change site url for drush

Check current Drush configs path and in the /public_html/vendor/drush/drush/drush.yml file add the following.

  uri: 'http://sparxsys.local'

5 Correct file permissions

chmod 755 /drupalroot Go inside drupal directory

find . -type d -exec sudo chmod 755 '{}' \; find . -type f -exec sudo chmod 644 '{}' \;

sudo chmod 777 -R sites/default/files/ sudo chmod 444 sites/default/settings.php

6 Most common modules needed on a new site

Very important modules that I use in all my sites.

pathauto token metatag Geshifilter pathologic google analytics xmlsitemap redirect

I use bootstrap, so let us install it.

Setup site

Create a user other than admin

Create Blog

Enable media and media library

Create Topics, add to the node

Add image field to Blog

Setup pathauto

Setup Metatag

Setup Google Analytics

7 Drupal errors and issues

7.1 index.php in the url

Install redirect module and make sure the "Enforce clean and canonical URLs." is checked

7.2 How To Solve Your lock file does not contain a compatible set of packages Please run composer update Error?

composer install --ignore-platform-reqs

7.3 Composer memory errors

Run the command prefixing with giving unlimited memory to composer.

COMPOSER_MEMORY_LIMIT=-1 composer remove drupal-composer/drupal-scaffold

7.4 Scaffold error


sudo composer selfupdate --1
composer remove drupal-composer/drupal-scaffold
sudo composer selfupdate --2
composer require drupal-composer/drupal-scaffold

7.5 Attempting to re-run cron while it is already running

This can be annoying but there are two possible fixes.

This one I think works on Drupal 9.

drush php-eval "\Drupal::lock()->release('cron');"

For older versions of Drupal prior to 9 try this.

DELETE FROM semaphore WHERE name = 'cron';

8 Update Drupal using composer with a proper development workflow

Keeping your Drupal site updated is important. Doing it with Composer is easy but it has to be done properly. In this blog let me share the steps I follow to update Drupal using a proper development workflow. These are the steps. Enjoy.

8.1 Recommended setup

We all have different ways of working. This setup works really well for me because I am the only developer working on this site.

  • Local site: www.ravisagar.test

This is for significant development work like adding a new module, design changes or some major functionality.

  • Staging site: www.staging.ravisagar.in

Only for testing.

  • Live site: www.ravisagar.in

Always has the most recent content like new blogs, new images. Sometimes I do some small css changes directly on live.

8.2 Upgrade a Drupal site

These are the steps involed in upgrading a Drupal site.

8.2.1 Refresh local with production data and configurations

I do lot of small changes and tweaks directly on production and of course production has latest content as well. So from time to time I refresh my local with production but I also do this when I have to upgrade a site.

  1. Take mysqldump of production database and save it in files/database/YYYY-MM-DD.tar.gz
mysqldump -u root -p db_live_ravisagar > web/sites/default/files/database/2022-12-28_db_live_ravisagar.sql
tar -czvf /var/www/html/ravisagar.live/public_html/web/sites/default/files/database/2022-12-28_db_live_ravisagar.tar.gz -C /var/www/html/ravisagar.live/public_html/web/sites/default/files/database/ 2022-12-28_db_live_ravisagar.sql

-C option will make the tar first change to the target directory. It is useful because this will remove the preceding path when the tar.gz is expanded.

  1. Git push (it won't have files directory). Do this if you installed new module directly on production or done some changes to the theme css.
  2. Go to local and rsync files directory (that has images and latest database). Change the path accordingly.
rsync --dry-run -av user@production:/PATH_TO_LIVE_SITE/sites/default/files/ files/
rsync -av drupal@ravisagar.in:/var/www/html/ravisagar.live/public_html/web/sites/default/settings.php settings.php
  1. Now local has files/ directory from live.
  2. Restore database. Now local has live database.
  3. Perform git pull and it will have any modules or theme changes done on production.
  4. Run composer install (if you installed any module on production). I always run this. Just in case.
  5. Clear cache vendor/bin/drupal cache:rebuild all
  6. Now you have local running as same configuration and content from production.

8.2.2 Update Drupal on local

First check this page for up to date information. https://www.drupal.org/docs/updating-drupal/updating-drupal-core-via-composer

Match composer version

sudo composer selfupdate --1

Core steps here: https://www.drupal.org/docs/upgrading-drupal/upgrading-from-drupal-8-or-later/upgrading-a-composer-based-site

STEP 1: Change file permissions

chmod 777 web/sites/default
chmod 666 web/sites/default/*settings.php
chmod 666 web/sites/default/*services.yml

STEP ": Put site in maitenance mode and clear cache.

vendor/bin/drush state:set system.maintenance_mode 1
vendor/bin/drush cache:rebuild

Update modules using composer to make them compatible with Drupal 9. Check modules that needs an update.

composer outdated "drupal/*"

For minor version upgrade do this for each module.

COMPOSER_MEMORY_LIMIT=-1 composer update drupal/address --with-dependencies
COMPOSER_MEMORY_LIMIT=-1 composer update drupal/adstxt --with-dependencies
COMPOSER_MEMORY_LIMIT=-1 composer update drupal/bootstrap --with-dependencies
COMPOSER_MEMORY_LIMIT=-1 composer update drupal/console --with-dependencies
COMPOSER_MEMORY_LIMIT=-1 composer update drupal/ctools --with-dependencies
COMPOSER_MEMORY_LIMIT=-1 composer update drupal/easy_install --with-dependencies
COMPOSER_MEMORY_LIMIT=-1 composer update drupal/geofield drupal/geofield_map drupal/geshifilter --with-dependencies
COMPOSER_MEMORY_LIMIT=-1 composer update drupal/h5p drupal/indieweb drupal/metatag drupal/metatag_views drupal/pathologic drupal/protected_pages drupal/redirect drupal/restui drupal/scheduler drupal/smtp drupal/token drupal/views_slideshow drupal/xmlrpc drupal/xmlsitemap --with-dependencies

For major version upgrade do this for each module.

COMPOSER_MEMORY_LIMIT=-1 composer require drupal/checklistapi:^2.0.0
COMPOSER_MEMORY_LIMIT=-1 composer require drupal/devel:^4.1.3
COMPOSER_MEMORY_LIMIT=-1 composer require drupal/devel_entity_updates:^3.0.1
COMPOSER_MEMORY_LIMIT=-1 composer require drupal/exif:^2.2.0
COMPOSER_MEMORY_LIMIT=-1 composer require drupal/field_token_value:^2.0.1
COMPOSER_MEMORY_LIMIT=-1 composer require drupal/geolocation:^3.7.0
COMPOSER_MEMORY_LIMIT=-1 composer require drupal/honeypot:^2.0.2
COMPOSER_MEMORY_LIMIT=-1 composer require drupal/oembed_providers:^2.0.0
drush updb

Verify if the project uses drupal/core-recommended or drupal/core. Run composer show drupal/core-recommended If drupal/core-recommended is installed, this command returns information about the package. If drupal/core-recommended is not installed, this command returns "Package drupal/core-recommended not found".

If you are running on Drupal 8.8.5 and above then this should work.

composer update drupal/core "drupal/core-*" --with-all-dependencies
drush updatedb
vendor/bin/drupal cache:rebuild all

If you want to upgrade to 8.9.0 first then do this.

COMPOSER_MEMORY_LIMIT=-1 composer require drupal/core-recommended:^8.9.0 --update-with-dependencies --no-update
composer update
drush updb
drush cache:rebuild

If you are on Drupal 9.3 then upgrade to 9.5.9. This is recommended as per this page: https://www.drupal.org/docs/upgrading-drupal/upgrading-from-drupal-8-or-later/upgrading-from-drupal-9-to-drupal-10/overview

composer update "drupal/core-*" --with-all-dependencies --with=drupal/core-recommended:~9.5.9 --with=drupal/core-composer-scaffold:~9.5.9  --ignore-platform-req=php+
drush updb
drush cache:rebuild

I received an error due to php 8.2 and had to use --ignore-platform-req=php+. Remove --dry-run once there are no blocking errors.

I also received an error related to insert module while performing database updates.

composer require drupal/insert --ignore-platform-req=php+
vendor/bin/drush en insert
vendor/bin/drush pmu insert
composer remove drupal/insert --ignore-platform-req=php+

STEP 2.1 Upgrade contrib modules. First check what modules have update available.

composer outdated "drupal/*"

Then for each of the available module where update is avalable do this.

composer update drupal/bootstrap --with-dependencies --ignore-platform-req=php+
drush updb
drush cache:rebuild

STEP 2.2 Also uninstall deprecated modules and themes.

For Drupal 9.5.9 to 10.0. If you are using drupal/core-recommended:

composer update "drupal/core-*" --with-all-dependencies --dry-run

If you receive error that no update available then do this.

composer require 'drupal/core-recommended:^10' 'drupal/core-composer-scaffold:^10' 'drupal/core-project-message:^10' --update-with-dependencies --no-update

STEP 3: Or to a specific Drupal 10 version of 10.0.9. This is mentioned here: https://www.drupal.org/project/drupal/releases/10.0.9

composer require drupal/core-recommended:10.0.9 drupal/core-composer-scaffold:10.0.9 drupal/core-project-message:10.0.9 --update-with-all-dependencies --no-update

STEP 3.1 Uninstall seven theme

And then try update again.

composer update "drupal/core-*" --with-all-dependencies --dry-run

STEP 4: If this doesn't work then just do.

composer update

STEP 5: Revert permissions

chmod 755 web/sites/default
chmod 644 web/sites/default/*settings.php
chmod 644 web/sites/default/*services.yml

STEP 6: Modify theme In my ravisagar bootstrap theme I had to change to Core: 10.x and core_version_requirement: ^8 || ^9 || ^10.

If you are not able to upgrade the this command can help.

composer why-not drupal/core 10.0.9

I had issues with guzzle and get list of requirements

composer show --no-dev --direct --name-only | xargs

and then use the output from this command to run this.

composer require composer/installers cweagans/composer-patches drupal/bootstrap drupal/console drupal/core-composer-scaffold drupal/core-recommended drupal/devel_generate drupal/google_analytics drupal/metatag drupal/pathauto drupal/redirect drush/drush vlucas/phpdotenv webflo/drupal-finder zaporylie/composer-drupal-optimizations --update-with-dependencies

Now mosy likely you will encounter this error "The entitytype and fieldname fields on Comment entities are now required and should not be NULL".

Find the comments where these fields are null. This is an example database query which should return the comment IDs.

SELECT cid FROM comment_field_data WHERE field_name IS NULL OR entity_type IS NULL;

Delete the comments you just found, by browsing to example.com/comment/{commentid}/delete for each comment returned by the query.

Then try drush updb again.

If the above command doesn't work then find what is blocking it.

COMPOSER_MEMORY_LIMIT=-1 composer prohibits drupal/core 9.3.0

Update Composer back to 2

sudo composer selfupdate --2

In composer.json Remove all lines drupal/core*** except drupal/core-recommended and drupal/core-composer-scaffold. Those two will require all other stuff, the superfluent drupal/core*** just make future upgrading harder.

You may also need to remove drupal/core-dev from the require-dev section.

For upgrading to Drupal 9. Source: https://github.com/drupal-composer/drupal-project/issues/565

COMPOSER_MEMORY_LIMIT=-1 composer require drupal/core-recommended:^9.3.0 drupal/core-composer-scaffold:^9.3.0 drupal/core:^9.3.0  drush/drush:^10.6 symfony/yaml:^4.4.34 drupal/views_responsive_grid:^1.x.dev --update-with-dependencies --no-update
composer update
drush updatedb
vendor/bin/drupal cache:rebuild all

Install these modules post upgrade https://www.drupal.org/project/h5p/releases/2.0.0-alpha1

composer require 'drupal/h5p:2.0@alpha'

https://www.drupal.org/project/geshifilter/releases/8.x-2.0-beta1 composer require 'drupal/geshifilter:2.0@beta'

composer remove drupal/geocoder composer require drupal/geocoder composer require geocoder-php/google-maps-provider COMPOSERMEMORYLIMIT=-1 composer require drupal/googleanalytics:4.0.0

Keep on trying the above command until all the missing modules are installed. Remove them from composer.json.

Also refer to this page for up to date information on how to update Drupal using Composer.

  1. Error: Mismatched entity and/or field definitions", specifically, "The URL alias field needs to be installed"?
    composer require drupal/devel_entity_updates
    vendor/bin/drush en devel_entity_updates
    vendor/bin/drush entup
    vendor/bin/drush pmu devel_entity_updates

8.2.3 Config export

If you did configuration changes on local site then you need to export them and import them later on production.

vendor/bin/drupal config:export

You can also do it from the UI. Later use the same command to import.

vendor/bin/drupal config:import

Personally I haven't used it yet, because I hardly add any configuration on local and then push to production. I also refresh local database from live from time to time.

8.2.4 Commit your updated Drupal site to the repository

Now you have local running on updated Drupal site with latest content and files from live. Celebrate!

git add .
git commit -m "updating to Drupal 9.3.0"
git push

8.2.5 Test your newly updated site on staging

Composer update on production. I didn't need to update composer on production, I guess because on staging/production I am only going to run composer install. BTW on production ideally run ~ composer install –no-dev~ so that it won't install dev modules on production, but not me, because I like living on the edge.

Time to test your site on staging. Good opportunity to make sure it works on production environment.

  • Go to your staging directory and bring the files from the repository by doing git pull
  • Also bring the new files from production site.
rsync --dry-run -avv user@production:/PATH_TO_LIVE_SITE/sites/default/files/ /PATH_TO_STAGING_SITE/sites/default/files/
  • From the files/database directory restore the mysql database on staging
  • At this staging you have latest files from production, latest database from production and latest upgrade code from local which usually in the composer.json and composer.lock files. The last thing you need to do on staging is to use composer to bring new files need for the update.
  • Add the following line in settings.php and comment the previous array for sync.
sudo chmod 777 web/sites/default/settings.php
$settings["config_sync_directory"] = '../config/sync';
//$config_directories['sync'] = '../config/sync';
sudo chmod 444 web/sites/default/settings.php
composer install
drush updb
vendor/bin/drupal cache:rebuild all

Now your staging is updated.

8.2.6 Update your live.

Ready to update live? Lets do it.

git pull
composer install
drush updatedb
vendor/bin/drupal cache:rebuild all

Simple right? Your live already has the latest database and files. We just need to bring the latest updated composer.json and composer.lock, along with any other changes to theme that you may have done on local.

Now time to open a beer and celebrate.

8.3 Letsencrypt certificate

Just follow this tutorial and you are done: https://linuxhostsupport.com/blog/how-to-install-lets-encrypt-on-centos-7-with-apache/

yum install certbot 
yum -y install certbot-apache

Install certificate using the command.

sudo certbot --apache

It will make changes to the following files for you.

sudo emacs /etc/httpd/conf.d/vhost-le-ssl.conf

It will also add redirect (if you choose) in the following file.


9 Modules

9.1 Configure domain module

Install it like usual using composer.

  • Create domain
  • Change your apache configuration to point your additional domain to the same document root as your primary one
  • Make sure you add the additional domain in the your settings.php under $settings['trusted_host_patterns'] array

9.2 DONE Let us learn how to configure insert module   video

It is one of my favourite module because it makes life so easy when working with images.

  • Install it as usual composer require drupal/insert.
  • Enable the module vendor/bin/drush pm:enable insert.
  • Go to the Administration | Structure | Content types | "Your content type" | Manage form display.
  • For the image field use "Image Insert" and also click on the cog and select all styles. When all the styles are selected then while using insert for an image the styles are available to select.
  • Enjoy the module, it will create proper links to images and save lot of your time.

10 Bootstrap

I use bootstrap theme, I quite like it. Learn about grid system here: https://getbootstrap.com/docs/4.0/layout/grid/

The grid is divided into 12 parts.

In your view or custom HTML use the following.

col-sm-6: 2 columns col-sm-3: 4 columns col-sm-4: 3 columns

11 Bulk delete content of specific type

There are various ways of doing it.

11.1 Using drush

vendor/bin/drush entity:delete node --bundle=rfp

12 Setup ecommerce

12.1 Installation

composer require 'drupal/commerce:^2.35'

12.2 Enable the modules

vendor/bin/drush en commerce
vendor/bin/drush en commerce_cart
vendor/bin/drush en commerce_checkout commerce_promotion commerce_payment commerce_payment_example commerce_log

12.3 Error: Commerce requires the BC Math PHP extension.

In the /etc/php/php.in uncomment the line extension=bcmath

12.4 Configure commerce

12.4.1 Add a store

12.4.2 Add a tax type

12.4.3 Install commerce registration

composer require 'drupal/commerce_registration:^3.0@beta'

12.4.4 First let us configure the registration module

vendor/bin/drush en registration
vendor/bin/drush en registration_purger registration_scheduled_action registration_waitlist registration_workflow

12.4.5 Error: Entity queries must explicitly set whether the query should be access checked or not

13 Simulate emails

On local server you may want to test emails.

composer require 'drupal/maillog:^1.0'

Disable on production