This is an easy and efficient way to get your Django application hosted on AWS for free. I documented these steps while deploying Contikey, an application to share articles between friends.
Note: This is NOT meant for production. Rather it is to quickly host an application on AWS such that it can be accessed without running it on your computer. For a more robust deployment, check this guide.
We will be using RDS to host our database. Create a MariaDB instance in the RDS console. Choose ap-southeast-1b as the Region.
In the navigation pane, launch a DB Instance and select MariaDB as the engine, with the most supported version (10.0.32).
Check the Publicly Accessible Box, and set Storage Size to 20GB. Choose Yes for Multi-AZ Deployment. Enter your DB name, DB instance identifier, master username and password. Leave the other settings as default.
Once the database is created, go to RDS Console > Parameter Groups > Create Parameter Group. Select MariaDB 10.0 as the parameter group family and give it a name and description. Select Create.
In Parameter Groups, select your newly created group and filter for the parameter ‘logbintrustfunctioncreators’. Select ‘Edit Parameters’ and set the value to 1.
Go back to RDS Console > Instances > YourInstance. In the Details pane, note your DB name, username, password, and host endpoint. Remember this for later.
Now to connect to the database, if you have a mysql client such as SequelPro or MySQLWorkbench you can simply input the DB name, username, password, port=3306 and host endpoint into the input fields.
Otherwise, on command line you can run
mysql -h <host endpoint> -P 3306 -u <username> -p <password>
Make sure you have MariaDB installed. Otherwise, run
sudo apt update -y
sudo apt install -y mariadb-server
Start the MariaDB service
sudo systemctl start mariadb.service
sudo systemctl enable mariadb.service
Secure the installation of MariaDB
sudo /usr/bin/mysql_secure_installation
Then login to the MySQL shell:
mysql -h <host endpoint> -P 3306 -u <username> -p <password>
You should then be inside the MariaDB monitor. Congrats you are connected to your database!
We will be using EC2 to host our application. Create an EC2 instance. Choose Ubuntu Server 16.04 LTS as the Amazon Machine Image. The free tier is good enough for our needs.
Under security group, make sure to open the ports for SSH (22) and HTTP (80)
Make sure to save the private key given by AWS (we will need it later to login to the server)
Before we configure our ssh settings, lets assign a IP to our AWS instance. By default, AWS will assign any available IP to the instance when it is started. The IP might change is shutdown and started again. We will associate an IP with the instance, which allows us to reserve the IP for that instance.
Go to EC2 Dashboard > Elastic IPs > Allocate new address > Allocate. You will now have a Elastic IP reserved for you use.
Go to Instances, click on your instance. Under Actions > Network > Associate Elastic IP address
At this point, if you have a domain registered you can also point the domain/subdomain to your Elastic IP. Check your domain registrar for more instructions. (I use Namecheap)
Before we connect to the server we need to configure the permission of the private key to prevent it being accessed by other users. Move the private key to the ~/.ssh
folder and execute the following command.
$ chmod 600 ~/.ssh/your_private_key
Now to connect to ur server. Go to your command line and type
$ ssh -i ~/.ssh/your_private_key ubuntu@your_elasticip
Alternatively create a file named config
in the ~/.ssh
folder and populate it with the following.
Host your_elastic_ip
Port 22
IndentityFile ~/.ssh/your_private_key
If you have a domain add another record for your domain.
Host your_domain
Port 22
IndentityFile ~/.ssh/your_private_key
Now you can $ ssh ubuntu@your_elasticip
or $ ssh ubuntu@your_domain
to connect to your server!
$ sudo apt update
$ sudo apt upgrade
Install python packages. virtualenv
is manage your python environments, while virtualenvwrapper
(optional) is a really convenient wrapper to easily setup virtual environments.
$ sudo apt install python-pip
$ sudo apt install python3-dev
$ sudo apt install libmysqlclient-dev
$ sudo pip install virtualenv virtualenvwrapper
Add the following lines to your ~/.bashrc
file
export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
And restart it
$ source ~/.bashrc
Now create ur virtualenv (assuming python3)
$ mkvirtualenv --python=/usr/bin/python3 your_app
We will now install the application and its dependencies
$ git clone your_app
$ cd your_app
$ pip install -r path/to/requirements/file
Test your server (make sure to change ur settings for your database to the one hosted on aws)
$ python manage.py runserver
We use nginx to route HTTP requests to our application
Install nginx
$ sudo apt install nginx
Configure nginx
$ sudo rm /etc/nginx/sites-enabled/default
$ sudo vim /etc/nginx/sites-available/your_app
Paste in the below. DNS name is either your elastic IP or the domain that points to your elastic IP.
server {
listen 80;
server_name your_dnsname_here;
location / {
proxy_pass http://127.0.0.1:8000;
}
}
If your backend application is communicating with a frontend application, you need to enable CORS headers for the domain of your frontend
server {
listen 80;
server_name your_dnsname_here;
location / {
set $cors '';
if ($http_origin ~ '^https?://(localhost|www\.<domain>\.com|<domain>\.com)') {
set $cors 'true';
}
if ($cors = 'true') {
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
# add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Mo fied-Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always;
# required to be able to read Authorization header in frontend
#add_header 'Access-Control-Expose-Headers' 'Authorization' always;
}
proxy_pass http://127.0.0.1:8000;
}
}
$ sudo ln -s /etc/nginx/sites-available/your_app/etc/nginx/sites-enabled/
$ sudo nginx -t
$ sudo systemctl restart nginx
Install gunicorn and run application (Make sure wsgi.py file is serving your production database)
$ pip install guincorn
$ gunicorn your_app.wsgi:application - bind 127.0.0.1
If you visit your Elastic IP/domain you should now see your application running!
However this requires you to be connected to the server to run it. To solve, this we use tmux
. Tmux is a package which turns your command line into a terminal. However, the feature we will be using today is the ability of it to run sessions. It allows you leave a session running that you can detach from, but the session will still continue executing its tasks. This allows you to easily spin up servers/execute long running tasks (eg. running a ML model). Cntrl-C
to stop the application that is running and open up tmux
$ tmux
$ gunicorn your_app.wsgi:application - bind 127.0.0.1
<Cntrl-B d>
And you are done! The application is running the same way as before, but you can log out of your server and the application will still be running.
If you ever want to attach back to the tmux session:
tmux attach -t <session>
Check out more commands for tmux here
If your application needs to be updated, attach to your tmux session, stop the application, pull the changes, restart the application. Not perfect, but it works!