Udacity Linux Server Configuration: udacity-catalog
This Python application provides a list of items within a variety of categories, as well as a user registration and authentication system.
Note: The walkthrough is the solution to the final project of the Udacity Full Stack Web Developer Nanodegree and deploys the solution of project 3 on the virtual machine.
- The web application accessible under the AWS-server instance. It uses port 2200.
The steps that are listed below are, in large part, a replication of the following guide. Items that are in CAPS should be replaced by app-specific information.
Source: Udacity
- Create a new development environment.
- Download private keys and write down your public IP address.
- Move the private key file into the folder ~/.ssh:
$ mv ~/Downloads/udacity_key.rsa ~/.ssh/
- Set file rights (only owner can write and read.):
$ chmod 600 ~/.ssh/udacity_key.rsa
- SSH into the instance:
<pre>$ ssh -i ~/.ssh/udacity_key.rsa root@PUBLIC-IP-ADDRESS
Source: DigitalOcean
- Create a new user:
$ adduser grader
- Give new user the permission to sudo
- Open the sudo configuration:
$ visudo
- Add the following line below
root ALL...
:
grader ALL=(ALL:ALL) ALL
- *List all users (Source: Ask Ubuntu):
$ cut -d: -f1 /etc/passwd
Source: Ask Ubuntu
- Update the list of available packages and their versions:
$ sudo apt-get update
- Install newer vesions of packages you have:
$ sudo sudo apt-get upgrade
Source: Ask Ubuntu
-
Change ssh config file:
-
Open the config file:
$ sudo nano /etc/ssh/sshd_config
-
Change to Port 2200.
-
Change
PermitRootLogin
fromwithout-password
tono
. -
Temporalily change
PasswordAuthentication
fromno
toyes
. -
Append
UseDNS no
. -
Append
AllowUsers NEWUSER
.
Note: All options on UNIXhelp -
Restart SSH Service:
$ /etc/init.d/ssh restart
or# service sshd restart
-
Create SSH Keys:
Source: DigitalOcean -
Generate a SSH key pair on the local machine:
$ ssh-keygen
-
Copy the public id to the server:
$ ssh-copy-id username@remote_host -pPORTNUMBER
-
Login with the new user:
$ ssh -v grader@PUBLIC-IP-ADDRESS -p2200
-
Open SSHD config:
$ sudo nano /etc/ssh/sshd_config
-
Change
PasswordAuthentication
back fromyes
tono
.
7 - Configure the Uncomplicated Firewall (UFW) to only allow incoming connections for SSH (port 2200), HTTP (port 80), and NTP (port 123)
Source: Ubuntu documentation
- Turn UFW on with the default set of rules:
$ sudo ufw enable
- *Check the status of UFW:
$ sudo ufw status
- Allow incoming TCP packets on port 2200 (SSH):
$ sudo ufw allow 2200/tcp
- Allow incoming TCP packets on port 80 (HTTP):
$ sudo ufw allow 80/tcp
- Allow incoming UDP packets on port 123 (NTP):
$ sudo ufw allow 123/udp
Source: Ubuntu documentation
- Open the timezone selection dialog:
$ sudo dpkg-reconfigure tzdata
- Then chose 'None of the above', then UTC.
- *Setup the ntp daemon ntpd for regular and improving time sync:
$ sudo apt-get install ntp
Source: Udacity
- Install Apache web server:
$ sudo apt-get install apache2
- Open a browser and open your public ip address, e.g. http://35.165.202.220/ - There should be an Apache landing page that says 'It works!' at the top.
- Install mod_wsgi for serving Python apps from Apache and the helper package python-setuptools:
$ sudo apt-get install python-setuptools libapache2-mod-wsgi
- Restart the Apache server for mod_wsgi to load:
$ sudo service apache2 restart
Source: DigitalOcean (alternatively, nice short guide on Kill The Yak as well)
- Install PostgreSQL:
$ sudo apt-get install postgresql postgresql-contrib
- Check that no remote connections are allowed (default):
$ sudo nano /etc/postgresql/9.3/main/pg_hba.conf
- Open the database setup file:
$ sudo nano catalog_database.py
- Change the line starting with "engine" to (fill in a password):
engine = create_engine('postgresql://catalog:PW-FOR-CATALOG-DB@localhost/catalog')
- Change the same line in catalog.py and catalog_populator.py
- Rename catalog.py:
$ mv catalog.py __init__.py
- Create needed linux user for psql:
$ sudo adduser catalog
(choose a password) - Change to default user postgres:
$ sudo su - postgres
- Connect to the system:
$ psql
- Add postgres user with password:
Sources: Trackets Blog and Super User - Create user with LOGIN role and set a password:
# create user catalog with password 'PW-FOR-CATALOG-DB';
- Allow the user to create database tables:
# alter user catalog createdb;
- *List current roles and their attributes:
# \du
- Create database:
# create database catalog with owner catalog;
- Connect to the database catalog
# \c catalog
- Revoke all rights:
# revoke all on scheme public from public;
- Grant only access to the catalog role:
# grant all on schema public to catalog;
- Exit out of PostgreSQl and the postgres user:
# \q
, then$ exit
- Create postgreSQL database schema:
$ python catalog_database.py
Source: GitHub
- Install Git:
$ sudo apt-get install git
- Set your name for the commits:
$ git config --global user.name "YOUR NAME"
- Set up your email address to connect your commits to your account:
$ git config --global user.email "YOUR EMAIL ADDRESS"
Source: DigitalOcean
- Extend Python with additional packages that enable Apache to serve Flask applications:
$ sudo apt-get install libapache2-mod-wsgi python-dev
- Enable mod_wsgi (if not already enabled):
$ sudo a2enmod wsgi
- Create a Flask app:
- Move to the www directory:
$ cd /var/www
- Setup a directory for the app:
1.$ sudo mkdir catalog
2.$ cd catalog
and$ sudo mkdir catalog
3.$ cd catalog
and$ sudo mkdir static templates
4. Create the file that will contain the flask application logic:
$ sudo nano __init__.py
5. Paste in the following code:
python from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello!" if __name__ == "__main__": app.run()
- Install Flask
- Install pip installer:
$ sudo apt-get install python-pip
- Install virtualenv:
$ sudo pip install virtualenv
- Set virtual environment to name 'venv':
$ sudo virtualenv venv
- Enable all permissions for the new virtual environment (no sudo should be used within):
Source: Stackoverflow
$ sudo chmod -R 777 venv
- Activate the virtual environment:
$ source venv/bin/activate
- Install Flask inside the virtual environment:
$ pip install Flask
- Run the app:
$ python __init__.py
- Deactivate the environment:
$ deactivate
- Configure and Enable a New Virtual Host#
- Open the existing config file:
$ sudo nano /etc/apache2/sites-available/000-default.conf
- Paste in the following lines of code and change names and addresses regarding your application:
<VirtualHost *:80>
ServerName PUBLIC-IP-ADDRESS
ServerAdmin admin@PUBLIC-IP-ADDRESS
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>
- Enable the virtual host:
$ sudo a2ensite catalog
- Create the .wsgi File and Restart Apache
- Create wsgi file:
$ cd /var/www/catalog
and$ sudo nano catalog.wsgi
- Paste in the following lines of code:
#!/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'
- Restart Apache:
$ sudo service apache2 restart
- Clone project 3 solution repository on GitHub:
$ git clone https://github.com/zachnewburgh/udacity-catalog.git
- Move all content of created udacity-catalog directory to
/var/www/catalog/catalog/
and delete the leftover empty directory.
$ sudo mv udacity-catalog/* catalog
$ sudo rm -r udacity-catalog
- Make the GitHub repository inaccessible:
Source: Stackoverflow - Create and open .htaccess file:
$ cd /var/www/catalog/
and$ sudo nano .htaccess
- Paste in the following:
RedirectMatch 404 /\.git
- Activate virtual environment:
$ source venv/bin/activate
- Install httplib2 module in venv:
$ pip install httplib2
- Install requests module in venv:
$ pip install requests
- *Install flask.ext.seasurf (only seems to work when installed globally):
$ *sudo pip install flask-seasurf
- Install oauth2client.client:
$ sudo pip install --upgrade oauth2client
- Install SQLAlchemy:
$ sudo pip install sqlalchemy
- Install the Python PostgreSQL adapter psycopg:
$ sudo apt-get install python-psycopg2
- Restart Apache:
$ sudo service apache2 restart
- Open a browser and put in your public ip-address as url, e.g. 35.165.202.220 - if everything works, the application should come up
- *If getting an internal server error, check the Apache error files:
Source: A2 Hosting - View the last 20 lines in the error log:
$ sudo tail -20 /var/log/apache2/error.log
- *If a file like 'google_client_secrets.json' couldn't been found:
Source: Stackoverflow
- Open http://www.hcidata.info/host2ip.cgi and receive the Host name for your public IP-address, e.g. for 35.165.202.220, it's ec2-35-165-202-220.us-west-2.compute.amazonaws.com
- Open the Apache configuration files for the web app:
$ sudo nano /etc/apache2/sites-available/000-default.conf
- Paste in the following line below ServerAdmin:
ServerAlias HOSTNAME
, e.g. ec2-35-165-202-220.us-west-2.compute.amazonaws.com - Enable the virtual host:
$ sudo a2ensite catalog
- To get the Google+ authorization working:
- Go to the project on the Developer Console: https://console.developers.google.com/project
- Navigate to APIs & auth > Credentials > Edit Settings
- add your host name and public IP-address to your Authorized JavaScript origins and your host name + oauth2callback to Authorized redirect URIs, e.g. ec2-35-165-202-220.us-west-2.compute.amazonaws.com/oauth2callback
- To get the Facebook authorization working:
- Go on the Facebook Developers Site to My Apps https://developers.facebook.com/apps/
- Click on your App, go to Settings and fill in your public IP-Address including prefixed hhtp:// in the Site URL field
- To leave the development mode, so others can login as well, also fill in a contact email address in the respective field, "Save Changes", click on 'Status & Review'