Linux Server Configuration

Get a web application running live on a secure web server.

Access information

Name Value
IP Address 35.159.31.11
SSH Port 2200
URL http://ec2-35-159-31-11.eu-central-1.compute.amazonaws.com

Summary of software and configuration

Performing basic configuration

1. Launch your Virtual Machine and log in

I accessed the EC2 instance using SSH with the following command:

ssh -i .ssh/LightsailDefaultKey-eu-central-1.pem ubuntu@35.159.31.11

2. Create a new user named grader and grant this user sudo permissions

Created a new user named grader using the following command:

sudo adduser grader

Followed the instructions in command line and added a secure password. After that I granted sudo permissions to grader user (described in User management).

3. Update all currently installed packages

Updated all currently installed applications:

sudo apt-get update
sudo apt-get upgrade

In order to install packages kept back I run:

sudo apt-get update && sudo apt-get dist-upgrade

And setup Python environment:

sudo apt-get install python-psycopg2
sudo apt-get install python-flask python-sqlalchemy
sudo apt-get install python-pip

4. Configure the local timezone to UTC

Changed EC2 instance time zone to UTC:

sudo dpkg-reconfigure tzdata

And set time sync with NTP:

sudo apt-get install ntp

Then added additional servers to /etc/ntp.conf file:

server ntp.ubuntu.com
server pool.ntp.org

And reloaded the NTP service:

sudo service ntp reload

5. Server needs

Apache HTTP Server

Installed Apache HTTP Server:

sudo apt-get install apache2
mod_wsgi

Then I installed mod_wsgi:

sudo apt-get install libapache2-mod-wsgi

And configured a new Virtual Host by sudo vim /etc/apache2/sites-available/catalog-app.conf with the following content:

<VirtualHost *:80>
        ServerName 35.159.31.11
        #ServerAdmin admin@mywebsite.com
        WSGIScriptAlias / /var/www/catalog-app/catalog.wsgi
        <Directory /var/www/catalog-app/catalog/>
            Order allow,deny
            Allow from all
        </Directory>
        Alias /static /var/www/catalog-app/catalog/static
        <Directory /var/www/catalog-app/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>

And enabled the new Virtual Host:

sudo a2ensite catalog-app

After that I created the .wsgi file by sudo vim /var/www/catalog-app/catalog.wsgi with the following content:

#!/usr/bin/python
import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0, "/var/www/catalog-app/")
from catalog import app as application
application.secret_key = 'Add your secret key'

And restarted Apache:

sudo service apache restart
PostgreSQL

Installed PostgreSQL:

sudo apt-get install postgresql postgresql-contrib

To setup, I connected to the postgres user:

sudo -i -u postgres

Created a new role:

createuser --interactive

Created database for new user catalog:

createdb catalog

And set a password for the catalog role:

psql
\password catalog

And followed the commnand line instructions

Git

To install Git:

sudo apt-get install git-all

Then to setup Catalog project I cloned the Catalog app repository inside the /var/www/ and followed the README instructions. I made additional changes for the project to work with PostgreSQL. I changed /instance/config.py file from

SQLALCHEMY_DATABASE_URI = "sqlite:///../catalog/catalog.db"

to

SQLALCHEMY_DATABASE_URI = "postgresql://catalog:password@localhost/catalog"

And also changed /catalog/models.py file from

description = db.Column(db.String(500))

to

description = db.Column(db.TEXT)

to support long description in PostgreSQL.

Securing server

1. Adding Key Based login to new user grader

Changed from root user to new grader user:

su - grader

Then added directory .ssh with

mkdir .ssh

Added file .ssh/authorized_keys and copied ssh public key contents of udacity_key to authorized_keys, and finally restricted permissions to .ssh and authorized_keys:

chmod 700 .ssh
chmod 644 .ssh/authorized_keys

2. Forcing Key Based Authentication

To force key based authentication I edited /etc/ssh/sshd_config file from

PasswordAuthentication yes

to

PasswordAuthentication no

Then, restarted ssh service:

sudo service ssh restart

3. SSH is hosted on non-default port

To host SSH on non-default port 22, I edited /etc/ssh/sshd_config file from

Port 22

to

Port 2200

And finally restarted ssh service:

sudo service ssh restart

4. Configure the Uncomplicated Firewall (UFW)

To setup UFW, first I check firewall status with:

sudo ufw status

Then, to deny incoming traffic:

sudo ufw default deny incoming

And allow outgoing traffic:

sudo ufw default allow outgoing

And finally start establishing rules. For SSH (port 2200):

sudo ufw allow 2200/tcp

For HTTP (port 80):

sudo ufw allow www

And for NTP (port 123):

sudo ufw allow ntp

And finally to enable UFW:

sudo ufw enable

User management

1. Grant sudo permission and prompt for user password at least once

To accomplish this task I added a text file named grader to /etc/sudoers.d/ directory with the following content:

grader ALL=(ALL) ALL

This way the user is asked for password at least once per session. The remote user grader is given sudo privileges.

2. Disable remote login of the root user

To disable root user login, I edited /etc/ssh/sshd_config file, and changed line:

PermitRootLogin without-password

to

PermitRootLogin no

Then we need to restart SSH with service ssh restart.

Third-Party Resources