(Version 0.9.15) Tutorial related to the installation and configuration of Graphite on an Ubuntu 16.04 virtual machine. Note that these instructions follow the “Install using pip” process from the documentation in an attempt to avoid dependency issues among Python packages (although as seen in the instructions, some versions are specifically required in order for the setup to function on the Ubuntu system).

Dependencies

Install the required dependencies:

$ sudo apt-get update
$ sudo apt-get install -y python-pip \
                          python-dev \
                          apache2 \
                          libcairo2-dev \
                          libapache2-mod-wsgi \
                          memcached \
                          libffi-dev \
                          libfontconfig1-dev \
                          libfreetype6-dev
$ sudo -E pip install "cffi>=1.8.3" \
                      "django==1.6" \
                      "django-tagging<0.4" \
                      service_identity \
                      pytz \
                      enum34 \
                      fontconfig \
                      python-memcached \
                      cairocffi

Process

Installation/Configuration

Install the respective components using pip and the version(s) desired. Note that these instructions function for the 0.9.15 release and are not guaranteed to function with later releases/versions:

# whisper - places files in /usr/local/bin, /usr/local/lib
$ sudo -E pip install whisper==0.9.15

# carbon - places files in /opt/graphite
$ sudo -E pip install carbon==0.9.15

# graphite-web - places files in /opt/graphite
$ sudo -E pip install graphite-web==0.9.15

# set up environment settings
$ export PATH=/opt/graphite/bin:$PATH

Create the Graphite group and user:

$ sudo -E groupadd _graphite
$ sudo -E useradd -c "User for graphite" -g _graphite -s /dev/null _graphite

Create the configuration (default) files:

# carbon config
$ cd /opt/graphite/conf
$ sudo cp carbon.conf.example carbon.conf
# update the following configuration parameter in the carbon.conf file
# ensures it does not run as superuser, and increases the max updates/sec
#   USER = _graphite
#   MAX_UPDATES_PER_SECOND = 800

# whisper config
$ cd /opt/graphite/conf
$ sudo cp storage-schemas.conf.example storage-schemas.conf
# update the storage-schemas.conf file to ensure the following are included
#   ...
#   [default_10s1d_60s30d_15m455d]
#   pattern = .*
#   retentions = 10s:1d,60s:30d,15m:455d
#   xFilesFactor = 0.0
#   ...

# graphite web config
$ cd /opt/graphite/conf
$ sudo cp graphite.wsgi.example graphite.wsgi
$ cd /opt/graphite/webapp/graphite
$ sudo cp local_settings.py.example local_settings.py
# update the local_settings.py file to uncomment and update the following, respective to your environment
# these settings will ensure that the date/time is set correctly, memcache is known and a secret is defined
#   SECRET_KEY = 'super_secret_key'
#   TIME_ZONE = 'America/New_York'
#   MEMCACHE_HOSTS = ['127.0.0.1:11211']

Perform the database migration for graphite-web:

$ sudo -E PYTHONPATH=/opt/graphite/webapp django-admin.py syncdb --settings=graphite.settings --noinput

Configure permissions for the various users:

$ sudo -E chown www-data:www-data /opt/graphite/storage/graphite.db
$ sudo -E mkdir -p /opt/graphite/storage/log/carbon-cache
$ sudo -E mkdir -p /opt/graphite/storage/log/carbon-relay
$ sudo -E mkdir -p /opt/graphite/storage/log/carbon-aggregator
$ sudo -E chown -R _graphite:_graphite /opt/graphite/storage/log
$ sudo -E chmod 775 /opt/graphite/storage
$ sudo -E chown -R _graphite /opt/graphite/storage/whisper
$ sudo -E chown www-data:_graphite /opt/graphite/storage
$ sudo -E chown www-data:_graphite /opt/graphite/conf/graphite.wsgi
$ sudo -E chown -R www-data /opt/graphite/storage/log/webapp

Configure the Apache instance for the Graphite Web application:

$ sudo cp /opt/graphite/examples/example-graphite-vhost.conf /etc/apache2/sites-available/graphite-webapp.conf
# edit the file to ensure the following are adjusted - most other defaults are sufficient
# ...
#   WSGISocketPrefix /var/run/apache2/wsgi
# ...
#   <Location "/content/">
#     SetHandler None
#     Require all granted
#   </Location>
#
#   ...
#
#   <Directory /opt/graphite/conf/>
#     Require all granted
#   </Directory>
# ...

Disable the default site and enable the Graphite Web application:

# disable the default site
$ sudo -E a2dissite 000-default

# enable the graphite-web application
$ sudo -E a2ensite graphite-webapp

Start the Carbon Cache daemon and ensure it is running:

$ sudo -E /opt/graphite/bin/carbon-cache.py start
# to check the status of the carbon-cache daemon:
$ sudo -E /opt/graphite/bin/carbon-cache.py status
#   carbon-cache (instance a) is running with pid 15812

Restart (or start) Apache for enabling graphite-web:

$ sudo -E service apache2 restart

Optional - Service Script

It is entirely possible to use the Graphite setup above via the bin/ directory scripts. However, it is likely a better idea to have a service/init script - there is an example script inside the examples/ directory of the Graphite folder that can be used as a starting point:

$ sudo cp /opt/graphite/examples/init.d/carbon-cache /etc/init.d/
$ sudo chmod 755 /etc/init.d/carbon-cache
$ sudo vim /etc/init.d/carbon-cache
# You will likely need to replace any occurrence of "echo_success" or "echo_failure" with
# "echo 'success'" and "echo 'failure'", respectively, or write a custom function of your choosing.
# In addition, if you wish to define/use multiple cache instances, in the "start", "stop" and "status" functions,
# there is a for loop that iterates over each "INSTANCES" instance - one of the first conditions checks if
# "${INSTANCE}" == "${CARBON_DAEMON}" and, if true, sets "INSTANCE="a"" - change the content of this entire "IF"
# condition in each start/stop/status function to simply read "continue" - this will ensure that the "[cache]"
# section of the carbon.conf (default globals when defining multiple cache instances) is not considered cache
# instance "a", causing confusing errors during the service management.

Once you have completed the above, the Graphite/Carbon-Cache instances can be managed via the following command(s):

# start the Carbon Cache instance(s)
$ sudo service carbon-cache start

# check the status of the Carbon Cache instance(s)
$ sudo service carbon-cache status

# stop the Carbon Cache instance(s)
$ sudo service carbon-cache stop

Validation

Ensure the carbon process is running/listening on correct ports:

$ cat /opt/graphite/storage/carbon-cache-a.pid
# 15182
$ pgrep -fa carbon
# 15812 /usr/bin/python /opt/graphite/bin/carbon-cache.py start
$ netstat -vant | grep LISTEN | grep '[27]00'
# tcp        0      0 0.0.0.0:2003            0.0.0.0:*               LISTEN
# tcp        0      0 0.0.0.0:2004            0.0.0.0:*               LISTEN
# tcp        0      0 0.0.0.0:7002            0.0.0.0:*               LISTEN

Ensure that data is being collected for the carbon host:

$ /usr/local/bin/whisper-fetch.py /opt/graphite/storage/whisper/carbon/agents/devbox-1/cpuUsage.swp
# should output a list of metrics like so:
#   1471861740       0.012192
#   1471861800       0.011875
#   1471861860       0.013435

Send some new data and validate the data for the carbon cache:

# send a metric "test.metric.foo" with value 2 at current time to local port 2003
$ echo "test.something.foo 2 `date +%s`" | nc localhost 2003
# check to ensure that the metric shows up
$ /usr/local/bin/whisper-fetch.py /opt/graphite/storage/whisper/test/something/foo.wsp
# should output a bunch of metrics for time series, including value sent above

Credit

Contributions to some of the above were gleaned from: