Running a Django app with Gunicorn and Upstart

Skimmed from here, I mostly just changed the last line that starts Gunicorn from using gunicorn_django to plain gunicorn, as recommended by the Django overlords.

/etc/init/yourapp.conf:

description "Your App"
author "Your Name "

start on (net-device-up and local-filesystems)
stop on shutdown
respawn

script
    export HOME="/root/of/django/app" # i.e. where "manage.py" can be found
    export PATH="$PATH:/root/of/django/app/env/bin" # "env" is our virtualenv
    export DJANGO_SETTINGS_MODULE="settings"
    export LANG="en_US.UTF-8"
    cd $HOME
    exec $HOME/env/bin/gunicorn -b 127.0.0.1:8000 -w 1 --log-file /var/log/gunicorn/yourapp.log app
end script

app.py:

import os, sys

sys.path.insert(0, '/root/of/django/app/')
path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if path not in sys.path:
    sys.path.append(path)

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

Tagged with:

Categorised as:


Basic iptables setup (Ubuntu)

Accept anything coming in from 127.0.0.1:

iptables -A INPUT -i lo -j ACCEPT
    

Accept "related" ("packet is starting a new connection, but is associated with an existing connection") and "established" ("packet is associated with a connection which has seen packets in both directions") packets:

iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
    

SSH; set port (XXXXX) to 22 if you're running the default, which you perhaps should not do as the script kiddies will not leave you alone. If this is changed to something non-default then do not forget to change the port in /etc/ssh/sshd_config (the Port configuration directive) and do these changes coordinatedly. Otherwise you will be locked out.

iptables -A INPUT -p tcp -m tcp --dport XXXXX -j ACCEPT
    

HTTP and HTTPS:

iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
    

NTP, because we're part of the NTP Pool Project:

iptables -A INPUT -p udp -m udp --dport 123 -j ACCEPT
    

Log dropped packets, but not too much:

iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables DROP: " --log-level 7
    

Do the actual dropping:

iptables -A INPUT -j DROP
    

In order to save these settings on shutdown, create the following file in /etc/network/if-post-down.d/iptables:

#!/bin/sh
iptables-save -c > /etc/iptables.rules
exit 0
    

To restore the settings on boot, create the following file in /etc/network/if-pre-up.d/iptables:

#!/bin/sh
iptables-restore < /etc/iptables.rules
exit 0
    

And make the two executable:

chmod +x /etc/network/if-post-down.d/iptables /etc/network/if-pre-up.d/iptables
    

Tagged with:

Categorised as:


Gone DigitalOcean

In order to try something new (and save money) I switched my personal "utility" server from EC2 to DigitalOcean. As I was running just a t1.micro instance anyway, I selected DigitalOcean's cheapest offering, which costs $5/month (512MB/20GB(SSD)/1TB). Plus $1/month for regular backups (they somehow backup the whole server while the server is running, so I'm not sure how consistent said backup can possibly be but at least it's cheap).

DigitalOcean is offering just servers, and the whole experience isn't of course quite as polished as with Amazon. Nor can you, say, access S3 (or other services) at quite the same speed as when in Amazon's network. But for my use case it's a good fit.

Tagged with:

Categorised as:


Autossh with Ubuntu Upstart

Like the title says, the point of this post is getting autossh up when Ubuntu boots. Place this in e.g. /etc/init/autossh.conf, after which you will be able to says things like sudo start autossh and sudo stop autossh.

    description "autossh tunnel"
    author "Joni Kähärä "
	
    start on (local-filesystems and net-device-up IFACE=eth0 and net-device-up IFACE=eth1) # assuming we have multiple interfaces
    stop on runlevel [016]
	
    respawn
    respawn limit 5 60
	
    exec autossh -M 0 -N -R 10000:192.168.1.1:22 -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3" -o "StrictHostKeyChecking=no" -o "BatchMode=yes" -i /home/user/.ssh/id_rsa username@hostname
    

The “start on” line ensures that autossh won’t start before all network interfaces are up, and “stop on” will stop autossh (if it’s running) on runlevels 0, 1 and 6 (halt, single user and reboot, respectively). The “respawn limit” line will ensure that if autossh goes crazy, it will not be started again. Note that the plain “respawn” line is still needed to actually respawn the process. Of the command line options only the first one (-M 0) is for autossh, the rest are regular ssh options.

  • -M 0 denotes that autossh should not set up it’s own monitoring channel and should instead rely on ssh terminating itself when it decides that the connection’s been lost (see ServerAlive* options below).
  • -N means “Do not execute a remote command”, i.e. just set up the connection and port forward.
  • -R 10000:192.168.1.1:22 means that we want TCP port 10000 on the remote host forwarded to port 22 on local host (192.168.1.1).
  • -o "ServerAliveInterval 60" send “keepalive” messages every 60 seconds
  • -o "ServerAliveCountMax 3" terminate ssh if three consecutive ServerAliveInterval inquiries fail (and thus respawn)
  • -o "StrictHostKeyChecking=no" don’t fail if remote server’s identity changed
  • -o "BatchMode=yes" don’t attempt to use a passphrase if public key login fails
  • -i /home/user/.ssh/id_rsa the private key we’ll use for the tunnel
  • username@hostname connect to this host with this username

Tagged with:

Categorised as:


Amazon DynamoDB basics with Boto

The code assumes that Boto credentials have been set up.

      import boto.dynamodb
      from boto.dynamodb.condition import *
      
      connection =  boto.dynamodb.connect_to_region('eu-west-1')
      table = connection.get_table('table')
      
      id = '1'
      timestamp = 1234
      attrs = {
        'key1': 'value1',
        'key2': set(['value2', 'value3'])
      }
      
      # create
      item = table.new_item(hash_key=id, range_key=timestamp, attrs=attrs)
      item.put()
      
      # read
      item = table.get_item(hash_key=id)      
      key2 = list(item['key2'])
      
      # update
      item['key1'] = 'foo'
      item['key3'] = 'bar'
      item.put()
      
      # query
      table.query(hash_key=id, range_key_condition=LT(1500))
      
      # scan
      table.scan(scan_filter={'key1': EQ('foo')})
      
      # delete
      item = table.get_item(hash_key=id)
      item.delete()
      
    

Tagged with:

Categorised as: