Udacity FSND Project5
Goals of the project given by our instructors from Udacity:
You will take a baseline installation of a Linux distribution on a virtual machine and prepare it to host your web applications, to include installing updates, securing it from a number of attack vectors and installing/configuring web and database servers.
The application meant to be deployed is the Restaurant-Menu-App, previously developed for Project 3. (See 'Deployment Branch')
IP address: 52.25.246.88
Accessible SSH port: 2200.
Application URL: http://ec2-52-25-246-88.us-west-2.compute.amazonaws.com/.
- create an EC2 instance: use Ubuntu Server 14.04 LTS (HVM), SSD Volume Type and launch it
- by default, the instance's security group will provide a SSH port 22
- copy the public IP address for future use. (52.25.246.88)
- Log into the remote VM as root user through ssh:
$ ssh [email protected]
. - Add a new user called udacity:
$ sudo adduser udacity
. - Create a new file under the suoders directory:
$ sudo nano /etc/sudoers.d/udacity
. Fill that newly created file with the following line of text: "udacity ALL=(ALL:ALL) ALL", then save it.
$ sudo apt-get update
.$ sudo apt-get upgrade
.- Install finger, a utility software to check users' status:
$ apt-get install finger
.
- Open time configuration dialog and set it to UTC with:
$ sudo dpkg-reconfigure tzdata
. - Install ntp daemon ntpd for a better synchronization of the server's time over the network connection:
$ sudo apt-get install ntp
.
Source: UbuntuTime.
- Generate an encryption key on remote machine with:
$ ssh-keygen -f /home/udacity/.ssh/udacity_key.rsa
. - keep the public key udacity_key.pub in the same path and rename it to authorized_keys.
Then change some permissions:
$ sudo chmod 700 /home/udacity/.ssh
.$ sudo chmod 644 /home/udacity/.ssh/authorized_keys
.- Finally change the owner from root to udacity:
$ sudo chown -R udacity:udacity /home/udacity/.ssh
.
- copy the private key udacity_key.rsa to local machine and use puttygen.exe(in Windows) transfer it into ppk for putty use.
- Now you are able to log into the remote VM through ssh by using putty with the generated private key udacity_key.ppk
$ sudo nano /etc/ssh/sshd_config
. Find the PasswordAuthentication line and edit it to no.$ sudo service ssh restart
.
$ sudo nano /etc/ssh/sshd_config
. Find the Port line and edit it to 2200.$ sudo service ssh restart
.- add 2200 as the inbound custom TCP Rule port in AWS EC2 used Security Group.
- Now you are able to log into the remote VM through ssh by using putty with udacity_key.ppk and port 2200.
Source: Ubuntu forums.
$ sudo nano /etc/ssh/sshd_config
. Find the PermitRootLogin line and edit it to no.$ sudo service ssh restart
.
Source: Askubuntu.
Project requirements need the server to only allow incoming connections for SSH (port 2200), HTTP (port 80), and NTP (port 123).
$ sudo ufw allow 2200/tcp
.$ sudo ufw allow 80/tcp
.$ sudo ufw allow 123/udp
.$ sudo ufw enable
.- also add these 3 rules as Security Group inbound rules of AWS EC2
Install fail2ban in order to mitigate brute force attacks by users and bots alike.
$ sudo apt-get update
.$ sudo apt-get install fail2ban
.- We need the sendmail package to send the alerts to the admin user:
$ sudo apt-get install sendmail
. - Create a file to safely customize the fail2ban functionality:
$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
. - Open the jail.local and edit it:
$ sudo nano /etc/fail2ban/jail.local
. Set the destemail field to admin user's email address.
Notes: It doesn't make much sense to use fail2ban when the ssh key-based authentication is enforced. Though it is still useful for other things, like smtp/imap-logins.
Sources: DigitalOcean, Reddit.
- Install unattended-upgrades if not already installed:
$ sudo apt-get install unattended-upgrades
. - To enable it, do:
$ sudo dpkg-reconfigure --priority=low unattended-upgrades
.
$ sudo apt-get install apache2
.- Mod_wsgi is an Apache HTTP server mod that enables Apache to serve Flask applications. Install mod_wsgi with the following command:
$ sudo apt-get install libapache2-mod-wsgi python-dev
. - Enable mod_wsgi:
$ sudo a2enmod wsgi
. $ sudo service apache2 start
.
$ sudo apt-get install git
.- Configure your username:
$ git config --global user.name <username>
. - Configure your email:
$ git config --global user.email <email>
.
- Install pip, the tool for installing Python packages:
$ sudo apt-get install python-pip
. - If virtualenv is not installed, use pip to install it using the following command:
$ sudo pip install virtualenv
. - Move to the catalog folder:
$ cd /var/www/catalog
. Then create a new virtual environment with the following command:$ sudo virtualenv venv
. - Activate the virtual environment:
$ source venv/bin/activate
. - Change permissions to the virtual environment folder:
$ sudo chmod -R 777 venv
. - Install Flask:
$ pip install Flask
. - Install all the other project's dependencies: `$ pip install bleach httplib2 request oauth2client sqlalchemy'
- Install python-psycopg2:
$ sudo apt-get install python-psycopg2
.
Sources: DigitalOcean, Dabapps.
How To Deploy a Flask Application on an Ubuntu VPS
$ cd /var/www
. Then:$ sudo mkdir catalog
.- Change owner for the catalog folder:
$ sudo chown -R udacity:udacity catalog
. - Move inside that newly created folder:
$ cd /catalog
and clone the catalog repository from Github:$ git clone https://github.com/Mayer5/Restaurant-Menu-App catalog
. - create a catalog.wsgi file in '/var/www/catalog/' folder to serve the application over the mod_wsgi. That file should look like this:
import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0, "/var/www/catalog/")
from catalog import app as application
- Some tweaks were needed to deploay the Restaurant-Menu-App, so I made a deployment branch which slightly differs from the master. Move inside the repository,
$ cd /var/www/catalog/catalog
and change branch with:$ git checkout deployment
.
Notes: the .git folder will be inaccessible from the web without any particular setting. The only directory that can be listed in the browser will be the static folder: static assets.
- Create a virtual host conifg file:
$ sudo nano /etc/apache2/sites-available/catalog.conf
. - Paste in the following lines of code:
<VirtualHost *:80>
ServerName 52.25.246.88
ServerAlias ec2-52-25-246-88.us-west-2.compute.amazonaws.com
ServerAdmin [email protected]
WSGIDaemonProcess catalog python-path=/var/www/catalog:/var/www/catalog/venv/lib/python2.7/site-packages
WSGIProcessGroup catalog
WSGIScriptAlias / /var/www/catalog/catalog.wsgi
<Directory /var/www/catalog/catalog/>
Order allow,deny
Allow from all
</Directory>
Alias /static /var/www/catalog/catalog/static
<Directory /var/www/catalog/catalog/static/>
Order allow,deny
Allow from all
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
- The WSGIDaemonProcess line specifies what Python to use and can save you from a big headache. In this case we are explicitly saying to use the virtual environment and its packages to run the application.
- Enable the new virtual host:
$ sudo a2ensite catalog
.
Source: DigitalOcean.
- Install some necessary Python packages for working with PostgreSQL:
$ sudo apt-get install libpq-dev python-dev
. - Install PostgreSQL:
$ sudo apt-get install postgresql postgresql-contrib
. - Postgres is automatically creating a new user during its installation, whose name is 'postgres'. That is a tusted user who can access the database software. So let's change the user with:
$ sudo su - postgres
, then connect to the database system with$ psql
. - Create a new user called 'catalog' with his password:
# CREATE USER catalog WITH PASSWORD 'sillypassword';
. - Give catalog user the CREATEDB capability:
# ALTER USER catalog CREATEDB;
. - Create the 'catalog' database owned by catalog user:
# CREATE DATABASE catalog WITH OWNER catalog;
. - Connect to the database:
# \c catalog
. - Revoke all rights:
# REVOKE ALL ON SCHEMA public FROM public;
. - Lock down the permissions to only let catalog role create tables:
# GRANT ALL ON SCHEMA public TO catalog;
. - Log out from PostgreSQL:
# \q
. Then return to the udacity user:$ exit
. - Inside the Flask application, the database connection is now performed with:
engine = create_engine('postgresql://catalog:sillypassword@localhost/catalog')
- Setup the database with:
$ python /var/www/catalog/catalog/database_setup.py
. - Add data into the database with
$ python /var/www/catalog/catalog/initial_the_database.py
. - To prevent potential attacks from the outer world we double check that no remote connections to the database are allowed. Open the following file:
$ sudo nano /etc/postgresql/9.3/main/pg_hba.conf
and edit it, if necessary, to make it look like this:
local all postgres peer
local all all peer
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
Source: DigitalOcean.
$ sudo apt-get update
.$ sudo apt-get install glances
.- To start this system monitor program just type this from the command line:
$ glances
. - Type
$ glances -h
to know more about this program's options.
Source: eHowStuff.
- Go to the project on the Developer Console: https://console.developers.google.com/project
- Navigate to APIs & Auth > Credentials > Edit Settings
- add the hostname and piblic IP address to the Authorized JavaScript origins and host name + 'oauth2callback' to Authorized redirect URIs, e.g 'http://ec2-52-25-246-88.us-west-2.compute.amazonaws.com/oauth2callback'
$ sudo service apache2 restart
.
Note: If getting an internal server erroe, check the Apache error files:
Source: A2 Hosting
$ sudo tail -20 /var/log/apache2/error.log
is a good help for debugging
Special Thanks to iliketomatoes and stueken who wrote really helpful documents.