Search code examples
djangoamazon-web-servicesamazon-s3boto3python-django-storages

Django + AWS s3 can upload files but not access them


Following this tutorial I set up our system to use Amazons S3 file storage using boto3 and Django-storages. I ran the collectstatic command and it worked just fine, the files show up in the AWS Management Console. But when running the server locally (runserver) all static files are missing. Looking at the console there are the error messages

GET https://BUCKET.s3.eu-central-1.amazonaws.com/static/admin/css/nav_sidebar.css net::ERR_ABORTED 403 (Forbidden)

for each of the files. The url looks right to me, the upload worked fine, but apparently the access doesn't work. Does this have something to do with my config in AWS? Or is this a Django settings issue?

The settings file looks like this:

STATICFILES_DIRS = []
AWS_ACCESS_KEY_ID = 'XYZ'
AWS_SECRET_ACCESS_KEY = 'XYZ'
AWS_STORAGE_BUCKET_NAME = 'BUCKET'
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME

AWS_S3_OBJECT_PARAMETERS = {
    'CacheControl': 'max-age=86400',
}

AWS_STATIC_LOCATION = 'static'
STATICFILES_STORAGE = 'hq.storage_backends.StaticStorage'
STATIC_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, AWS_STATIC_LOCATION)

AWS_MEDIA_LOCATION = 'media'
DEFAULT_FILE_STORAGE = 'hq.storage_backends.MediaStorage'


Solution

  • make sure the bucket policy is public (and files are publicly accessible), if it is you might try to run runserver --insecure, don't use it in production though obviously if files are not publicly accessible you might try setting AWS_DEFAULT_ACL='public-read' and run collect static again to make them public

    I'd suggest using environ to alter this settings something like

    import environ
    
    ...
    
    AWS_DEFAULT_ACL = env('AWS_DEFAULT_ACL')
    

    in your settings.py or where ever you store the settings to s3 bucket And use env vars to alter that upon need

    So after installing and setting up environ you can easily change that using env variables be simply setting AWS_DEFAULT_ACL to public-read like export AWS_DEFAULT_ACL=public-read