This is the last project of Udacity Full Stack Web Developer Nanodegree Program .
- Creation and installation of a linux server in the cloud environment.
 - Setting up of this server to host a web application.
 - Securing the server from a number of attack vectors.
 - Installation and configuration of a database server to serve the web application.
 - Deployment of the web application.
 
Application is live here
This project requires the student to create and set up linux server (e.g. Ubuntu) using the cloud services such as Google Cloud, Amazon AWS or DigitalOcean. The server should be then configured to host a web application while ensuring security, availability and accessibility of the server and the app. The server should:
- be initialized and available through a cloud environment.
 - be made secure and remotely accessible through 
SSH- using the public-private key pair authentication feature instead of typical password protection. - have an account for the user 
graderwithsudoprivileges. - let the user 
graderto log in to the server remotely throughSSHusing a public-private key pair authentication. - not allow remote logins for the root user.
 - allow the incoming network traffic only for 
SSHon port 2200,HTTPon port 80, andNTPon port 123. - enforce the key-based authentication for the SSH.
 - have all the packages up-to-date.
 - have a database server set up and running for the web application.
 - be set up to serve the Item Catalog Project as wsgi application.*
 
View more information about the project's requirements here.
I started initially with the Amazon Lightsail but soon found it somewhat restricting in terms of making the tweaks and availability of helpful resources. While Amazon EC2 provides somewhat more feature-rich and usable interface to set up, configure and run virtual machine or servers.
I created an Ubuntu 16.94 (Xenial) machine on EC2. These links (this guide and this tutorial proved quite helpful for setting up the instance.
IPv4 Public IP: 18.222.209.154
Public DNS (IPv4): ec2-18-222-209-154.us-east-2.compute.amazonaws.com
Accessible SSH Port: 2200
Application's URL: http://ec2-18-222-209-154.us-east-2.compute.amazonaws.com
- I used the Git SSH client and logged in using: 
ssh -i "FullPathToTheFile\PrivateKey.pem" ubuntu@18.222.209.154 
- Initially the instance was set up using the key-pair generated by the AWS services.
 - I created a new key-pair on my PC locally using the 
ssh-keygen. - Updated the key pair such that the private key resides on my PC while the newly generated public key replaces the contents of the current one for the 
ubuntuuser using:/home/ubuntu/.ssh/authorized_keys. - Logged out and logged back in using the new key-pair.
 
All the packages were updated using:
sudo apt-get updateand thensudo apt-get upgrade
- Added the user 
graderusing the commandsudo adduser grader - Created the 
/etc/sudoers.dentry for thegraderuser usingsudo nano /etc/sudoers.d/grader - Added the line 
grader ALL=(ALL) NOPASSWD:ALLto it - Set up SSH public key authorization for the user "grader" by following commands in order
mkdir /home/grader/.sshchown grader:grader /home/grader/.sshchmod 700 /home/grader/.sshcp /home/ubuntu/.ssh/authorized_keys /home/grader/.ssh/chown grader:grader /home/grader/.ssh/authorized_keyschmod 644 /home/grader/.ssh/authorized_keys
 - Logged out as 
ubuntuand login back asgraderusingssh -i "fullPathtoFile\LinuxServer.pem" grader@18.222.209.154 - Generated a separate key-pair for the user 
graderand replaced it with current version from/home/grader/.ssh/authorized_keys - Checked if there is any error in using 
sudofor thegraderuser. 
(P.S: You may or may not get the following warning: sudo: unable to resolve host "ip-SOME-IP". To fix this, the hostname was added to the loopback address in the /etc/hosts file so that the first line now reads: 127.0.0.1 localhost "ip-SOME-IP")
Updated the settings in /etc/ssh/sshd_config as follows:
sudo nano /etc/ssh/sshd_configto edit the file- modified the line 
PermitRootLogin prohibit-passwordtoPermitRootLogin no - uncommented the line 
AuthorizedKeysFile %h/.ssh/authorized_keys - ran 
ssh restartfor the changes to take effect 
Changed the port for SSH from 22 to 2200 in "/etc/ssh/sshd_config" as follows:
sudo nano /etc/ssh/sshd_configto edit- modify the line 
Port 22to `Port 2200 ssh restartfor the changes to take effect
(Note: After the Port change of the server, the "inbound rules" for the "security group" of the server also needs to be updated from the console / AWS Dashboard. Changes should be made as:
- for the rule's "Type" value, change it from "SSH" to "Custom TCP Rule"
 - change the value of "Port Range" from "22" to "2200"
 - this may or may not result in changing/update of Public IP & DNS
 - it's better option to reboot the server after this step)
 
Used following commands:
sudo ufw allow 2200/tcp
sudo ufw allow 80/tcp or use sudo ufw allow www
sudo ufw allow 123/udp
sudo ufw enable
sudo ufw status verbose
(Note: Similar changing need to be made again from the console's "security group" tab as in the above step for each of the added firewall rules)
Modified the time zone to UTC using sudo timedatectl set-timezone UTC
The NTP daemon was installed to continuously adjust the system clock so no large differences in time develop. Installed with:
sudo apt-get install ntp
Installed Apache server and relevant library using:
sudo apt-get install libapache2-mod-wsgi- Enabled mod_wsgi with 
sudo a2enmod wsgi - Started the web server with 
sudo service apache2 start sudo apt-get install apache2
Cloned the Item-Catalog-Project as www-user
- installed git: 
sudo apt-get install git - moved to srv: 
cd /srv - made the application directory: 
sudo mkdir sports-bazar sudo chown www-data:www-data sports-bazar/- sudo -u www-data git clone https://github.com/abdullah-22/Item-Catalog-Project.git sports-bazar
 
Installed the Postgresql database engine
sudo apt-get install postgresql- Checked if no remote connections are allowed by 
sudo cat /etc/postgresql/9.5/main/pg_hba.conf - Logged in as user "postgres" by 
sudo su - postgres - Got into postgreSQL shell by 
psqlCREATE USER sportsbazar WITH PASSWORD 'password';ALTER USER sportsbazar CREATEDB;CREATE DATABASE sportsbazar WITH OWNER sportsbazar;\c sportsbazarREVOKE ALL ON SCHEMA public FROM public;GRANT ALL ON SCHEMA public TO sportsbazar;\q
 exitthe postgres user
Created a new OAuth 2.0 client ID credentials for Google OUATH
- In Google Developer's consoloe
- set the javascript origin of the project to the IPv4 & Default DNS
 - set the redirect_uris to 
http://ec2-18-222-209-154.us-east-2.compute.amazonaws.com/gconnect 
 - downloaded the new credentials
 - updated the credentials in the project in 
g_client_secrets.json& in/templates/login.html - updated the 
g_client_secrets's path by appending/srv/pathto it in theauth.pyfile (where needed) - updated the URL for the database in 
app.py&db_setup.pytoDB_URL = "postgresql://sportsbazar:password@localhost/sportsbazar" 
- Add wsgi file as follows:
 cd /srv/sports-bazarsudo nano sportsbazar.wsgi- added the following script:
 
#!/usr/bin/env python
import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0, '/srv/sport-sbazar/')
import random
import string
from sportsbazar import app as application
from sportsbazar.db_setup import db_create
from sportsbazar.db_populate import db_populate
application.config['DB_URL'] = "postgresql://sportsbazar:password@localhost/sportsbazar"
# Secret key to secure session and cookies
secret_key = "".join(random.choice(string.ascii_uppercase + string.digits) for x in xrange(32))
application.secret_key = secret_key
# Credentials of admin
application.config['ADMIN_ID'] = 2
application.config['ADMIN_NAME'] = "Abdullah A. Salman"
application.config['ADMIN_EMAIL'] = "abdullahahmadsalman22@gmail.com"
db_create(application.config['DB_URL'])
db_populate()
Using the following:
sudo apt-get install python-psycopg2 python-flasksudo apt-get install python-sqlalchemy python-pipsudo pip install oauth2clientsudo pip install requestssudo pip install httplib2
Created the configuration  file as: sudo nano /etc/apache2/sites-available/sportsbazar.conf
Added the following script to it:
<VirtualHost *:80>
        ServerName 18.222.209.154
        ServerAlias ec2-18-222-209-154.us-east-2.compute.amazonaws.com
        ServerAdmin abdullahahmadsalman22@gmail.com
        # Define WSGI parameters. The daemon process runs as the www-data user.
        WSGIDaemonProcess sportsbazar user=www-data group=www-data threads=5
        WSGIProcessGroup sportsbazar
        WSGIApplicationGroup %{GLOBAL}
        # Define the location of the app's WSGI file
        WSGIScriptAlias / /srv/sports-bazar/sportsbazar.wsgi
        # Allow Apache to serve the WSGI app from the catalog app directory
        <Directory /srv/sports-bazar/>
                Require all granted
        </Directory>
        # Setup the static directory (contains CSS, Javascript, etc.)
        Alias /static /srv/sports-bazar/sportsbazar/static
        # Allow Apache to serve the files from the static directory
        <Directory  /srv/sports-bazar/sportsbazar/static/>
                Require all granted
        </Directory>
        ErrorLog ${APACHE_LOG_DIR}/error.log
        LogLevel warn
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Ran the following commands in order:
sudo a2dissite 000-default.confsudo a2ensite sportsbazar.confsudo service apache2 reload
Hurrah! Application is now up & running!
(stuck at someplace? found any error? or just want to connect? see below :))
Abdullah A. Salman