A project to set up a Linux server. Item Catalog web application runs live on Amazon Lightsail secure web server. A baseline installation of a Linux distribution on a virtual machine is taken and prepared to host the web application, installing updates, securing it from a number of attack vectors and installing/configuring web and database servers.
The item catalog is a RESTful web application that displays an item catalog allowing the user to login and add, manage items they add. It interacts with a sqlite database using SQLAlchemy, an Object-Relational Mapping (ORM) layer. The CRUD (create, read, update and delete) operations and web page templates are handled using Python Flask framework. OAuth 2.0 framework allows users to securely login to the application using Google+ Sign-In or Facebook Login so users can create items that are viewable by everyone but only modifiable by the original creator. This application also provides a JSON endpoint.
AWS URL: http://ec2-52-26-30-44.us-west-2.compute.amazonaws.com
Raw IP: 52.26.30.44
SSH port: 2200
JSON Endpoint: http://52.26.30.44/catalog/JSON
- Download the AWS provided default private key to the local machine
- Change the private key file permission not to be accessible by others
chmod 600 LightsailDefaultPrivateKey-us-west-2.pem
- Logged in, ssh successful
ssh ubuntu@52.26.30.44 -p 22 -i ~/Downloads/LightsailDefaultPrivateKey-us-west-2.pem
- Updates the list of available packages and versions for upgrade
sudo apt-get update
- Installs newer versions of the packages
sudo apt-get upgrade
- Upon logging in, status shows 0 packages can be updated.
- Create new user grader
sudo adduser grader
- Give grader the permission to sudo
sudo touch /etc/sudoers.d/grader
- Check if grader file was added in sudoers directory
sudo ls /etc/sudoers.d
- Edit the file grader to add the sudo access
sudo nano /etc/sudoers.d/grader
. grader ALL=(ALL) NOPASSWD:ALL
. Save changes(Ctrl+X, Ctrl+Y, Enter)
- On the local machine terminal, generate key pair using
ssh-keygen
, providing passphrase - Named it linuxServerConfig.pub
- Save the private key in
~/.ssh
on local machine - On the server instance i.e virtual machine:
su - grader mkdir .ssh touch .ssh/authorized_keys nano .ssh/authorized_keys Copy the public key content from local machine to this file and save, change the access level chmod 700 .ssh chmod 644 .ssh/authorized_keys
- Configure the Lightsail firewall in AWS console to allow port 2200 ssh connections
- Make changes in the config file in the server from port 22 to 2200
sudo nano /etc/ssh/sshd_config
- Restart SSH
sudo service ssh restart
- Configure the Lightsail firewall in AWS console to allow incoming conections into ports HTTP (port 80), and NTP (port 123)
- Configure the Uncomplicated Firewall (UFW) to only allow incoming connections for SSH (port 2200), HTTP (port 80), and NTP (port 123)
sudo ufw allow 2200/tcp sudo ufw allow www sudo ufw allow 123/udp sudo ufw deny 22 sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw enable sudo ufw status
- SSH into grader using the key on 2200 port
ssh grader@52.26.30.44 -p 2200 -i ~/.ssh/linuxServerConfig
SSH to the server
- Check current timezone setting
sudo cat /etc/timezone
- Configure the local timezone to UTC
sudo dpkg-reconfigure tzdata
- Install mod_wsgi package(although using python3, this serves well without causing errors)
sudo apt-get install libapache2-mod-wsgi
- Install Apache
sudo apt-get install apache2
- Once done http://52.26.30.44 serves the default apache page
sudo apt-get install postgresql
-
Test switching to postgres user
sudo su - postgres psql \q exit
-
Do not allow remote connections Whether remote connections are allowed to be made to the database is controlled in the pg_hba.conf file. The default is to only allow connections from localhost
sudo ls /etc/postgresql/9.5/main sudo cat /etc/postgresql/9.5/main/pg_hba.conf sudo service apache2 restart
-
Create a new database user named catalog that has limited permissions to catalog application database
sudo su - postgres CREATE USER catalog WITH PASSWORD 'catalog'; \du CREATE DATABASE catalog; \l
-
Create the FlaskApp, cloning the git repository
cd /var/www sudo mkdir FlaskApp cd FlaskApp sudo git clone https://github.com/sarithk/ItemCatalog.git tree sudo apt install tree tree
-
Since my GitHub did not have the client_secrets.json and fb_client_secrets.json, create the files and copy the contents in them
sudo nano client_secrets.json
sudo nano fb_client_secrets.json
-
Make changes for the app in Google API Console and Facebook app to accept the lightsail public IP, URL and redirect URIs. Edit both secret files on server to reflect the changes if any
-
Edit the python files to reflect the correct postgresql database connection - username, password, DBname
sudo nano projectFinal.py
sudo nano DatabaseSetup.py.py
change engine = create_engine('sqlite:///itemcatalog.db') to engine = create_engine('postgresql://catalog:catalog@localhost/catalog') -
Rename projectFinal.py to init.py using
sudo mv projectFinal.py __init__.py
Setting up a virtual environment will keep the application and its dependencies isolated from the main system. Changes to it will not affect the cloud server's system configurations.
sudo apt-get install python-pip
sudo pip install virtualenv
sudo virtualenv venv
source venv/bin/activate
sudo pip install Flask
pip install httplib2
sudo apt-get install python3-oauth2client
sudo apt-get install python3-requests
sudo apt-get install python-requests
sudo apt-get install python3-sqlalchemy
sudo apt-get python3-psycopg2
sudo python __init__.py
sudo nano /etc/apache2/sites-available/FlaskApp.conf
<VirtualHost *:80>
ServerName 52.26.30.44
ServerAdmin sarithakamath24@gmail.com
WSGIScriptAlias / /var/www/FlaskApp/flaskapp.wsgi
<Directory /var/www/FlaskApp/ItemCatalog/>
Order allow,deny
Allow from all
</Directory>
Alias /static /var/www/FlaskApp/ItemCatalog/static
<Directory /var/www/FlaskApp/ItemCatalog/static/>
Order allow,deny
Allow from all
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
sudo a2ensite FlaskApp
cd /var/www/FlaskApp
sudo nano flaskapp.wsgi
Add the following lines of code to the flaskapp.wsgi file
#!/usr/bin/python3
import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0,"/var/www/ItemCatalog/")
from FlaskApp import app as application
application.secret_key = 'super_secret_key'
sudo service apache2 restart
Check error log for errors if any, features not working: sudo cat /var/log/apache2/error.log
Run database setup file: sudo python3 /var/www/FlaskApp/ItemCatalog/DatabaseSetup.py
Connect to database using : \c catalog
\dt
Update test data: sudo nano /var/www/FlaskApp/ItemCatalog/TestDataUpload.py
Run the file: sudo python3 TestDataUpload.py
Update data from the website as well
Change the reference to DatabaseSetup file import relative to the path that was added in the WSGI file i.e ItemCatalog.DatabaseSetup
Change the file references for client_secrets to reflect the full path i.e /var/www/FlaskApp/ItemCatalog/client_secrets.json
CLIENT_ID = json.loads(open(r'/var/www/ItemCatalog/client_secrets.json', 'r').read())['web']['client_id']
Fix import errors by installing the modules for python3 using apt-get
Disable the default apache2 site
sudo a2dissite 000-default
service apache2 restart
Make sure the correct app details reflect in the client_secrets files and the coresponding redirect settings in the app consoles.
Since the python files have PEP8 formatting, make sure there is no space or newline in URL construction to the API calls