Automate installing drupal on ubuntu for drupal training purpose
This post will explain how to automate installing drupal on a development environment using a stack installer script.
We used the script to speed up a drupal training. With the script and the install profile we could set up a development workstation very fast. Leaving us more time to look at the important stuff.
It also gave us a chance to explain the power of drupal distributions. The fact that drupal is capable of being installed as a different product using an install profile gives it an edge over other competing opensource cms. This could be interesting for bigger (enterprise) clients who want to develop products on top of drupal using install profiles. More about distributions and install profiles can be found here (http://drupal.org/node/326175 and to follow http://www.drupaldistrowatch.com)
Installing
We assumed an ubuntu was already installed. If not, installing the operating system is trivial. Go to the ubuntu website (http://www.ubuntu.com/desktop/get-ubuntu/download), download and install it.
The install script configures the LAMP stack for drupal, installs APC, drush, drush make and sets up a database for our drupal. After this we launch the make file which downloads all needed code for our drupal. Now the script will configure the drupal file system, set up the permissions and copy the drupal install profile and resources.
execute the script :
./mbs_drupal_installer.sh drupal_instance_name mysql_existing_power_user mysql_power_user_password
#!/bin/bash #!/bin/bash color_echo() { text_reverse_bold="$(tput rev) $(tput bold)" text_normal="$(tput sgr0)" echo "${text_reverse_bold}$*${text_normal}" } if [ $UID != 0 ] then echo "This script must be run by root". exit 1 fi if [ $# != 3 ] then echo "Usage : $0 drupal_instance_name mysql_existing_power_user mysql_power_user_password" echo "Example: $0 mywebsite root \"\"" echo "Example: $0 mywebsite mysqlpoweruser secretpassword" exit 2 fi home_dir=$(dirname $0) bin_dir=$home_dir/bin drupal_instance_name=$1 mysql_existing_power_user=$2 mysql_power_user_password=$3 color_echo "Starting Drupal install..." color_echo "Installing Debian/Ubuntu packages..." apt-get --yes install apache2 php5 php-pear php5-dev php5-gd mysql-server-5.0 php5-mysql mysql-client wget curl color_echo "Setting up the Apache mod_rewrite for Drupal clean urls..." a2enmod rewrite color_echo "Setting up the Apache mod_expires for Apache Cache-Control directive..." a2enmod expires color_echo "Setting up the Apache mod_deflate to save bandwidth..." a2enmod deflate sed -i 's|DEFLATE text/html text/plain text/xml|DEFLATE text/html text/plain text/xml text/css text/javascript application/x-javascript|' /etc/apache2/mods-available/deflate.conf color_echo "Adding PEAR package: progress bars on upload..." pecl install uploadprogress sed -i '/; extension_dir directive above/ a\ extension=uploadprogress.so' /etc/php5/apache2/php.ini color_echo "Installing APC php opcode cache..." pecl install apc sed -i '/; extension_dir directive above/ a\ extension=apc.so' /etc/php5/apache2/php.ini #sed -i 's/query_cache_limit = 1M/query_cache_limit = 1M\ #query_cache_type = 1/' /etc/mysql/my.cnf #echo "Reloading mysql..." #/etc/init.d/mysql force-reload color_echo "Reloading Apache..." /etc/init.d/apache2 force-reload drush_extract_dir=/opt drush_install_dir=$drush_extract_dir/drush color_echo "Installing drush in $drush_install_dir ..." resources_dir=$home_dir/resources tar xvf $resources_dir/drush-6.x-3.3.tar.gz -C $drush_extract_dir cp $resources_dir/Console_Table-1.1.3/Table.php $drush_install_dir/includes/table.inc #Installing drush make drush_make_extract_dir=~/.drush mkdir $drush_make_extract_dir tar xvf $resources_dir/drush_make-6.x-2.2.tar.gz -C $drush_make_extract_dir color_echo "Creating the MySQL database for drupal on localhost ..." $bin_dir/create_database.sh $drupal_instance_name $mysql_existing_power_user $mysql_power_user_password drupal_path="/var/www/$drupal_instance_name" color_echo "Installing drupal in $drupal_path ..." color_echo "Executing make file..." /opt/drush/drush make ./multimediabs.make $drupal_path color_echo "Creating additional Drupal directories and files..." mkdir $drupal_path/profiles/multimediabs mkdir $drupal_path/sites/all/themes mkdir $drupal_path/sites/all/modules/custom mkdir $drupal_path/sites/all/modules/contrib_patched touch $drupal_path/sites/all/modules/contrib_patched/patches.txt mkdir $drupal_path/sites/default/files mkdir $drupal_path/sites/default/tmp color_echo "Copying Drupal profile and installer translation files..." cp ./multimediabs.profile $drupal_path/profiles/multimediabs/ cp -R $resources_dir/translations $drupal_path/profiles/multimediabs/ color_echo "Copying and completing the Drupal settings file..." cp $drupal_path/sites/default/default.settings.php $drupal_path/sites/default/settings.php cat $resources_dir/settings_snippet.php >> $drupal_path/sites/default/settings.php color_echo "Copying jquery.ui to module folder..." cp -R $resources_dir/jquery.ui $drupal_path/sites/all/modules/contrib/jquery_ui/jquery.ui color_echo "Setting the work files and directories as writable..." chmod 777 $drupal_path/sites/default/files chmod 777 $drupal_path/sites/default/tmp chmod 777 $drupal_path/sites/default/settings.php color_echo "Copying the drush config file..." cp $resources_dir/drushrc.php $drupal_path/ color_echo "Restarting apache..." apachectl restart #color_echo "Installing xhprof" #pecl download xhprof-0.9.2 #tar -xvf xhprof-0.9.2.tgz -C /var/tmp #cd /var/tmp/xhprof-0.9.2/extension #phpize #./configure #make #make install #make test #cp -R /build/buildd/php5-5.3.3/pear-build-download/xhprof-0.9.2/xhprof_html /var/www/xhprof #ln -s /build/buildd/php5-5.3.3/pear-build-download/xhprof-0.9.2/xhprof_html /var/www/xhprof #mkdir /var/tmp/xhprof #chmod 777 /var/tmp/xhprof color_echo "*) creating an Apache virtual host for $drupal_instance_name with path $drupal_path" cp $resources_dir/vhost /etc/apache2/sites-available/ sed -i "s/multimediabs/$drupal_instance_name/g" /etc/apache2/sites-available/$drupal_instance_name color_echo color_echo "To complete the installation you must:" color_echo color_echo '*) add the drush command to the PATH:' color_echo " export PATH=$drush_install_dir:\$PATH" color_echo color_echo '*) Change your error settings in php.ini to : error_reporting = E_ALL & ~E_DEPRECATED & ~E_NOTICE' color_echo color_echo "*) Create an entry in /etc/hosts : 127.0.0.1 $drupal_instance_name" color_echo color_echo "*) Update the virtual host file /etc/apache2/sites-available/$drupal_instance_name" color_echo "create a symlink ln -s /etc/apache2/sites-available/$drupal_instance_name /etc/apache2/sites-enabled/$drupal_instance_name" color_echo "restart apache with : sudo apachectl restart" color_echo color_echo "Open your browser, go to http://$drupal_instance_name and start the 'multimediabs' pressflow install profile" color_echo color_echo "You can then add code and modules in the Drupal instance directory in $drupal_path ." #color_echo #color_echo "Add this to php.ini to make xhprof run extension=xhprof.so and xhprof.output_dir=\"/var/tmp/xhprof\" and restart server"
The make file.
; $Id$ ; ; ---------------- ; Multimediabs Make file ; ---------------- ; Core version ; ------------ ; Each makefile should begin by declaring the core version of Drupal that all ; projects should be compatible with. core = 6.x ; API version ; ------------ ; Every makefile needs to declare its Drush Make API version. This version of ; drush make uses API version `2`. api = 2 ; Core project ; ------------ ; In order for your makefile to generate a full Drupal site, you must include ; a core project. This is usually Drupal core, but you can also specify ; alternative core projects like Pressflow. Note that makefiles included with ; install profiles *should not* include a core project. ; Use Pressflow instead of Drupal core: projects[pressflow][type] = "core" projects[pressflow][download][type] = "get" projects[pressflow][download][url] = "<a href="http://launchpad.net/pressflow/6.x/6.20.97/+download/pressflow-6.20.97.tar.gz" ">http://launchpad.net/pressflow/6.x/6.20.97/+download/pressflow-6.20.97.t...</a> ; Modules ; -------- projects[admin_menu][subdir] = contrib projects[vertical_tabs][subdir] = contrib projects[cck][subdir] = contrib projects[filefield][subdir] = contrib projects[imagefield][subdir] = contrib projects[date][subdir] = contrib projects[jquery_ui][subdir] = contrib projects[imageapi][subdir] = contrib projects[imagecache][subdir] = contrib projects[views][subdir] = contrib projects[features][subdir] = contrib projects[diff][subdir] = contrib projects[pathauto][subdir] = contrib projects[token][subdir] = contrib projects[i18n][subdir] = contrib projects[l10n_update][subdir] = contrib projects[l10n_client][subdir] = contrib ;Development modules projects[devel][subdir] = contrib projects[coder][subdir] = contrib projects[devel_themer][subdir] = contrib projects[schema][subdir] = contrib projects[install_profile_api][subdir] = contrib projects[update_api][subdir] = contrib projects[module_builder][subdir] = contrib ; Themes ; -------- ; Libraries ; ---------
Now you still need to set your drush PATH, error reporting settings in php.ini, an entry in the hosts file and a vhost. This is not done automatic because the dev station may be used for other projects and we do not want to interfere with these settings. Note also that drush and drush make versions are hard coded in the script. This is to make sure that everyone had the same version of everything so we would waste time in the training on tracing version specific problems.
After you have setup all necessary you ll open the browser and go to your drupal site. There you can select this simple install profile which allows you to select the language.
<?php
function multimediabs_profile_modules() {
return array(
// core modules
'menu', 'search', 'taxonomy', 'path', 'update', 'syslog', 'comment', 'locale', 'dblog',
// cck
'content', 'filefield', 'text', 'imagefield', 'date_api', 'date', 'date_popup', 'jquery_ui',
// imagecache
'imageapi', 'imageapi_gd', 'imagecache', 'imagecache_ui',
// pathauto,
'pathauto', 'token',
// views
'views', 'views_ui',
// admin improvements
'admin_menu', 'vertical_tabs',
//IPP
'features', 'diff',
//Languages
'i18n', 'l10n_update', 'l10n_client',
// devel tools
'coder', 'schema', 'install_profile_api', 'update_api', 'module_builder',
);
}
function multimediabs_profile_details() {
return array(
'name' => 'Multimediabs pressflow',
'description' => 'Installation drupal multimediabs Tours.'
);
}
function multimediabs_profile_task_list() {
$tasks = array();
if (_l10n_install_language_selected()) {
$tasks['l10n-install-batch'] = st('Download and import translations');
}
return $tasks;
}
function multimediabs_profile_tasks(&$task, $url) {
global $install_locale;
install_include(multimediabs_profile_modules());
if ($task == 'profile') {
// Perform the default profile install tasks.
include_once('profiles/default/default.profile');
default_profile_tasks($task, $url);
// administration theme
variable_set('admin_theme', 'garland');
variable_set('node_admin_theme', TRUE);
// user registration
variable_set('user_register', FALSE);
// hide all Garland blocks
db_query("UPDATE {blocks} SET status = 0 WHERE theme = 'garland'");
// image quality
variable_set('image_jpeg_quality', 100);
variable_set('imageapi_jpeg_quality', 100);
// files
variable_set('file_directory_temp', 'sites/default/tmp');
variable_set('file_directory_path', 'sites/default/files');
// date & time
variable_set('configurable_timezones', 0);
variable_set('date_format_short', 'd/m/Y - H:i');
variable_set('date_format_short_custom', 'd/m/Y - H:i');
variable_set('date_format_media', 'D, d/m/Y - H:i');
variable_set('date_format_media_custom', 'D, d/m/Y - H:i');
variable_set('date_format_long', 'l, j F, Y - H:i');
variable_set('date_format_long_custom', 'l, j F, Y - H:i');
// error reporting
variable_set('error_level', 0);
// roles
db_query("INSERT INTO {role} (name) VALUES ('%s')", 'site administrator');
db_query("INSERT INTO {role} (name) VALUES ('%s')", 'editor');
// pathauto
variable_set('pathauto_node_pattern', '');
variable_set('pathauto_taxonomy_pattern', '');
variable_set('pathauto_user_pattern', '');
variable_set('pathauto_ignore_words', '');
// permissions
$admin_permissions = array('access administration menu', 'administer blocks', 'use PHP for block visibility', 'administer menu', 'access content', 'administer nodes', 'revert revisions', 'view revisions', 'administer url aliases', 'create url aliases', 'search content', 'use advanced search', 'access administration pages', 'access site reports', 'administer taxonomy', 'access user profiles', 'administer permissions', 'administer users');
$editor_permissions = array('access administration menu', 'administer menu', 'access content', 'administer nodes', 'revert revisions', 'view revisions', 'search content', 'use advanced search', 'access administration pages');
_multimediabs_add_permissions(3, $admin_permissions);
_multimediabs_add_permissions(4, $editor_permissions);
// input format permissions
db_query("UPDATE {filter_formats} SET roles = ',4,3,' WHERE format IN (2, 3)");
// hide module descriptions for admin
db_query("UPDATE {users} SET data = '%s' WHERE uid = 1", serialize(array('admin_compact_mode' => TRUE)));
// Update the menu router information.
menu_rebuild();
//Activate devel and set xhprof
drupal_install_modules(array('devel'));
/*
variable_set('devel_xhprof_enabled', 1);
variable_set('devel_xhprof_directory', '/build/buildd/php5-5.3.3/pear-build-download/xhprof-0.9.2');
variable_set('devel_xhprof_url', '<a href="http://localhost/xhprof'">http://localhost/xhprof'</a>);
*/
// Move forward to our install batch.
$task = 'l10n-install';
}
// Download and import translations if needed.
if ($task == 'l10n-install') {
if (_l10n_install_language_selected()) {
$history = l10n_update_get_history();
module_load_include('check.inc', 'l10n_update');
$available = l10n_update_available_releases();
$updates = l10n_update_build_updates($history, $available);
module_load_include('batch.inc', 'l10n_update');
$updates = _l10n_update_prepare_updates($updates, NULL, array());
$batch = l10n_update_batch_multiple($updates, LOCALE_IMPORT_KEEP);
// Overwrite batch finish callback, so we can modify install task too.
$batch['finished'] = '_l10n_install_batch_finished';
// Start a batch, switch to 'l10n-install-batch' task. We need to
// set the variable here, because batch_process() redirects.
variable_set('install_task', 'l10n-install-batch');
batch_set($batch);
batch_process($url, $url);
}
}
if ($task == 'l10n-install-batch') {
include_once 'includes/batch.inc';
return _batch_page();
}
}
function multimediabs_form_alter(&$form, $form_state, $form_id) {
if ($form_id == 'install_configure') {
$form['site_information']['site_name']['#default_value'] = 'MBS';
$form['site_information']['site_mail']['#default_value'] = ini_get('sendmail_from') ? ini_get('sendmail_from') : '<a href="mailto:info@orangembs.fr">info@orangembs.fr</a>';
$form['admin_account']['account']['name']['#default_value'] = 'admin';
$form['admin_account']['account']['mail']['#default_value'] = '<a href="mailto:info@orangembs.fr">info@orangembs.fr</a>';
}
}
function _multimediabsformat_set_roles($roles, $format_id) {
$roles = implode(',',$roles);
// Drupal core depends on the list of roles beginning and ending with commas.
if (!empty($roles)) {
$roles = ','. $roles .',';
}
db_query("UPDATE {filter_formats} SET roles = '%s' WHERE format = %d", $roles, $format_id);
}
function _multimediabs_add_permissions($rid, $perms) {
// Retrieve the currently set permissions.
$result = db_query("SELECT p.perm FROM {role} r INNER JOIN {permission} p ON p.rid = r.rid WHERE r.rid = %d ", $rid);
$existing_perms = array();
while ($row = db_fetch_object($result)) {
$existing_perms += explode(', ', $row->perm);
}
// If this role already has permissions, merge them with the new permissions being set.
if (count($existing_perms) > 0) {
$perms = array_unique(array_merge($perms, (array)$existing_perms));
}
// Update the permissions.
db_query('DELETE FROM {permission} WHERE rid = %d', $rid);
db_query("INSERT INTO {permission} (rid, perm) VALUES (%d, '%s')", $rid, implode(', ', $perms));
}
/**
* Check whether we are installing in a language other than English.
*/
function _l10n_install_language_selected() {
global $install_locale;
return !empty($install_locale) && ($install_locale != 'en');
}
/**
* Batch finish callback for l10n_install batches.
*/
function _l10n_install_batch_finished($success, $results) {
if ($success) {
variable_set('install_task', 'profile-finished');
}
// Invoke default batch finish function too.
module_load_include('batch.inc', 'l10n_update');
_l10n_update_batch_finished($success, $results);
// Set up l10n_client and inform the admin about it.
// @todo This message will not show up for some reason.
global $user;
variable_set('l10n_client_use_server', 1);
variable_set('l10n_client_server', '<a href="http://localize.drupal.org'">http://localize.drupal.org'</a>);
drupal_set_message(t('Localization client is set up to share your translations with <a href="@localize">localize.drupal.org</a>. Each participating user should have a localize.drupal.org account and set up their API key on their user profile page. <a href="@edit-profile">Set up yours</a>.', array('@localize' => '<a href="http://localize.drupal.org'">http://localize.drupal.org'</a>, '@edit-profile' => url('user/' . $user->uid . '/edit'))));
//Set language defaults
variable_set('language_negotiation', 1);
db_query("UPDATE {variable} SET value = '%s' WHERE name = '%s'", 'O:8:"stdClass":11:{s:8:"language";s:2:"en";s:4:"name";s:7:"English";s:6:"native";s:7:"English";s:9:"direction";s:1:"0";s:7:"enabled";i:1;s:7:"plurals";s:1:"0";s:7:"formula";s:0:"";s:6:"domain";s:0:"";s:6:"prefix";s:0:"";s:6:"weight";s:1:"0";s:10:"javascript";s:0:"";}', 'language_default');
global $theme_key;
$theme_key = 'garland';
_block_rehash();
install_set_block('user', '0', 'garland', 'left');
install_set_block('locale', '0', 'garland', 'left');
}
?>
Using this script to automate install is fast but it is not the only solution.
Here are some Other possibilities:
Drubuntu
You can get the script here (http://drupal.org/drubuntu). It works great. It installs lots of things(project page) but there isn't a lot of transparancy there. Meaning unless you read all the code to see what it actually does and where it puts everything, which versions, ... you don't really know whats going on. Note that it does quit a lot to your system, perhaps you dont want certain things but there are no options available.
It has some powerful capabilities though. Besides what you find on the project page, it provides drush commands to set up a site, to create a sandbox. It looks like a great tool but it is not very documented. So for beginners it might be a bit too complicated.
Quickstart
Yet another option is working in a vbox. You have http://drupal.org/project/quickstart to use. It has installed quit a bit (lamp stack, drush, eclipse, netbeans, ...). It is easy to use. When launching the browser you ll see everything you need. It works great but it assumes you ll be working in a vbox. I really like the philosophy behind it not polluting you instance, every project has its own environment and it is easy to share a vbox with other developers. I use it daily for personal development.
Acquia
Ofcourse you have Acquia drupal, which also comes as a stack installer on all platforms. You can get it here (http://network.acquia.com/downloads).
Buildkit
Created by development seed an install profile to create distrubtion and drupal sites. (http://drupal.org/project/buildkit)
It follows the logic as the install profile we build an easy simple setup to get started fast. However this is only an install profile it has no server setup. (Note that it only supports D7.)
Conclusion
A lot has been done around automating drupal installation, you should use it when possible to save yourself and others some time. Pick the one that suits your needs best.
For us drubuntu installed too much and it was a bit too intrusive, quickstart was no option because we had a machine at our disposal that we needed to use, acquia comes with acquia drupal which we didnt want and buildkit was drupal 7 and the training was presented for D6, so we ended up creating this lightweight script that configures the LAMP stack and installs our localisable pressflow drupal.
RESOURCES:The script and its required resources you can get on github. (https://github.com/dominiquedc/drupal-stack-installer-mbs)
NEXT:In the next post I ll report how the training of two days using this installer went.
Add new comment