Note: This article was written in late 2014, and whilst a lot of the commands and advise in this article are still relevant, a couple of links might be to an old ‘end of line’ version of software
When deploying the new version of Plagiarism Guard, I didn’t want to disturb the existing install. So instead I decided to order a new server (in this case a VPS) and get everything setup on the new server first, before switching over the DNS. This post details the steps I took to setup the basics of the server and deploy the Django application.
NB: Plagiarism Guard is written by Python 3 so I decided to boot the server as Ubuntu 14.04, which comes with both Python 2.7 and Python 3.4 installed by default. It wouldn’t be much more work to choose a Python 2-only distro and setup Python 3 via virtualenv, although for a brand new box it seemed sensible to choose a recent Linux distro which comes with Py3 by default. Firstly I logged into the server via SSH using PuTTY as a client. Your server/VPS provider will provide you with an IP address when they have provision the server. If they don’t specify an SSH port, it’ll probably be 22.
Initial Server Setup
To speed up the server config I decided to firstly install Webmin/Virtualmin which is a free server control panel. In comparison to cPanel/WHM, Webmin is like WHM and Virtual is like cPanel. To install this I typed the following commands into the SSH window:
cd / wget http://software.virtualmin.com/gpl/scripts/install.sh chmod +x install.sh ./install.sh
Using the install script you shouldn’t be prompted for any input mid-installation, but keep an eye on the SSH window in-case they ask you to provide any information. Once complete, go to https://[serverip]:10000 in your browser. At this stage you will be shown an ‘Invalid SSL certificate’ browser warning which is safe to ignore for now. On first login, you will be prompted to follow a post installation wizard. It’s fairly self explanatory so just choose settings relevant to your requirements. I tend to disable email anti-virus unless the server has over 1 GB RAM. I also choose an alternative SSH port, something above 10000. This is because some common hacking scripts will try to break into your server’s SSH by using common passwords and going to port 22. By using a non standard port, you are slightly increasing security of your box. On the topic of security, a great free software firewall is CSF which can be installed with the following commands:
cd /usr/local/src wget http://www.configserver.com/free/csf.tgz tar –xvf csf.tgz cd csf sh install.sh
CSF has a GUI via Webmin which can be easily activated as per the installation instructions:
To install or upgrade the csf webmin module: Install csf as above Install the csf webmin module in:
Webmin > Webmin Configuration > Webmin Modules > From local file > /usr/local/csf/csfwebmin.tgz > Install Module
Once installed and activated within Webmin, go to Webmin -> System -> ConfigServer Security & Firewall -> Firewall Configuration. Firstly set TESTING to 0. Then verify that the alternative SSH port you specified above is listed under both TCP_IN and TCP_OUT and remove port 22 if it’s listed (obviously only do this if you chosen to change your SSH port from 22!). Since my application is written in Python 3 and will be powered by PostgreSQL and Django, I run the following commands to configure Python and Apache as required:
apt-get update apt-get install libapache2-mod-wsgi-py3 apt-get install nano apt-get install python3-pip apt-get install python-psycopg2 pip3 install psycop2
Django is run via mod-wsgi and since I’m running Python 3, I installed this dependency via the ‘apt-get install libapache2-mod-wsgi-py3’ command. At this point, you can install any Python packages you need by running pip3 install [package name], e.g.:
pip3 install Django==1.7
If you haven’t been keeping track of your project’s Python dependencies, you can run ‘pip list’’ or similar on your current dev environment.
Publishing/Installing Your Website
Firstly add your website via Virtualmin -> Create Virtual Server and filling out the relevant options. This creates the relevant Zone files (DNS), Apache2 configuration files and a directory for your website files under /home. To setup email accounts on this domain, select your newly created virtual server and click ‘Edit Users’. Click “Add a user to this server.” and choose the relevant settings. The tricky bit with installing a Django app for the first time is knowing where to put your website files and how to configure it under Apache2. I found the guides by Linode and Django to be useful but hopefully the below advise will also prove useful. Firstly, only your static files (images, Javascript, CSS etc) need to be uploaded to your /public_html directory. The rest of your files can then be uploaded under your /home/[username] directory. By installing Webmin you will have FTP ready to go so login to FTP via a client such as Filezilla (using the provided IP address, port 21 and the chosen username and password when creating this virtual server). You can see how I uploaded my Django app’s files in the following screenshot:
As can be seen, my Django manage.py file was uploaded into the /home/[username] folder whereas the Django apps and settings folder (e.g. /PlagiarismGuard and /plag) was uploaded into sub-folders of /home/[username]/. Only my static files were uploaded into /home/[username]/public_html since these are the only parts of a Django app that need to be publicly facing. You will probably also need to edit your wsgi.py file to add your site’s path into Python:
nano /home/plagiarismguard/PlagiarismGuard/wsgi.py
And I added:
import sys sys.path.insert(0, '/home/plagiarismguard/')
After uploading the files I went into the settings.py file and made the following changes:
- Changed DEBUG to: False
- Changed TEMPLATE_DEBUG to: False
- Changed ALLOWED_HOSTS to: [‘*’]
- Changed DATABASES to match the PostgreSQL database information (go to ‘Edit Databases’ under Virtualmin):
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'database_name', 'USER': 'username', 'PASSWORD': 'password', 'HOST': '127.0.0.1', 'PORT': '5432', } }
- Changed MEDIA_ROOT to the location where I will be storing any file uploads (in this case, /home/plagiarismguard/media/)
At this point you have uploaded your Django files and configured the environment so that Python and WSGI should serve your app as expected. The final step involves needing to modify the Apache2 conf file (in Ubuntu, this is under /etc/apache2/sites-enabled) so that it’s aware that it should serve your Python files via WSGI. The Django guide on this is very useful and I’ve also copy & pasted my final conf file at the end of this post. If you’ve never had experience with Apache2 configuration, this can be tricky, but the main thing to add is the WSGIScriptAlias command and ‘Require all granted’ for wsgi.py in the relevant . When complete, restart Apache2 with:
service apache2 restart
If you get any errors when visiting your site via the IP address, check your site’s error_log with:
tail -f /home/[username]/logs/error_log
If the error is not useful, you can also try temporarily setting DEBUG to True in settings.py (you will need to restart Apache2 for this change to take affect) and you’ll (hopefully) get a useful Django/Python error stack. If the error is something like:
ImportError: Could not import settings ‘settings.py’ (Is it on sys.path? Does it have syntax errors?): No module named settings.py.
Then re-check that you have correctly added your site’s path into wsgi.py as mentioned earlier. Overall though the steps described above should be sufficient to get your website up and running. Congratulations! You can verify that it works as expected by going to your virtual host’s IP address in your browser.
Change DNS
Once your server is setup as expected, you will need to setup the nameservers and change the domain’s DNS. Firstly go to Webmin -> BIND DNS Server -> Select site under ‘Existing DNS zones’ -> Address. Then add two nameservers (ns1.yourdomain.com. and ns2.yourdomain.com. – remembering the trailing period – and point them to your IP address(es). Then setup these nameserver/IP records at your domain name registration company. Methods for doing this vary but the guide for doing this on GoDaddy can be seen here.
Then change your domain’s nameservers to ns1.yourdomain.com and ns2.yourdomain.com and after a short wait (usually 1-12 hours), your website should resolve when going to yourdomain.com.
Optional: Migrate the Database
If you are starting from a fresh database (as configured in settings.py), you can simply run:
cd /home/[username] python3 manage.py syncdb
To create a fresh database. However if you are looking to migrate data as well, I found the tutorial by Matthew Wittering to be useful.
Optional: Add an SSL Certificate
To setup SSL certificates via Virtualmin, you can:
- Go to Virtualmin -> Server Configuration -> Manage SSL Certificate -> Create Signing Request
- After generating a CSR, buy an SSL certificate with your favourite SSL provider. They will email you instructions but part of it will involve sending them the CSR generated above. Never send out the private key which is generated at the same time.
- After a short wait, the SSL provider will send you your SSL certificate. Copy and paste the SSL key into Virtualmin -> Server Configuration -> Manage SSL Certificate -> Update Certificate and Key -> Signed SSL Certificate -> Pasted Text
- If you purchased a less known type of SSL certificate (some of which give errors, especially on mobile devices and tablets), you might be sent an ‘intermediate’ certificate. You can upload this to Virtualmin -> Server Configuration -> Manage SSL Certificate -> CA Certificate.
If you want all visitors to see the SSL (https) version of your website, you can change the :80 (http) Apache2 config to:
<VirtualHost [your IP address]:80> RewriteEngine on RewriteCond %{HTTPS} off RewriteRule (.*) https://www.[yourdomain].com%{REQUEST_URI} [R=301,L] </VirtualHost>
Optional: Redirect Old URLs
If your Django/Python application replaces another website, you should redirect any old URLs to your new ones to ensure that your visitors and the search engines don’t get confused. To do this, you can enable RewriteEngine in Apache2’s configuration and redirect your URLs as applicable:
RewriteEngine on Redirect 301 /Features.php https://www.plagiarismguard.com/features-screenshots/
Optional: Also Run PHP Applications
If you also want to run PHP applications via this virtual host, you can upload the site into the relevant folders (e.g. /home/[username]/public_html/php-app) and then insert the following lines into your site’s Apache2 conf file:
Alias /[php-app] /home/[username]/public_html/[php-app]/ <Directory /home/[username]/public_html/[php-app]> Options -Indexes +IncludesNOEXEC +SymLinksIfOwnerMatch +ExecCGI Require all granted AddHandler fcgid-script .php FCGIWrapper /home/[username]/fcgi-bin/php5.fcgi .php DirectoryIndex index.php </Directory>
Future Server Configuration
This is a basic guide covering an initial server setup; you will probably want to make further changes to your newly configured box. Feel free to search around Webmin and the internet if you are unsure how to make certain changes. One key bit of advice after all this is complete is to update your system. You can either do this via Webmin -> System Information -> Virtualmin Package Updates or by running:
apt-get update apt-get upgrade
Final Apache2 Configuration File for Plagiarism Guard
This configuration file redirects http:// requests to https://, non-www requests to www and also redirects old page URLs to their new forms. I’m also running two PHP applications (/blog which is powered by WordPress and /support which is powered by OSTicket).
cat /etc/apache2/sites-enabled/plagiarismguard.com.conf
<VirtualHost 107.191.102.183:80> RewriteEngine on RewriteCond %{HTTPS} off RewriteRule (.*) https://www.plagiarismguard.com%{REQUEST_URI} [R=301,L] </VirtualHost> <VirtualHost 107.191.102.183:443> SuexecUserGroup "#1000" "#1000" ServerName plagiarismguard.com ServerAlias www.plagiarismguard.com DocumentRoot /home/plagiarismguard/public_html ErrorLog /var/log/virtualmin/plagiarismguard.com_error_log CustomLog /var/log/virtualmin/plagiarismguard.com_access_log combined ScriptAlias /cgi-bin/ /home/plagiarismguard/cgi-bin/ WSGIScriptAlias / /home/plagiarismguard/PlagiarismGuard/wsgi.py <Directory /home/plagiarismguard/PlagiarismGuard> Require all granted </Directory> <Directory /home/plagiarismguard/cgi-bin> allow from all AllowOverride All Options=ExecCGI,Includes,IncludesNOEXEC,Indexes,MultiViews,SymLinksIfOwnerMatch Require all granted </Directory> Alias /robots.txt /home/plagiarismguard/public_html/robots.txt Alias /sitemap.xml /home/plagiarismguard/public_html/sitemap.xml Alias /favicon.ico /home/plagiarismguard/public_html/static/plag/img/favicon.png Alias /blog /home/plagiarismguard/public_html/blog/ Alias /support /home/plagiarismguard/public_html/support/ Alias /static/ /home/plagiarismguard/public_html/static/ <Directory /home/plagiarismguard/public_html/static> Require all granted </Directory> <Directory /home/plagiarismguard/public_html> <Files ~ "(robots.txt|sitemap.xml)"> Require all granted </Files> </Directory> <Directory /home/plagiarismguard/public_html/blog> Options -Indexes +IncludesNOEXEC +SymLinksIfOwnerMatch +ExecCGI Require all granted AddHandler fcgid-script .php FCGIWrapper /home/plagiarismguard/fcgi-bin/php5.fcgi .php DirectoryIndex index.php RewriteEngine On RewriteBase /blog/ RewriteRule ^index\\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /blog/index.php [L] </Directory> <Directory /home/plagiarismguard/public_html/support> Options -Indexes +IncludesNOEXEC +SymLinksIfOwnerMatch +ExecCGI Require all granted AddHandler fcgid-script .php FCGIWrapper /home/plagiarismguard/fcgi-bin/php5.fcgi .php DirectoryIndex index.php </Directory> RewriteEngine on RewriteCond %{HTTP_HOST} !^www\\. [NC] RewriteRule ^(.*)$ https://www.%{HTTP_HOST}$1 [R=301,L] Redirect 301 /Features.php https://www.plagiarismguard.com/features-screenshots/ Redirect 301 /Pricing.php https://www.plagiarismguard.com/pricing/ Redirect 301 /Plagiarism.php https://www.plagiarismguard.com/risks-of-plagiarism/ Redirect 301 /Company.php https://www.plagiarismguard.com/about-us/ Redirect 301 /Order.php https://www.plagiarismguard.com/order/ Redirect 301 /TOS.php https://www.plagiarismguard.com/terms-of-service/ Redirect 301 /PrivacyPolicy.php https://www.plagiarismguard.com/privacy-policy/ RemoveHandler .php RemoveHandler .php5 php_admin_value engine Off IPCCommTimeout 31 FcgidMaxRequestLen 1073741824 SSLEngine on SSLCertificateFile /home/plagiarismguard/ssl.cert SSLCertificateKeyFile /home/plagiarismguard/ssl.key SSLCertificateChainFile /home/plagiarismguard/ssl-bundle.txt </VirtualHost>