Apache + Ubuntu + Varnish painless upgrades

Varnish is a reverse proxy
working with apache, with all traffic go thriugh Varnish cache first
if cache missed, Varnish will be the one to grab content from Apache
It is because Apache ignore file types
For example, deliver a jpg by Apache will load mod_php into RAM
the same applies to CSS and JS files
This will cause massive RAM footage
And Varnish cache help greatly helped these static files with less resources drain
and improve overall performance

My target is install Varnish with minimum downtime
Remember to backup the config files before continue

Install Varnish

curl http://repo.varnish-cache.org/debian/GPG-key.txt | sudo apt-key add -
echo "deb http://repo.varnish-cache.org/ubuntu/ lucid varnish-3.0" | sudo tee -a /etc/apt/sources.list
sudo apt-get update
sudo apt-get install varnish

Default Varnish will connect to localhost port 8080 for Apache
So we open port 8080 on Apache:

sudo vim /etc/apache2/ports.conf

NameVirtualHost *:80
NameVirtualHost *:8080
Listen 80
Listen 8080

To minimize downtime, apache will open both 80 and 8080 for the moment
80 for normal operations
8080 For testing out connection with Varnish
VirtualHost settings

sudo vim /etc/apache2/sites-avaiable/default

<VirtualHost *:80 *:8080>

restart Apache

sudo service apache2 restart

open a browser and go to http://localhost:8080/ test Apache port 8080

Varnish will use 256M RAM by default, change to 64M:

sudo vim /etc/default/varnish

DAEMON_OPTS="-a :6081 \
             -T localhost:6082 \
             -f /etc/varnish/default.vcl \
             -S /etc/varnish/secret \
             -s malloc,64m"

sudo /etc/init.d/varnish restart

You can see Varnish use port 6081 as default
open http://localhost:6081/ and test Varnish
Using chrome's network inspector you can see under “Response Header" "Via 1.1 varnish" as identicator

After testing success, time to use Varnish for real thing
Modify Apache:

sudo vim /etc/apache2/ports.conf

#NameVirtualHost *:80
NameVirtualHost *:8080
#Listen 80
Listen 8080

Modify Varnish:

DAEMON_OPTS="-a :80 \
             -T localhost:6082 \
             -f /etc/varnish/default.vcl \
             -S /etc/varnish/secret \
             -s malloc,64m"

restart Apache, Varnish at the same time

sudo service apache2 restart;sudo /etc/init.d/varnish restart

Taking up imagefield_crop module as maintainer

So as I had starting my own business, sometimes I am very busy, sometimes nth to do...

So I kindly pickup imagefield_crop module on drupal.org as a maintainer.

As a long time git user, and drupal.org provide great "version control" tab for every module,
maintaining a module is actually not that hard.
You pick reviewed patch and commit, review some patch if there is extra time, reply to support request etc...

Hope to contribute back to the community other than just write blogs and tutorials.

Customize Drupal commerce checkout flow

Commerce is the new born from ubercart developers For Drupal 7.x

Background information

ubercart had long been the e-commerce solution for Drupal 6.x
but it is some what different from other modules, it existed away from Drupal.org (www.ubercart.org)
So Drupal community is trying to merge back to Drupal.org and some conflicts happens
Some developers decided to start from scratch and build a new e-commerce solution for Drupal 7.x
and hence the born of commerce module

Recent updates fo commerce

Commerce module had been around for more than a year already is it is looking even more impressing ever since.


The "display node" usability problem had been replaced by the concept of "variations"
where you define a product and add "Color variations", "Size variations" etc
they will display as the same product with a dropdown for customers to select

Commerce kickstart

Commerce kickstart is a Drupal "Profile" which bundles lots of extra modules so you can have a store clicks away
Demo products and settings can also be imported so you have real life examples for terminology and setups
You can evaluate the functionality in minutes
and it is a huge step forward for starters to lower the learning curve

Checkout workflow customization

The checkout flow can be customized in "Checkout Settings"
where you can drag and drop different "Panes" to different steps
So if you know how to define "Steps" and "Panes", you can rearrange them right away


The important two functions are: hook_commerce_checkout_page_info() and hook_commerce_checkout_pane_info()
where you define Steps and Panes

 * hook_commerce_checkout_page_info()
function custom_checkout_commerce_checkout_page_info() {
$checkout_pages = array();

$checkout_pages['custom_checkout'] = array(
'title' => t('Custom Step'),
'weight' => 6,


 * hook_commerce_checkout_pane_info()
 * @param  string $value [description]
 * @return [type]        [description]
function custom_checkout_commerce_checkout_pane_info($value='')
$checkout_panes = array();

$checkout_panes['custom_checkout'] = array(
'title' => t('Custom Checkout'),
'page' => 'custom_checkout',
'weight' => 2,
'review' => TRUE,
'callbacks' => array(
'checkout_form' => 'custom_checkout_pane_checkout_form',


Easy easy!

Custom Rules action example

The actions being used inside rules and actions in trigger is not the same
But we can still take code example from rules/modules/*.rules.inc
and you will see lots of "core - optional" module rules

Rules action example module:

 * hook_rules_action_info
 * @return
 *   An array of information about the module's provided rules actions.
 *   The array contains a sub-array for each action, with the action name as
 *   the key. Actions names may only contain lowercase alpha-numeric characters
 *   and underscores and should be prefixed with the providing module name.
 *   Possible attributes for each sub-array are:
 *   - label: The label of the action. Start capitalized. Required.
 *   - group: A group for this element, used for grouping the actions in the
 *     interface. Should start with a capital letter and be translated.
 *     Required.
 *   - parameter: (optional) An array describing all parameter of the action
 *     with the parameter's name as key. Each parameter has to be
 *     described by a sub-array with possible attributes as described
 *     afterwards, whereas the name of a parameter needs to be a lowercase,
 *     valid PHP variable name.
 *   - provides: (optional) An array describing the variables the action
 *     provides to the evaluation state with the variable name as key. Each
 *     variable has to be described by a sub-array with possible attributes as
 *     described afterwards, whereas the name of a parameter needs to be a
 *     lowercase, valid PHP variable name.
 *   - 'named parameter': (optional) If set to TRUE, the arguments will be
 *     passed as a single array with the parameter names as keys. This emulates
 *     named parameters in PHP and is in particular useful if the number of
 *     parameters can vary. Defaults to FALSE.
 *   - base: (optional) The base for action implementation callbacks to use
 *     instead of the action's name. Defaults to the action name.
 *   - callbacks: (optional) An array which allows to set specific function
 *     callbacks for the action. The default for each callback is the actions
 *     base appended by '_' and the callback name.
 *   - 'access callback': (optional) A callback which has to return whether the
 *     currently logged in user is allowed to configure this action. See
 *     rules_node_integration_access() for an example callback.
 *  Each 'parameter' array may contain the following properties:
 *   - label: The label of the parameter. Start capitalized. Required.
 *   - type: The rules data type of the parameter, which is to be passed to the
 *     action. All types declared in hook_rules_data_info() may be specified, as
 *     well as an array of possible types. Also lists and lists of a given type
 *     can be specified by using the notating list<integer> as introduced by
 *     the entity metadata module, see hook_entity_property_info(). The special
 *     keyword '*' can be used when all types should be allowed. Required.
 *   - bundles: (optional) An array of bundle names. When the specified type is
 *     set to a single entity type, this may be used to restrict the allowed
 *     bundles.
 *   - description: (optional) If necessary, a further description of the
 *     parameter.
 *   - options list: (optional) A callback that returns an array of possible
 *     values for this parameter. The callback has to return an array as used
 *     by hook_options_list(). For an example implementation see
 *     rules_data_action_type_options().
 *   - save: (optional) If this is set to TRUE, the parameter will be saved by
 *     rules when the rules evaluation ends. This is only supported for savable
 *     data types. If the action returns FALSE, saving is skipped.
 *   - optional: (optional) May be set to TRUE, when the parameter isn't
 *     required.
 *   - 'default value': (optional) The value to pass to the action, in case the
 *     parameter is optional and there is no specified value.
 *   - 'allow null': (optional) Usually Rules will not pass any NULL values as
 *     argument, but abort the evaluation if a NULL value is present. If set to
 *     TRUE, Rules will not abort and pass the NULL value through. Defaults to
 *     FALSE.
 *   - restriction: (optional) Restrict how the argument for this parameter may
 *     be provided. Supported values are 'selector' and 'input'.
 *   - default mode: (optional) Customize the default mode for providing the
 *     argument value for a parameter. Supported values are 'selector' and
 *     'input'. The default depends on the required data type.
 *   - sanitize: (optional) Allows parameters of type 'text' to demand an
 *     already sanitized argument. If enabled, any user specified value won't be
 *     sanitized itself, but replacements applied by input evaluators are as
 *     well as values retrieved from selected data sources.
 *   - translatable: (optional) If set to TRUE, the provided argument value
 *     of the parameter is translatable via i18n String translation. This is
 *     applicable for textual parameters only, i.e. parameters of type 'text',
 *     'token', 'list<text>' and 'list<token>'. Defaults to FALSE.
 *   - ui class: (optional) Allows overriding the UI class, which is used to
 *     generate the configuration UI of a parameter. Defaults to the UI class of
 *     the specified data type.
 *   - cleaning callback: (optional) A callback that input evaluators may use
 *     to clean inserted replacements; e.g. this is used by the token evaluator.
 *   - wrapped: (optional) Set this to TRUE in case the data should be passed
 *     wrapped. This only applies to wrapped data types, e.g. entities.
 *  Each 'provides' array may contain the following properties:
 *   - label: The label of the variable. Start capitalized. Required.
 *   - type: The rules data type of the variable. All types declared in
 *     hook_rules_data_info() may be specified. Types may be parametrized e.g.
 *     the types node<page> or list<integer> are valid.
 *   - save: (optional) If this is set to TRUE, the provided variable is saved
 *     by rules when the rules evaluation ends. Only possible for savable data
 *     types. Defaults to FALSE.
function rules_example_rules_action_info(){
  return array(
'rules_example_extra_node_title' => array(
'group' => t('Example'),
'label' => t('Add prefix to node title'),
'parameter' => array(
//pass in parameters
'node' => array(
'type' => 'node',
'label' => t('Node'),
'description' => t('The node to add the prefix.'),
'save' => TRUE,

 * Rules action implementation
 * Key defined in hook_rules_action_info
 * @param  Object $node node being editted
function rules_example_extra_node_title($node) {
$node->title .= '[Rules action example prefix] ';

It takes time to understand all hook_rules_action_info() parameters
perhaps take some code from rules modules and edit will be easier.