If you consider the LinkedIn and GitHub profile optional exercises as projects, this is the eighth project of the Full Stack Web Development Nanodegree program, from Udacity.
This project's goal is to set up a Linux server to host one of the web applications developed throughout the Udacity's Full Stack Web Development Nanodegree.
The configuration involved creating a new user, giving it the right credentials, creating a SSH key, protecting the server, etc.
Amazon Lightsail was the service used in this project, with the basic plan and a 512 MB RAM, 1 vCPU, 20 GB SSD machine.
Public IP: 34.201.53.27
SSH port: 2200
App URL: http://34.201.53.27.xip.io
The server was killed in order to avoid unnecessary billing.
The Udacity's Get Started on Lighsail guide was used to create this server's instance and to connect into it using SSH. The instance was created with Ubuntu 16.04.
-
Update package source list:
sudo apt-get update
-
Update all installed packages:
sudo apt-get dist-upgrade
When asked, choose to install the "package maintainer's version".
-
Remove unnecessary packages:
sudo apt-get autoremove
- Use
sudo nano /etc/ssh/sshd_config
to open the file and edit line 4 from Port 22 to Port 2200. Save and quit nano. - Reload SSH service:
sudo service ssh restart
- On your instance dashboard, Networking tab, add a Custom TCP application with Port range = 2200 to your instance's Firewall.
From this point onward, if I close the browser connection with my server, I won't be able to come back. Thus, I downloaded PuTTY, my default private key from Lightsail, and managed to continue with the next steps from this direct connetion through PuTTY.
Configure the Uncomplicated Firewall (UFW) to only allow incoming connections for SSH (port 2200), HTTP (port 80), and NTP (port 123)
-
Check the current UFW status:
sudo ufw status
It's expected that the UFW is disabled;
-
Block all incoming requests initially:
sudo ufw default deny incoming
-
Allow all outgoing connections:
sudo ufw default allow outgoing
-
Allow SSH setting port to 2200:
sudo ufw allow 2200/tcp
-
Allow HTTP on its default port 80:
sudo ufw allow www
-
Allow NTP on its default port 123:
sudo ufw allow ntp
-
Enable firewall:
sudo ufw enable
-
Check UFW states once again:
sudo ufw status
-
Create a new user account named grader:
sudo adduser grader
-
Give grader the permission to sudo:
- Open /etc/sudoers to check if it includes
#includedir /etc/sudoers.d
(usually on its last line), or include it if absent:sudo nano /etc/sudoers
- Create a file named grader in /etc/sudoers.d:
sudo touch /etc/sudoers.d/grader
- Check if the file was correctly created:
sudo ls -al /etc/sudoers.d
- Open the recently created file (/etc/sudoers.d/grader) with
sudo nano /etc/sudoers.d/grader
and add a single line containinggrader ALL=(ALL:ALL) ALL
, save the file - Check if the file was correctly saved:
sudo cat /etc/sudoers.d/grader
- Open /etc/sudoers to check if it includes
-
Create an SSH key pair for grader using ssh-keygen.
a. On local machine:
- Create an SSH key pair for grader on my local machine:
ssh-keygen
- As I'm on Windows10, I set the file name to grader with the following directory:
c:\Users\Marcus\.ssh\grader
- Leave empty the passphrase
- As I'm on Windows10, I set the file name to grader with the following directory:
- Read and copy the content of the recently created grader.pub:
cat ~/ssh/grader.pub
b. On server:
- Create a /home/grader/.ssh folder:
sudo mkdir /home/grader/.ssh
- Create an authorized_keys file inside the /.ssh folder:
sudo touch /home/grader/.ssh/authorized_keys
- Edit the recently created file to add the copied SSH key, not forgetting to save after it:
sudo nano /home/grader/.ssh/authorized_keys
- Check if the file now contains the key:
sudo cat /home/grader/.ssh/authorized_keys
- Change ownership status for /.ssh folder:
sudo chown grader:grader /home/grader/.ssh
- Check if the user grader is the owner of the folder /.ssh:
sudo ls -al /home/grader
- Change the credentials of /.ssh folder:
sudo chmod 700 /home/grader/.ssh
- Change the /.ssh/authorized_keys credentials:
sudo chmod 644 /home/grader/.ssh/authorized_keys
- Reload the SSH service once again:
sudo service ssh restart
- Create an SSH key pair for grader on my local machine:
From now on, we can login from your OS using Bash with the grader user: ssh grader@PUBLIC-IP -p 2200 -i PATH-TO-MY-KEY-FILE
In my case, PUBLIC-IP is 34.201.53.27
and PATH-TO-MY-KEY-FILE is ~/.ssh/grader
.
The SSH Key was sent in the "Notes to Reviewer field"
- Open the right file by using
sudo nano /etc/ssh/sshd_config
- Change
PermitRootLogin
to no - Set, if not already,
PasswordAuthentication
to no - Add, on the last line, DenyUsers root
- Save the file before exiting
- First, check the current date:
date
- Then, if not in UTC yet, change it with
sudo timedatectl set-timezone UTC
- Now check it again:
date
My server was already set to UTC, thus, steps 2-3 were unnecessary.
-
For
Apache
:sudo apt-get install apache2
- For
mod_wsgi
:sudo apt-get install libapache2-mod-wsgi
- For
-
Instal PostgreSQL with
sudo apt-get install postgresql
-
To create a new database user named
catalog
with limited permissions to my catalog application database:-
Login as postgres:
sudo su - postgres
-
Start PostgreSQL shell:
psql
-
Create a new database (in my case, themehospitals) and a user named catalog:
postgres=# CREATE DATABASE themehospitals; postgres=# CREATE USER catalog;
-
Set password for the user catalog:
postgres=# ALTER ROLE catalog WITH PASSWORD 'SECRET-MAGIC-WORD';
-
Give full access to the database themehospitals to the user catalog:
postgres=# GRANT ALL PRIVILEGES ON DATABASE themehospitals TO catalog;
-
Exit PostgreSQL shell:
postgres=# \q
-
Logout from postgres user:
exit
-
The user password was also sent in the "Notes to Reviewer field"
- Install Git with
sudo apt-get install git
- Move to the directory watched by Apache with
cd /var/www
- Create the application directory with
sudo mkdir ItemCatalog
- Move to the recently created folder:
cd ItemCatalog
- Initiate an empty git repository in the current folder:
sudo git init
- Add my Item Catalog App Repo as a remote repository:
sudo git remote add origin https://github.com/mguidoti/FSND-p4-item_catalog.git
- Check if the remote repository was added successfully:
sudo git remote -v
- Pull the remote repository:
sudo git pull origin master
- Check if the files were downloaded successfully:
sudo ls
- Rename hospitals.py to
__init__.py
withsudo mv hospitals.py __init__.py
- Edit initiate_database.py, fill_database.y, and the now renamed
__init.py__
, and change all occurrences of 'sqlite:///themehospitals.db' to'postgresql://catalog:password@localhost/themehospitals'
, editing the files with:sudo nano 'FILE-NAME'
Remember: the password was given in the "Notes to Reviewer field".
- First, install pip:
sudo apt-get install python-pip
- Then, use it to install all dependencies listed on requirements.txt:
sudo pip install -r requirements.txt
- To create the database:
sudo python initiate_database.py
- To fill the database:
sudo python fill_database.py
Remember, to understand why it's necessary to run two *.py to get this project started, refer to the original README.
-
Create ItemCatalog.conf:
sudo nano /etc/apache2/sites-available/ItemCatalog.conf
-
Add the following to the recently created and opened file:
<VirtualHost *:80> ServerName 34.201.53.27 ServerAdmin marcus.guidoti@gmail.com ServerAlias 34.201.53.27.xip.io WSGIScriptAlias / /var/www/ItemCatalog/itemcatalog.wsgi <Directory /var/www/ItemCatalog> Order allow,deny Allow from all </Directory> Alias /static /var/www/ItemCatalog/static <Directory /var/www/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>
-
Enable the virtual host:
sudo a2ensite ItemCatalog
-
Activate the new configuration:
sudo service apache2 reload
-
To create AND edit the desired file:
sudo nano /var/www/ItemCatalog/itemcatalog.wsgi
-
Add the following to the recently created and opened file:
#!/usr/bin/python import sys import logging logging.basicConfig(stream=sys.stderr) sys.path.insert(0,"/var/www/ItemCatalog") from __init__ import app as application application.secret_key = 'super_secret_key'
The application.secret_key is correctly provided above. I know, I know... I should have changed it, but I didn't, and now it looks like a fake/dummy secret key but it's the real one!
- Restart:
sudo service apache2 restart
- Reload:
sudo service apache2 reload
If something breaks or go wrong, you can access a log for this application with the following command:
sudo tail -f /var/log/apache2/error.log
The following sources were consulted in order to finish this project:
Udacity's Linux Commandas Line Basics
Udacity's Configuring Linux Web Servers
SSH: How to access a remote server and edit files
Apache error “Could not reliably determine the server's fully qualified domain name”
How to connect to Amazon LightSail instance from Windows 10
How to Set Up Time Synchronization on Ubuntu 16.04
What is the difference between apt-get update and upgrade?
Ubuntu Server message says packages can be updated, but apt-get does not update any duplicate