Cerb5 is a fast and flexible CRM toolkit. Remember anything about anybody, deftly reply to an email flood, quarantine spam, capture organic feedback, track time, flag opportunities, share tasks, and otherwise collaborate or execute efficiently. Built for one-person startups to Fortune 500 giants.
((expand))
The goal in the design of Virtual Attendants was to provide a way for workers and group managers to automate various workflows without having to create custom plugins. Workers can now automate sophisticated business logic from their browser without any knowledge of programming software.
This may sound complicated, but taking the time to understand how Virtual Attendants work will give you some incredibly powerful tools to apply to countless situations. For example:
Virtual Attendants can even create tasks, write comments, automatically reply to customers, and set custom field values. One of the most powerful aspects of Attendants is that you aren’t limited to our built-in conditions and actions. Through plugins, Attendants can even send SMS text messages to workers’ mobile phones, or write messages to instant messengers and chat rooms. While we’ve tried to eliminate the requirement of plugins for automation, combining plugins and Virtual Attendants will allow you to automate almost any kind of behavior.
Virtual Attendants monitor specific events and react with pre-defined behavior. Each decision chooses the best outcome and runs the associated actions.
An event is triggered when something noteworthy occurs.
Examples:
A behavior is a set of linked decisions that determine how to react to an event.
Examples:
A decision chooses the best outcome from several possible choices. The result of a decision can be a series of actions, or another decision; or both.
Examples:
A condition is the comparison of a single property to one or more values using an operator. There are many possible operators depending on the type of field: equals, doesn’t equal, contains phrase, is greater than, is any of, etc. The result of a condition will always be either true or false.
Examples:
The first outcome to pass all of its conditions is selected by the decision. The final outcome in a list of choices can have zero conditions in order to catch every other outcome. If no outcomes match the behavior is terminated.
Examples:
An action defines a set of things to do.
Examples:
The rest of this book is organized into a series of guides depending on your role.
Jump to the Guide for Administrators if you would like to learn how to:
Jump to the Guide for Group Managers if you’ve been made the manager of a group and you would like to learn how to:
Jump to the Guide for Workers if you’re new to the helpdesk and you would like to learn how to:
Jump to the Guide for Developers if you are a software developer and you would like to learn how to:
If you’re using Cerb5 On-Demand then you don’t need to worry about installing the software. You can skip ahead.
While it is possible to successfully install Cerb5 on a shared hosting account, we highly recommend that you control the server you’re installing the software on.
First, change directory to your website’s document directory. The directory will usually be named something like htdocs, httpdocs, or www, under the appropriate website.
On Unix-based servers:
$ cd /home/vhosts/example.com/httpdocs
On Windows-based servers:
Use Windows Explorer to open the website’s document directory.
If you are planning on contributing patches back to the project then you should fork the project on GitHub first. This will give you your own copy of the source code. Once that is done you should use your own repository information in the command below. If you want to checkout the project from our official repository use the following command:
On Unix-based servers:
$ git clone git@github.com:wgm/cerb5.git
On Windows-based servers:
Use a graphical Git client, like TortoiseGit.
When deploying Cerb5 on a production server you should use Subversion. This allows you to quickly upgrade the software to benefit from future updates. Subversion compares your files to our files and it will only download the changes. You’ll never need to download the entire project again after your initial installation. With Subversion you won’t have to worry about an update resetting the contents of your framework.config.php file, or erasing your other changes.
On Unix-based servers:
$ svn checkout http://svn.github.com/wgm/cerb5.git cerb5
On Windows-based servers:
Use a graphical Subversion client, like TortoiseSVN.
In the event you don’t have access to Git or Subversion, you can download a ZIP archive from the project website. This archive includes the Subversion repository information in case you want to take advantage of the convenience of version control in the future.
You can download the latest release using cURL:
$ curl -O http://www.cerberusweb.com/downloads/cerb5/cerb5-latest.zip
Or you can use wget:
$ wget http://www.cerberusweb.com/downloads/cerb5/cerb5-latest.zip
Make sure the Cerb5 files are owned by the proper user and group on the webserver.
There are only two locations that need write access by the webserver during your installation:
framework.config.phpstorage/On Unix-based servers:
$ cd cerb5
$ chown -R www-data:www-data .
$ chmod -R framework.config.php storage
Note: You will need to use your own user and group information instead of www-data.
On Windows-based servers:
Configure your site in IIS.
Create a new MySQL database using the console or your favorite GUI.
mysql> CREATE DATABASE cerb5 CHARACTER SET utf8;
mysql> GRANT ALL PRIVILEGES ON cerb5.* \
TO cerb5@localhost \
IDENTIFIED BY 'secret_password';
Note: Substitute your own database login for cerb5, and replace secret_password with something more secure.
If you don’t want to use ALL PRIVILEGES, the minimum required privileges for the database user are:
SELECTINSERTUPDATEDELETECREATEALTERDROPCREATE TEMPORARY TABLESCerb5 comes with a guided installer that helps you initially configure the system.
To start the installer, point your browser to: http://www.example.com/cerb5/install
Note: You will need to replace www.example.com with your actual domain name.

The requirements checker in the guided installer.
The installer will determine if your server meets the requirements for installing Cerb5. Correct any problems before proceeding, and then click the “Next Step” button.
Click the “I Accept” button if you agree to the licensing terms.

Adding database connection details.
Add your database connection details:
MySQLi driver then you should select it. It’s newer than the standard MySQL driver. Otherwise, use the default.MyISAM and InnoDB both have advantages and disadvantages. Your choice will impact performance and various processes like backups. If you are unsure about the tradeoffs, use MyISAM. If you are familiar with InnoDB then you may experience better performance under high loads with that engine. This decision isn’t permanent; you can switch database engines later.localhost to use sockets rather than TCP/IP connections (which are faster). Otherwise, enter a hostname or IP address.GRANT PRIVILEGES command.GRANT PRIVILEGES command.Once you have entered your database details, click the “Test Settings” button to verify the software can connect to your database.
If successful, the installer will create your initial database structure from incremental patches for each plugin. This may take a few moments because the database is created by incrementally running the updates from each previous version; so don’t worry if it doesn’t look like anything is happening right away.

Personalizing your helpdesk.
In this step you’ll configure the general settings of the helpdesk.
From: "WebGroup Media LLC" <support@webgroupmedia.com>
Click the Continue button when you’ve entered your preferences.

Configuring outgoing mail.
Your helpdesk won’t be very useful if it can’t send mail to your contacts.
25587465http://mail.google.com/support/bin/answer.py?hl=en&answer=13287.Click the “Test Outgoing Mail” button to verify your settings.

Creating your account.
Now the installer will prompt you to create an administrator account that you will use to log in to the helpdesk. Use an email address that you check, but not something that routes back to the helpdesk. Your helpdesk will use this email address to contact you in the event you lose your password, or if you configure notifications.
Choose a password and then click the “Continue” button.
In the final step of the installer you are given the opportunity to introduce yourself to the Cerb5 development team in exchange for a free 3 seat (simultaneous workers) license to help you get started. There are no strings attached. This license provides full functionality with no expiration and it is valid for the version of the helpdesk you are installing, but it does not provide access to product updates. We hope that you find the software useful, and we’re looking forward to growing along with you.
If you choose not to register your copy of Cerb5 then the software will default to “Free Mode” which is limited to a single seat but has no other restrictions.
Complete the short survey in exchange for your free license and then click the “Register” button.

The installation process is complete.
You’re almost ready to start using your new helpdesk.
If this is a production installation, you should delete the install directory since it is no longer necessary and it provides access to some particular sensitive information (specifically, your phpinfo() output that describes your webserver environment). If you’re planning to use language packs for localization of your helpdesk, be sure to copy the install/extras/translations/* files to another location.
If this is a development installation, then you should leave the install directory intact since it contains many useful scripts and examples for plugin development.
Once you’re ready to log in, click the “Take me there!” link.
Cerb5 will determine the appropriate From: address to use on outgoing email based on the group or bucket. These are collectively referred to as Receipts addresses_.
For example:
billing@example.comreceipts@example.comsales@example.comTo ensure that you receive customer replies, it is very important that your mail servers route these reply-to addresses to a mailbox that is checked by Cerb5.
You can add new reply-to addresses from Setup:

Navigating to the helpdesk addresses setup page.
Click the Add button to add a new reply-to address, and enter the following information:
From:.billing@example.com may use the personal name “Widget Factory - Billing Dept.”. This gives the recipient an idea of who you are; especially if they don’t recognize your email address.
Configuring a new reply-to address.
You can repeat this process for any additional reply-to addresses you want to add.
There is nothing wrong with using a single reply-to address for all outgoing mail — in fact, that may simplify your mail server configuration considerably, and you can still personalize the sender name for each group or bucket. If you have multiple products, brands, or initiatives, you may want to configure a reply-to address for each of them so your audience can instantly recognize who you are and why you’re contacting them. Otherwise, a busy or inattentive recipient may unintentionally delete your message as spam because they don’t recognize the sender.
The people who log in to Cerb5 to accomplish work and represent your organization to your audience are called workers. These workers might work in customer service, billing, sales, I.T., or marketing; or they may be executives, developers, or system administrators.
If this is a brand new helpdesk, the only worker that exists at the moment is yourself. This is the account that was created for you during the installation process.
First, let’s update your own account information. Click the link on the first or last name of Super User in the Workers list.

Configuring a worker account.
In Contact Information you can update a worker’s name, title, and email address. Keep in mind that if you change a worker’s primary email address it will become their new helpdesk login.
Authentication is used to update a worker’s password, and you can also promote them to Administrator, which will give them the permission to do absolutely everything in the helpdesk; they are like the root account on Unix-based systems, or the Administrator account in Windows. Only workers who are administrators can enter Setup. Grant administrator access judiciously.
Lastly, the Memberships box defines the worker’s membership to each of your groups. You can also designate the worker as a manager of a group. Managers can perform group-level administration: adding other workers as new group members, creating buckets for organizing the group’s work, etc.
When you’ve finished with your changes, click the Save Changes button.
Start collaborating by inviting your co-workers with the Add Worker button. In the next step we’ll organize your workers into groups.

A list of helpdesk workers.
Workers are organized into groups. Groups are a flexible concept that can be based on anything: brand, product, department, timezone, language, etc. By default you will have three groups based on common departments: Dispatch, Support, and Sales. The defaults were chosen because they’re common departments across most industries, not because they’re all-encompassing. You are free to modify these groups to suit your needs.
If you stick with the defaults, this is the proposed workflow:
billing@example.com) that you may want to route directly to a particular group.The workers inside groups can either be managers or members. Groups are designed to be autonomous; a group manager has the power to make most configuration changes related to the group without requiring help from an administrator. Managers can add new members to the group, manage buckets, and configure workflow using the group’s Virtual Attendant.
The common practice is to use groups for building a roster of fairly interchangeable workers. Work can be given to the group from the outside with the confidence that any member knows what to do with it. Groups share an organization system based on buckets, but workers outside the group aren’t expected to know how other groups organize their work (and it shouldn’t matter to them). Instead, new work is given to groups through their inbox, and the group’s own filters will decide how work is routed or assigned from there.
Let’s add a couple new groups. At this point you’re also welcome to change the default groups.

Configuring a group.
From this point, the managers of your new group can take over. They should refer to the Quick Start Guide for Group Managers.

This URL isn’t very pretty.
You may notice that your URLs look a bit ugly with the omnipresent /index.php/ in the path. Cerb5 can use URL rewriting to make URLs shorter and more user-friendly, but this requires webserver support.

This looks much nicer with friendly URLs enabled!
If you’re using the Apache web server you can enable “friendly URLs” with the following commands:
$ cd /path/to/cerb5
$ cp .htaccess-dist .htaccess
For this to work you will need mod_rewrite to be enabled in your Apache configuration. This is usually the case, unless you have just compiling or installed it.
If mod_rewrite isn’t enabled, you can enable it with the following command on many Linux-based servers:
$ sudo a2enmod rewrite
$ /etc/init.d/apache2 reload
nginx is another popular lightweight webserver for serving PHP content. It doesn’t support the Apache .htaccess file format, but you can add the following directives to your server configuration to get the same effect:
location / {
if (!-e $request_filename) {
rewrite ^/(.+)$ /index.php/$1 last;
}
}
location ~ ^(.+.php)(.*)$ {
fastcgi_split_path_info ^(.+.php)(.*)$;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
include fastcgi_params;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_intercept_errors on;
fastcgi_ignore_client_abort off;
fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
}
This assumes that Cerb5 is installed in the root of the webserver. Otherwise, just prepend the path in your configuration. You also will want to create a blank .htaccess file so Cerb5 will automatically generate friendly URLs for you.
Traditionally, when you access a URL like http://www.example.com/pages/help.html from your browser there is corresponding file on the webserver with the name help.html in the pages directory. This same process is used for HTML, images, Javascript, CSS, and other files available for download.
Cerb5 uses a different approach for serving content, which is known to web application developers as the Model-View-Controller (MVC) 1 architectural pattern. As a consequence of this, all the public interaction with your helpdesk occurs with two main files in the root directory of your Cerb5 installation. The pages that your workers interact with are virtual. This means that there isn’t a file on your webserver that corresponds with each URL.
Here are some common examples of Ajax functionality:
You only need to expose three files to the outside world. The application will transparently manage access to other resources, such as images or file attachment downloads.
You should make the following files available to web requests:
ajax.phpindex.phpfavicon.icoBrowser access to the following locations should be forbidden:
.svn/.git/api/features/libs/storage/If you’re using the provided .htaccess file for friendly URLs, then we’ve already given you some defaults for blocking access to these directories:
RewriteRule ^(.*/)?\.svn(/|$) - [F,L]
RewriteRule ^(.*/)?\.git(/|$) - [F,L]
RewriteRule ^(.*/)?api(/|$) - [F,L]
RewriteRule ^(.*/)?features(/|$) - [F,L]
RewriteRule ^(.*/)?libs(/|$) - [F,L]
RewriteRule ^(.*/)?storage(/|$) - [F,L]
With Apache, you can use directives in your virtual host configuration to protect these directories:
http://httpd.apache.org/docs/2.0/sections.htmlhttp://httpd.apache.org/docs/2.0/misc/security_tips.html#protectserverfilesWith nginx, you can use the following directive in your server configuration:
location ~ ^/cerb5/(api|features|libs|storage)/ {
return 403;
}
Your organization may have a requirement that all worker access should be password protected or restricted to requests coming from inside your corporate network. That’s a fine policy, but there are a few things you need to consider when implementing a firewall, HTTP authentication, or IP-based security restrictions.
All scheduled tasks are triggered by automated requests to the /cerb5/cron URL. If these requests are coming from a cronjob on the same webserver then this usually doesn’t present a problem. However, once you’ve established IP-based restrictions you should test the scheduled automated access to that URL to make sure it can get through. These scripts will also need to provide HTTP authentication details if you’re enforcing them.
If you have applications that use the Web-API (http://wiki.cerb5.com/wiki/Web-API) to integrate with your helpdesk then you’ll need to make sure they can make requests to the /cerb5/rest/* path. You’ll need to provide some extra code to handle HTTP authentication.
Community portals also make requests to Cerb5. If you install the Support Center, or another community portal, on an external webserver then you need to make sure that machine can make requests to the /cerb5/portal/* path. The default community portal script doesn’t provide a mechanism for HTTP authentication, but you could provide an override by IP address. This feature is on the project wishlist 3.
When a webserver receives an HTTP request for a PHP script, the human-readable source code is compiled into a machine-friendly format called opcodes 4. By default, opcodes are only kept around long enough to serve an individual request and then they’re disposed of to free up resources.
The default behavior makes sense in a shared hosting environment where dozens of scripts and applications may be sharing the same system resources. However, as you can imagine, when a single PHP web-app receives a disproportionately large amount of the traffic then the process of constantly recompiling its source code can become a performance bottleneck.
XCache (http://xcache.lighttpd.net/) is an extension for PHP which caches the most frequently-accessed scripts in the machine-friendly opcode format. Typically, XCache is a moderate, turnkey performance-boost that doesn’t require any application-level changes to benefit from the cache.

XCache flowchart
Installing XCache is an advanced topic. If you don’t have administrator-level control of your server then it’s likely not something you’re going to be able to do.
XCache is not found in the PHP Extension and Application Repository (PEAR) (http://pear.php.net/), so you’ll need to install it through a package manager or compile it manually.
On Debian and Ubuntu systems you can install XCache with apt-get:
$ sudo apt-get install php5-xcache
Depending on your installation method the XCache configuration will be at the end of your php.ini file, or in a conf.d/xcache.ini file.
If you have other applications on your webserver that you don’t want to be managed by XCache, you can disable caching by default with the following settings in your php.ini or conf.d/xcache.ini file:
xcache.cacher = Off
Then you can add the following option in your virtual host configuration or an .htaccess file:
php_flag xcache.cacher On
The Alternative PHP Cache (APC) 5 is a popular choice for opcode caching because it’s part of PEAR, which makes installing it really simple. However, APC suffers from some major drawbacks. It has limited support for recent versions of PHP, and there are many situations where it will produce segmentation faults 6, cryptic FATAL errors on “Line 0” 7, or blank white pages in the web browser.
One of the major sources of latency in web applications is often database interaction. Databases are used to save information between sessions (persistence), and they provide functionality for sorting, joining, and filtering large collections of information. Databases are a natural fit for dynamic content — that which changes frequently as people use the application (e.g. profiles, voting, comments).
The use of a database may feel so convenient for novice developers that they begin to serve all content that way, including static content — that which doesn’t change while the application is in use (e.g. HTML templates, CSS stylesheets, files for download).
In our experience, the worst kind of content to frequently read from a database is immutable — that which is written once and then never changes (e.g. email messages, file attachments, log entries).
There is nothing inherently wrong with storing this information in a database. Issues arise when infrequently changed information is frequently read from the database, due to the overhead of aggregating, joining, filtering, sorting, and returning results. At best, the database itself caches the results of these extraneous read queries. At worst, the database expends considerable resources every request to retrieve data that hasn’t changed in the past 1,000 read queries.
Memcached (http://memcached.org/) provides a shared memory cache for arbitrary information. This allows static or immutable content to be retrieved from the database once and then requested many times without incurring database overhead. Even better, content in a single Memcached instance can be cached from multiple databases, and read by multiple servers.
Memcached advantages:
Memcached disadvantages:

Memcached flowchart
It’s often best to install Memcached from your platform’s package manager; however, some distributions (such as Debian Etch) will install rather old versions. You want version 1.2.2 or later.
You’ll use PECL to install PHP’s Memcached extension (http://us3.php.net/memcached). The similarly named Memcache extension (http://us3.php.net/memcache) will also work, although it is an older library with fewer features.
Once Memcached is installed you need to edit your Cerb5 framework.config.php file and change the following lines:
//define('DEVBLOCKS_CACHE_PREFIX',''); // ONLY A-Z, a-z, 0-9 and underscore
//define('DEVBLOCKS_MEMCACHED_SERVERS','127.0.0.1:11211');
To something like:
define('DEVBLOCKS_CACHE_PREFIX','myhelpdesk'); // ONLY A-Z, a-z, 0-9 and underscore
define('DEVBLOCKS_MEMCACHED_SERVERS','127.0.0.1:11211');
DEVBLOCKS_CACHE_PREFIX - This prefix allows multiple applications to share a single Memcached. If no prefix is used, then only one application can use a particular key (e.g. “worker_list”). The prefix can be anything as long as it’s unique. We often suggest using the database name as the prefix.
DEVBLOCKS_MEMCACHED_SERVERS - This is a list of Memcached instances to distribute requests between. Usually you won’t need more than a single Memcached instance, but if you want to distribute requests then add more host:port pairs delimited by commas (e.g. 127.0.0.1:11211, 127.0.0.2:11211).
By default, Memcached does not have any form of authentication. Make sure you don’t bind Memcached to a publicly-accessible network interface without establishing firewall rules. It defaults to only serving local requests on the 127.0.0.1 address.
You also need to consider if other local users and scripts can connect to Memcached’s port (11211 by default). Choosing a unique prefix will help safeguard your cached data, but it shouldn’t be all you rely on.
In summary:
netstat --tcp -l
To fully protect your Cerb5 helpdesk data you need to backup both the MySQL database and the /cerb5/storage/ filesystem. While there are countless good approaches for performing backups, this document will focus on the best practices we’ve discovered over the past several years of hosting hundreds of helpdesk instances on our On-Demand network. The examples will be Unix-based since that’s what we’re most comfortable with.
For convenience and permissions, it’s a good idea to make a backups user on the local system. If at all possible, you should put the backups user home directory on a different hard disk than your live databases to provide for fault tolerance and better write performance. The examples below will refer to this location as ~backups. A separate location is important — while a RAID configuration will protect you from the failure of individual storage hardware devices, it won’t protect you from filesystem corruption or non-hardware-related data loss (e.g. bugs, errant queries, maliciousness).
You can usually accomplish this with something like:
# adduser --home /backups --disabled-password --disabled-login backups
It’s a really smart idea to make a separate backup user that is read-only, especially when you start automating backups.
In MySQL you can do this with the following query (make up your own password!):
mysql> GRANT SELECT, RELOAD, LOCK TABLES
ON *.*
TO backups@localhost
IDENTIFIED BY 's3cret';
You should then create a Shadow file which will “securely” store your password for automation:
Put the password text inside a hidden file. It’s better to use something like vi instead of echo, since you don’t want to leave your password in your command history. We’ll use echo here for simplicity:
# echo -n "s3cret" > ~backups/.db.shadow;
Make the backups user the owner:
# chown backups:backups ~backups/.db.shadow;
Make the file read-only by the owner and invisible to world:
# chmod 400 ~backups/.db.shadow;
In the examples below we’ll use this shadow file in place of literally typing the password on the command line. In addition to enabling automation, this also helps prevent sensitive information from being visible to other users in the global process list.
The database stores the majority of your helpdesk information. In the majority of cases, it stores anything that isn’t an attachment.
One of the quickest ways to backup (and restore) a MyISAM-based MySQL database is to use the mysqlhotcopy 8 tool, which copies the raw .frm, .MYD, and .MYI files to a new location. This utility will flush any pending row changes from memory to the disk and then lock the tables while copying them to a new location. Unless your database is huge (relative to your hardware), or your disk or network I/O is very slow, you should be able to hotcopy a live database with minimal interruption. If you’re using replication you can make hotcopies of a slave without any service interruption.
Pros:
Cons:
It’s important to reiterate that mysqlhotcopy will not properly back up InnoDB tables, but it won’t give you an error if you try. If you’re using InnoDB tables you must use mysqldump or an Inno-DB specific hotcopy solution.
Usage: (to local filesystem)
$ mysqlhotcopy -u backups -p`cat ~backups/.db.shadow` --addtodest --noindices \
c5_database ~backups/dbs/
Usage: (to SCP)
$ mysqlhotcopy -u backups -p`cat ~backups/.db.shadow` --addtodest --noindices \
--method='scp -c arcfour -C -2' c5_database backups@remotehost:~backups/dbs/
If you’re using InnoDB tables, or you don’t have access to the mysqlhotcopy tool or you aren’t comfortable using it, then mysqldump is the standard tool for performing database backups.
Pros:
Cons:
--disable-keys flag to improve this.mysqlhotcopy to copy the binary data files.--lock-tables. This prevents data from being written in a file you’ve already backed up while you’re still backing up other files. Without locking, some tables will have references to data in other tables that doesn’t exist. However, if you’re using InnoDB you can use the --single-transaction flag to make a consistent snapshot without locks (but you should ensure the database schema itself doesn’t change during the process; which usually only happens during a software update).Usage: (MyISAM)
$ mysqldump -Q --disable-keys --e -u backups -p`cat ~backups/.db.shadow` \
--lock-tables c5_database > c5_database.sql
The /cerb5/storage filesystem stores the pending mail parser queue, import queue, and all the file attachments from mail. It’s the only filesystem hierarchy you need to backup for a full recovery (the rest of the files are temporary caches, or can be downloaded from the project website). Since the bulk of the storage directory is comprised of tons of small file attachments that will never be modified (only deleted), it’s the ideal candidate for incremental backups.
rsync is one of the simplest ways to copy only changed files to a new location. In a nutshell, its purpose is to keep two copies of the same directory in-sync.
Pros:
Cons:
Usage: (to local filesystem)
rsync -a --verbose --delete /path/to/cerb5/storage ~backups/storage
Usage: (to SSH)
rsync -aze ssh --verbose --delete /path/to/cerb5/storage \
backups@remotehost:~backups/storage
Tips:
storage/) means to copy the directory’s contents and not the directory. Excluding the trailing slash (storage) will copy a directory and its contents.--delete option will remove files from the destination directory that are no longer in the source directory. Since this can be dangerous if you mistype a directory, you may omit this option until you’re confident things work.It’s crucial to assume that anything that can go wrong will go wrong (at some point). You can’t trust your local RAID, your server, or your datacenter, to store the only copy of data that your business is doomed without.
At the simplest, off-site backups may involve downloading a copy of your backups to your office and burning an extra copy to DVD. Keep in mind, it does you no good to have 250GB of backups on your office network with a 256Kbps upstream to your datacenter. If you could drive across the country to hand deliver the backups faster than you could upload them then you’ll want to place your backups somewhere where you can retrieve them quickly. However, there’s something to be said for the secure feeling of having tangible, offline copy of your critical data; and even WebGroup Media’s 9 years old Cerb5 database could fit on a DVD and be re-uploaded from a residential Internet connection.
If you have the resources, you may also choose to have a standby server in a different location than your production server. This would allow you to make server-to-server backups, which would require two hardware configurations, or two datacenters, to fail at the same time before you follow them into the blackness of failure.
Our favorite choice, cloud and utility computing, also provides a great opportunity for off-site backups, since you can store massive amounts of data, highly redundantly, for a few dollars per month; and you’ll likely be able to move data to and from a cloud computing network MUCH faster than using your office DSL.
Amazon S3 is a storage service. At the time of this writing, Amazon S3 costs 10 cents (USD $) per month per gigabyte stored. For that price, your data is protected by being replicated to multiple locations. You also get reasonably fast network access to it (generally 10–20 MB/sec for us at WGM in Southern California). That’s $1/mo per redundant 10GB! Be sure to read the terms on their site, as there are also similar rates for bandwidth (though most of the time you’ll just be uploading).
Pros:
Cons:
Usage:



The Jets3t project provides a Synchronize tool that works much like rsync, replicating changes from a local directory structure to a remote S3 bucket. It requires a Java Runtime Environment (JRE) of version 1.5 or later to be available.
Usage:
~backups/jets3t/bin/synchronize.sh -k UP yourbucket/backups/server1/dbs/20110531 *.gz
Tips:
-k option above prevents files from being deleted from S3 if they no longer exist in the local filesystem.jets3t/config/jets3t.properties and set s3service.https-only to false. This should give you a moderate speed boost on uploading.Our favorite tool for browsing S3 buckets is the S3Fox extension for Firefox. Once installed, you can simply drag files back and forth between your S3 account and your local machine. It will also allow you to modify the access level (ACL) of any file, which gives you the option of creating a publicly sharable URL. This is great, since S3 is useful for far more than just off-site backups — you can host downloads or high-resolution screencasts without bogging down your servers (and paying a bandwidth ransom at the datacenter) if your content becomes popular.

The S3Fox extension for Firefox
The officially supported way of upgrading Cerb5 is by using version control software like Git9 or Subversion10. These tools will automatically update your helpdesk files to the latest version. The major advantage of version control is that it will attempt to automatically merge official code changes with any customization you have done. It also gives you the ability to list all your local changes to any project files, and to revert to an official version when desirable.
We recommend that you use Git whenever possible because the official project is hosted using Git on GitHub. This environment makes it much easier for people to collaborate and share improvements. You can even fork your own copy of Cerb5 so you can keep track of your custom changes.
If you aren’t able to use Git directly, GitHub provides a Subversion interface to our project repository.
On Unix-based servers you can check if Git is installed by typing:
$ git --version
If you need to install Git, it’s usually available in a package named git-core. The actual package name will depend on your distribution of Linux/BSD.
On Unix-based servers you can check if Subversion is installed by typing:
$ svn --version
On Windows-based servers, a graphical tool like TortoiseGit or TortoiseSVN is your best option.
If you can’t use Git or Subversion, you really should consider having us host your helpdesk on Cerb5 On-Demand rather than managing it yourself.
Always make a backup of your helpdesk database prior to upgrading. MySQL backups are best done with mysqlhotcopy or mysqldump. See the chapter on Backups for more information.
Copy your framework.config.php file to backup.config.php
Change directory to your cerb5 installation.
The choice of using Git or Subversion to update will depend on how you originally installed the software.
Ensure that you’re using Git:
$ git status
You can also verify that a .git directory exists. If the above command returns an error, or the .git directory doesn’t exist, then you probably installed using Subversion. Skip to the next section.
Update the list of branches from the remote repository.
$ git fetch origin
If this gives an error, you can check your list of remotes with the git remote command. Use another remote in place of remote.
Display the list of available branches:
$ git branch
Switch to the new version, using the -m switch to merge your local changes (e.g. framework.config.php):
$ git checkout -m 5.4.1
You can ensure that you’re using Subversion with the following command:
$ svn info
You can also verify that a .svn directory exists. If this returns an error, or the .svn directory doesn’t exist, then you may have installed the software using Git instead. Refer to the previous section.
In most cases you can update to the latest stable version using:
$ svn update
Using TortoiseSVN to update Cerberus Helpdesk

TortoiseSVN integrates with your Windows GUI. To update Cerberus Helpdesk:
You should be shown a list of updated files and the new build versions for the project. Press the “OK” button when finished reading.
If you encounter conflicts while updating, you can attempt to resolve them manually, or you can revert your changes and restore your framework.config.php settings by hand. Don’t simply copy over the new file with your old file, because it may have changed in the recent version.
Ensure that you have no remaining conflicts before continuing with the upgrade.
Git:
$ git status
Subversion:
$ svn status
You should set file ownership and permissions again after updating your files using Subversion.
Unix-based servers:
From your cerb5/ directory at the console (replace www-data with your appropriate Apache user and group):
chown -R www-data:www-data .
chmod -R 0774 storage/
Permissions, especially on php files are a common upgrade issue. See Troubleshooting (below) for more details.
Windows-based servers:
Use Windows Explorer to set the appropriate write permissions on the /cerb5/storage directory for your IIS user.
Some Cerb5 updates contain database changes which require a helpdesk administrator to finalize. This will prohibit all helpdesk activity (e.g., logins, scheduled tasks, mail parsing) to prevent any database corruption while you’re between versions.
After your files are updated, attempt to log into your Cerb5 helpdesk instance as you normally would. If a database update is required the software will automatically prompt you. Upon finalizing you should be able to log in and continue working.
Very rarely, the index.php file which drives Community Tools like the Support Center may change during an upgrade.
How to tell if you need to update your Community Tool file:
Compare the following line from the index.php output with your deployed index.php:
define('SCRIPT_LAST_MODIFY', 2009070901); // last change
If the number is different you should replace the index.php file for your Community Tool with the new version from the helpdesk.
We’re working on a way to make this check happen automatically.
Git will usually leave your cerb5/install directory deleted, but Subversion will always restore it. Delete the install directory if it exists.
If you’ve been given manager status in a group then you have autonomous control over its roster, configuration, and workflow.
To manage a group:

Managing a group.
Group management is organized between several tabs:

Setting group mail preferences.
You have one option in your group’s mail preferences — whether or not a reference number should be displayed in the subject line of your email responses. There are some considerations for both users and technology.
For users, a reference number makes it easy to refer to the details of a particular conversation at a later date, in any channel. For example, a user may decide to follow-up their original email through a live-help chat, IM, Twitter, Facebook, or phone conversation. In public channels, a reference number like “ABC–12345–678” is far more anonymous than providing a name, company, or email address. In private channels, like a phone call, it’s probably easier to just ask a customer for their email address when retrieving their conversation history.
From a technical standpoint, the reference number was used in earlier versions of Cerb5 to associate a reply with the message it was replying to. When someone replies to a message sent from Cerb5, the headers are checked first, and then the subject line is scanned for a reference number as a last resort. This is not necessary with most modern email applications. Incoming messages can be associated with the message they are replying to using the In-Reply-To: and References: headers from the RFC–2822 standard. Unsurprisingly, Microsoft chose to implement their own proprietary headers in Exchange and Outlook (Thread-Topic: and Thread-Index:), but the proper In-Reply-To: header should still be added by Exchange when mail originated from outside a sender’s organization. However, it’s not uncommon to encounter users with misconfigured Exchange servers.
Ultimately, the decision to display a reference number on the subject line is entirely subjective. If you find it useful then you can enable the feature. Otherwise, there is no penalty to having your outgoing mail look more personal with a subject line that simply reads “Re: That stuff you asked about.”
With reference numbers enabled, your recipients will receive replies with a subject like:
Re: [Support #ABC–98765–123]: My printer seems to vaporize paper.
When reference numbers are disabled, the subject of your replies is provided in the traditional format:
Re: My printer seems to vaporize paper.
Buckets are flexible containers used by groups to organize their workload. Work can queue up in buckets, making it more efficient to handle similar issues at the same time (e.g. processing orders, issuing refunds, sending out beta information). Buckets are also useful to move piles of work out of the way if they shouldn’t be handled immediately (e.g. newsletters, survey responses, feature requests).
With department-themed groups your buckets might look like:
Or if you had product-related groups you might do the following:
Since buckets are often only concerned with a single shared characteristic they aren’t always the best way to organize work. They provide a simple building block for more complex workflows.
To add new buckets, select the Buckets tab, and click the Add button. Enter the following information:

Creating a new bucket.
Name: This is the name of the bucket. For example: receipts, leads, newsletters, etc.
Send replies as email: This specifies an email address to use as the sender in From:. This will default to the sender address on the group’s inbox.
Send replies as name: This allows you to provide a personal name that will display next to the sender address when your recipient reads their email. For example, billing@example.com may use the personal name “Widget Factory - Billing Dept.”. This gives the recipient an idea of who you are; especially if they don’t recognize your email address. This will default to sender name on the group’s inbox.
Bucket email signature: This defines the worker signature that will be used when mail is sent from this bucket. You can use placeholders like the current worker’s name or title, which will automatically fill in the appropriate values depending on who is sending the email. This will default to the signature on the group’s inbox. You can also use conditional logic and modifiers in this template. Refer to the section about Snippets for more information.
Workflow: If you check this box then the bucket will be hidden from the Workflow tab on the Mail page.
When you’re finished, click the Save Changes button.
For workflow purposes, buckets can be designated as assignable (visible) or non-assignable (hidden).
Assignable buckets contain work that is actionable — that is, the work should be assigned and handled in a relatively quick timeframe in an effort to keep the bucket empty and the recipients happy. Some examples of assignable work include:
Non-assignable buckets contain work that doesn’t need immediate attention and would otherwise detract from the goal of having empty buckets and quick handling of actionable work. Non-assignable work is usually queued up until a future point and then handled in bulk. Some examples of non-assignable work include:
Given these definitions, you should hide your spam quarantine buckets from the Workflow view, making it easier to focus on actionable work.
A group’s inbox is always the top bucket in the list. You can drag custom buckets into a new desired order. It’s a good idea to move the default Spam bucket to the bottom of the list so it’s out of the way.
Each group has a Virtual Attendant that provides a way for you to automate workflow and business logic. If necessary, you can review the topic of Virtual Attendants in the Concepts chapter.
It’s fairly common for a group to want to send an automated acknowledgement when new conversations are started.

Changing the group roster.
As a group manager you can add or remove members. You can also promote members or demote managers.
Important Note: Until you’ve handled a few hundred messages, the anti-spam system will probably come to some seemingly bizarre conclusions based on little evidence that messages are “spammy”. This is part of the training process. It’s important to spend a few minutes each day reviewing the spam filtering decisions that were automatically made for you. Cerb5 will learn when you make corrections, and it will be far less likely to make the same mistakes in the future. Our helpdesk at WebGroup Media has been trained for several years, and it’s rare to see a single false positive in 10,000 messages quarantined as spam.
Cerb5 employs a Bayesian filtering algorithm 11 to combat spam.
This filtering tactic is useful because it’s highly adaptable; it learns to recognize spam based on a studious analysis of the patterns of content found in your typical daily mail. For example, a pharmacy’s helpdesk may receive mail that mentions words like “pills” and “prescription” on a daily basis, and Cerb5 won’t considered these messages to be spam because those terms are familiar to the health care industry. However, to the rest of us they’re very suspicious words to find in our inbox. Likewise, messages from unknown contacts that mention both “Java” and “programming” have a much higher probability of being junk mail when sent to a pharmaceutical company compared to a software development company.
3 and 24 characters in length. This is a performance tweak that helps keep the database manageable.Once Cerb5 has reduced an email to a list of unique, less-than-common words it sorts the words by interestingness. Words are considered interesting by being either very innocent (“Cerberus”) or very suspicious (“pills”) on a scale of 0.0001 to 0.9999. The most interesting words are used to calculate a spam score, based on how the content of those messages was perceived by helpdesk workers in the past. Words are more interesting as they deviate in either direction from a 0.5000 median (the median being where a word shows up as often in spam as in non-spam and cancels itself out).
The main goal of Cerb5’s anti-spam functionality is to quarantine suspicious messages so they don’t show up as active tickets in your worklists. Companies vary in their anti-spam processes — from deleting suspicious mail immediately, to quarantining and reviewing — and we don’t want to force people to adopt an arbitrary “the one true way” process. The downside of this philosophy is that it’s not obvious at first how to best configure anti-spam functionality.
While the ideal process will depend on your own particular environment and preferences, the following steps are recommended to all new helpdesk managers.
The first step in filtering spam is configuring the behavior of your groups:

Configuring a group to quarantine probable spam.
>=85%) into a bucket called Spam.
Workers should always use the ‘Report Spam’ button
We’ve designed training to happen naturally based on a worker’s actions throughout the helpdesk:
Because the goal of spam filtering is to prevent workers from wasting their valuable time looking at junk mail, it’s not enough to just report mail as spam. You should also hide spam from worklists. To do so, navigate to the Workflow tab for each group and uncheck the Assignable checkbox for each Spam bucket. This will hide their contents from the totals on the Workflow list on the Mail page.
Hiding the spam buckets is also important because it allows workers to accomplish the goal of having zero active tickets. Otherwise, a Spam bucket in the Sales group with 20 messages will always show a Sales group total of more than 20.
Whitelisting is the process of ignoring a particular set of rules for trusted entities.
We’re often asked why Cerb5 doesn’t whitelist contacts from the address book and never consider their messages as spam. The problem with that approach is how easy it is for spammers to forge (“spoof”) the sender on email they’re sending you. It’s not uncommon to receive a lot of spam from your own email addresses.
By not automatically whitelisting address book senders, Cerb5 has a chance to filter out spoofed mail as well — and that’s mail that would otherwise create thousands of junk messages that you would have to manually clean up.
The spam buckets should only be cleared once per day. It’s inefficient for workers to have to manage the spam buckets every time they quarantine something. Each group should elect members to review and empty the spam bucket. This helps make sure that a legitimate message that has been mistakenly flagged as spam (as rare as that may be) isn’t ignored for too long.

There are usually too many messages in a Spam bucket to audit them all individually.
We don’t expect your workers to read every single quarantined message in the Spam bucket, since most of the time everything is going to be junk. Here’s our process for rescuing legitimate mail from an overflowing spam bucket while quickly purging the rest:
Create a new workspace with a worklist that shows only the Spam buckets of the groups you’re responsible for.
100 (or whatever you find comfortable to read).Click the piles link on the worklist, select senders and click the red X icon to delete anything that’s obviously forged (e.g. junk mail sent to the helpdesk from your own email addresses). This process is quicker if you can delete mail sent from an entire domain (in our case: webgroupmedia.com). You don’t have to spend too long on this step, it just helps quickly reduce the amount of mail you’re auditing.

Use piles to automate a big chunk of the work in a few clicks.
Sort the # Nonspam column in the worklist in descending order by clicking on the column header until the icon is an arrow pointing downward.

Sorting the ‘# Nonspam’ column in descending order.
Quickly scan through the remaining subjects in the list until the # Nonspam count is 0. Use (peek) on any ambiguous tickets to check their content. Rescue anything legitimate (which should usually be nothing) by selecting the row in the worklist and clicking the Bulk Update button.

Using Bulk Update to rescue false positives.
At this point, don’t worry about confirming that anything is junk mail.
Once you’re done auditing for false positions, click the Bulk Update button at the bottom of the list:

Using Bulk Update to purge the rest of the quarantined spam.

Logging in
Let’s log in and take a look. Enter your email address and password, then click the Sign On button (or press ENTER after typing your password).
There are several terms that you will hear used throughout this book:
Cerb5 refers to this application, originally known as Cerberus Helpdesk (5th generation). The project was started in January 2002 to help online teams efficiently distribute and handle large volumes of work: customer support questions, technical problems, tasks, sales opportunities, business partnerships, and more.
A database provides long-term storage for arbitrary information (data). Databases help applications maintain relationships between data (e.g. “Which products were shipped for order #1234?”), and they assist with performing complex analysis (e.g. “How many orders over the past 12 months were from someone who has a surname that begins with F (AND) resides in Germany (AND) spent more than $100 USD?”).
The helpdesk is web-based hub for centrally managing and archiving tickets, and routing messages between workers and recipients. This allows several workers to receive and share email without recipients writing to any of them individually.
1, and a year later the most recent ticket ID may be 123500. These IDs are sequential; in other words, they add 1 for each new ticket, starting from 1. There are many reasons you should not share these IDs:1025 then they are now aware of 1,024 other valid IDs.XER-83472-879. Masks are designed to be short and verbally readable, while still providing a very large number of combinations. There are more combinations available in three letters (17,576) than there are for 3 numbers (1,000), so you can often enter the first three letters of a ticket mask to find a match without having to type in the whole thing. Masks are also very useful for verification outside of email (“I need your email address and the first three letters of the ticket from the subject line”).The people who log in to the helpdesk to represent your organization are called workers. Other software applications frequently use the term users, but we find that term ambiguous; users can refer to either customers or staff members.
A watcher is a worker who subscribes to notifications about new activity on specific records. For example, a manager may assign a task to another worker, and add themselves as a watcher to the task so they can be automatically notified about progress and completion. Being a watcher on something does not imply that you are taking responsibility for it. If you aren’t sure how to answer a particular question, it can be useful to watch it so you can leave from the answer a more experienced worker gives. Watching facilitates collaboration, observation, and training.
A person who corresponds with the helpdesk is referred to as a contact. These are your customers, partners, and prospects. If you’re part of the I.T. department for a large corporation, then contacts are likely your co-workers who ask questions and report problems.
The address book is a list of all the contacts in your helpdesk. It provides the ability to group contacts by various attributes (e.g. location, language, industry) to build customer lists and mailing lists.
Contacts that are associated with a particular ticket are called recipients. Recipients receive a copy of every new message on a ticket.
A bucket is a container for storing similar tickets together. Common buckets are: Leads, Receipts, Newsletters, Refunds and Spam. Buckets aren’t the only means for grouping tickets, but they’re the simplest to understand and use.
A group is a collection of workers who share responsibility for the same tickets and buckets. Common groups are: Sales, Support, Development, Billing, and Corporate. These examples happen to all be departments, but groups can be established based on any attribute (product, location, etc).
A worker in a group is called a member. A member with the authority to modify the group is called a manager. Managers can create buckets, add new group members, and establish routing rules for new work. Groups can have any number of managers.
Each group has an inbox where new tickets are delivered by default. These tickets are then dispatched automatically by workflow rules or manually by workers.

Tour mode
“Tour mode” is automatically enabled to provide basic training when you log in for the first time. As you navigate through the software, the yellow box at the top of the page will highlight relevant points of interest based on where you are. Clicking on each item of interest will display a speech bubble that highlights the location of the feature and explains how to use it. Once you are familiar with the software you can click the hide this link at the top right of the yellow box to disable the tour. You can resume the tour from your worker settings.
Set Timezone to your current location. The software will use this timezone when displaying dates and timestamps, making it easier for you to do time-based comparisons.
If you are in a multilingual environment, set Language to your preferred language. This will change all the text in the software. Any text that does not have an available translation will be displayed in English by default. This option won’t translate individual email messages; they will still be displayed in the language they were written in.
If you have additional email addresses that you would like to associate with your worker account you can add them in the Email Addresses section. This is useful if you want to be able to relay mail to a mobile email account. Keep in mind that these addresses will all represent your worker account, so you don’t need to add all your personal email addresses unless you intend to use them for this purpose.
Once you have established your preferences, click the Save Changes button at the bottom of the page.

The navigation menu.
The navigation menu at the top of each page divides the application into sections based on the type of information being presented.
We’ll now explore each of these sections and explain their functionality. Keep in mind that some of the sections and features listed below may not be visible if your account does not have access to them. If this happens, skip ahead to the next section. You may also see additional sections if various optional plugins are enabled.

The mail section.
The mail section is where you read, respond to, and initiate email conversations. These conversations are shared with other workers in the groups you are a member of.
There is a toolbar at the top left of the mail section with several buttons:
At the top right of the section there is a quick search text box. This time-saving feature allows you to perform a search from most pages in the mail section without having to navigate to the search page first.
The mail section is further divided by a series of tabs that provide specialized functionality.
The Workflow tab is where you will spend most of your time in the mail section. It is optimized for working with a large volume of mail by highlighting conversations that are immediately actionable.
In many environments there are conversations that sit idle for long periods of time because they’re waiting for something: a reply from a customer, a worker task to be completed, or a specific date and time. Additionally, there are several kinds of mail that may never need a response but can’t be closed without being reviewed: vendor newsletters, receipts, or automated reports. This work should be moved to a bucket that has been flagged by a group manager as being hidden from Workflow.
Workflow focuses on conversations that you can do something about by enforcing the following criteria:
The key to the efficient use of Workflow is to have groups and buckets that are organized by the process required to complete the work contained within them. For example, if you have buckets like Receipts, New Orders, and Leads, you can repeat the same process for each message in a bucket, while also reusing any resources you need in order to complete them.
You can also use the subtotals feature to group conversations based on criterion other than bucket.
The last thing you want to be doing is competing with a dozen workers who are randomly grabbing work. Cerb5 is not meant to be used in a social vacuum. Find a co-worker and tell them “I’ll handle the new orders if you want to go through the leads”. If your team is too large to organize with an informal process, you should nominate a group dispatcher to make assignments, or you should use a real-time, group-wide communication tool like Campfire by 37signals (http://www.campfirenow.com/).
The Search Tickets tab searches through the mail archive and provides results as tickets. This means that even if multiple messages from a conversation match they will be represented by a single result.
This is the best place to display all the conversations in the system, regardless of their status or other factors that prevent them from being displayed on the Workflow tab.
The Search Messages tab searches through the mail archive and provides results as messages. This is useful when you want to be able to match individual messages on a conversation as distinct results.
This is the best place to display a list of outgoing messages that behaves like a ‘Sent’ folder in a traditional email reader.
The Drafts tab displays a worklist of messages that you have saved but not yet sent. You can click on a draft to resume it.
The Snippets tab manages fragments of text that can be reused in various conversations. For example, when a customer asks for your price list you can simply insert the ‘Price Sheet’ snippet rather than monotonously typing it by hand or copying and pasting it from your website. Snippets can also contain placeholder text that will change depending on where they are used; for example, a {{first_name}} placeholder would be replaced by the first name of the contact you are talking to.

The activity section.
If necessary, you can review the topic of Virtual Attendants in the Concepts chapter.

The shortcut to your Virtual Attendant.
You can instruct your Virtual Attendant to send a copy of new notifications to your email address.

Our desired Virtual Attendant behavior.
It’s quite simple to send a copy of all notifications to your email address. First let’s create a new behavior and give it a name:
Select Edit Behavior from the menu.

The menu.
Click the Save Changes button.
Now that we’ve created a new behavior you could simply add a new action to it and receive a copy of all your notifications by email. However, to make this more interesting, let’s imagine that you only want a copy of your new notifications to be sent during the weekend. First, we want to a new decision to the behavior:
Now we want to add a positive outcome to the new decision:
Click the Save Changes button.

The outcome.
Finally, we want to add an action to send our mail during the weekend:
Set the text of Content: to:
{{message}}
{{url}}
Click the Save Changes button.

The action.
Now any time you receive a new notification during the weekend a copy will be sent to your email address.
Date: Sun, 15 May 2011 09:01:48 +0000
Subject: [Notification] Manager Mark commented on task Evaluate Cerb5: I
think it will do everything we want, and more!
From: "Example, Inc." <support@example.com>
To: you@example.com
Manager Mark commented on task Evaluate Cerb5: I think it will
do everything we want, and more!
http://localhost/cerb5/tasks/display/1/comments
If you click on the link provided in the email then your browser will open directly to the subject of the notification. In the example above you would end up on a specific task that your manager left a comment for you on.
Now that you understand how to forward your notifications to your email address you can customize the behavior to do exactly what you want. For example, if you want to send a copy of all notifications to your email address, you can simply add an action directly to the new behavior (the top gray bubble) and skip the steps for making a decision and an outcome.
You could also change the decision to allow for different outcomes. If you renamed the decision to “It is:”, you could add outcomes for “Weekend” and “Weekday After hours”, each with their own action.
Cerb5 is written in PHP and stores data in a MySQL database.
We use the following tools at WebGroup Media when developing Cerb5:
You should instruct end-users to install custom plugins in the /storage/plugins directory rather than the /features directory. While the design of plugins in either location is identical, the official plugins in the features/ directory have a special significance.
There are several important reasons for this:
In high-availability scaling and clustering, a shared filesystem (e.g. GlusterFS, NFS) should be used for serving storage/ content, but there’s no need to serve all content from a share since there’s more overhead and latency than the local disk. In some cloud environments, virtual volumes accumulate I/O costs. The files in features/ (and the rest of the application) can be considered static and loosely replicated across webserver nodes.
In On-Demand environments, a single copy of the core Cerb5 files should be symlinked between multiple instances. This allows opcode caching (e.g. XCache) to operate far more efficiently. Hundreds of Cerb5 instances can be served from a single XCache of around 32MB. Each of these sites only has a unique framework.config.php file and storage/ directory.
Filesystem backups should only need to account for a single directory of filesystem changes in storage/. They can exclude our project files, which may be easily recovered from our repositories. This is especially important in On-Demand environments with hundreds or thousands of copies of Cerb5.
The instructions for moving or upgrading Cerb5 take into account the storage/ directory, but changes to the core files are considered expendable. The files outside of storage/ can be easily replaced from our GitHub or Subversion repositories.
During upgrades or troubleshooting, we may need to disable all third-party plugins. It’s easy to exclude the features/ directory from this behavior, since it has been heavily quality-assurance tested prior to release.
(* is changelog-worthy) (reference bug tracker issue numbers when they are available)
In our increasingly interconnected world, you have probably realized that the clock on your wall is not useful for keeping track of an international timeline. For example, when it’s 9am on a Tuesday in Los Angeles, it’s 5pm that evening in London because there is an 8 hour time difference. At the same moment, it’s 2am Wednesday morning in Tokyo because there is a 17 hour time difference between it and Los Angeles.
To make comparisons in different time zones useful, we need a fixed point to compare everything to. Cerb5 uses universal time (UTC/GMT) when storing and comparing dates. Each time zone has an established offset from UTC which can be represented as 4 digits (2 for hours and 2 for minutes) prefixed with a - (before UTC) or + (after UTC). Los Angeles in Pacific Daylight Savings Time (PDT) is behind UTC by 7 hours, which you may see represented at the end of an email Date: as -0700. During British Summer Time (BST), London is 1 hour ahead of UTC, or +0100. Tokyo is in Japan Standard Time (JST), which doesn’t observe daylight savings time, so it is always 9 hours ahead of UTC, or +0900.
To simplify this, Cerb5 displays dates in relative time. In other words, something that happened 5 minutes ago in Tokyo also happened 5 minutes ago from the perspective of London. There is no offset for these relative times.
We could just as easily store all dates in your local time zone rather than universal time and you could still make comparisons between dates, but if your company headquarters moved to a new time zone then your entire historical timeline would be inaccurate by the offset between those time zones. When dates are stored in GMT/UTC, it doesn’t matter where you are currently located; historical dates can always be displayed for your current time zone with perfect accuracy.
The Cerb5 development team has been ironically fortunate in choosing our area of expertise. When we started the project in 2002, we possessed the naive belief that a web-based shared inbox “couldn’t take more than a couple of weeks to build”. We also couldn’t have imagined where that simple idea would take us. Nearly 10 years later, we’ve been pleasantly surprised. Online collaboration is a business challenge that is inherently unsolvable. We’ve had more than 20,000 organizations express interest in what we’re working on — including a countless number of companies, institutions, brands, and causes that we have always highly respected. For every task that we complete, the community spawns a dozen more great ideas. Every time we make a major improvement in some part of the application, we begin to see how that same approach could solve a wide variety of other feature requests or development obstacles.
Over the past 9 years, we’ve used this cumulative experience to refine a library of reusable web-based tools that can be applied to an increasingly wide variety of business requirements. When you hear us talk about Devblocks, we’re talking about these tools and the philosophy that guided their development. As we’re designing improvements to Cerb5 from interesting feedback, we assemble these tools like well-crafted blocks that can be combined in new and interesting ways. Every compelling idea that has come up so far can be reduced to a particular set of these blocks. Any time we sense there’s a missing piece, it leads us toward a new block that we can add to the toolkit. It has become part of our DNA — to the point that when we look at other applications, we start to instinctively break them down into the same compositional blocks.
Our ongoing improvements can leverage technology to make you faster, more efficient, and better informed — but there won’t be a point in the future where we can put down the tools and declare that we’ve solved online collaboration once and for all. In a perfect world, your team will continue to grow for countless years to come, and the information you gather will continue to expand at an exponential rate and become increasingly interconnected. There will always be room for improvement.
In many web-based applications, third-party extensions are an afterthought that have limited support for changing existing behavior or adding new functionality. Developers provide hooks that allow custom code to run when a particular event happens, but this code doesn’t have access to the same tools, services, and conveniences as the core application. This ties the hands of plugin developers and requires them to recreate solutions for problems that have already been solved in other places throughout the project.
When architecting Devblocks as the web development platform for Cerb5 (and all our future web projects), we made plugins the primary building block for the entire application. This means that every time we add new functionality and capabilities, we’re creating new extension points and event points that provide the same tools, services, and conveniences to plugin developers. We call our built-in functionality features to distinguish them from third-party add-ons, but these features are just a collection of plugins.
Our concept of plugins goes far beyond the ability to just add new interface elements like pages, tabs, and buttons; or providing a way to add custom behavior on built-in events.
All of the content for a plugin is in a single directory. To install a plugin you simply copy its directory to /storage/plugins, and to uninstall a plugin you simply delete that directory. A plugin should never require you to make changes to the rest of the project.
Plugins are only invoked when they are required, keeping your helpdesk fast and efficient even with a large number of plugins installed. Plugins that are disabled become invisible to the application and have absolutely no impact on performance.
Devblocks itself is a plugin, and the essence of Cerb5 is a “core” plugin that provides all the common functionality for other plugins to share and build with. These are the only two plugins that are required and cannot be disabled.
Below is a list of the capabilities of Devblocks plugins.
Plugins provide an XML12 “manifest” that tells the platform what contributions it is making to the application. Devblocks is designed to load and execute code to respond to requests in as few steps as possible. Manifests are cached in memory, so a quick lookup can tell the platform which plugins are needed to respond to a particular request without having to load a single plugin in advance.
This strategy makes the platform incredibly efficient, because it reduces the number of files accessed, the peak amount of memory utilized, and the amount of time spent compiling and executing unnecessary code.
A plugin can contribute new resources — images, scripts, stylesheets — as a bundle. These resources are not requested directly from the filesystem, but through a resource proxy that controls requests for access in conjunction with their plugin identifier (“ID”). When a browser is directed to make a request for resource — like an image — it uses the /resources/ controller in the URL. All resources must reside in a resources subdirectory in the plugin’s home directory to be accessible.
A plugin can provide incremental patches for automatic upgrades between any two versions. These patches can create or change the database schema, migrate data, perform maintenance tasks, or run custom code. Patches are automatically managed by Devblocks to ensure that they run in the proper order and only when they are needed.
A plugin can specify other plugins as dependencies. This means that a plugin should not be loaded unless other plugins are also loaded (i.e. it depends on them). Devblocks will analyze these dependencies to ensure plugins are loaded or updated in the proper order. Dependencies are useful when a plugin requires the use of functionality from another plugin and cannot function without it. Everything depends on cerberusweb.core, which itself depends on devblocks.core. These two dependencies don’t need to be specified in custom plugins, since they are declared for you automatically.
The primary purpose of plugins is to contribute new functionality, collectively referred to as extensions. Extensions are registered on extension points to notify the platform of their existence. With this strategy, plugins become a native part of the application, with the same rights and aesthetic as built-in features.
A plugin can also declare new extension points that may be extended by other plugins.
A plugin can register listeners that listen to event points and execute custom functionality when particular events occur.
A plugin can declare new events that may be observed by other plugins.
A plugin can contribute its own access control lists (ACL 13) to the global list of worker permissions. This allows seamless administration of the rights workers have when using plugins.
A plugin can contribute all of its interface text to the application’s translation system, which then becomes translatable with the Translation Editor just like the rest of the text in the application. No distinction is made between the text coming from plugins and that of built-in features, so popular plugins will become translated into new languages as a natural byproduct of their use. Plugins should also make judicious use of the shared internal translations for common words and phrases (e.g. save changes, delete, worker, email, etc), which reduces duplicate text and eases the work of translators.
A plugin can provide all of its own templates for rendering interface elements. It can also utilize common templates (known as “internal”) provided by Cerb5’s core plugin. For example, if a plugin needs to display a search filter for a text field or a date, it can simply use the existing template. There are many internal templates: search filters, comments, displaying relationships between objects, etc.
A plugin can also specify if any of its templates should be available for user editing. This allows you to make changes to a template. Devblocks will always maintain the original version of a template. This is primarily used in situations where a plugin will be in use in disparate places, such as plugins that contribute to community portals like the Support Center. You can customize these templates to be consistent with your brand on each community portal, without ever compromising the integrity (and sacrificing the upgradability) of your project files.
A plugin can register any of its classes in the global classloader. Plugins aren’t always loaded into memory, so classloading provides a hint to the platform telling it where the definition of particular objects comes from.
A plugin can take advantage of the platform’s built-in request routing by registering a unique uniform resource identifier (URI 14) and associating it with one of its controllers. For example, the files URI routes a request to a built-in controller that authenticates requesters before serving file attachments from storage.
(Objects are…)
(Records/Kinds)
(SDK in /cerb5/install/extras/sdk)
{devblocks_url}{$var|devblocks_date}{$var|devblocks_prettybytes}{$var|devblocks_prettytime}{$var|devblocks_translate}This chapter provides a comprehensive reference for use with the web-based user interface. The following sections are organized the same way that the application is structured. If you need more information about a specific page, tab, or button, simply skip ahead to that section.
At the top of the conversation display page, a toolbar provides shortcuts for common actions:

The conversation toolbar.
Edit displays a popup to edit the conversation properties.
Close closes the conversation. Closed conversations are considered to be resolved. If you want to hide a conversation that is dependent on a future date (e.g. “We’ll cancel your site at the end of the month.”) then use Waiting for reply instead. A closed conversation will be reopened automatically if a recipient replies.
Spam marks the current conversation as spam and delete it. This process trains your helpdesk to become more proficient at automatically detecting spam in the future. If a conversation is junk mail, and you want to avoid wasting time with mail like it in the future, be sure to mark it as spam rather than simply deleting it. You also shouldn’t mark these conversations as closed because they will be preserved forever, causing clutter in your database, wasting space in backups, reducing search performance, etc.
Delete deletes the current conversation. After a few days of inactivity all deleted conversations are permanently purged from the helpdesk and they will be unrecoverable without database backups. When you delete a conversation, it is the same as moving a file into the trashcan on your computer. You want to be absolutely sure that the conversation is not something you will need in the future. If it is something you will need later, then a better option is to mark the conversation as Closed or Waiting for reply.
Take is a shortcut to assign the conversation to yourself.
Print displays the conversation in a print-friendly format.
Refresh refreshes the conversation. It is exactly the same thing as refreshing a page in your browser, except that it always uses the full permalink URL for the conversation.
Merge shows a popup for merging multiple conversations together.
more>> displays additional actions that are less frequently used.
Move to is a shortcut for moving a conversation into a new bucket.

The Conversation tab.
The Conversation tab displays a timeline of messages and comments. This timeline uses Coordinated Universal Time (UTC 15). If a conversation is taking place between people in Los Angeles, London, and Tokyo, all that matters is the relative time. In other words, something that happened 5 minutes ago in Tokyo also happened 5 minutes ago from the perspective of London.
There is a toolbar at the top of the timeline:
There are three types of messages in the timeline:
Messages can be minimized or maximized. A minimized message condenses the sender information and hides the message content. Conversely, a maximized message displays everything. Older messages are minimized to reduce information overload. The latest message is usually the most important one.

A message.
When you send a physical letter through the mail you have to write an address on the outside center of the envelope for it to be deliverable (i.e. a destination address). You also write the name of a person or organization at that destination whom you authorize to open the letter (i.e. recipients). If the destination address is invalid, or your authorized recipients can’t be found there, then it is useful to include your own address on the outside top-left of the envelope so the letter can be sent back (i.e. a return address).
The delivery of email works in a similar way. With email, the writing on the envelope is replaced with information called headers. The most useful headers are displayed at the top of each message:
From: is the email address of the sender, and optionally their name.To: is a list of the primary recipients’ email addresses.Cc: is a list of carbon copy email addresses. These recipients are publicly declared to have received a copy of the message. Recipients who received a copy of the message in private would be included in the Bcc:, or blind carbon copy, list, but this header is not sent to each recipient for obvious reasons.Subject: is the current topic of conversation.Date: is the date and time that the message was sent. This is usually displayed in the local timezone of the sender since this information is helpful.You can also click the full headers link to view any additional headers associated with the message. This will often include information like spam scoring (X-Spam-Status:, X-Spam-Level:), routing and relay information (Received:), tools used to create the message (X-Mailer:), character encoding (Content-Type:), unique identifier (Message-ID:), and so on. These details are useful for troubleshooting and forensics, but they probably aren’t something you’ll need to look at for every message.
sender name
set organization
full headers
skip to bottom
Comments are private messages that only other workers can see.

Navigating to the setup page.
This tab provides access to branding, IP security, and updating your Cerb5 software license.
Two settings allow you to personalize your helpdesk branding.
There are two special helpdesk pages that do not require a login but should still be protected from abuse.
/cron is pinged from an automated script to execute time-based functionality. These scheduled tasks are defined in the Setup->Scheduler tab. This page can be accessed by an automated process that doesn’t need to log in, but it shouldn’t be freely accessible to anyone because it could be abused to create an unnecessary strain on your webserver and database; for example, by invoking hundreds of concurrent instances of the nightly maintenance task./update is invoked automatically when the application detects a new version has been installed. It is responsible for logging out users to ensure consistency, clearing caches, rebuilding templates, running database patches, and migrating data. Since this process is meant to occur when everyone is logged out, an authentication method other than a helpdesk account is required.Cerb5 uses IP-based security to protect both of these pages. You can authorize specific IP addresses for I.T. department machines, your corporate network subnet, intranet IPs, or webserver loopback IPs.
You can enter partial IPs to approve an entire subnet, such as:
If you authorize a loopback IP address (e.g. 127.0.0.1), you should use a command-line tool like wget or curl on the webserver to make requests for these pages. This is usually the preferred option, since /cron will usually be requested from a cronjob on the webserver, and /update is used in conjunction with upgrades to the helpdesk software (which are best handled with the git or svn command-line tools).
Without a product license your helpdesk will run in Evaluation Mode, which provides full functionality for a single seat. Purchasing a license will increase the number of seats, and it may also include a subscription to future software updates.
After ordering, you’ll receive a product license by email. It will look something like this:
Licensed to: Example, Inc.
Order email: a.smart.shopper@example.com
### BEGIN CERB5 LICENSE
Key: ABC1-DEF2-FED3-CBA4-ABC5
Created: 2010-05-12
Updated: 2011-02-01
Upgrades: 2012-02-01
Seats: 15
### END
To update your product license:
### BEGIN and ### END and paste it into the third text box.
Updating a Cerb5 license.
This tab provides access to enable and disable functionality provided in plugins. New plugins can be installed by dropping the folder containing the plugin you wish to install in storage/plugins directory, and then enabling them on this tab. Deleting a plugin is as simple as disabling it and removing the folder from the directory.

The storage tab in Setup.
One major benefit of working on Cerb5 for over 9 years is that we’ve been able to observe the long-term outcome of our technology decisions. It’s not uncommon for a popular helpdesk to have millions of tickets in the database after a few years. Most tickets have a conversation with several email messages, and occasionally those messages have file attachments.
Relational databases just aren’t designed for efficient document storage. If your email conversations average 10,000 characters in length (10KB) then you will require 1GB of storage for every 100,000 tickets in your database. Your email contents will take up around 10GB after you hit 1 million tickets. While it’s important to have fast access to historical ticket meta information for building worklists and running reports — such as sender, subject, status, group, bucket, owner, and last activity date — you rarely need fast access to message contents or attachments for tickets that have been closed for a considerable amount of time.
Even though the technology curve has storage capacity increasing while prices are decreasing, this type of usage would have a negative impact on the performance of your helpdesk:
There are several reasons why poorly-designed applications continue to bloat the database with heavy, immutable content:
In previous generations of Cerberus Helpdesk we also stored file attachments in the database. Based on our experience with scaling the project throughout the years, we now store attachments in the local storage/ filesystem where they can be handled more efficiently (note: message content is still stored in the database). Despite the advantages of this approach, there are still valid situations (like clustering) where the local filesystem is a source of constant inconveniences. System administrators have to rsync the storage/ filesystem around a cluster, or symlink the storage/ filesystem to a shared filesystem. In effect, we trade the inefficiencies of the database with new inefficiencies in scaling beyond a single webserver.
To provide a truly scalable and flexible solution, we designed the Devblocks Storage Service.
The Devblocks Storage Service automatically archives heavy content to long-term storage when it is deemed inactive, and it quickly unarchives inactive content if it becomes active again. The Storage Service can manage content from any functionality in the helpdesk, including third-party plugins. For example, while it’s great for efficiently managing a large number of file attachments or messages contents, it could also be used to manage driver downloads, a PDF document collection, or an image gallery.
Inactive content can be archived to one of three storage engines by default. A storage profile brings objects (e.g. attachments, message content) under Storage Engine management. Each storage object is given a unique storage key based on the storage engine. Additional storage engines and storage profiles can be added through plugins.
Disk: Content is stored in the local storage/ filesystem. Each storage profile receives its own subdirectory. Stored objects are hashed and distributed between 1,024 buckets — 32 directories with 32 subdirectories each. The 32 options represent the letters A through V, and the numbers 0 through 9. Each directory is a single character. Hash buckets look like storage/attachments/5/f and storage/messages/b/d. The storage key is the hash bucket and file record ID (e.g. 5/f/1000). There are no file extensions. This layout makes it easy to correlate filesystem files with database records irrespective of the hash buckets involved, simplifying maintenance and integrity checks.
Database: Content is stored in the database for situations where it makes sense. Each storage profile has its own database table. The storage key is the file record ID.
Amazon S3: Content is stored in Amazon’s Simple Storage Service (S3) through Amazon Web Services (AWS), which is distributed, redundant, scalable, secure, and durable. Each storage profile has its own virtual directory inside the designated S3 bucket. We chose to use a single S3 bucket per helpdesk so multiple storage objects for multiple helpdesks under the same management could share a single AWS account. Storage objects in S3 are stored with the same hash bucket approach as the Disk storage engine (1,024 hash buckets, 32 directories with 32 subdirectories each). The storage key is the hash bucket and file record ID.
The Storage System is also designed to be fast and fault-tolerant. You are free to configure the Storage System to save all attachments to Amazon S3 immediately, while saving all message content directly to the filesystem. All fresh content is written to either the disk or the database, since if the application is working they will always be available. This is more efficient than blocking the email parser while waiting for attachments to upload to a storage engine like Amazon S3. Once content is saved, it may then enter the queue to be moved to a remote storage engine.
(Explain how mail is routed into the helpdesk)
(Configuring POP3)
(Reply from; signatures)
(cerb5-plugins on GitHub)
Cerb5 accepts date entry in multiple formats:
If you don’t specify a time then the default is 00:00:00 (midnight at the start of the day). Dates are relative to your current timezone (defined in My Account), but they are always stored in the database as UTC/GMT.
When you’re doing a search with dates you should be sure to enter an explicit end time. The search “from today to tomorrow” will include anything that happened today (from 00:00:00 to 23:59:59). However, the search “from today to today” will likely return zero results because it’s looking for activity within the first second of today (from 00:00:00 to 00:00:00 inclusive).
It is often useful to use relative dates in mail filters and business rules, because setting a date (e.g. a due date) of “+2 hours” will always be 2 hours in the future regardless of the current time.
/cronspecial options (pop3 max, parse max, ignore wait, loglevel, etc)
Dual license?
Cerb5’s version numbers are in the format: <generation>.<release>.<update>
Therefore, a version of 5.4.2 means:
5.x)5.4.x)5.4.2)The next maintenance update is: 5.4.3
The next major release is: 5.5.0
The next generation is: 6.0.0
Two web server nodes; one database node
Install Cerb5 completely on one web node first (or outside of the cluster and move the database in)
Load balancer share sessions (cookies)
Memcached (share cache) — edit /etc/memcached.conf and make sure bind to internal IP — enable + copy MEMCACHED node list to all framework.config.php — make sure php5-memcache package (ext) is installed
rpcinfo -p: portmapper, nfs, nlockmgr, lockd)storage on slavesmount -o"rw,hard,intr,async,nosuid,nodev" host:/path/to/master/storage storage Wikipedia: Model-View-Controller (MVC)http://en.wikipedia.org/wiki/Model-View-Controller ↩
Wikipedia: Asynchronous Javascript and XML (Ajax)http://en.wikipedia.org/wiki/Ajax_(programming) ↩
Feature request: Community Tools should support HTTP authentication if the parent helpdesk is password protected.http://wgmdev.com/jira/browse/CHD-679 ↩
Wikipedia: Opcodehttp://en.wikipedia.org/wiki/Opcode ↩
PHP Manual: Alternative PHP Cache (APC)http://php.net/manual/en/book.apc.php ↩
Google: Segfaults caused by APC.http://www.google.com/search?q=apc+segfault ↩
Cerb5 forums: Cryptic errors on “Line 0” found to be caused by APC.http://forum.cerb4.com/showthread.php?t=3106&highlight=xcache ↩
MySQL Documentation: mysqlhotcopyhttp://dev.mysql.com/doc/refman/5.0/en/mysqlhotcopy.html ↩
Wikipedia: Githttp://en.wikipedia.org/wiki/Git_(software) ↩
Wikipedia: Subversionhttp://en.wikipedia.org/wiki/Subversion_(software) ↩
Wikipedia: Bayesian Spam Filteringhttp://en.wikipedia.org/wiki/Bayesian_spam_filtering ↩
Wikipedia: Extensible Markup Language (XML)http://en.wikipedia.org/wiki/XML ↩
Wikipedia: Access Control List (ACL)http://en.wikipedia.org/wiki/Access_control_list ↩
Wikipedia: Uniform Resource Identifier (URI)http://en.wikipedia.org/wiki/Uniform_Resource_Identifier ↩
Wikipedia: Coordinated Universal Timehttp://en.wikipedia.org/wiki/Coordinated_Universal_Time ↩