Share the Knowledge
RSS icon Home icon
  • How to configure Nginx so you can quickly put your website into maintenance mode

    Posted on April 6th, 2014 webmaster No comments         


    I had to rebuild my Rackspace VPS last night where my Django app runs as I wanted to downgrade it because it was underutilized.  Since I was already at the lowest tier for that category of servers, there’s no option to resize it down, I would need to spin up a new server from a different server category.

    Thanks to Ansible, though, provisioning a new server with all the applications and configurations I needed only took about 5 minutes.  But because of the new public IP that was assigned to this server, I had to change the A record for my domain which could take hours to fully propagate across DNS servers around the world.

    I configured Nginx on my old server to display an “Under Maintenance” page while I wait for the DNS change to take effect.  I figured this is something that would be really nice to be able to turn on and off quickly so I looked for a solution to do so.

    Here’s the solution I found (my configuration is a little bit different from the original source):

    1. Create a custom maintenance page and call it maintenance_off.html

     I forgot where I got this example from, but here’s what I use:

    <!DOCTYPE html>
    <title>Site Maintenance</title>
      body { text-align: center; padding: 150px; }
      h1 { font-size: 50px; }
      body { font: 20px Helvetica, sans-serif; color: #333; }
      article { display: block; text-align: left; width: 650px; margin: 0 auto; }
      a { color: #dc8100; text-decoration: none; }
      a:hover { color: #333; text-decoration: none; }
        <h1>We&rsquo;ll be back soon!</h1>
            <p>Sorry for the inconvenience but we&rsquo;re performing some maintenance at the moment. If you need to you can always <a href="mailto:support@glucosetrac">contact us</a>, otherwise we&rsquo;ll be back online shortly!</p>
            <p>&mdash; The GlucoseTracker Team</p>

    2. Change your app’s Nginx configuration to check if the maintenance page exists

    server {
        location / {
            if (-f /webapps/glucosetracker/maintenance_on.html) {
                return 503;
        # Error pages.
        error_page 503 /maintenance_on.html;
        location = /maintenance_on.html {
            root /webapps/glucosetracker/;

    What the configuration above will do is to check whether a file called maintenance_on.html exists in the specified path and if true, Nginx will return a 503 error.

    Then at the bottom, we’re telling Nginx that for 503 errors, serve the page /maintenance_on.html, which is located in /webapps/glucosetracker/ directory.

    3. Whenever you want to bring your website into maintenance, simply rename maintenance_off.html to maintenance_on.html 

    Nginx will automatically return the a 503 error and serve that page. Rename it back to maintenance_off.html when you’re finished. No restarts necessary.

  • How to deploy encrypted copies of your SSL keys and other files with Ansible and OpenSSL

    Posted on April 5th, 2014 webmaster 2 comments         

    I’ve been working on fully automating server provisioning and deployment of my Django app, GlucoseTracker, the last couple of weeks with Ansible. Since I made this project open-source, I needed to make sure that passwords, secret keys, and other sensitive information are encrypted when I push my code to my repository.

    Of course, I have the option to not commit them to the repo, but I want to be able to build my entire infrastructure from code and maintain all configuration in one place, the git repo.

    Fortunately, Ansible has a command line tool called Ansible Vault (comes with the core package) that will allow you to encrypt your configuration files and decrypt them during deployment by passing in the password or password file in the command.  This is mainly useful for encrypting your environment variables files that contain the passwords/keys for your application.

    For example, in my Django settings, instead of assigning the values directly in the settings file, I do something like this:

    SECRET_KEY = os.environ['DJANGO_SECRET_KEY']

    Django would then read the value from the server’s environment variables.  In my case, since I use virtualenv, I have a postactivate script that sets the environment variables for that virtualenv.

    Since I want Ansible to fully automate my server configuration and store all the information that I need to do so in a git repo, I have to encrypt the variables that my app use in production.  For example, I have a file called production in the env_vars folder of my repo that the playbook will use.  I encrypt this file with a password using Ansible Vault and when running the playbook I decrypt it by passing in the password in the command argument.  If you use CI tools like Jenkins you can then just set this password in Jenkins (perhaps as an environment variable) so you won’t have to type it in manually.

    If I need to make a change in the vars file, I can simply just type in:

    ansible-vault edit env_vars/production

    This will prompt me for the password and display the decrypted values in vim for me where I can make my changes and save it back in the encrypted version.  This is a nice option if you just need to make small changes as you won’t forget to encrypt the file again after decrypting it.

    Here’s what an Ansible Vault encrypted vars file will look like:


    What about files that get copied to the server such as private keys for SSL certificates?

    This is where I had to do something extra as the Ansible copy module will copy these files as they’re stored in the repository (i.e. the encrypted version).  To get around this, I simply used OpenSSL to encrypt these files using symmetric encryption and set the password to decrypt it in my vars file (which Ansible Vault will encrypt).

    To encrypt a file with OpenSSL using AES 256 encryption:

    openssl aes-256-cbc -salt -a -e -in ssl_signed/unencrypted.key -out ssl_signed/encrypted.key -k MysupasecuresecretPasswordZ.x!!

    To decrypt an AES 256 encrypted file with OpenSSL:

    openssl aes-256-cbc -salt -a -d -in ssl_signed/encrypted.key -out ssl_signed/unencrypted.key -k MysupasecuresecretPasswordZ.x!!

    Example vars file:

    # Nginx settings.
    ssl_src_dir: ssl_signed
    ssl_dest_dir: /etc/ssl
    ssl_key_password: MysupasecuresecretPasswordZ.x!!

    I have a task in my playbook that would copy my SSL keys to the remote server and run the OpenSSL command to decrypt it (using the password from the ssl_key_password variable in my vars file):

    - name: Copy the SSL cert and key to the remote server
      copy: src={{ ssl_src_dir }}/ dest={{ ssl_dest_dir }}
    - name: Decrypt the SSL key
      command: openssl aes-256-cbc -salt -a -d -in {{ ssl_dest_dir }}/nginx.key
               -out {{ ssl_dest_dir }}/decrypted.key -k {{ ssl_key_password }}
               creates={{ ssl_dest_dir }}/decrypted.key
    - name: Rename the decrypted SSL key
      command: mv {{ ssl_dest_dir }}/decrypted.key {{ ssl_dest_dir }}/nginx.key
               removes={{ ssl_dest_dir }}/decrypted.key

    Now let’s run the production playbook:

    ansible-playbook -i inventory/production –private-key=/aws-keys/ec2-glucosetracker.pem –vault-password-file=~/ansible/decryption_password -vvvv production.yml

    This is just one example and this same simple concept can be applied to different scenarios.  Just to summarize the steps:

    1. Encrypt your files with OpenSSL using symmetric encryption.
    2. Assign the decryption password to a variable in your Ansible vars file.
    3. Encrypt your vars file using Ansible Vault.
    4. Create a task in your playbook to decrypt the encrypted files using OpenSSL and the password in the encrypted vars file.
    5. Run your Ansible playbook, passing in the Ansible Vault password in the command or specifying the file where the password is stored.

    View my entire playbook here:

  • Django Tip: How to configure Gunicorn to auto-reload your code during development

    Posted on March 30th, 2014 webmaster No comments         

    I just finished fully automating my entire server stack for my Django app with Ansible and Vagrant (using VirtualBox).  One of the reasons I did this is to make my development environment as close to production as possible to hopefully eliminate any surprises when deploying to production.  It also allows me to setup a development environment very quickly as I won’t have to deal with manual installation and configuration of different packages.  In a team environment, the benefit of doing this multiplies.

    This is basically my process:

    1. Type in ‘vagrant up’ to create or start the VirtualBox virtual machine.

    2. I have my virtual machine configured via Vagrant to share my local code (which is located in my Dropbox folder) with the virtual machine.

    3. I make a change to my code, then I open my web browser and enter my virtual machine’s IP which is statically set to  The browser shows my changes.

    What I want Gunicorn to do is similar to what the Django runserver does: automatically reload the application server when the code changes.

    There are different ways to approach this, such as using a package called watchdog to watch the file changes and then restart Gunicorn.  But it turned out there’s an even simpler way to do this with Gunicorn by setting the max_requests setting to 1 (full list of settings).  When calling Gunicorn simply add this option (note that it’s 2 dashes in the beginning):

    –max-requests 1

    What this will basically do is tell Gunicorn to restart the process for every request, which would reload your code.  It won’t know whether your code changed or not, it will always reload it.  For production, this is probably not a good idea, but during development it’s a nice simple trick and you won’t really see a difference in performance as you’d be the only user.

    Here’s the shell script that I use to start my Gunicorn process (note that I use Nginx to communicate with Gunicorn via a socket file, also note that I have variables set here which Ansible replaces with the actual values):

    NAME="{{ application_name }}"
    DJANGODIR={{ application_path }}
    SOCKFILE={{ virtualenv_path }}/run/gunicorn.sock
    USER={{ gunicorn_user }}
    GROUP={{ gunicorn_group }}
    # Set this to 0 for unlimited requests. During development, you might want
    # to set this to 1 to automatically restart the process on each request
    # (i.e. your code will be reloaded on every request).
    MAX_REQUESTS={{ gunicorn_max_requests }}
    echo "Starting $NAME as `whoami`"
    # Activate the virtual environment.
    source ../../bin/activate
    source ../../bin/postactivate
    # Create the run directory if it doesn't exist.
    RUNDIR=$(dirname $SOCKFILE)
    test -d $RUNDIR || mkdir -p $RUNDIR
    # Programs meant to be run under supervisor should not daemonize themselves
    # (do not use --daemon).
    exec python run_gunicorn \
    		--settings={{ django_settings_file }} \
     		--name $NAME \
      		--workers $NUM_WORKERS \
      		--max-requests $MAX_REQUESTS \
      		--user=$USER --group=$GROUP \
      		--log-level=debug \
  • How to find out which web server a website is using with Telnet

    Posted on March 24th, 2014 webmaster No comments         

    Here’s a quick and easy way to figure out what kind of web server a website is using with good, old telnet.  I like this method as most operating systems (both old and new versions) have a telnet client already installed.


    1. Open a command/terminal window.

    2. Telnet to the server/website on port 80, e.g.

    telnet 80

    3. Type the following once you’re connected:

    HEAD / HTTP/1.0

    4. Hit the Enter key twice.

    That’s pretty much it.  You can get the web server in use, version, and operating system that the website is running on.  Here’s a sample output:

    Connected to
    Escape character is ‘^]’.
    HEAD / HTTP/1.0

    HTTP/1.1 301 Moved Permanently
    Server: nginx/1.2.6 (Ubuntu)
    Date: Tue, 25 Mar 2014 02:21:00 GMT
    Content-Type: text/html
    Content-Length: 193
    Connection: close

    Note that the response of the website here returns a 301 (permanent redirect) as the web server automatically redirects to https (which shows next to Location).

  • Living in Barcelona, Spain

    Posted on February 9th, 2014 webmaster No comments         


    I knew a few months ahead of time that I’ll be ending my round-the-world trip in Barcelona, Spain.  The main reasons being that airfare from Barcelona to New York is fairly low compared to other cities and I was told that weather here is still great through late October.  Barcelona is also known to be a very lively city with lots of things going on every day and a good place to meet people from all over the world due to its popularity.  Having a beach also doesn’t hurt.  I spent 5 weeks here and it definitely didn’t disappoint.

    Barcelona was pretty much an unknown city until 1992 when the Summer Olympics was held here.  A local told me that before the Olympics, the beach area of Barcelona was actually very tiny.  Then because of the boom in tourism, it was greatly expanded.  Today, the beaches cover about 3 miles of coastline with plenty of sand area.

    Cost of Living

    Living in Barcelona is definitely not cheap, but still cheaper than living in New York.  Just like in any big city, the closer you are to the center, the more expensive it gets.  Below is a breakdown of my expenses for 1 month of living there.

    Accommodation (including utilities): $1,400 Small studio apartment in the city center.
    Transportation: $26 10-ride subway ticket (x2).
    Food and Drinks: $470 Includes drinks when going out.
    Total: $1,896



    As you can see, my accommodation expense is very high.  The apartment itself wasn’t even that nice, but it had a really nice private terrace with a nice view of Tibidabo.  The private terrace was pretty much what sold me.  I loved waking up in the morning (and sometimes afternoon if I was out late) to have breakfast there, enjoying the nice breeze, and doing some reading.

    Since I was in the city center, my transportation cost was fairly low as I walked most of the time.  A 10-ride subway ticket goes for about 10 euros, a big discount compared to buying the tickets individually.

    Food and drinks weren’t too bad as I didn’t eat out much.  Buying groceries and cooking at home saved a lot of money.  Eating out would run about $15-$20 at a decent restaurant.

    When I go to a bar or a club, I usually just buy a drink or two.  Spanish red wine, if bought at the store, can be very cheap.  You can get a regular-sized bottle of red wine for less than $3.

    Getting Around


    Barcelona is a very walkable city and if you’re staying near the center, you can pretty much get to the popular areas/districts within 40 minutes on foot.

    The city is also bike-friendly and there’s a bike sharing program called bicing, where you pay a subscription fee to use the bikes parked all over the city.  Someone told me that you have to be a resident to use them, though.

    If you don’t like to walk, the subway lines can pretty much take you anywhere in the city.  There are also buses if you prefer seeing what’s around you.

    You can also get to nearby towns/cities such as Sitges by taking the RENFE trains.


    The official language in Barcelona is Catalan, which I heard is kind of a mix of French, Portuguese, and Italian.  But pretty much everyone here speaks Spanish and many people now speak English as well.

    From what other people have told me, English wasn’t really spoken much in Spain until recently.  When I was there, lots of people wanted to practice English, language exchange events were very popular.  This push to learn English might have had something to do with the recession.

    Things to Do

    There are plenty of things to do and see here, and a lot can be done for free.  Here’s a few:

    • Explore the city on foot. Barcelon_Spain_20131020_043
    • Go to the beach (note that in Spain it’s very common to see people topless/nude in public beaches, just a warning if that bothers you).
    • Check out the Sagrada Familia (I’ve only seen it from the outside as entrance is pretty expensive and there’s usually a line of people waiting to get in).
    • Go to Parc Guell, especially if you’re a fan of Gaudi (this used to be free but they started charging sometime last November. I was able to visit it on the last day it was free and it was packed).
    • Watch the sunset at El Bunker and see the city come to life as it gets dark (easily one of my favorite spots in Barcelona, pretty romantic setting, women love it).
    • See a Castelleres, building a human tower.  Very fun to watch.
    • Attend one of the many language exchange events in the city if you want to learn Spanish or Catalan.  You’ll probably find one every night of the week.
    • Watch a Flamenco show.  Some bars offer a free Flamenco show every week.
    • Watch a free fountain light show in Placa d’Espanya.
    • Visit one of the many nightclubs (see if they have some kind of list where you can have your name added, usually on Facebook, so you can get in for free).
    • Go hiking.

    There are also plenty of events to attend.  For meeting people, Barcelona has a lot of very active groups on and a very active Couchsurfing community.  You can also reach nearby towns such as Sitges easily by train.

    Movies Filmed in Barcelona

    • Vicky Cristina Barcelona.  Sounds like a chic flick, but it’s actually a pretty good movie with an interesting story that I think most guys will enjoy as well.
    • REC.  Really good zombie movie. A Spanish girl told me this is probably the best movie Spain has produced.
    • Tengo Ganas De Ti.  This looks like a romantic movie.  I haven’t seen it yet but a Catalan friend told me this made the Bunker site popular because of a sex scene that was filmed there.

    I have to say that I’m really starting to miss Barcelona a lot while writing this post.  Brings back a lot of great memories.  Definitely up there in my list of favorite cities.  Unfortunately, it’s getting expensive so I probably won’t be living here in the future, but it would be nice to come back on vacation and visit some of the friends I’ve made here.