Wednesday, March 18, 2015

Django and cPanel

In my day job I work on cpanel systems with Centos 5 and 6. I have installed django on my system using a manual installation process.

The following describes hopefully enough to get you close to the following setup:

  • Centos 6
  • Current cPanel installation
  • mod_wsgi for apache
  • Python 3.4.3
  • django 1.7
  • a working django install on one subdomain

For Centos 6 and cPanel, you'll need these installed already, operating systems updates on your host are outside the scope of this guide.

Install Python 3.4

You'll need a current Python version to run the latest django. Get it from You should build this with the following options, the prefix /usr won't hurt anything the way it would for python 2.7, since the redhat tools in centos use python 2.6. It's possible to install to /usr/local/ or alternate locations by later either adding this to the ldconfig information, or to the build instructions for mod_wsgi. Putting this in /usr, though bad discipline, appears the path of least resistance. Note here make install will require root privileges.: ./configure --enable-shared --prefix=/usr make && make install

After this, executing "/usr/bin/python3.4 --version" should show 3.4.3, and all is well (you should install the latest available python from the download link, 3.4.3 was current as I wrote.)

Install mod_wsgi

There exists a mod_wsgi EasyApache Custom Opt Module that will make wsgi a menu option at build time. This is preferable to other manual installation methods for a few reasons, the principal being that all others are likely to break on easyapache rebuilds. If you have managed hosting, that may have been initiated by your host rather than directly by you, and you might not like waking up to broken sites. So we'll play the cpanel way. EasyApache documentation has a link to a google code project to build this, it's a little dated, but we'll start from there. Get the module from this comment, then wonder why code is being linked from comments. Mind the date (Feb 2013, right now about 24 months old, and a few versions back). This has earlier instructions for installation, specifically, after download, extract to the easy apache directory: tar -C /var/cpanel/easy/apache/custom_opt_mods -xzf ModWSGI.tar.gz

This however, bundles version 3.4 of mod_wsgi, and nobody seems to be repackaging it. Let's get a current version (check the source for the current version): wget -O \ mv -v /var/cpanel/easy/apache/custom_opt_mods/Cpanel/Easy/{,-3.4} cp -av /var/cpanel/easy/apache/custom_opt_mods/Cpanel/Easy/

This will give us a current version of mod_wsgi, we'll need to tell easy apache to use that. If you're curious, run your editor on the /var/cpanel/easy/apache/custom_opt_mods/ perl source for this module, and look for the src_cd2 line, update that to mod_wsgi-4.4.9 from mod_wsgi-3.4 (what came in the module bundle earlier). If you're not interested in how easy apache modules are built, just run the following, which backs up the file, then replaces the old version with the one we made (this is in fact the name of the directory created when you extract the tar archive): cp -av /var/cpanel/easy/apache/custom_opt_mods/Cpanel/Easy/{,.save} sed -i 's/mod_wsgi-3.4/mod_wsgi-4.4.9/' /var/cpanel/easy/apache/custom_opt_mods/Cpanel/Easy/

One final thing, this will default to using the system python version. We're cutting edge, we'll use the latest python 3 version we installed above, so we'll need to modify the call to configure to include that. If you still have your editor in the perl file, you'll see the configure command options in the qw quote call, and it's easy to add the needed --with-python argument, otherwise, sed does this for us: sed -i \ 's;bin/apxs;bin/apxs --with-python=/usr/bin/python3.4;'\ /var/cpanel/easy/apache/custom_opt_mods/Cpanel/Easy/

Now run EasyApache (/usr/local/cpanel/scripts/easyapache) and check mod_wsgi. If you get any errors, either you or I did something wrong. I'd love to hear if that happens, and might be able to help. Fortunately, failed builds default to restoring the previous setup, so there's little danger in getting it wrong, and if apache won't compile, you won't break everything else. I would recommend using the least changes possible, so do this with the last working build, and only change adding mod_wsgi from the options menu.

Install Django

Since this will be a system wide feature, and I'm not going to delve into virtualenv + virtualhosts, let's just install django, at this time, the target was 1.7.6, but version numbers get bigger every day: pip3.4 install django==1.7

Install a Django site

You should really consult either a basic django book, or the official tutorial (make the polls app). However, assuming you know what you're doing, at this point, you should be ready to run django-admin as one of the users. Let's pretend we're starting the polls app: django-admin startproject polls

This isn't 100% ready to run, let's spiff it up a little. cd polls cp -av polls/ ./ EDITOR

You'll need to add the following to your to get python able to find any custom modules in your current site (which is not in the path):

import sys
Let's define a STATIC_ROOT for django in as well:
STATIC_ROOT = os.path.abspath(os.path.join(BASE_DIR, '../static'))
Now let's let apache know about this. Let's add this to a custom user include (in /usr/local/apache/conf/userdata/std/2_4/USERNAME/DOMAINNAME/django.conf, or whichever include directory is listed in your virtual host definition in httpd.conf, which you'll also need to uncomment to get this to load):
WSGIDaemonProcess USERNAME-django display-name=USERNAME-django user=site processes=2 threads=15
WSGIScriptAlias / /home/USERNAME/polls/

Alias /static /home/USERNAME/static

<Directory /home/USERNAME/static>
    Require all granted

Finally, we'll set django to collect the static elements (you know, so admin isn't ugly, and things work correctly): python3.4 collectstatic

Make it run? If this does not say ok, and emits any syntax errors, then restarting apache is a BAD idea: httpd -t If you're in the clear, restart: httpd -k restart

Sunday, March 08, 2015

Disable PHP execution in a directory

For a while it has bothered me that code was able to be loaded to wp-content/uploads on a wordpress site, then executed (for example, loading php code in a gif image is a common tactic). I've decided to enable a no-execute line, but wasn't' sure how to do it. My first attempt follows.

Add to the htaccess file in the directory to block the following directive (basically disabling execution of php files):

AddType text/plain php
The idea may need refinement, basically, no code will run. If you have other code extensions calling handlers (like .php5 or .pl or similar), then the line would change. I'm not sure this is 100% desired, but does change my test program from executing to returning the code, I used echo("running") as my example. Since there's no code handler for text/plain, the server sends it to the client directly, maybe with compression, but with no backend processing. This seems adequate to default a large chunk of malicious upload exploits.

Tuesday, November 25, 2014

Turnkey Internet

I've been playing around with Digital Ocean's cloud servers lately, and appreciated the time to destroy and allocate VPS servers. They've been rock solid, and I can't complain about the price. This week, Turnkey Internet had their black friday deals. $10/mo for a 4GB Ram, 4 core, 40GB disk VPS is a pretty good deal. Turnkey uses Xen for paravirtualization, which should be fine.

My first disappointment or surprise was that they advertised debian 7 wheezy as a target, but only allowed preinstallation of squeeze. This for me is a pretty big deal, because I'd like the deployment environment and the development environment to be the same. Right now all my home computers (except this laptop) are on wheezy, and will likely be for a while. Since I have in the past done a squeeze to wheezy upgrade in situ (without reimaging), I'm curious how this will go in a VPS where the kernel is not under my control. I always do this wrong, that is, not doing it first. Upgrading takes longer when you have additional packages installed. Afterword - that failed. The remote console also failed to help - this was showing a public key rejected, suggesting the "PasswordAuthentication No" option I'd set in the sshd_config was being read by the 'serial console' (strange). However, at that point, having destroyed the OS and left it in an unbootable position, it looks like installation of a debian 7.2 system is supported once you log in to the control panel area.

They have a pretty strict policy about spam (thats good), at least on paper, including surprisingly punitive service fees for addressing complaints. It looks like they don't delegate the PTR records, so that might be my first support ticket. Right now this resolves back to I'm not sure whether I care enough to pursue this.

Sunday, October 26, 2014

Interactive Programming in Web2py

I've been working on Beth's website over the past few months. I find the easiest way to work through building the logic is to leave the views empty in the controller, and work with the web2py debug view to get the locals(), when this is working, I can move on to the next step. I find I'm making a few temporary lists to hold intermediate results, and inspecting. The web browser is a pretty useful tool for what' essentially printf debugging. I haven't used the other debug tools much, but I think the tickets (unless the model gets so wrong the tickets won't load) are a good way to return to a stack trace, and present both a developer view of open issues, and allow the user to forward a link to the website.

I had initially been working live, which was nerve wracking when the changes would break a migration and take down the site. I think having many controllers is better for small local changes, since broken code in the same file can prevent interpretation. I might have structured this differently if python could ignore some blocks...

I just wish that the wsgi setup on cpanel servers weren't so counter-productive. I currently have a cron to ensure the socket is owned by the site user, since it defaults to root/nobody, and under cpanel's configuration (maybe this is suexec related), the account doesn't have access to the wsgi server.

Sunday, September 28, 2014

GPG and You

Last night I was reading through PGP & GPG - Email for the Practical Paranoid, and found this marvel of a tip when talking about non-repudiation.

WARNING Do not digitally sign email while drunk or emotional. Sending email at all in such a state is very inadvisable.   

I think they're right.

Wednesday, September 03, 2014

Ad Block and Do Not Track Me

I still use firefox. I know it's a little silly to post on a blogspot site that I don't have full faith in google to play nice, but I trust mozilla, and I know what it's doing. Plus, it still uses metaphors I've grown to love, like urls, menus with words, and so on. I know it's very 1993 of me, but it's what I expect from a user interface. Due to paranoia, I log out of google except to use their services, which I pop in, work, pop out. You're unlikely to 'hang out' with me in plus.

Using Firefox, there are a few addons that I prefer to use. Apart from some utility types (show ip/dns information for all pages), the ones I most commonly install are adblock plus (the internet is a very different place with this disabled) and Do Not Track Me. One thing I've started noticing is that the number of tracking requests being blocked seems to go down about 50% when ads are being blocked. I guess one or the other is effective in decreasing the noise to signal ratio, and the combination playing off each other seems particularly effective.

Sunday, August 17, 2014

First Javascript function

Well, I put it off for years. Today I wrote an (albeit short) javascript function to toggle a check. I find the checkbox with the name specified, and set it to on. I meant to have a much more rich selection of all items by name, but I was getting confused between the code I was using to call this, and the code I was writing in.

I think the web developers deserve credit for existing in three levels and three languages simultaneously (php/perl/python/ruby/whatever for programming the server, html/css for presentation, and javascript for manipulating the page content and animations). When I was using lisp more, I think I would have solved this problem by moving one syntax into each of the three domains, and maybe adding a translation to the outside language. I'd have to look more into hunchentoot and seaside to see if this is how those are done. It looks like the dominant pattern now is a rich set of client side processing in javascript/jquery, and a gradually thinning server side logic for persistence and ubiquity.  I don't think I can ignore javascript any longer, and may need to make this my next language (along with relearning python at a functional competency.)