This documents explains how to deploy your Python Flask application
- Deploying system requires Linux virtual machine. I used AWS Lightsail., but you can also use Aws EC2, or DigitalOcean
 - public link is http://3.85.37.79/
 - domain name:
 
- AWS lightsail
 - Python Flask and WSGI
 - Apache2
 - Ubuntu 18.04
 - creating database by Postgress SQL
 
- Go to AWSLightSail and create an OS Only Ubuntu 18.04 instance.
 - Select the lowest priced plan option (for this project), identify your instance and create.
 - Download SSH key in your local machine. Name of the file is LightsailDefaultKey-us-east-1.pem
 - use connect, then Linux Machine will start
 - When you enter the virtual machine terminal , write the following command to start to update and upgrade all missing packages and security   
Sudo apt-get updateandsudo apt-get upgrade 
- this allows you to connect your virtual machine by your local machine Terminal or FTTP program
 - Go to your AWS account and select SSH keys
 - Create .ssh folder in your local machine terminal by 
mkdir .ssh. if you cannot trysudo mkdir .ssh. - Download the default file, it woul be name like this LightsailDefaultKey-us-east-1.pem
 - Save the file in your .ssh folder.
 - Restric file permission by running chmod 600 LightsailDefaultPrivateKey-*.pem
 - Change the file name to aws.rsa.
 - To connect run in your terminal 
ssh -i ~/.ssh/aws.rsa ubuntu@34.201.105.57 
- Run in your terminal 
sudo nano /etc/ssh/sshd_configeditetc/ssh/sshd_configfile. - Edit the file changing 22 to 2200 in the 5th line.
 - Save by 
ctrl+Sand exit from nano withctrl+X - Restart SSH with 
sudo service ssh restart 
- it is important to add new countom port on AWS manage page under the NETWORKING tab
 
| Custom | TCP | 2200 |
| Custom | TCP | 5000 |
| Custom | TCP | 8000 |
| Custom | udp | 123 |
sudo ufw statusThe UFW should be inactive.sudo ufw default deny incomingDeny any incoming traffic.sudo ufw default deny outgoingEnable outgoing traffic.udo ufw allow 2200/tcp # Allow incomingtcp packets on port 2200.sudo ufw allow 80/tcp# Allow HTTP traffic in.sudo ufw allow 123/udp# Allow incoming udp packets on port 123.sudo ufw deny 22# Deny tcp and udp packets**sudo ufw enableThe output should be like this Command may disrupt existing ssh connections. Proceed with operation (y|n)? y Firewall is active and enabled on system startupsudo ufw status Status. check the port- Your output should like this
 
To                         Action      From
--                         ------      ----
Apache                     ALLOW       Anywhere                  
22/tcp                     ALLOW       Anywhere                  
2200/tcp                   ALLOW       Anywhere                  
123/udp                    ALLOW       Anywhere                  
80/tcp                     ALLOW       Anywhere                  
22                         DENY        Anywhere                  
2200                       ALLOW       Anywhere                  
Apache (v6)                ALLOW       Anywhere (v6)             
22/tcp (v6)                ALLOW       Anywhere (v6)             
2200/tcp (v6)              ALLOW       Anywhere (v6)             
123/udp (v6)               ALLOW       Anywhere (v6)             
80/tcp (v6)                ALLOW       Anywhere (v6)             
22 (v6)                    DENY        Anywhere (v6)             
2200 (v6)                  ALLOW       Anywhere (v6)             
- Install finger to manage user by 
sudo apt-get install finger - to create user 
sudo adduser grader - Set password and details for user.
 - check grader by 
finger grader - Set the password and fill out info.
 - Grant sudo access 
sudo visudo - Add the following line after root 
ALL=(ALL:ALL) ALL: grader ALL=(ALL:ALL) ALL- Save and close the file.
 - check the sudo permissioon by 
sudo -l 
Matching Defaults entries for grader on ip-172-2X-14-XX:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User grader may run the following commands on ip-172-2X-14-XX:
    (ALL : ALL) ALL
    (ALL : ALL) ALL
- open your terminal on your local machine
 - Create keys 
ssh-keygen - Choose a location for the tow files 
~/.ssh/authorized_keys - Open the file and copy the content 
sudo nano .ssh/authorized_keys - In the grader account, create the following directories:
 sudo mkdir .ssh-cd .sshsudo nano authorized_keys- Paste the public key into authorized_keys file. Save and close.
 - Grant permissions
 
sudo chmod 700 .ssh
sudo chmod 644 .ssh/authorized_keys
Close terminal sesssion and check grader account to test connectty
ssh -i ~/.ssh/grader grader@34.201.105.57 -p 2200
Install Apache2 & WSGI packagesudo apt-get install apache2sudo apt-get install libapache2-mod-wsgi- Enable mod_wsgi: 
sudo a2enmod wsgi sudo service apache2 start- Verify apache2 Ubuntu Default Page.
 
- Install software 
sudo apt-get install postgresql - Setting up ubuntu role:
 - Switch to root user:
 sudo -u postgres psql- alter user postgres with password 'password';
 - Create role
 create role catalog superuser;- create database catalog
 - Create role catalog;
 - Allow catalog role to create a db:
 alter role catalog CREATEDB;- Create catalog database
 create database catalog- Exit psql:
 \q- change engine of database both application python file and creating database file in ypur python script 
engine = create_engine('postgresql://catalog:password@localhost/catalog') 
- Install GIT 
sudo apt-get install git - Create directory to save project cd /var/www 
sudo mkdir webApp - create one more directory in cd /var/www/webApp 
sudo mkdir webApptotally you should create 2 directory under the www foldersudo chown -R grader:grader webApp - cd webApp/webApp
 - git clone https://github.com/user/project.git
 - rename the app.py file by   
sudo mv app.py __init__py 
- Install the follwoing dependencies: (for python2)
 sudo -H apt-get install python-pipsudo -H pip install flasksudo -H pip install flask sqlalchemysudo -H pip install --upgrade google-api-python-client oauth2clientsudo -H pip install requestssudo -H pip install psycopg2-binary.- if you install python3 your code should continue 
sudo -H pip3 install flask 
- Configure Apache to handle requests using the WSGI module. there is already default set file in 
/etc/apache2/sites-enabled/000-default.conf.but we need to create new one - Lets create a new file with:
sudo nano /etc/apache2/sites-enabled/webApp.conf 
The /etc/apache2/sites-enabled/webApp.conf should now look like this:
<VirtualHost *:80>
                ServerName XX.XXX.XXX
                ServerAdmin email@gmail.com
                WSGIScriptAlias / /var/www/webApp/webapp.wsgi
                <Directory /var/www/webApp/webApp/>
                        Order allow,deny
                        Allow from all
                </Directory>
                Alias /static /var/www/webApp/webApp/static
                <Directory /var/www/webApp/webApp/static/>
                        Order allow,deny
                        Allow from all
                </Directory>
                ErrorLog ${APACHE_LOG_DIR}/error.log
                LogLevel warn
                CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
- Enable the virtual host with the following command:
 - Reload Apache with
 sudo service apache2 reload.- Enable the virtual Host 
sudo a2ensite webApp 
- Create and config the .wsgi file 
sudo nano /var/www/webApp/webapp.wsgi - Add the following content
 
import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0,"/var/www/webApp/")
sys.path.insert(0,"/var/www/webApp/webApp")
from webApp import app as application
application.secret_key = 'xxxxxx'
- run your script to check any bugs before serving. 
python webapp.wsgi - if there is a missing package use 
sudo -H pip XXXX sudo service apache2 restart
- if you have port 500 error please run 
sudo tail /var/log/apache2/error.logandsudo tail -100 /var/log/apache2/access.logand check the errors - dont forget the change JSON file location in your script
 - Google Authorization need valid domain name, xip.io extension of domain name is not accepted after 2020
 - You can access the logs of the application on the apache logs, they are located, by default, on 
/var/log/apache2/access.logor/var/log/apache2/error.logfor errors.You'll need sudo access to read the files. 
`
- How to Deploy a Flask App to a Linux Server
 - How To Deploy a Flask Application on an Ubuntu VPS
 - 20 Basic Ubuntu Commands And Terminal Shortcuts Every Beginner Must Know
 - https://aws.amazon.com/premiumsupport/knowledge-center/ec2-linux-fix-permission-denied-errors/
 - https://aws.amazon.com/premiumsupport/knowledge-center/ec2-server-refused-our-key/
 - error handling
 - public and private key handling
 - Linux cheat sheet
 - Go to the Support Web Site
 - How To View Apache Access & Error Logs