CloudCube (S3) in Django on Heroku

Have you ever wanted to have persistent storage for your Heroku app because ephemeral storage was just not cutting it?

Cloudcube is a storage addon that gives you an S3 bucket with a 5mb limit in the free tier. Fairly generous! This is great because by default Heroku apps are ephemeral (storage is deleted when a new version is deployed).


Install the add on for your Heroku app, or if you’re using Review apps then you’ll want to add "cloudcube:free" to your addons key in app.json:

  "addons": [


Make sure you install django-storages and boto3:

$ pip install django-storages boto3
# settings/
import os

# =============================================================================
# Cloudcube storage
# =============================================================================
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'

# example cloudcube url:
cloudcube_url = os.environ.get('CLOUDCUBE_URL')
cloudcube_bucket = os.path.basename(cloudcube_url)   # "bucketname"
cloudcube_base_url = os.path.dirname(cloudcube_url)  # "" 

AWS_S3_ENDPOINT_URL = cloudcube_base_url
AWS_STORAGE_BUCKET_NAME = cloudcube_bucket
AWS_DEFAULT_ACL = os.environ.get('AWS_DEFAULT_ACL', 'private')

We want everything by default to be private, so we’ve set the AWS_DEFAULT_ACL setting to "private". If we want to override this private setting, we can subclass S3Boto3Storage and change the setting.

For example, static file storage or user image uploads should be public. We’ll want to use a "public-read" setting.

Example demonstrating public and private styles:

# custom settings class in yourapp/
from import get_storage_class

class PublicStorage(get_storage_class()):
    default_acl = 'public-read'

class PrivateStorage(Storage):
    """When you call file.url using this storage, URLs are automatically appended with
    SAS (Signed Access Signature) parameters."""
    default_acl = 'private'
    secure_urls = True
    querystring_auth = True

# static files in settings/
STATICFILES_STORAGE = 'yourapp.storages.PublicStorage'

# image uploads in someapp/
from yourapp.storages import PublicStorage
class MyModel(models.Model):
    logo = models.ImageField(upload_to='logos', storage=PublicStorage())
    private_upload = models.FileField(upload_to='private', storage=PrivateStorage())

CloudCube interface


Thanks CloudCube folks for giving us free persistent storage! 5mb aint much, but it allows us to give our clients an easy place to upload small CSVs at least. If we need to test more, $5/mo for 5gb aint bad!

..although, it would be neat to have a $1/mo 100mb tier :)