12 May 2015
Awang Setyawan

As a drupal developer, there are times we need to install and configure the same things over and over which can become mundane, repetitive and time consuming. Fortunately, Drupal has a solution to help automate these repetitive tasks by creating a custom installation process that can be executed before commencing development. This capability is referred to as Drupal installation “Profiles” and these are often packaged up as “Distributions” or Distro’s.

This article provides detailed step-by-step instructions on how to create a Drupal installation profile or distribution. This includes:

  • How to include common modules, configurations
  • Creating custom content types
  • Adding text formats and wysiwyg editors
  • Setting up user roles and permissions in our Distribution
  • Adding/removing installation steps, and changing installation theme


Overview of installation profiles

Installation profiles (or Distro’s) are pre-defined packages that can include core Drupal modules, third party modules, themes and other pre-configurations to get a site working quickly. Profiles can speed up development by reducing some initial processes like configuring text formats / editors, module views, basic templates, content types etc. This provides a big head start when it comes to customising a site based on project requirements. Installation profiles are perfect when you need to create multiple sites with similar functionality.

There are many popular Drupal distributions available off the shelf, to suit various needs. Some examples include “Open Atrium” for building collaboration software where a group of users can have their own conversations and collaborate; “Commerce Kickstart” for creating a flexible yet powerful shopping cart; “OpenPublish” when you need to create a news site; and there are many more out there; navigate to page to get the complete list and check out some of them to find one that suits your needs.

How to create an installation profile

Before we get started on creating a custom installation profile for our project, first I’ll show you where this profile will show up when you begin the process of installing Drupal. Your profiles or distributions will be displayed on the first step on Drupal installation, see figure below.

Drupal CMS - Select installation profile

figure 1: Select installation profile

On latest Drupal 7, there are 3 profiles available. Yes, that’s right, three, however on the screenshot above there are only 2 profiles available to select from. The other, hidden, profile is used for testing purposes only. You can see it if you checkout the /profiles directory. Ok, so lets create a custom profile and list it on the page above.

A Drupal installation profile acts just like a module. Profile files need to be placed inside the “profiles” directory on Drupal installation. First, let’s create a salsadistro directory, and then tell Drupal that salsadistro exists and that it’s an installation profile. To do this, we need to create 2 files inside salsadistro directory, they should be and profilename.profile. In our example, we would call these files and salsadistro.profile. And third, for the .info files, let’s put in some basic module information to tell Drupal what this profile is about. We use something like this below:

name = Salsa Distro
description = Salsa distribution for <a href="">Salsa Digital</a>
core = 7.x
dependencies[] = block
dependencies[] = color
dependencies[] = comment

The Text items shown in bold format above are mandatory for the .info file. Let me explain the purpose of each variables above:

  • The name value will be displayed on the “select installation profile” page when you install Drupal for the first time and this is should be a sensible readable name.
  • The description value will be displayed after the name and it tells the person installing Drupal what this profile does. It’s a good idea to make this succinct, descriptive and contains any relevant links to more detailed documentation or information.
  • The core value tells Drupal which version this profile works with. For all Drupal 7 the core value should be expressed as 7.x rather than, for example, 7.32.
  • The dependencies array lists all core or custom or contrib modules that will be enabled when the profile is installed. Here you can list any modules you like.

Your installation should look something like this figure below:

Drupal CMS - Salsa distro profile files init

figure 2: Salsa distro profile files init

Ok! Above we’ve covered the basic settings for a .info file, and for a .profile file, now let’s just include a php opening tag in the .profile file for now, we will come back to this later. With this configuration you should see your custom profile during installation on the “select installation” profile page as per the screenshot below.

Drupal CMS - Select installation profile with custom profile

figure 3: Select installation profile with custom profile

Congratulations, so far you’ve created a custom installation profile to enable some of Drupal’s core modules. And with a little coding skill and some magic, we can get into how to tell Drupal to tackle some more advanced tasks.

Adding a .install File

As mentioned above, a profile is a bit like a module. When you build a custom module you may sometimes need to add a .install file to work a little magic when the module is being installed / updated / uninstalled. A Profile also supports this file and creates the ability to take on many tasks here. For example, creating a custom content type; setting the default theme for installation and other stuff you may want during an install process. Later on in this article I’ll show you how to use different themes during the Drupal installation process. This will allow you to personalise your distribution even more with a branded company theme.

For the sake of this tutorial, we will use the same install script as a Drupal basic profile. This script will install a minimal set of blocks, setup access roles, enable default themes and grant access for users to register with administrator approval. You can see what’s really going here on by checking out the minimal .install that ships as standard with Drupal. As you need more features like adding new content types, roles, settings, taxonomies, blocks and other stuff that is enabled after installation process is finished, you can take a look at the standard profiles which Drupal provides and modify them to suit your needs. Below shows the minimal setup for our custom profile:

 * Implement hook_install().
 * Perform actions to set up the site for this profile.
function salsadistro_install() {
  include_once DRUPAL_ROOT . '/profiles/minimal/minimal.install';

As you can see above our install module will execute the minimal_install() function from Drupal’s minimal profile. You can also add something here but remember, for this install all of your custom or contributed modules are not yet enabled. If you want to use functions from contrib / custom modules you need to use hook_install_tasks() (we’ll cover this a little later on).

If you’ve already created a distribution and need to update the previous distribution installed on your site, in a similar fashion to modules, we can use the hook_update_N() function and add this function to a .install file. What we can do with this hook? You can for example, control the Drupal “features” module, add new content types, etc.

We also need to follow some rules when creating an update function. The function uses a particular naming convention. In the function call above (hook_update_N()), the “N” can utilise up to 4 digits, with the first digit is the Drupal version, second digit is the major update number of your profile, and third and fourth digits are the minor update number for your profile. Minor updates according to Drupal naming conventions, usually use two digits and commence at 00. Here is the example, salsadistro_update_7100(). Remember, do not renumber your updates - once you commence utilising a particular number for each major/minor update combination, you must add 1 to each subsequent minor update. And keep in mind, not all module functions are available by default, so if you want to use them, you must explicitly include them in the file.

Adding Modules to the profile

Our custom profile would not be complete without contributed modules included. In this profile we will add a couple of modules to give you an idea of how this works. Ideally, when we create a distribution, the most hassle free approach is to put all contributed modules and custom modules in same directory as our installation profile. This allows users to download, install and everything! There may be occasions when you want to put all contributed modules and/or your custom modules under the Drupal standard directory location for these modules (i.e. sites/all/modules). If you take this approach it gives the end-user flexibility when it comes time to upgrade them, but make sure your distribution/profile can work with any version of those modules. Usually you would choose this method if you need your installation profile to install common modules in their default state or with simple customisations only. To enable modules after installation, just add a dependencies variable to your .info file, for example:

dependencies[] = admin_menu
dependencies[] = pathauto

The code above will tell drupal to enable those modules after installation is finished, and will produce an error if one or more are missing.

Drupal CMS - Installation requirements problem

figure 4: Installation requirements problem

The Figure above shows the error received when we try to install our profile when dependency modules are missing. Leave that as-is for now, as on the next step we will create a distribution which includes all dependency modules, themes and a “drush make” file. If you don’t want to create a specific distribution using this installation profile just download these modules and your custom installation profile is ready for initial build in any future Drupal project.

How to create a distribution

In this tutorial, we will use the pathauto, and admin_menu module for our custom distro. Don’t forget to include all dependency modules for the associated contrib modules, in this case, the token module is needed for pathauto. Here we are going to utilise drush make to download all contributed modules and the drupal core. Using drush will provide clean and nice process for adding a module and its dependencies so that we don’t need to manually download them.

But before that you need to make sure drush is running on your machine; on your terminal/console go to your drupal directory and run drush status. It should return something like this:

Drush status result

figure 5: Drush status result

If you don’t see results like figure 5 above you may need to setup drush first. Drush may be found via github on its project page ( which covers installing drush on many platforms. It’s really straight forward and easy to follow.

After you have drush setup on your local machine you can create a drush make file for your profile. The .make file will tell drush to download those modules and their dependencies. Create a distro.make and place this file to your custom profile directory. Your .make file should be look like this:

api = 2
core = 7.x

projects[drupal][version] = 7.32

; our custom profile
projects[salsadistro][type] = profile
projects[salsadistro][download][type] = "file"
projects[salsadistro][download][url] = "/Volumes/MacData/Server/www/distro-test/"

; contrib modules
projects[admin_menu][type] = module
projects[admin_menu][version] = 3.0-rc4
projects[admin_menu][subdir] = contrib

projects[token][type] = module
projects[token][version] = 1.5
projects[token][subdir] = contrib

projects[pathauto][type] = module
projects[pathauto][version] = 1.2
projects[pathauto][subdir] = contrib

Let me explain what the make file above will do (note for complete list of available options, you might need to check this page

  • The api variable will define which install the particular drush api version to be used, and this should be always 2.
  • The core variable will define which drupal version this profile is built for. This value can be ‘7.x’, but in this case, it is always better to specify what drupal version this profile can work with.
  • The projects variable will define what modules/themes need to be downloaded.

As can be seen in the example, I’ve included my profile zip file in the .make file above. By doing this the drush make command will include this custom profile in our distribution.

The url here can be a http://, or files:// or any relative/absolute local directory. In the .make file example above I’m using absolute directory path to my profile zip file - you may need to alter this to suit your local environment. Don’t forget to compress only the files inside your custom profile, not your custom profile directory itself.

Now, we need to move our profile out of the Drupal directory. In doing this, the drush make command will download all Drupal core files plus our contributed modules and themes if you define them. In this case I put my profile in a directory called distro-test and it’s sitting outside Drupal files.

Drupal CMS - Salsadistro under distro-test directory

figure 6: Salsadistro under distro-test directory

After you’ve moved your custom profile go to your terminal/console and go to your custom profile directory and make sure you can call your drush command from that location. Your console should look something like this:

Drupal CMS - Profile files on console/terminal

figure 7: Profile files on console/terminal

With preparation now complete we can execute the .make file to build our custom distribution. On your console, type drush make distro.make ../demo. It should return something like this:

Drupal CMS - Drush make command

figure 8: Drush make command

Done! We now have our distribution and installation profile on demo directory. This directory is on same level with salsadistro directory. See below:

Drupal CMS - Drush make command result

figure 9: Drush make command result

Let me explain what the drush make command did. In this case, drush make downloaded the Drupal core, our custom profile and contrib modules based on our profile .make file (in this case distro.make). All downloaded contrib modules will be placed under /sites/all/modules/contrib and our custom installation profile will be placed on /profiles. Try your distribution, open the site on your favourite web browser and you should see the same process as installation profile above. Below are the front-end result of our custom distribution and installation profile.

Drupal CMS - Drush make command result

figure 10: Drush make command result

As you can see above, our installation profile and distribution already has an admin menu by default. From here you can more further add more contrib modules or custom modules as required.

Adding Themes to a distribution

Let’s enrich our distribution with a contrib theme or our own custom theme. To add a contrib theme we use the same process as adding contrib module. If you need to add your theme from a local directory please refer the sample above for adding a profile from a local path. We will add a bootstrap theme as our base theme but here I’ll not include my custom sub-theme. If you want to add you own sub-theme feel free to do so. OK, let’s add a base theme bootstrap to distribution:

; themes
projects[bootstrap][type] = theme
projects[bootstrap][version] = 3.0

There we go, this configuration will tell the drush make command to download the theme and place it in the correct directory. Below are the results when you run the drush make command at the console with this new configuration:

Drupal CMS - Drush make command result with bootstrap base theme

figure 11: Drush make command result with bootstrap base theme

You will see that the bootstrap base theme was downloaded and you can find it under /sites/all/default/theme.

When you run the installation profile, you will not see this theme enabled by default, unlike modules, theme’s can’t be enabled via the .info file, instead we need take a slightly different approach and use a small script. If you have a look at the minimal_install() function in the Drupal minimal profile, you will notice there is code for activating the theme. From here, what we need to do is to copy that code and make some modifications to enable our bootstrap theme to become the default front-end theme. And because I am such a nice guy, I’ll give you a bonus, we will set the theme for backend as well while we are at it!

Open the salsadistro.install file and locate the salsadistro_install() function, The idea here is, we want to replicate the minimal_install() function and do some modifications. The modifications will be like this:

function salsadistro_install() {
  // enable default theme
  $frontend_theme = 'bootstrap';
  // first we need to enable the theme
    ->fields(array('status' => 1))
    ->condition('type', 'theme')
    ->condition('name', $frontend_theme)

  // set bootstrap as default theme
  variable_set('theme_default', 'bootstrap');

  include_once DRUPAL_ROOT . '/profiles/minimal/minimal.install';

With this code, the system will set the default theme and install standard blocks in the bootstrap base theme. Let’s try our installation profile with update code above. It should give you something like this below:

Drupal CMS - Distribution with bootstrap base theme

figure 12: Distribution with bootstrap base theme

Cool, isn’t it? Now let’s activate the admin theme or backend theme. Open your salsadistro.install file. and modify salsadistro_install(), and just add this piece of code below:

function salsadistro_install() {

  // Enable the administration theme.
  $admin_theme = 'seven';
  // first we need to enable the theme
    ->fields(array('status' => 1))
    ->condition('type', 'theme')
    ->condition('name', $admin_theme)
  // set the variables to enable adminstration theme.
  variable_set('admin_theme', $admin_theme);
  variable_set('node_admin_theme', '1');


The code above is similar to the code we used to set the default theme before. In short, this will tell Drupal to set the admin_theme variable and enable editing nodes in the admin/backend template. See figure below for the results:

Drupal CMS - Distribution with seven admin theme

figure 13: Distribution with seven admin theme

Customising Site config during installation

OK, so far I think we’ve covered the basics of how installation profiles and distributions work. Now lets tackle something a little more advanced like updating site config utilising hook_form_alter(). The idea here is to allow you to auto populate the fields on Configure site step so you don’t need to retype something repeatedly. For example, we will pre-populate the following: site email address, username, default country, timezone, and update notifications. If you’re anything like me, you get pretty tired of filling this stuff in over and over again! Thank to Drupal, we have a great “hook” function to modify that standard form.

At the beginning of this tutorial I asked you to leave the .profile file for us to revisit later, so now we’re ready to tackle that part. On salsadistro.profile create a function called salsadistro_form_alter(). See code snippet below:

 * Implements hook_form_alter().
function salsadistro_form_alter(&$form, &$form_state, $form_id) {
  switch ($form_id) {
    case 'install_configure_form':
      // magic code goes in here

With the function above now you have access to modify the form, please note the form_id used to Configure a site page is install_configure_form. You can also create another hook function like salsadistro_form_install_configure_form_alter(), this function is a shortcut to modify Configure site form, so you don’t need to use switch statement.

Inside that function, we can use this code:

// pre-populate site email address
$form['site_information']['site_mail']['#default_value'] = '';

// pre-populate username
$form['admin_account']['account']['name']['#default_value'] = 'admin';

// pre-populate admin email
$form['admin_account']['account']['mail']['#default_value'] = '';

// pre-populate default country
$form['server_settings']['site_default_country']['#default_value'] = 'AU';

// pre-populate timezone setting
$form['server_settings']['date_default_timezone']['#default_value'] = 'Australia/Melbourne';

// disable notifications
$form['update_notifications']['update_status_module']['#default_value'][1] = 0;

With the code above you will only need to fill in the password and sitename. Of course you can add new fields as you wish in a way very similar with how you would create a custom module. You also can access your contrib modules. Below is the result from code above:

Drupal CMS - Configure site with pre-populate values

figure 14: Configure site with pre-populate values

For the drush junkies out there like me you can manually set some of these values in hook_install to allow you to run your installation via the command line.

//set defaults
$site_mail = '';
$site_default_country = 'AU';
$date_default_timezone = 'Australia/Melbourne';
<other hook_install code here>
variable_set('node_admin_theme', '1');
variable_set('site_mail', $site_mail);
variable_set('site_default_country', $site_default_country);
variable_set('date_default_timezone', $date_default_timezone);

Then just run drush site-install like this, replacing the <db_username> with the username for your database, <db_password> with the password for that user, <localhost> with the hostname, or just use localhost if the database is on your local machine and finally <db_name> with the name of your database:

drush site-install salsadistro --db-url=mysql://<db_username>:<db_password>@<localhost>/<db_name>


drush site-install salsadistro --db-url=mysql://salsa:salsa_pass@localhost/salsa_distro_test

The drush command above will install the site site-install, using the profile salsadistro with the database credentials --db-url=mysql://salsa:salsa_pass@localhost/salsa_distro_test. Once the site is install, drush will provide a new password for user 1, the username will be admin.

Installation complete. User name: admin User password: <password>

Creating content types

Creating content types during the installation process is also possible. All you need to do is just write a piece of code and put in the .install file. Our distribution above does not provide a content type, so let’s create a content type and call it “Standard page”. Add the following snippet to salsadistro_install() function:

function salsadistro_install() {

  include_once DRUPAL_ROOT . '/profiles/minimal/minimal.install';

  // build content type array
  $types = array(
      'type' => 'standard_page',
      'name' => st('Standard page'),
      'base' => 'node_content',
      'description' => st("Use <em>standard pages</em> for your static content, such as an 'About us' page."),
      'custom' => 1,
      'modified' => 1,
      'locked' => 0,

  foreach ($types as $type) {
    $type = node_type_set_defaults($type);

  // Default "Standard page" to not be promoted and have comments disabled.
  variable_set('node_options_standard_page', array('status'));
  variable_set('comment_standard_page', COMMENT_NODE_HIDDEN);

  // Don't display date and author information for "Standard page" nodes by default.
  variable_set('node_submitted_standard_page', FALSE);


Visit hook_node_info() documentation on Drupal to check what options are available when building a content type array. If you need to create more content types, just add more array elements to the $types variable. And if you’re wanting to know how to add more fields to those content types, we can achieve this by using Drupal’s field API (see code below) which basically creates a new text field call “My Field Name” in the example:

function salsadistro_install() {

  // Don't display date and author information for "Standard page" nodes by default.
  variable_set('node_submitted_standard_page', FALSE);

  // create custom field
  $field = array(
    'field_name' => 'field_myfield',
    'type' => 'text',

  // Create the field instance on the bundle.
  $instance = array(
    'field_name' => 'field_myfield',
    'entity_type' => 'node',
    'label' => 'My Field Name',
    'bundle' => 'standard_page',
    // If you don't set the "required" property then the field wont be required by default.
    'required' => TRUE,
    'widget' => array(
      'type' => 'textfield',

...this code will create a custom field like the Figure below:

Drupal CMS - Programmatically create custom field

Figure 15: Programmatically create custom field

For more information on creating fields read the Field API Documentation or follow this tutorial on

Adding text formats & WYSIWYG editor

Text formats and a WYSIWYG editor in Drupal are almost a mandatory feature that most administrators need to be able to manage their site. Unfortunately Drupal doesn’t include this by default and only provides plain text editing for most textarea fields. This gives the developer freedom to choose from the various WYSIWYG editors out there.

Adding text formats can be done via the .install file. First, locate your install function and add the following code:

function salsadistro_install() {

  // Add text format.
  $text_formats['full_html'] = array(
    'format' => 'full_html',
    'name' => 'Full HTML',
    'weight' => 1,
    'filters' => array(
      // URL filter.
      'filter_url' => array(
        'weight' => 0,
        'status' => 1,
        // Line break filter.
      'filter_autop' => array(
        'weight' => 1,
        'status' => 1,
      // HTML corrector filter.
      'filter_htmlcorrector' => array(
        'weight' => 10,
        'status' => 1,

  foreach ($text_formats as $text_format) {
    $text_format = (object) $text_format;

If you need more text formats, for example if you need html without any filters, it’s quite easily done, just add new $text_formats array, without the “filters” variable and it will allow the user to add any html tags they need.

Next we will add WYSIWYG editor for specific text formats and include them in our distribution. To enable WYSIWYG, we need the libraries API and WYSIWYG module, also the ckeditor WYSIWYG editor. To add this, let’s edit the .make file of our profile:

projects[wysiwyg][type] = module
projects[wysiwyg][subdir] = contrib
projects[wysiwyg][version] = 2.x-dev

projects[libraries][type] = module
projects[libraries][subdir] = contrib
projects[libraries][version] = 2.2

; libraries
libraries[ckeditor][type] = library
libraries[ckeditor][download][type] = get
libraries[ckeditor][download][url] =

...and enable it after the installation process, by modifying .info file:

dependencies[] = libraries
dependencies[] = wysiwyg

At this stage, you still need to assign an editor to filters. See the code below to assign these to Full HTML text format and enable buttons. Paste this code in the install function, after saving the filter format:

// Add the ckeditor editor to the Full HTML text format.
  $ckeditor_settings = array(
    'default' => 1,
    'user_choose' => 0,
    'show_toggle' => 0,
    'language' => 'en',
    'buttons' => array(
      'default' => array(
        'Bold' => 1,
        'Italic' => 1,
        'Strike' => 1,
        'JustifyLeft' => 1,
        'JustifyCenter' => 1,
        'JustifyRight' => 1,
        'BulletedList' => 1,
        'NumberedList' => 1,
        'Link' => 1,
        'Unlink' => 1,
        'Anchor' => 1,
        'Image' => 1,
    'toolbarLocation' => 'top',
    'resize_enabled' => 1,
    'block_formats' => 'p,address,pre,h2,h3,h4,h5,h6,div',
    'css_setting' => 'theme',
    'css_path' => '',

  // Create the record.
  $record = array(
    'format' => 'full_html',
    'editor' => 'ckeditor',
    'settings' => $ckeditor_settings,

  // Save the record to the database.
  drupal_write_record('wysiwyg', $record);

Upon finishing installation you should have a working WYSIWYG editor. Below is the result you should expect when you execute the code above:

Drupal CMS - Drupal WYSIWYG editor

figure 16: Drupal WYSIWYG editor

Creating roles and user permissions

By default, Drupal has 2 roles, Anonymous and Authenticated User. But in most cases, we need more than that depending on how the site is working. In this tutorial I’ll add one more role, let’s call it Editor where users with this role can create/edit standard pages. The Editor will have access to Full HTML WYSIWYG, create/edit/delete for standard pages and access to the administrator menu.

To do this, try the following code below:

function salsadistro_install() {

  // Create new user roles for Editor
  $roles = array('Editor');
  $rid = array();
  foreach ($roles as $weight => $name) {
    $role = new stdClass;
    $role->name = $name;

    // New roles must have at least a weight of 2.
    $role->weight = $weight + 2;

    // Save the new role.

    $rid['Editor'] = $role->rid;

  // Assign some permissions
  $full_html_permission = filter_permission_name((object) $text_formats['full_html']);
      'access content',
      'access content',
      'access administration menu',
      'create standard_page content',
      'edit own standard_page content',
      'delete own standard_page content',

Change installation theme

When I tried Drupal Commerce Kickstart I wondered how the Drupal team managed to change the installation profile theme and make it so clean / nice. As far as I know, Drupal won’t let you to change it. Here’s a snapshot of this theme:

Drupal CMS - Drupal Commerce Kickstart 2 installation profile theme

figure 17: Drupal Commerce Kickstart 2 installation profile theme

So after having a dig around in their installation profile I found it’s actually easy to do. It’s common knowledge that Drupal uses ‘Seven’ as their theme. This theme is also used for the administration theme. Here is where the trick lies; when the user selects our custom installation profile we can use the hook_install_tasks_alter() function to change the theme. Below is the Drupal default installation theme:

Drupal CMS - Drupal default installation theme (Seven)

Figure 18: Drupal default installation theme (Seven)

To try this, just add the following code to your .install file, change the $target_theme to your theme name - here I’ll use garland as the installation theme but feel free to change it with your company theme:

 * Implements hook_install_tasks_alter().

function salsadistro_install_tasks_alter(&$tasks, $install_state) {

  // change installation theme
  $target_theme = 'garland';
  if ($GLOBALS['theme'] != $target_theme) {

    $GLOBALS['conf']['maintenance_theme'] = $target_theme;

And here is the result; pretty straightforward:

Drupal CMS - Change Drupal installation theme using garland theme

figure 19: Change Drupal installation theme using garland theme

Adding new install steps and removing install steps

During the installation process you can also add new steps. For example you may want every user who installs your distribution to accept your Privacy Policy and User Agreement. You can also use the Drupal hook_install_tasks_alter() function to support this. See how to set them up below. I will add a new step called “Welcome” and the new step will show up after language selection:

  // The "Welcome" screen needs to come after the first two steps
  // (profile and language selection), despite the fact that they are disabled.
  $new_task['install_welcome'] = array(
    'display' => TRUE,
    'display_name' => st('Welcome'),
    'type' => 'form',
    'run' => isset($install_state['parameters']['welcome']) ? INSTALL_TASK_SKIP : INSTALL_TASK_RUN_IF_REACHED,
  $old_tasks = $tasks;
  $tasks = array_slice($old_tasks, 0, 2) + $new_task + array_slice($old_tasks, 2);

And here is in action:

Drupal CMS - Welcome step

Figure 20: Welcome step

We’re not done yet, we need to create a callback function and submit function for the welcome page. See below how the page is constructed:

 * Task callback: shows the welcome screen.
function install_welcome($form, &$form_state, &$install_state) {
  drupal_set_title(st('Welcome to Salsa Distro'));
  $message = '<p>' . st('Thank you for choosing Salsa Distro, a Drupal profile provided by Salsa Digital') . '</p>';

  // regular form, same on when you are creating a module.
  $form = array();
  $form['welcome_message'] = array(
    '#markup' => $message,
  $form['eula-accept'] = array(
    '#title' => st('I agree to the User Agreement'),
    '#title_display' => 'attribute',
    '#type' => 'radios',
    '#default_value' => 1,
    '#options' => array(
      1 => st('I agree'),
      0 => st('I don\'t agree'),
    '#suffix' => '</div>',
  $form['actions'] = array(
    '#type' => 'actions',
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => st("Let's Get Started!"),
    '#weight' => 10,
  return $form;

The form handler below:

function install_welcome_submit($form, &$form_state) {
  global $install_state;

  if ($form_state['values']['eula-accept'] == 0) {
  else {
    $install_state['parameters']['welcome'] = 'done';
    $install_state['parameters']['locale'] = 'en';

Perfect, now if the user accepts the agreement the install process will continue to the next step, otherwise it will revert back to the profile selection. Below is the welcome page result:

Drupal CMS - Custom welcome step page

figure 21: Custom welcome step page

Cool, isn’t it? Using hook_install_tasks_alter() function you can also disable the first 2 steps and force Drupal to automatically use your installation profile. See below how to remove / disable language selection:

function salsadistro_install_tasks_alter(&$tasks, $install_state) {
  $tasks['install_select_locale']['display'] = FALSE;
  $tasks['install_select_locale']['run'] = INSTALL_TASK_SKIP;
Drupal CMS - Disable language selection on installation profile

Figure 22: Disable language selection on installation profile

Now let’s make sure our installation profile runs by default. We can achieve this by adding exclusive = 1 into file. And we can also disable the profile selection step now by adding this code to the hook_install_tasks_alter() function:

$tasks['install_select_profile']['display'] = FALSE;

Your installation profile now should look like this:

Drupal CMS - Installation profile with deleted steps

figure 23: Installation profile with deleted steps

Creating your own install finalisation

Sometimes you have a few steps that you need to run right at the end of your install process. This is a little tricky as you need to delve into core to make your changes (remember don’t hack core, override it). In your tasks alter change the finish function. Then copy the finish function from core function install_finished() from drupal_root/includes/ Then add whatever function you need to the end of your new function, like this:

 * ibsa_vpcf_install_tasks_alter
 * replace the function install_finished from includes/ with a
 * custom function
function ibsa_vpcf_install_tasks_alter(&$tasks, $install_state) {
  $tasks['install_finished']['function'] = 'ibsa_vpcf_install_finished';
 * Function ibsa_vpcf_install_finished
 * This is mainly here to create all of the taxonomies.
function ibsa_vpcf_install_finished(&$install_state) {
  code copied from install_finished
  your own custom functions

This concludes this custom installation profile and distribution tutorial. You can also add the “features” modules to make your distribution more powerful, instead of creating content types, Drupal settings, permissions etc with code, this approach should make life easier and faster when using the features module. You just need to create new steps and enable the “features” modules you need.

I hope this has helped you start your Drupal development faster. I have also included the installation profiles here so you can take a look and modify them. Don’t forget to run drush make before using the profile to create a distribution.

Thanks for reading!!

Subscribe to Salsa Source

Subscribe to Salsa Source to keep up to date with technical blogs.