This readme is a tutorial on how to create an instance of a WSGI Apache server with DigitalOcean and host a Python app.
The catalog's built with PostgreSQL & Flask;
- Utilizes mod_wsgi
- SQLAlchemy to connect Python with PSQL;
- Jinja as templating engine
- OAuth2 as user authentication/registration
- Has it's own API
First, I needed to be certain the app would run with PostgreSQL.
The adjustments needed to be made weren't that large:
-
Change all 'NVARCHAR' columns in dbmodels.py to 'Text'
-
Make sure all paths are absolute and configured for a Linux OS
-
Make sure the items table's foreign keys reference unique columns
- Before the shop and manufacturer tables had a foreign key on their 'id' column, now the foreign key for manufacturer is 'name'
This means that when specifying a manufacturer when creating an item, you type their name.
-
Another change to be made was setting up a Postgres user and database, both named catalog, to enable testing of the app
- When the database and user had been made, the last step was:
-
Changing
create_engine()
in catalog.py & dbmodels.py topostgresql://catalog:catalog@localhost/catalog
This was a great time to test everything in the app and make sure nothing was broken. As you'd hope no breaking changes had been made and everything runs smoothly.
The following guide assumes you are redirecting your DNS provider's name servers to DigitalOcean.
Setting up DNS on DigitaOcean is done as follows:
- Go to the network tab
- Enter the domain
- Declare your favorite DNS records, mine are:
- A record to gideonservice.me
- CNAME record to make any prefix redirect to gideonservice.me
- NS records to DigitalOcean
Go to digitalocean.com and create a droplet with Ubuntu 14.04 and wait for it to deploy.
- Open a bash terminal locally
- On Windows: install git and use git-bash
- Copy the temporary password from the email you received at droplet creation
ssh root@< server IP-address >
< temporary password >
adduser < user >
gpasswd -a < user > sudo
sudo cp /etc/sudoers.d/90-cloud-initusers /etc/sudoers.d/< user >
sudo nano /etc/sudoers.d/< user >
inside the sudoers.d/grader change the word root
to < user >
-
< user > can run commands with sudo privileges now!
-
Locally run
ssh-keygen
, name the key by saving it to your default .ssh directory -
Locally run
cat ~/.ssh/< RSA-key-name >.pub
and copy it
On the server as root user
su < user >
cd /home/< user >
mkdir .ssh
sudo nano .ssh/authorized_keys
(Paste the contents of < rsa-key-name >.pub then save and exit)
sudo chmod 644 .ssh/authorized_keys
sudo chmod 700 .ssh
exit (until current user is root)
-
Run
sudo nano /etc/ssh/sshd_config
-
Change the line
PermitRootLogin yes
toPermitRootLogin no
-
Change the line
PasswordAuthentication yes
toPasswordAuthentication no
-
Change the line
Port 22
toPort 2222
-
Save and exit
-
-
Run
sudo service ssh restart
Locally, open bash and run ssh < user >@< server-IP > -p 2222 -i ~/.ssh/< rsa-key-name >
Run the following commands:
sudo apt-get -y update
sudo apt-get -y install finger
sudo apt-get -y install python2.7 python-pip
sudo -H pip2 install --upgrade pip
sudo apt-get -y install postgresql postgresql-contrib
sudo apt-get -y install apache2 libapache2-mod-wsgi
sudo apt-get -y install python-dev
sudo apt-get -y install git
sudo apt-get -y update
sudo apt-get -y upgrade
sudo apt-get -y autoremove
To confirm everything is working as it should so far: go to your browser, enter your servers IP-address and see if the default apache page is there. If nothing displays, run above commands again. If you still don't receive anything you should start over.
Make sure no remote connections are allowed by looking in the host based authentication file:
sudo nano /etc/postgresql/9.3/main/pg_hba.conf
Check if the following text matches the bottom of the file:
# Database administrative login by Unix domain socket
local all postgres peer
# TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only
local all all peer
# IPv4 local connections:
host all all 127.0.0.1/32 md5
# IPv6 local connections:
host all all ::1/128 md5
Anything else in this section of the config file should be deleted.
sudo su postgres
createuser --interactive -W -P < DB-username > (catalog no no no catalog catalog)
createdb -O < DB-owner > < DB-name >
exit
Whenever you make a change to the configuration of most services in Linux, you will have to restart them for the change to take effect. For now, use these commands:
-
sudo service postgresql restart
-
sudo service ssh restart
This is assuming apache2 is installed properly.
cd /var/www/
sudo mkdir flaskapps
sudo cd /flaskapps
sudo mkdir catalog
sudo git clone https://github.com/GideonFlynn/Item-Catalog.git
sudo mv /Item-Catalog/* /catalog/
To remove unused files/folders (and the .git folder), run these commands:
cd /var/www/flaskapps/
sudo rm -r -f Item-Catalog/
cd var/www/flaskapps/catalog
sudo pip install virtualenv
sudo virtualenv venv
source venv/bin/activate
sudo pip install -r requirements.txt
deactivate
Then we'll enable the app, first run:
sudo a2enmod wsgi
sudo nano /etc/apache2/sites-available/catalog.conf
Then paste the following code into catalog.conf
<VirtualHost *:80>
ServerName < server-IP >
ServerAlias < DNS >
ServerAdmin < admin-email@example.com >
WSGIScriptAlias / /var/www/flaskapps/catalog.wsgi
<Directory /var/www/flaskapps/catalog/>
Order allow,deny
</Directory>
Alias /static /var/www/flaskapps/catalog/static
<Directory /var/www/flaskapps/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>
Save and exit
sudo a2ensite catalog
cd /var/www/flaskapps/
sudo nano catalog.wsgi
Paste the following code into /var/www/flaskapps/catalog.wsgi
#!/usr/bin/python
import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0,"/var/www/flaskapps/catalog")
from catalog import app as application
application.secret_key = 'Add your secret key'
Save and exit
Run cd /var/www/flaskapps/catalog
We want to make sure the /static/uploads/images folders are present.
If not:
cd /static
sudo mkdir uploads
cd /uploads
sudo mkdir images
cd /var/www/flaskapps/catalog
If/when the folder is present:
cd /var/www/flaskapps/catalog
sudo chmod 777 -R static/
sudo service apache2 restart
We waited to configure the firewall until now, so we're certain to be able to log in even if something goes wrong.
sudo ufw status
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp
sudo ufw allow www
sudo ufw allow ntp
sudo ufw enable (press 'y')
sudo ufw status
Now your terminal should display this text:
Status: active
To Action From
-- ------ ----
22 ALLOW Anywhere
2222/tcp ALLOW Anywhere
80/tcp ALLOW Anywhere
123 ALLOW Anywhere
22 (v6) ALLOW Anywhere (v6)
2222/tcp (v6) ALLOW Anywhere (v6)
80/tcp (v6) ALLOW Anywhere (v6)
123 (v6) ALLOW Anywhere (v6)
- Run
sudo dpkg-reconfigure tzdata
- Select 'None of these' with your arrow keys
- Select UTC
After initial configuration, it would be a good idea to reboot the system:
-
Run
sudo apt-get update
andsudo apt-get -y dist-upgrade
. -
Run
reboot
-
Login with ssh
ssh < user >@< server-IP > -p 2222 -i ~/.ssh/< rsa-file-name >