p2-insta485-serverside

AWS Tutorial

This tutorial will walk you through setting up AWS to deploy a web application.

In EECS 485, each team will deploy with one team member’s account. In other words, it’s not necessary for each team member create an AWS account.

You’ll create and configure one instance, and then reuse the same instance for each project. That means you’ll follow the create, launch and configure instructions once, and the deploy instructions multiple times.

Create an account

Create an AWS account at https://aws.amazon.com. You should be free tier eligible, which means that you will be able to run an instance for free for the duration of the course.

You will need a credit card on the account, even if you only use free tier resources. This is how Amazon charges, in case you request more resources than provided in the free tier. Do not launch any additional instances other than the one we specify in order to avoid additional charges.

Optionally, you may redeem extra benefits as a student, including $100 in AWS credits. https://aws.amazon.com/education/awseducate/.

Start instance

Navigate to the AWS Management Console. Select the “Services” dropdown menu, then “EC2”. An EC2 “instance” is a virtual machine running on Amazon AWS hardware.

Click launch an instance.

Select the “Ubuntu Server 20.04 LTS” Amazon Machine Image (AMI).

Select the “t2.micro” instance type. You should see “free tier eligible”. Click “Next”.

Click “Next”

Click “Next”

Click “Next”

Add a rule to allow both SSH and HTTP traffic in and out of your instance. Then, click “Review and Launch”.

Click “Launch”. Ignore a warning about “Improve your instances’ security”.

Create a key pair and download it. You’ll use this later to SSH into in the instance. Finally, click “Launch Instances”.

Click “View Instances”.

Instance status

Navigate to the AWS Management Console. Select the “Services” dropdown menu, then “EC2”.

Click “Instances”.

Select one of the instances and view its status and Public DNS.

SSH to instance

In this section, we’ll configure SSH access using the eecs485deploy.pem file generated in the Start instance section.

Copy or move your instance’s SSH key to your project directory and set the permissions to read-only. Notice the single r when showing the permissions with ls -l.

$ pwd
/Users/awdeorio/src/eecs485/p2-insta485-serverside
$ mv ~/Downloads/eecs485deploy.pem .
$ chmod 400 eecs485deploy.pem
$ ls -l eecs485deploy.pem 
-r-------- 1 awdeorio staff 1.7K May 12 15:55 eecs485deploy.pem

SSH into your instance. Replace ec2-54-86-86-246.compute-1.amazonaws.com with your Public DNS from the Instance status section.

$ ssh -i eecs485deploy.pem ubuntu@ec2-54-86-86-246.compute-1.amazonaws.com
...
ubuntu@ip-172-31-81-21:~$ 

Pitfall Make sure your instance is running. See Instance status.

Install Nginx

We’ll use Nginx to listen for HTTP requests and then proxy them (“pass them on”) to your Flask app Python code, which will run in a gunicorn server.

First, SSH into your instance.

Install Nginx.

$ sudo apt-get update
$ sudo apt-get install nginx

Verify that it’s working by navigating to your Public DNS in a web brower.

Configure Nginx

Optionally install your favorite editor make it the default for this login session by setting the $EDITOR environment variable. Vim should be installed already.

$ sudo apt-get install emacs-nox
$ export EDITOR=emacs

Edit /etc/nginx/sites-available/default. Note that sudoedit uses the default editor specified by the $EDITOR environment variable.

$ sudoedit /etc/nginx/sites-available/default

Modify /etc/nginx/sites-available/default. Replace the entire default server settings with the settings specified below. Save and exit.

server {
  listen 80;
  server_name <Public DNS (IPv4)>;

  location / {
    proxy_pass http://localhost:8000;
  }
}

Edit /etc/nginx/nginx.conf.

$ sudoedit /etc/nginx/nginx.conf

Modify one line in /etc/nginx/nginx.conf, uncomment the line saying, server_names_hash_bucket_size and change its value to 128. Save and exit.

server_names_hash_bucket_size 128;

Restart the nginx server.

$ sudo systemctl restart nginx

Install Flask app

Use these install instructions for every project.

First, SSH into your instance.

Make sure you have Python virtual environment tools installed.

$ sudo apt-get install python3-venv sqlite3

Clone your web app source code.

@ip-172-31-81-21:~$ pwd
/home/ubuntu
$ git clone https://gitlab.eecs.umich.edu/your/project/repo
$ cd p2-insta485-serverside/

Note: if your GitHub/Gitlab account has two-factor authentication enabled, you may need to create an SSH key on the AWS instance.

Install back end

Create a virtual environment.

$ pwd
/home/ubuntu/p2-insta485-serverside
$ python3 --version
Python 3.8.2
$ python3 -m venv env

Activate the virtual environment and install python package dependencies, including your project. Also, install gunicorn, which will be used for server deployment.

$ source env/bin/activate
$ pip install --upgrade pip setuptools wheel
$ pip install -e .
$ pip install gunicorn

Initialize database.

$ ./bin/insta485db create

Install front end

Skip this subsection if you’re not using JavaScript.

Install node and npm.

$ pip install nodeenv
$ nodeenv --python-virtualenv
$ source env/bin/activate  # again, after installing node

Install JavaScript packages, including obfuscator.

$ npm install .
$ node_modules/.bin/webpack
$ npm install javascript-obfuscator

Compile and obfuscate JavaScript.

$ node_modules/.bin/webpack
$ node_modules/.bin/javascript-obfuscator insta485/static/js/bundle.js
$ mv insta485/static/js/bundle-obfuscated.js insta485/static/js/bundle.js

Run server

Make sure that no old gunicorn processes are running.

$ pkill -f gunicorn
$ pgrep -af gunicorn
# no process should appear here!

Start gunicorn in the background (-D for daemon mode).

$ gunicorn -b localhost:8000 -w 2 -D insta485:app
$ pgrep -af gunicorn
17498 /home/ubuntu/p2-insta485-serverside/env/bin/python3 /home/ubuntu/p2-insta485-serverside/env/bin/gunicorn -b localhost:8000 -w 2 -D insta485:app
17500 /home/ubuntu/p2-insta485-serverside/env/bin/python3 /home/ubuntu/p2-insta485-serverside/env/bin/gunicorn -b localhost:8000 -w 2 -D insta485:app
17501 /home/ubuntu/p2-insta485-serverside/env/bin/python3 /home/ubuntu/p2-insta485-serverside/env/bin/gunicorn -b localhost:8000 -w 2 -D insta485:app

Pitfall If you’re having trouble, trying running Gunicorn in the foreground with debug messages enabled.

$ pkill -f gunicorn
$ gunicorn -b localhost:8000 -w 2 insta485:app --log-level debug

Browse to your Public DNS name (or refresh) and you should see your web app.

After successfully deploying, go back to the project spec and follow the deployment submission instructions. After submitting, be sure to kill your gunicorn process using pkill.

You may exit the ssh session with the exit command.

$ exit

Stop instance

To avoid using your AWS credits, shut down your instance when you’re done with it.

Check the status of your instance.

Right click on your instance -> “Instance State” -> “Stop”.

You should now see that your instance is stopped.