This is a two part post which will guide you to host your own django app in a production environment using Amazon Web Services (AWS) for storing static files and Heroku for hosting the project.
This part will cover the storing of static files in AWS S3 Bucket.
AWS Setup
1. Create an AWS Account here.
2. Create a new S3 Bucket
- Navigate to S3 from here.
- Click
Create Bucket
. - Create a unique bucket name.
- Select region according to your Primary user’s location. For reference, see: AWS Regions and Endpoints.
- Keep other settings as the default ones and create the bucket.
3. Create credentials for AWS User
- Navigate to IAM Users.
- Select
Create New Users
- Enter the username.
- Ensure
Programmatic Access
is selected and hitNext
. - Select
Download credentials
and keep thecredentials.csv
file safe as it will be required later.
4. Add policies to your IAM user
Default policies
- Navigate to IAM Home.
- Select user and click on
Permissions
tab. - Click on
Attach Existing Policies Directly
and add any policies as per your requirement.
Custom Policies
- Navigate to IAM Home.
- Select user and click on
Permissions
tab. - Click on
Attach Existing Policies Directly
and selectCreate Policy
. - Go to the
JSON
tab and paste the policy given below. Change all<your_bucket_name>
to the name of your bucket in S3 (set above). Do not change version date.{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:ListAllMyBuckets" ], "Resource": "arn:aws:s3:::*" }, { "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetBucketLocation", "s3:ListBucketMultipartUploads", "s3:ListBucketVersions" ], "Resource": "arn:aws:s3:::<your_bucket_name>" }, { "Effect": "Allow", "Action": [ "s3:*Object*", "s3:ListMultipartUploadParts", "s3:AbortMultipartUpload" ], "Resource": "arn:aws:s3:::<your_bucket_name>/*" } ] }
- The Actions that we choose to set are based on what we want this user to be able to do. The line
"s3:*Object*"
, will handle a lot of our permissions for handling objects for the specified bucket within the Recourse Value.
Django Setup
1. Install requirements
boto and boto3 are python bindings for AWS. django-storages are used by django to send static files to AWS.
$ pip install boto boto3 django-storages
2. Update settings and migrate
- Add the app
storages
to theINSTALLED_APPS
insettings.py
INSTALLED_APPS = [ ... 'storages', ... ]
- Run migrations
$ python manage.py migrate
3. Set up the AWS module
- Create
aws
module in same directory assettings.py
$ pwd /path/to/<your-project>/<main-app>/ $ ls __init__.py settings.py wsgi.py urls.py $ mkdir aws && cd aws $ touch __init__.py $ touch utils.py $ touch conf.py
- In
utils.py
add the followingfrom storages.backends.s3boto3 import S3Boto3Storage StaticRootS3BotoStorage = lambda: S3Boto3Storage(location='static') MediaRootS3BotoStorage = lambda: S3Boto3Storage(location='media')
- Fetch the
Access Key Id
andSecret Access Key
fromcredentials.csv
downloaded earlier. Then inconf.py
add the followingimport datetime AWS_ACCESS_KEY_ID = "<your_access_key_id>" AWS_SECRET_ACCESS_KEY = "<your_secret_access_key>" AWS_FILE_EXPIRE = 200 AWS_PRELOAD_METADATA = True AWS_QUERYSTRING_AUTH = True DEFAULT_FILE_STORAGE = '<your-project>.aws.utils.MediaRootS3BotoStorage' STATICFILES_STORAGE = '<your-project>.aws.utils.StaticRootS3BotoStorage' AWS_STORAGE_BUCKET_NAME = '<your_bucket_name>' S3DIRECT_REGION = 'us-west-2' S3_URL = '//%s.s3.amazonaws.com/' % AWS_STORAGE_BUCKET_NAME MEDIA_URL = '//%s.s3.amazonaws.com/media/' % AWS_STORAGE_BUCKET_NAME MEDIA_ROOT = MEDIA_URL STATIC_URL = S3_URL + 'static/' ADMIN_MEDIA_PREFIX = STATIC_URL + 'admin/' two_months = datetime.timedelta(days=61) date_two_months_later = datetime.date.today() + two_months expires = date_two_months_later.strftime("%A, %d %B %Y 20:00:00 GMT") AWS_HEADERS = { 'Expires': expires, 'Cache-Control': 'max-age=%d' % (int(two_months.total_seconds()), ), }
4. Update settings.py
from <your-project>.aws.conf import *
5. Push the static files to S3 Bucket
$ python manage.py collectstatic
Note
- Any existing media files (before the AWS setup) cannot be uploaded to the bucket automatically, they have to be manually uploaded either from AWS website, Django admin or through aws-cli. For cli, see: AWS CLI Setup
Once AWS has been setup, all media files will be directly uploaded to AWS bucket. - For testing, to disable the AWS upload and use local static files, comment out
from <your-project>.aws.conf import *
from settings.py