Fixing graphite-api on Ubuntu 20.04

graphite-api is a lightweight frontend for graphite-carbon timeseries database, which enables grafana to access carbon’s data. I install graphite-api from Ubuntu repository, and by default it runs on The issue is grafana accesses this directly, meaning you access it from your browser, so graphite-api needs to listen on not on localhost. Also, at the moment of writing this post, graphite-api fails to start because of a change in Python 3.8.

Fixing bind address

The configuration file is /etc/default/graphite-api, but it says:

# This file is not used when using systemd.
# Use "systemctl edit graphite-api" instead.

and this is the case. If you do what it writes here, systemctl edit graphite-api, then what do you write ? You can check the default configuration options on default systemd files under /lib/systemd/system, there are two files: graphite-api.service and graphite-api.socket. graphite-api.service is where gunicorn3 is started but it does not mention any bind parameters. graphite-api.socket has this option among others:


so that is what should be changed. However, if you do systemctl edit graphite-api and create an override.conf to override this, it does not work. Because ListenStream is an option of graphite-api.socket not graphite-api.service. So you have to run systemctl edit graphite-api.socket and create an override for that instead.

However, after doing that, it gives an error. The issue is the ListenStream option you thought you overwrote actually by adding options so you did not re-set it. In order to do that, it should be first set to empty, like this:


and then issue a restart, and now it binds to .

Fixing findCaller

If you are using python3.8, probably graphite-api will fail to start. This is because python3.8 has changed the findCaller signature, and the structlog library used by graphite-api is not updated (yet, at the moment of this post). So I modified the /usr/lib/python3/dist-packages/structlog/ file and changed the findCaller signature and added stacklevel=1 argument.

def findCaller(self, stack_info=False, stacklevel=1):