I have successfully set up my app to use S3 for storing all static and media files. However, I would like to upload to S3 (current operation), but serve from a cloudfront instance I have set up. I have tried adjusting settings to the cloudfront url but it does not work. How can I upload to S3 and serve from Cloudfront please?
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
DEFAULT_FILE_STORAGE = 'app.custom_storages.MediaStorage'
STATICFILES_STORAGE = 'app.custom_storages.StaticStorage'
STATICFILES_LOCATION = 'static'
MEDIAFILES_LOCATION = 'media'
STATIC_URL = "https://s3-eu-west-1.amazonaws.com/app/%s/" % (STATICFILES_LOCATION)
MEDIA_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, MEDIAFILES_LOCATION)
from django.conf import settings
from storages.backends.s3boto import S3BotoStorage
location = settings.STATICFILES_LOCATION
location = settings.MEDIAFILES_LOCATION
Your code is almost complete except you are not adding your cloudfront domain to STATIC_URL/MEDIA_URL and your custom storages.
In detail, you must first install the dependencies
pip install django-storages-redux boto
Add the required settings to your django settings file
INSTALLED_APPS = ( ... 'storages', ... ) AWS_STORAGE_BUCKET_NAME = 'mybucketname' AWS_CLOUDFRONT_DOMAIN = 'xxxxxxxx.cloudfront.net' AWS_ACCESS_KEY_ID = get_secret("AWS_ACCESS_KEY_ID") AWS_SECRET_ACCESS_KEY = get_secret("AWS_SECRET_ACCESS_KEY") MEDIAFILES_LOCATION = 'media' MEDIA_ROOT = '/%s/' % MEDIAFILES_LOCATION MEDIA_URL = '//%s/%s/' % (AWS_CLOUDFRONT_DOMAIN, MEDIAFILES_LOCATION) DEFAULT_FILE_STORAGE = 'app.custom_storages.MediaStorage' STATICFILES_LOCATION = 'static' STATIC_ROOT = '/%s/' % STATICFILES_LOCATION STATIC_URL = '//%s/%s/' % (AWS_CLOUDFRONT_DOMAIN, STATICFILES_LOCATION) STATICFILES_STORAGE = 'app.custom_storages.StaticStorage'
Your custom storages need some modification to present the cloudfront domain for the resources, instead of the S3 domain:
from django.conf import settings from storages.backends.s3boto import S3BotoStorage class StaticStorage(S3BotoStorage): """uploads to 'mybucket/static/', serves from 'cloudfront.net/static/'""" location = settings.STATICFILES_LOCATION def __init__(self, *args, **kwargs): kwargs['custom_domain'] = settings.AWS_CLOUDFRONT_DOMAIN super(StaticStorage, self).__init__(*args, **kwargs) class MediaStorage(S3BotoStorage): """uploads to 'mybucket/media/', serves from 'cloudfront.net/media/'""" location = settings.MEDIAFILES_LOCATION def __init__(self, *args, **kwargs): kwargs['custom_domain'] = settings.AWS_CLOUDFRONT_DOMAIN super(MediaStorage, self).__init__(*args, **kwargs)
And that is all you need, assuming your bucket and cloudfront domain are correctly linked and the user's AWS_ACCESS_KEY has access permissions to your bucket. Additionally, based on your use case, you may wish to make your s3 bucket items read-only accessible by everyone.