This page explains how to set up a secure linux web server using a Digital
Ocean droplet. This server will then be used to deploy the vinyls catalogue
I previously developed.
The address of the server I deployed is http://104.248.253.240.xip.io/
- On your local machine create RSA key pairs with the following command:
$ ssh-keygen
- Create digital ocean droplet
I chose the following configuration: 1 GB Memory / 25 GB Disk / FRA1 - Ubuntu 18.04 x64.
Provide the ssh.pub
key you created at the previous step. - Log in to your droplet with ssh:
$ ssh -i /path/to/private/key root@ip.ad.dr.ess
As explained in this tutorial, there are a few basic initial configuration steps that should be taken over in order to secure the server:
- Create a new user:
$ adduser username
- Grant sudoer rights:
$ usermod -aG sudo username
- Update and upgrade (keeping local existing configuring files, if asked):
$ apt update && apt upgrade
- Enable external access via ssh for the newly created user by copying the ssh public key:
$ rsync --archive --chown=username:username ~/.ssh /home/username
- Change ssh port from 22 to 2200:
$ nano /etc/ssh/sshd_config
Replace #port 22
by port 2200
.
7. Restart:
service ssh restart
exit
- Log in as the new via ssh:
ssh -i /path/to/private/sshkey username@ip.ad.re.ss -p 2200
- Configure the firewall to only allow incoming connections for SSH (port 2200), HTTP (port 80), and NTP (port 123) and OpenSSH:
$ sudo ufw default deny incoming # deny all incoming connections
$ sudo ufw default allow outgoing # allow all outgoing connections
$ sudo ufw allow OpenSSH
$ sudo ufw allow 2200/tcp # open port 2200 for ssh connection
$ sudo ufw allow www # open port 80 for HTTP requests
$ sudo ufw allow 123/udp
$ sudo ufw deny 22 # close this port as it was replaced by 2200
$ sudo ufw enable
$ sudo ufw status # should list all the rules you just set up
- Disable root login:
$ sudo nano /etc/ssh/sshd_config
Replace PermitRootLogin yes
by PermitRootLogin no
.
$ service ssh restart
$ ssh -i /path/to/private/sshkey root@ip.ad.dr.ess -p 2200
Should not work anymore.
12. Configure Timezone to Use UTC
sudo dpkg-reconfigure tzdata
Select none of the above
.
$ sudo apt update
$ sudo apt install apache2
Check your website at http://ip.ad.dr.ess. You should see the default apache 'it works' page.
$ sudo apt install libapache2-mod-wsgi
The application I am deploying is written in python 2.7.
$ sudo apt install python-pip
Check with pip --version
that the installation was successful.
$ sudo add-apt-repository ppa:git-core/ppa
$ sudo apt update
$ sudo apt-get install git
$ git config --global user.name "username"
$ git config --global user.email "username@mail.com"
You can check your settings with git config -l
.
7.1 Install
$ sudo nano /etc/apt/sources.list.d/pgdg.list
- Add
deb http://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main
- Import the repository signing key
$ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
- Install
$ sudo apt-get update
$ sudo apt install postgresql-10
- Create
catalog
role for the database:
$ sudo su - postgres
$ psql
postgres=# CREATE ROLE catalog WITH PASSWORD 'catalog';
postgres=# ALTER ROLE catalog CREATEDB;
You can check with \du
that the catalog user has been created.
- Quit and exit:
\q
,exit
. - Create catalog user and add to sudoers :
$ sudo adduser catalog
$ sudo usermod -aG sudo catalog
- Log as
catalog
user and create thecatalog
database:
$ su - catalog
$ createdb catalogue
You can check with \l
that the database has been created.
- Create application directory:
$ sudo mkdir /var/www/catalog && cd /var/ww/catalog/
- Clone application repository, renaming it 'catalog':
$ sudo git clone https://github.com/Gry0u/vinyls_catalogue.git catalog
- Rename and edit
views.py
Change
app.debug = True
app.run(host='0.0.0.0', port=5000)
to
app.run()
And give the absolute path of the client_json file when defining the CLIENT_ID variable (file isn't found otherwise!):
CLIENT_ID = json.loads(
open('/var/www/catalog/catalog/client_secrets.json', 'r').read())['web']['client_id']
- Edit
database_setup.py
, change the engine creation statement to:
engine = create_engine('postgresql://catalog:catalog@localhost/catalog')
- Add your server's IP address to your authorized origins in your OAuth client ID settings (I use the Google API)
- Update
client_secrets.json
in catalog/catalog accordingly (dowload file, then copy paste content). Check that the client_secret key is in the json file. - Update login.html with your CLIENT ID if necessary
- Create a python virtual environment
$ sudo apt install python-virtualenv
- Install required modules
In catalog/catalog/:
$ sudo virtualenv venv
$ chown -R grader:grader catalog/
$ . venv/bin/activate
$ pip install --upgrade flask sqlalchemy httplib2 oauth2client requests
$ sudo apt install libpq-dev
$ pip install psycopg2
- Create
/etc/apache2/sites-available/catalog.conf
and add the following lines:
<VirtualHost *:80>
ServerName your.server.ip.address
ServerAdmin you@mail.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>
- Enable the virtual host:
$ sudo a2ensite catalog
And reload as prompted
$ sudo systemctl reload apache2
$ sudo nano /var/www/catalog/catalog.wsgi
- Add the following lines:
#!/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
$ sudo a2dissite 000-default.conf
$ sudo service apache2 restart
Enjoy your application by accessing directly to the IP address of your droplet (mine is listed at the very beginning) in your browser.
Note: Unlike the initial application which was accessed locally, the deployed application (or more specifically the catalog
back end database) is not populated beforehand with any genre, album or songs --> it is completely clean and free to be filled!
- Application written in Python 2.7, leverages the Flask microframework.
- Back-end built using the PostgreSQL database system together with the SQLAlchemy Python toolkit
- Application deployed on a Linux Server hosted on a Digital Ocean droplet, using an Apache server.
How to Create a Droplet from the DigitalOcean Control Panel
Connect with SSH
Initial Server Setup with Ubuntu 18.04
How To Deploy a Flask Application on an Ubuntu VPS
How To Secure PostgreSQL on an Ubuntu VPS