How to Configure a Linux Server to deploy a Flask App using Amazon Lightsail

How to Configure a Linux Server to deploy a Flask App using Amazon Lightsail

Posted by

In this tutorial, you will learn how to configure a Linux Server to host your Flask App. We will use Amazon Lightsail to get a Linux Server. You will take a baseline installation of a Linux distribution on a virtual machine and prepare it to host your web applications, including installing updates, securing it from a number of attack vectors, and installing/configuring web and database servers

This is part of a project that was required for the Udacity Full Stack Nano Degree Program.

Required

  1. Knowledge of some basic Linux Commands
  2. A terminal, I prefer git bash
  3. A flask app ready to be deployed

How to configure your Linux Server

Get a server from AWS Lightsaild

  1. Go to Amazon LightSail
  2. Create an account/sign in to your existing account
  3. Click Create an instance and choose Linux/Unix,OS only and Ubuntu 16.04LTS
Lightsail Instance Settings for Linux
Screenshot of Linux Configuration

4. Choose the cheapest Plan (3.5 USD/month). It is free for the first month so if you finish this tutorial within a month, you can delete the instance and won’t have to pay a dime unless you want to keep the instance.

5. Give the instance a host name. I have given mine Item-Catalog (Udacity Project’s name). Feel free to chose any name.

Linux Instance Cost Plans
Linux Instance Cost Plans

6. Click Create and wait a few minutes for it to start up

7. After a few seconds, the instance should be up and running.

Now, we can move on to trying to ssh into our newly created Linux machine.

SSH into the Linux Machine

  1. Go to your account and click on SSH Keys. Download the default key for your instance. The file name will be similar to LightsailDefaultKey-eu-central-1.pem For this tutorial, I’ll download the private key for the first instance.

2. In the terminal Navigate to the downloaded file’s directory and restrict file permission by typing 

chmod 600 LightsailDefaultPrivateKey-*.pem

This is your private key, do not share with anybody.

3. Rename the file to lightsail_key.rsa for easy use.

4. SSH into your instance by typing the following (Change IP address accordingly)

ssh -i lightsail_key.rsa ubuntu@3.121.206.97

If successful, you should see the screen below

You are now logged in as ‘ubuntu’ in your instance.

Secure your Linux Instance

Update all currently installed packages

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get update && sudo apt-get dist-upgrad

Change the SSH port from 22 to 2200

  1. Edit the sshd_config file by typing: sudo nano /etc/ssh/sshd_config
  2. Search for the port number and change it from 22 to 2200. It will be near line 5.
  3. Restart SSH connection with sudo service ssh restart

Configure the Uncomplicated Firewalll (UFW)

We should only allow incoming connections for SSH (port 2200), HTTP (port 80), and NTP (port 123).

First check the current ufw status, it should be inactive

sudo ufw status

Deny all incoming request 

sudo ufw default deny incoming

Allow all outgoing requests 

sudo ufw default allow outgoing

Allow the required incoming requests:

  • to allow ssh requests
sudo ufw allow 2200/tcp
  • to allow http requests
sudo ufw allow 80/tcp
  • to allow ntp requests
sudo ufw allow 123/udp 
  •  to deny requests from port 22
sudo ufw deny 22

Finally enable ufw and set it’s status to active

sudo ufw enable

Check the status

sudo ufw status

It should look something like this

Status: active

    To                         Action      From
    --                         ------      ----
    2200/tcp                   ALLOW       Anywhere
    80/tcp                     ALLOW       Anywhere
    123/udp                    ALLOW       Anywhere
    22                         DENY        Anywhere
    2200/tcp (v6)              ALLOW       Anywhere (v6)
    80/tcp (v6)                ALLOW       Anywhere (v6)
    123/udp (v6)               ALLOW       Anywhere (v6)
    22 (v6)                    DENY        Anywhere (v6)

12. Edit the rules accordingly in Networking in your lightsail account

You’ve secured your server and configure the firewall for proper functioning

If you are viewing this article to complete the final project in the Udacity Full Stack Nanodegree, follow the next steps else you may skip it and move on to ‘Prepare to Deploy your project’. You can follow the next steps if you want to create a new user.

Give Grader Access

  1. Create a new user account named grader
sudo adduser grader

2. Give grader the permission to sudo

sudo nano /etc/sudoers.d/grader

3. Type the following line grader ALL=(ALL:ALL) ALL

4. Create an SSH key pair for grader using the ssh-keygen tool. In your local machine, start up git bash and type ssh-keygen. Set a file directory and passphrase and view the contents of the .pub file using the cat command. Copy the content.

sudo cat ~/.ssh/test.pub
  1. log in as grader and create a folder ssh in home directory. mkdir .ssh
  2. Create a file authorized_keys touch .ssh/authorized_keys
  3. Paste the content into the file and save it. sudo nano .ssh/authorized_keys
  4. Restrict file permissions
chmod 700 .ssh
chmod 644 .ssh/authorized_keys

5. To disable password based login/ disable root login:

sudo nano /etc/ssh/sshd_config

Search for password based authentication and change it to no Search for PermitRootLogin and change the value to no. Restart the server.

sudo service ssh restart 

You should now be able to log in with your private key and passphrase.

6. exit and ssh -i ~/.ssh/grader -p 2200 grader@3.121.206.97\

You’ve created a new user, given them sudo access and created a SSH key pair for them

Prepare to deploy your project.

Configure the local timezone to UTC

  1. sudo dpkg-reconfigure tzdata Choose your timezone

Install Apache to serve a Python mod_wsgi application

  1. Install Apache sudo apt-get install apache2 Check your public IP and it should display the default Apache web page.
  2. sudo apt-get install python-setuptools libapache2-mod-wsgi Install python mod-wgsi module

Install and Configure PostgreSql

  1. Type sudo apt-get install postgresql to install postgresql
  2. Log in as postgres sudo su - postgres
  3. Enter psql shell by typing psql
  4. Type the following Commands in the shell. I have named my database and user Catalog, you can name something else.
CREATE DATABASE Catalog;
CREATE USER Catalog;
ALTER ROLE catalog WITH PASSWORD 'grader';
GRANT ALL PRIVILEGES ON DATABASE catalog TO catalog;

Quit the shell \q

Exit postgres by typing exit

Install Git

  1. Type sudo apt-get install git to install git
  2. Configure Email Id and Username:
  3. git config --global user.name <username>
  4. git config --global user.email <email>
  5. change directory to /var/www cd /var/www
  6. Create a new folder. sudo mkdir catalogApp . This is where you’ll store your flask application and the .wsgi file.
  7. cd into the folder cd catalogApp

Clone and setup the project

  1. clone the required repo sudo git clone https://github.com/rahulbanerjee26/Item-Catalog.git Rename file to catalogApp or flaskApp. I am naming it catalogApp.
  2. Go into the repo using cd and rename app.py to __init__.py

sudo mv app.py __init__.py . Apache only recognizes __init__.py

3. In __init__.py and databaseSetup.py files, remove the sqlite connection and connect to postgresql database. engine = create_engine('postgresql://catalog:password@localhost/catalog')

Create and Configure a New Virtual Host

  1. sudo apt-get install python-virtualenv to install the virtual environment
  2. cd into your repo and type sudo virtualenv -p python3 venv3
  3. sudo chown -R grader:grader venv3/ to change permission
  4. . venv3/bin/activate to activate the environment
  5. Install Flask and other dependencies as neede
  6. sudo apt-get install python-pip
  7. sudo pip install Flask
  8. sudo pip install sqlalchemy oauth2client httplib2 requests
  9. sudo apt-get install postgresql libpq-dev postgresql-client postgresql-client-common
  10. deactivate
  11. sudo nano /etc/apache2/sites-available/catalogApp.conf
  12. Add the following code in catalogApp.conf file. Change IP address, directories, DNS as required.
<VirtualHost *:80>
        ServerName 3.121.206.97
        ServerAlias http://ec2-3-121-206-97.eu-central-1.compute.amazonaws.com/
        ServerAdmin banerjeer2611@gmail.com
        WSGIScriptAlias / /var/www/catalogApp/catalogapp.wsgi
        <Directory /var/www/catalogApp/catalogApp/>
                Order allow,deny
                Allow from all
        </Directory>
        Alias /static /var/www/catalogApp/catalogApp/static
        <Directory /var/www/catalogApp/catalogApp/static/>
                Order allow,deny
                Allow from all
        </Directory>
        ErrorLog ${APACHE_LOG_DIR}/error.log
        LogLevel warn
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost> 

13. You can use this link find the DNS of your IP address to add the value for ServerAlias

14. sudo a2ensite catalogApp.conf

15. Setup the dataBase sudo python databaseSetup.py

16. Reload apache2 sudo service apache2 reload

Create .wgsi file

  1. sudo nano /var/www/catalogApp/catalogapp.wsgi
  2. Paste the following and save the file:
activate_this = '/var/www/catalogApp/catalogApp/venv3/bin/activate_this.py'
with open(activate_this) as file_:
    exec(file_.read(), dict(__file__=activate_this))    #!/usr/bin/python
    import sys
    import logging
    logging.basicConfig(stream=sys.stderr)
    sys.path.insert(0,"/var/www/catalogApp")
    from catalogApp import app as application
    application.secret_key = 'my_secret_key'

3. Go to __init__.py and change the path of the client_secrets.json from relative to absolute if necessary.

4. Run sudo service apache2 restart

5. If you get an error, sudo tail /var/log/apache2/error.log to view the error log.

If you go to your public IP, you’ll be able to view your flask application.

Congratulations 👏 👏 👏 👏

You’ve successfully deployed your application

Common Commands

If you make any changes in the .config file, you’ll need to restart the server 

sudo service ssh restart

 to reload apache

sudo service apache2 reload

to restart apache

sudo service apache2 restart 

to read files

sudo cat fileDestination 

to write into files

sudo nano fileDestination 

to view error logs

sudo tail /var/log/apache2/error.log

the directory of your repo

/var/www/catalogApp/catalogApp

the directory where your virtual host config file

/etc/apache2/sites-available/catalogApp.conf

the directory of your .wsgi file.

/var/www/catalogApp/catalogapp.wsgi

Resources

  1. https://www.fullstackpython.com/blog/postgresql-python-3-psycopg2-ubuntu-1604.html
  2. https://www.digitalocean.com/community/tutorials/how-to-deploy-a-flask-application-on-an-ubuntu-vps