Udacity Full Stack Web Developer Nanodegree Program
Project 5: Linux Server Configuration
Author: Aleksandr Zonis
In this project, I configured an Ubuntu Linux server instance on AWS and deployed a Flask app to the Apache server(Flask Catalog Application). The app is available at http://35.175.70.121.xip.io/.
The purpose of this project is to deploy a Flask (python) application on the Amazon Web Service(AWS) Lightsail platform, take a baseline installation of a Linux server and prepare it to host web applications. Secure server from a number of attack vectors, install and configure a database server, and deploy "Catalog Application" onto it.
Below you can find a computational narrative.
-
First, log in to Lightsail. If you don't already have an Amazon Web Services account, you'll be prompted to create one.
-
Once you're logged in, Lightsail will give you a friendly message with a robot on it, prompting you to create an instance. A Lightsail instance is a Linux server running on a virtual machine inside an Amazon data center.
-
For this project, you'll want a plain Ubuntu Linux image. There are two settings to make here. First, choose "OS Only" (rather than "Apps + OS"). Second, choose Ubuntu 16.04 as the operating system.
-
Choose your instance plan. (I picked the cheapest one, which was $3.50 at the moment)
-
Give your instance a hostname.
-
Click the 'Create' button.
-
Once the instance is running. Find 'Networking' and create Static IP address
-
To log into your instance you will need to download SSH key. Once you are on the instance page click on the 'Account' button. Find 'SSH Keys' and download 'Default key' with
.pem
extension to your local machine. -
Once the key is downloaded place it in
.ssh
file in your home directory, name it as you like. -
Change permissions to the key
chmod 400 ~/.ssh/{ default key }.pem
- Now you are ready to log in from your terminal
ssh -i ~/.ssh/{ default key }.pem ubuntu@{ ip address }
- Once you are logged in and in the Ubuntu terminal, update and upgrade Ubuntu
sudo apt-get update
sudo apt-get upgrade
- Create a new user
sudo adduser { username }
-
Give sudo access to user:
-
sudo cp /etc/sudoers.d/90-cloud-init-users /etc/sudoers.d/{ username }
-
sudo nano /etc/sudoers.d/{ username }
-
Change Ubuntu to { username } and save the file.
-
-
Go to username directory
cd /home/{ username }
- Create
.ssh
directory inside username
sudo mkdir .ssh
- Change user and group ownership of the .ssh folder
sudo chown { username }:{ username } .ssh
- Create 'authorized_keys' file
sudo touch .ssh/authorized_keys
- Change user and group ownership of 'authorized_keys' file
sudo chown { username }:{ username }
Once steps above are completed switch to your local machine terminal. We will generate a key pair for the new user.
- Generate a key
ssh-keygen
Save in the suggested directory, such as '/Users/< username >/.ssh/< keyname >'. You can give whatever name to the key you prefer. It will generate to two keys: and .pub
-
Copy and paste the pub key:
-
cat .ssh/<keyname>.pub
-
Copy the content of the public key
-
In the Ubuntu terminal open {username}/.ssh/authorized_keys file
sudo nano {username}/.ssh/authorized_keys
- Paste the content of the public key and save the file
-
-
Set permissions to
.ssh
and.ssh/authorized_keys
:-
sudo chmod 700 .ssh
-
sudo chmod 644 .ssh/authorized_keys
-
-
Allow to log in only with the key pair, not password:
-
sudo nano /etc/ssh/sshd_config
-
Find
PasswordAuthentication
change tono
-
-
You are ready to log in. On your local machine run:
ssh -i <keyname> { username }@{ IP address}
-
Add port 2200
- On Ubuntu terminal open
sshd_config
file:
sudo nano /etc/ssh/ssh_config
-
Find
Port 22
, don't delete it yet to avoid getting locked out. On the next line addPort 2200
-
Go to the Lightsail AWS instance. Find 'Networking'. Add port to the 'Firewall' table. Set Application to 'Custom', protocol to 'TCP', port to 2200
- On Ubuntu terminal open
-
Configure the Uncomplicated Firewall (UFW) to only allow incoming connections for SSH (port 2200), HTTP (port 80), and NTP (port 123).
-
sudo ufw default deny incoming
-
sudo ufw default allow outgoing
-
sudo ufw allow ssh
-
sudo ufw allow 2200
-
sudo ufw allow http
-
sudo ufw allow ntp
-
sudo ufw enable
-
Check if all configurations are set.
sudo ufw status
-
-
Change the SSH port from 22 to 2200.
- On your local machine try to log in using port 2200
ssh -i <keyname> { username }@{ IP address } -p 2200
-
If you logged in successfully. Then follow these steps:
- In
sshd_config
file deleteport 22
line and save the changes
sudo nano /etc/ssh/sshd_config
-
Go to the Lightsail AWS instance. Find 'Networking'. Delete Port 22 connection.
-
sudo ufw deny 22
-
Check is configurations are changed
sudo ufw status
- In
- Install Apache using your package manager with the following command, confirm that Apache is working by visiting your Public IP:
sudo apt-get install apache2
- Install mod_wsgi:
sudo apt-get install libapache2-mod-wsgi
- Delete the directory /var/www/html
sudo rm -rf /var/www/html
- Create the new directory
sudo mkdir /var/www/catalog
- Create a test file inside 'catalog' directory with the fig-a text, save the file:
sudo nano /var/www/catalog/catalog.wsgi
fig-a
def application(environ, start_response):
status = '200 OK'
output = 'Hello World!'
response_headers = [('Content-type', 'text/plain'), ('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]
- Go to Apache configuration files:
cd /etc/apache2/sites-available
- Copy default file
sudo cp 000-default.conf catalog.conf
-
Make changes to file.
sudo nano catalog.conf
- Change from
DocumentRoot /var/www/html
toDocumentRoot /var/www
- Before closing tag insert
WSGIScriptAlias / /var/www/catalog/catalog.wsgi
- Close and Save the file
-
Disable 000-default and enable catalog.conf, reload Apache after. Read about a2dissite/a2ensite commands.
sudo a2dissite 000-default.conf
sudo a2ensite catalog.conf
sudo service apache2 reload
-
Go to Public IP address, it should display 'Hello World' message.
DigitalOcean. "How To Deploy a Flask Application on an Ubuntu VPS" was a very helpful resource. I recommend trying to deploy a simple Flask application from this tutorial if you are doing it for the first time.
- Install Git.
sudo apt-get install git
-
Clone your application from the github:
-
cd /var/www/catalog
-
Clone your application inside new 'catalog' directory:
sudo git clone https://github.com/AlikZi/udacity-fullstack-catalog-project4.git catalog
-
-
Replace with the following lines of code to the 'catalog.wsgi' file:
#!/usr/bin/python
import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0,"/var/www/catalog/")
from catalog import app as application
application.secret_key = 'Add your secret key'
- Inside /var/www/catalog/catalog rename 'project.py' to 'init.py' and change the code in the bottom of the 'init.py' file to match:
if __name__ == "__main__":
app.run()
-
Create a virtual environment for our flask application inside /var/www/catalog/catalog:
- Install python and virtualenv
sudo apt-get install python-pip
sudo pip install virtualenv
- Run the following command, venv is the name for a temporary environment:
sudo virtualenv venv
- Activate the virtual environment:
source venv/bin/activate
- Install neccessary modules:
sudo pip install Flask sudo pip install httplib2 sudo pip install sqlalchemy sudo pip install oauth2client sudo pip install psycopg2
- Deactivate the virtual environment:
deactivate
-
Now your directory structure should look like this:
|--------catalog
|----------------catalog
|-----------------------static
|-----------------------templates
|-----------------------addproducts.py
|-----------------------database_setup.py
|-----------------------README.md
|-----------------------venv
|-----------------------__init__.py
|----------------catalog.wsgi
- Add (or replace) the following lines of code from fig-b to the file to configure the virtual host:
sudo nano /etc/apache2/sites-available/catalog.conf
fig-b
<VirtualHost *:80>
ServerName http://35.175.70.121.xip.io/
ServerAdmin zonis7@gmail.com
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>
- It should be already enabled, but just in case run:
sudo a2ensite catalog.conf
- For troubleshooting, check logs for errors:
sudo cat /var/log/apache2/error.log
sudo cat /var/log/apache2/access.log
- Create a new database user named catalog that has permissions to the Catalog Application database.
sudo apt-get install postgresql
sudo passwd postgres
su postgres
postgres~: psql
>> CREATE USER catalog;
CREATE ROLE
>> ALTER USER catalog WITH PASSWORD 'catalog';
ALTER ROLE;
>> CREATE DATABASE catalog WITH OWNER catalog;
CREATE DB
>> REVOKE ALL ON SCHEMA public FROM public;
>>GRANT ALL ON SCHEMA public TO catalog;
-
Quit psql.
-
As a super user make configurations for PostgreSQL instead of SQLite in files 'init.py', 'database_setup.py' and 'addproducts.py':
engine = create_engine("postgresql://{ DB user }:{ DB user password }@{ IP address }/{ DB name }")
or
engine = create_engine('postgresql://catalog:catalog@localhost/catalog')
- Reload Apache:
sudo service apache2 reload
- Change path to 'client_secrests.json' in the 'init.py' file to the relative path:
/var/www/catalog/catalog/client_secrets.json
-
To make sure Google Sign In is working you need to create new OAuth Client ID credentials.
-
Go to credentials section at https://console.cloud.google.com/apis/api
-
Create new Credential
-
Enter Authorized JavaScript origins. I entered my IP address with xip.io extension
http://35.175.70.121.xip.io/
- Enter Redirect URIs:
http://35.175.70.121.xip.io/ http://35.175.70.121.xip.io/login http://35.175.70.121.xip.io/gconnect http://35.175.70.121.xip.io/gdisconnect
-
Click 'Create Credential'
-
Download JSON
-
Copy content of the downloaded JSON client secrets and paste it into 'client_secrets.json' in the /var/www/catalog/catalog
-
-
To view your application, open your browser and navigate to the domain name or IP address that you entered in your virtual host configuration.
-
DigitalOcean. How To Install the Apache Web Server on Ubuntu 16.04
-
DigitalOcean. How To Configure the Apache Web Server on an Ubuntu or Debian VPS
-
DigitalOcean. How To Deploy a Flask Application on an Ubuntu VPS
-
Apache a2dissite/a2ensite commands
The contents of this repository are covered under the MIT license.