IMPORTANT: The deployment server has now been deleted so some links here might not work.
Project url: http://catalog.aavi.me/ Project IP: http://165.227.16.72/
In this tutorial, we will deploy a flask server project to a linux server (here Digital Ocean). We will setup an internal postgres server as the database and demonstrate some advanced server management magic.
Note - Here we are taking a project named "catalog". You should replace "catalog" with your project name everywhere in this article.
- Start a new server on Digital Ocean.
- SSH into the server.
- Update all currently installed packages.
- Change the SSH port from 22 to 2200. Make sure to configure the firewall to allow it.
- Configure the Uncomplicated Firewall (UFW) to only allow incoming connections for SSH (port 2200), HTTP (port 80), and NTP (port 123).
- Create a new user account named
grader
. - Give
grader
the permission to sudo. - Create an SSH key pair for
grader
using the ssh-keygen tool. - Configure the local timezone to UTC.
- Install and configure Apache to serve a Python mod_wsgi application.
- Install and configure PostgreSQL.
- Do not allow remote connections.
- Create a new database user named
catalog
that has limited permissions to yourcatalog
application database.
- Install git.
- Clone and setup your git project (here Catalog).
- Set it up in your server so that it functions correctly when visiting your server’s IP address in a browser. Make sure that your .git directory is not publicly accessible via a browser.
- Use a custom domain with Digital Ocean.
- Disable root remote login and enforce key-based authentication.
To start a new server on Digital Ocean, create a new droplet. Use the following specifications -
- Distribution - Ubuntu 16.04 x64
- Size -
$5/mo
- Datacenter region - San francisco
- Create a new ssh-key called
catalog_root
.- Open your terminal and run
ssh-keygen
. - You will be asked for the file path to save your key. Enter
/Users/USER_NAME/.ssh/catalog_root
where USER_NAME is your username. - Set up a passphrase, here we are setting it to "password".
- Done, you should have your key pair now.
- Open your terminal and run
- In the DO interface, click on New SSH key and paste the contents of
~/.ssh/catalog_root.pub
in it. Name the key ascatalog_root
. Enter. - Keep number of droplets to
1
. - Finish. Click on Create button.
To ssh into the server, copy the IP address from Digital Ocean interface. Here it is 165.227.16.72
.
ssh into the server with the following command.
ssh -i ~/.ssh/catalog_root root@165.227.16.72
# ssh -i /full/path/to/key root@IP
You will have to enter the passphrase for the ssh key that you created. Enter it and you should be connected.
Try running pwd
to check if things are working. Congrats, you officially now have access to your server.
To update currently installed packages, run the following command-
sudo apt-get update
sudo apt-get upgrade
# security updates
sudo apt-get install unattended-upgrades
# install them manually
sudo unattended-upgrades
# sudo is actually not required in case of DO but never mind :)
# sudo apt-get -u upgrade # checks list of updates
To change ssh port to 2200, follow the given steps-
Open ssh config in nano
.
sudo nano /etc/ssh/sshd_config
Locate "Port 22" in that file. Change it to "Port 2200".
Restart ssh service.
sudo service ssh restart
To configure UFW to allow given connections, follow the steps:
sudo ufw allow 2200
sudo ufw allow 80
sudo ufw allow 123
Then enable ufw.
sudo ufw enable
Now ssh port has been changed to 2200. Try exiting the ssh connection and re-connecting with the following command.
ssh -p 2200 -i ~/.ssh/catalog_root root@165.227.16.72
Notice the -p 2200
there. Clean, isn't it.
To create a user called grader
, run the following command.
sudo adduser grader
Fill in the details, use password
as the password for this user.
To check if the new user has been created successfully or not, run ls /home/grader
. If the command exits without any problems, then that means
the path is valid.
To give grader
sudo permission, we first create grader
file inside sudoers.d
.
touch /etc/sudoers.d/grader
Then we open the file in nano
(sudo nano /etc/sudoers.d/grader
) and add the following-
grader ALL=(ALL) NOPASSWD:ALL
We will now have to setup a ssh key-pair for grader.
Follow the steps in Step 1 to create a new ssh key at ~/.ssh/catalog_grader
.
Don't give a password this time as ssh keys are themselves meant to be credentials so you can say that they are themselves passwords.
Copy the contents of catalog_grader.pub
file.
On the server terminal, run -
su - grader
mkdir .ssh
chmod 700 .ssh
nano .ssh/authorized_keys
# paste the contents and save the file
chmod 644 .ssh/authorized_keys
Restart the ssh service.
sudo service ssh restart
Now you should be able to login as grader
. Exit current connection and do the following.
ssh -p 2200 -i ~/.ssh/catalog_grader grader@165.227.16.72
To configure timezone, run the following command.
sudo dpkg-reconfigure tzdata
Select "None of the above" and then select UTC.
When done, you should see something like this in the terminal.
Current default time zone: 'Etc/UTC'
Local time is now: Sat Jul 15 04:50:15 UTC 2017.
Universal Time is now: Sat Jul 15 04:50:15 UTC 2017.
To serve Python using Apache and mod_wsgi, install the following components.
sudo apt-get install python3
sudo apt-get install python3-setuptools
sudo apt-get install apache2 libapache2-mod-wsgi-py3
# this is for Python 3
# for python2 it is python, python-setuptools and libapache2-mod-wsgi
Then start apache service.
sudo service apache2 restart
Install postgresql as follows
sudo apt-get install postgresql
To disable remote connections, make sure you don't have any other IPs besides 127.0.0.1
in the following file.
sudo nano /etc/postgresql/VERSION/main/pg_hba.conf
# VERSION = your postgres version
# here we have
# sudo nano /etc/postgresql/9.5/main/pg_hba.conf
Now to create catalog
database, run the following to get into psql shell.
sudo -u postgres psql
Then when inside psql shell, run the following.
create user catalog with password 'password';
create database catalog with owner catalog;
Then exit psql shell with the following command.
\q
To install git, run-
sudo apt-get install git
Our project is at https://github.com/aviaryan/ud-catalog
First we need to clone it on server.
cd /var/www
sudo git clone https://github.com/aviaryan/ud-catalog.git catalog
Then we need to setup the project. See the project README for instructions.
# install pip3
sudo easy_install3 pip
# install requirements
cd catalog
sudo pip3 install -r requirements.txt
# setup database
export DB_URI=postgresql://catalog:password@localhost/catalog
python3 manage.py db upgrade
# create initial categories
python3 create_category.py
# setup auth config
sudo nano config.py
# ^^ and add credentials there
# also change redirect_uri to http://catalog.aavi.me/gCallback
# see step 15 for why we are doing so
Now we need to run the project using Apache and mod-wsgi. So we will first create a configuration file for your project.
sudo nano /etc/apache2/sites-available/catalog.conf
It should have the following components.
<VirtualHost *:80>
ServerName 165.227.16.72
WSGIScriptAlias / /var/www/catalog/wsgi.py
<Directory /var/www/catalog>
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
The wsgi file has been already added to the project. It should look like this.
import sys
sys.path.insert(0, '/var/www/catalog')
from catalog import app as application
application.secret_key = 'New secret key. Change it on server'
application.config['SQLALCHEMY_DATABASE_URI'] = (
'postgresql://'
'catalog:password@localhost/catalog')
Once this is done, enable the site and restart Apache.
sudo a2ensite catalog # enable site
sudo service apache2 reload
The server should be live now. Visit the IP to check (http://165.227.16.72). If an error occurs, check the logs.
sudo cat /var/log/apache2/error.log
Now we would like to use a domain name for the server. I am using Namecheap as the domain registar but the steps should be same everywhere.
But why are we doing so? Because Google OAuth doesn't work for bare IPs.
So, go to Networking tab in Digital Ocean and create new domain. I want to use a sub-domain for this application catalog.aavi.me
.
Add an @
record with the target as your created server. After this the dashboard should look like the following.
Now we need to make changes in the domain registrar's side as well. Add digital ocean's nameserver records there.
Now go visit your sub-domain. It should work. (Here: http://catalog.aavi.me)
PS - You may need to disable the default nginx site here. sudo a2dissite 000-default
To disable root login & password-based login through ssh, open the ssh config file.
sudo nano /etc/ssh/sshd_config
Make changes as shown below.
PermitRootLogin no
PasswordAuthentication no
Save the file and restart ssh server.
sudo service ssh restart