To My Children

We’re buried in about 3′ of snow right now and you guys seem to be okay with it.

20150207_140059B, You’re sledding every chance you get which means I get to enjoy the hill too. We built a luge-type track extending all the way to the bottom of the hill with a “starting gate” that you’re sitting on here. There’s a ramp at the bottom that suits you just fine; I end up crashing through it and getting a face full of snow.

20150207_142221C, Still a challenge getting you to sled, but you love “constructing” the snow pile that the plow leaves at the end of the driveway. We played “treasure hunt in the snow over the weekend, We stuck our shovels into the ground, walked back to the garage and went back out to find them.

Speedwork Log

Trying to keep myself accountable on speedwork days…
Calculate time using http://www.csgnetwork.com/timescalc.html

01/13/2015 – 3 x 1 mi @ 7:55 / 2 min rest / Oxford Greens
01/19/2015 – 6 x 800 m @ 8:00 / 1 min rest / Riggs-Greenbriar-Autumn Ridge-Oxford Greens-Riggs
02/03/2015 – 4 x 1 mi @ 8:10 / 2 min rest / Treadmill 1.0 incline
02/10/2015 – 8 x 800m @ 8:05 / 1 min rest / Treadmill 1.0 incline (do these at 8:00 or 7:55 next time)
02/17/2015 – 8 x 400m @ 7:45 / 30 sec rest / Treadmill 0.5 incline (down for race)
03/10/2015 – 6 x 800 m @ 8:00 / 1 min rest / Riggs-Greenbriar-Autumn Ridge-Oxford Greens-Riggs

To My Children

20150111_101150B, We went sledding this weekend. We were both riding down in a tube together and were going a little too fast. We ran right over a red bud tree we got from aunt Cheryl’s yard; snapped it right off at the base. As I hid the pain that shot through my leg you looked over at me laughing… “That was cool dad, right? Let’s do it again.”

20150109_174526C, I can get you to go down the hill sledding with me once or twice every time we get out into the front yard, but that’s about it. Despite your daringness and couch-flying aptitude you’re still a little unsure about the sledding thing. That doesn’t stop you from coming out side and slicing down all the enemy snow with your toy sword.

To My Children

20141231_194529C, We let you stay up late for New Years eve last night. Your mom and I should have put you to bed after you made yourself a bed in the living room. Instead, we let you stay up and you fell with a noise-maker in your mouth and scraped up your throat pretty food. You were a trooper though, as always.

20150103_142352B, It snowed and I wanted to take a walk on the bridal trail. Mom and C wouldn’t come, so you and I went out for a 1/2 mile walk. You spent most of the time drawing things in the snow with a stick. It was a slow walk.

Create a Django ContentType/Model Without a Table

We needed to have a contenttype in the django_content_type table to support one of our apps, but the particular model/contenttype didn’t have any instances. Here’s what we came up with to get something “artificially” inserted into that table with a proxy model so that when you run syncdb it will create the appropriate record in django_content_type.

class FakeModel(ContentType):
    """
    Model to create a content_type in django without having to create tables associated with the model.
    """

    class Meta:
        proxy = True

    def save(self, *args, **kwargs):
        ct, created = ContentType.objects.get_or_create(
            name="press_release", app_label=self._meta.app_label
        )
        self.content_type = ct
        super(FakeModel, self).save(*args, **kwargs)

Finding All Related Objects to a ContentType in Django

This is a handy little script for finding all related objects to a given ContentType in Django. It essentially is doing the same thing as Django-Admin when you delete an object and it lists for you all of the things that will get deleted along with that object. Super handy when for finding out what’s going to be affected when you delete stale contenttypes from your system while running syncdb, too.

from django.contrib.contenttypes.models import ContentType
contenttype = ContentType.objects.get(id=1)
related_objects = [rel.get_accessor_name() for rel in contenttype._meta.get_all_related_objects()]
 
for rel_object in related_objects:
    objects = getattr(contenttype, rel_object).all()
    for object in objects:
        print object

Setting up uWSGI, Nginx, Flask and MySQL on Ubuntu

I had a difficult time getting this stack to work properly, so I thought it might be nice to document publicly.  The goal was to setup a system on a small VPS that is able to handle a lot of simple requests that burst quickly. We’re getting a request that looks like mydomain.com/123.html and we need to update a database record based on the requested file. I’m used to using a Django/Apache stack, but I wanted something that wasn’t as bloated, so I decided on Flask and Nginx.

All of this system setup stuff is optional. If you already have a system up and running you can probably skip it. The only important note is that I’m creating a user called admin, adding that user to the www-data group and storing my virtualenvs in my /home/admin directory.

Setup System

Create user with a home dir and using bash as shell

sudo useradd -s /bin/bash -d /home/admin -m admin
sudo passwd admin

Add user to sudo/www-data group

usermod -a -G sudo admin
usermod -a -G www-data admin

Disable root login from ssh. Open the ssh config file

vi /etc/ssh/sshd_config

Update PermitRootLogin, set it to no

PermitRootLogin no

Log out as root and reconnect as admin

exit
ssh admin@yourhost

Add hostname; edit the hostname file and enter yourservername.

sudo vi /etc/hostname

Edit hosts

sudo vi /etc/hosts
127.0.0.1 localhost
127.0.1.1 myhost myhost.mydomain.com

Add internal IP to interfaces, final file should look like this:

sudo vi /etc/network/interfaces

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0 eth0:0

# eth0 - This is the main IP address that will be used for most outbound connections.
# The address, netmask and gateway are all necessary.
iface eth0 inet static
 address xxx.xxx.xxx.xxx 
 netmask 255.255.255.0
 gateway xxx.xxx.xxx.1 

# eth0:0 - Private IPs have no gateway (they are not publicly routable) so all you need to
# specify is the address and netmask.
iface eth0:0 inet static
 address 192.168.1.xxx 
 netmask 255.255.128.0

Install Software

sudo apt-get update
sudo apt-get install -y nginx uwsgi
sudo apt-get install uwsgi-plugin-python
sudo apt-get install python-pip
sudo pip install virtualenv
sudo pip install virtualenvwrapper

Setup Virtualenv

sudo mkdir -p /srv/myapp
mkvirtualenv myenv
workon myenv
pip install Flask
deactivate
sudo chown -R www-data:www-data /srv/myapp

Configure Nginx

Delete the default config and create a new config file:

rm /etc/nginx/sites-available/default
sudo vi /etc/nginx/sites-available/mysite

Paste into your new config file:

server {
     listen   80;
     charset utf-8;
     root /srv/myapp;
     server_name myhost.mydomain.com;

location / {
     include uwsgi_params;
     uwsgi_pass unix:/tmp/uwsgi.myapp.socket;
     uwsgi_param UWSGI_PYHOME /home/admin/.virtualenvs/myenv;
     uwsgi_param UWSGI_CHIDIR /srv/myapp;
     uwsgi_param UWSGI_SCRIPT index; # this should be the .py file name without suffix
     }
}

Symllink config

cd /etc/nginx/sites-enabled
sudo ln -s ../sites-available/mysite .

uWSGI

Add config file.

cd /etc/uwsgi/apps-available/
sudo vi myapp.ini

Paste into new config file:

[uwsgi]
plugins = python
socket = /tmp/uwsgi.myapp.socket
pythonpath = /srv/myapp
# This line below was important
callable = app
# Turn this off for production
catch-exceptions = true

* I got close following some of the other tutorials I list below, but “callable = app” was missing from a couple, or it’s possible that I missed it in the long lines of people running uWSGI from the command line using arguments rather than .ini files.

** When I started trying to debug this app I couldn’t get uWSGI to log or display any error messages. This was very frustrating.  Adding “catch-exceptions = true” was the first step in having the ability to see errors. The other will come later when we’re writing our application.

Symlink to config.

cd /etc/uwsgi/apps-enabled/
ln -s ../apps-available/myapp.ini .

Application

Create python/flask application file.

/srv/myapp/index.py

Contents:

from flask import Flask
app = Flask(__name__)
app.debug = True  # Turn this off for production

@app.route('/')
def hello_world():
    return 'Hello Flask.'

if __name__ == '__main__':
    app.run(host='0.0.0.0')

* The “app.debug = True” was the other gotcha that I needed to add in order to display meaningful debugging output in my browser. Apparently app.debug in your Flask app will cause it to throw meaningful error messages and adding catch-exceptions to uWSGI config will pass them onto your web sever, in our case, Nginx.

Restart Services

sudo service uwsgi restart
sudo service nginx restart

After you restart your services you should able to go to myhost.mydomain.com and see the “Hello Flask” message. Any changes after that to your index.py file don’t require restarting nginx, just modify your app and restart uWSGI.

I also needed to access a database, so I added MySQL to the mix.

Add MySQL Support

sudo apt-get install libmysqlclient-dev
sudo apt-get install python-dev
workon myenv
pip install flask-mysql

Resources

Primarily:
http://fclef.wordpress.com/2013/01/12/bottle-virtualenv-uwsgi-nginx-installation-on-ubuntu-12-04-1-lts/
http://serverfault.com/questions/412849/uwsgi-cannot-find-application-using-flask-and-virtualenv
http://stackoverflow.com/questions/18753085/uwsgi-no-app-loaded-going-in-full-dynamic-mode
http://flask-mysql.readthedocs.org/en/latest/
http://stackoverflow.com/questions/10364854/flask-debug-true-does-not-work-when-going-through-uwsgi

Additional Resources that may have helped:
http://vladikk.com/2013/09/12/serving-flask-with-nginx-on-ubuntu/
http://conra.dk/2012/05/06/flask-uwsgi-nginx-ubuntu.html
http://eshlox.net/en/2012/09/11/nginx-uwsgi-virtualenv-and-django-ubuntu-1204/
http://stackoverflow.com/questions/15179836/how-to-configure-pythonuwsginginx
http://stackoverflow.com/questions/12647266/where-is-virtualenvwrapper-sh-after-pip-install
https://uwsgi-docs.readthedocs.org/en/latest/tutorials/Django_and_nginx.html
http://stackoverflow.com/questions/12201588/uwsgi-unrecognized-option-module-myproject-wsgiapplication