In this post, I show how I set up this blog step-by-step from square one using DigitalOcean, Flask, Python, Gunicorn, MongoDB and nginx.


If you want to learn how to set up a blog from scratch, on your own Linux server, and learn everything involved, this article will explain that to you. I will be assuming the reader is a complete beginner, and explain everything as thoroughly as possible. The open-source blog software we are going to use is not perfect, but that leaves you the opportunity to dig into some basic web code and improve it yourself. Without having to start from zero.

I will be using DigitalOcean as my hosting provider. Using this link, you can get 2 months of their lowest-tier VPS for free. If you choose to use them as your provider, set up a droplet with the following settings. If not, you will need a Linux image (preferably Ubuntu or this tutorial will be hard to follow) with the following packages installed:

[code] MongoDB Python 2.7+ Gunicorn Nginx Virtualenv [/code]

If you don't want to pay for a cloud server to practice on (0.7ยข per hour!), I recommend using VirtualBox to install Linux and get up and running. Or maybe you're already using linux, or have a linux computer at home you can try on.

Setting up the Droplet

After logging in to your account, set up a droplet with the following settings.

DigitalOcean droplet creation settings

If you are familiar with SSH keys and how to use them, you should choose to use that option. If not, create the droplet and a root password will be emailed to you.

Using Secure Shell to access your server

Once the droplet is finished creating, you will receive an email with a root password. You will need to access the server using SSH. If you're on windows, you'll need an SSH client such as PuTTY. If you're on MacOS or Linux, you can simply use the SSH program from your terminal. That command would look like: ssh root@your_server_ip You will be prompted for the password from the email you received earlier.

In PuTTY, you will enter the IP in the Host Name field like so: PuTTY connection screen

Then click Open.

You will receive a popup window asking you to confirm the identity of the server, click Yes and you will be prompted for your username and password. Enter root for the username then your password.

Once you're logged in, you will be prompted to change the password for the server. Enter the password again, then your own password that you will remember. When you're done, you'll be released into the command prompt and we can start setting up the Flask Blog

SSH First Login

Setting up the Blog Software

We will be using an open source project from GitHub for this. (The same one I used to make this blog!) First, we need to install Git on our server so we can download the repository. To do this, simply enter the command

apt-get install git

in your terminal.

Installing Git

Once it's finished, we need to create a directory to download the repository to. To do that, execute the command

mkdir -p /app/blog && cd /app/blog

Now, we need to make a 'clone' of the software we're going to use.

git clone

Cloning flask-blog

Then, cd into the directory that was created.

cd flask-blog

Once that's done, we're going to create something called a Virtual Environment. This allows Python programs to run inside of a semi-sandboxed environment, that is limited to packages installed within the virtual environment. It sounds harder than it is, so simply execute the following commands:

virtualenv ./venv source venv/bin/activate You will then get a (venv) on the beginning of your terminal prompt.

Creating the Virtual Environment

Installing Dependencies

The first thing we need to do, now that we have our code and the environment to run it in, is install the dependencies. Luckily, the developer provided us with a list of dependencies! All we have to do, is tell pip, python's package manager, where the list is. Pip will handle the rest for us.

pip install -r requirements.txt

Installing Dependencies with Pip

We also need MongoDB for flask-blog to work properly. All we need to do for that is:

apt-get install mongodb

Once it's finished we can finally...

Run the WSGI server!

We are using Gunicorn as the WSGI server for our app. To run it, just execute the command

gunicorn -D web:app

Running Gunicorn

You can also run ps aux | grep gunicorn to confirm that it's running. ps aux lists all processes running on the machine, and grep does a text search for the argument gunicorn in the output of ps by using something called a pipe. Try running ps on it's own, and you'll get much more output than you see above!

Setting up the nginx reverse proxy

In order to make the blog publicly accessible, we need to tell our public-facing webserver, nginx, how to communicate with our instance of gunicorn. We will need to edit the configuration files located in /etc/nginx/sites-available

So first, we need to get to where the configuration files are, and then edit them. We will be using the Nano text editor to change the configuration files. We're going to copy the content of the default django configuration, so we have something to work with. We need to do a few things here as well, so we don't have multiple websites trying to run on the same port and IP.

Delete the django symlink in /etc/nginx/sites-enabled

rm /etc/nginx/sites-enabled/django

Copy the django config to a new file called flask-blog in /etc/nginx/sites-available

cp /etc/nginx/sites-available/django /etc/nginx/sites-available/flask-blog

Now, using nano, we will edit this configuration file to work for our setup. First, a couple of nano commands you should know are:

  • Arrow Keys - Navigation
  • Ctrl + K - Remove (cut) an entire line of text out of the file
  • Ctrl + O - Write file changes to disk
  • Ctrl + X - Exit nano

Now, open the configuration file flask-blog in nano and edit the contents to match this:

upstream app_server {
    server fail_timeout=0;

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /usr/share/nginx/html;
    index index.html index.htm;

    client_max_body_size 4G;
    server_name _;

    keepalive_timeout 5;

    location /static {
        alias /app/blog/flask-blog/static;

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://app_server;

Then, we need to create a symlink (a.k.a shortcut) to this configuration file in /etc/nginx/sites-enabled so that nginx knows that we want it to use that configuration file. Follow these steps to enable the configuration file:

[code] cd /etc/nginx/sites-enabled ln -s /etc/nginx/sites-available/flask-blog . service nginx restart [/code]

Finalizing nginx configuration


Then, at the end we restart nginx and the blog app should be available at the IP of your droplet!


Now, you can continue with the setup of your blog, and dig into the code in /app/blog/flask-blog to make it your own! Good luck!