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).
Heroku
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": [
"cloudcube:free"
],
}
Django/Python
Make sure you install django-storages
and boto3
:
$ pip install django-storages boto3
# settings/base.py
import os
# =============================================================================
# Cloudcube storage
# =============================================================================
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
# example cloudcube url: https://cloud-cube.s3.amazonaws.com/bucketname
cloudcube_url = os.environ.get('CLOUDCUBE_URL')
cloudcube_bucket = os.path.basename(cloudcube_url) # "bucketname"
cloudcube_base_url = os.path.dirname(cloudcube_url) # "https://cloud-cube.s3.amazonaws.com/"
AWS_S3_ENDPOINT_URL = cloudcube_base_url
AWS_ACCESS_KEY_ID = os.environ.get('CLOUDCUBE_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.environ.get('CLOUDCUBE_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = cloudcube_bucket
AWS_DEFAULT_ACL = os.environ.get('AWS_DEFAULT_ACL', 'private')
AWS_QUERYSTRING_AUTH = False
AWS_S3_SIGNATURE_VERSION = "s3v4"
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/storages.py
from django.core.files.storage 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/base.py
STATICFILES_STORAGE = 'yourapp.storages.PublicStorage'
# image uploads in someapp/models.py
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
Conclusion
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 :)