There’s a few other examples out there but I thought another clean one won’t hurt. This upstart script, runs as a privileged user and is placed in “/etc/init/”. It picks up your virtualenv settings because it invokes the python interpreter found in the “virtualenv/bin” directory. The actual django project basedir is in “/djangoapp/project” and the virtualenv is in “/djangoapp/”. See the ‘script’ stanza for syntactical composition.
# filename example: /etc/init/celeryworkers.conf
description "djangoapp - Celery Workers"
author "Me"

# Assuming a django app is related and wrapped in a uwsgi upstart script
# the worker daemons are now related/linked to that app.
start on started djangoapp
stop on stopping djangoapp

# Try respawn a few times in case of errors, then bug out.
respawn limit 20 5

# Time to wait between TERM and KILL signals (relate this to your task execution time)
kill timeout 30

# Some django ENV settings (settings file in settings dir)
env DJANGO_SETTINGS_MODULE=settings.settings
# Keep the logs clean
env PYTHONWARNINGS="ignore::DeprecationWarning:RemovedInDjango19Warning"

# Celery debug level. Can be: DEBUG, INFO, WARNING, ERROR, CRITICAL, or FATAL.

# Celery's specific app definition (django app folder is in a project/apps/djangoapp dir)
env APP=apps.djangoapp.celeryapp:app

post-start script
   echo "djangoapp - Celery workers started"
end script

# the actual djangoapp is in /djangoapp/project and the virtualenv is in /djangoapp
    cd /djangoapp/project
    exec su -c "/djangoapp/bin/python /djangoapp/bin/celery --app=${APP} worker --loglevel=${LOGLEVEL} --autoreload -E --concurrency=10"
end script
Hope it helps!