This post is part 4 of the "Building a Blog" series:

  1. Building a Blog: Overview
  2. Building a Blog: Generating Static Files
  3. Building a Blog: Authentation
  4. Building a Blog: Deploy

Finally the last step: deploy! In the final step, we will setup a server with a custom domain, SSL support, and automatically updates on a git push.

We'll use uWSGI to run the flask application, use systemd to manage uWSGI services, use nginx for reverse proxy and SSL, and finally use gitlab CI to trigger update.

Note that if all you want is static blog, you can do this using like gitlab pages with minimal configuration. All the uWSGI, systemd services, nginx staff is because you need to run a flask application. While there'are some SaaS, I decided to use a nano instance from vultr.

System Prep.

After creating a new server, you need to change some configurations like user, privilidge, ssh, firewall etc. It's important that you do not run your web applications with root user for security reasons. I suggest following this fantastic tutorial from Digital Ocean by Mitchell Anicas. Note that it's recommanded to setup a dedicated user for the hosting, and also disable password ssh logins.

Deply Flask Application

There's a section for deploying in the flask documentation. I tried gunicorn and uwsgi, personally I found uwsgi easier to understand. It's fairly simple, write a configuration file, and a systemd unit to manage it. I basically followed this tutorial by Justin Ellingwood. There's also a tutorial on systemd unit files. You may want to setup a virtualenv for your blogs.


Once the falsk application is ready, we need to configure nginx to pass web requests to that socket using the uwsgi protocol. It's not difficult too, just a configuration file, also described in the tutorial above. There's a installation and manage tutorial here. Just change the server_name and location, and you are mostly done. Nginx can be handy when you are serving more than one domain on the same server.

There's somthing not covered in the tutorial: SSL. And this part is simple too. If you already have a certificate, a settings example is already included in the DEFAULT nginx site; if you are using Let's Encrypt, it will write it for you!

You should be able to see your site with your browser now!

CI Integration

Now we have a server runing our blog, but it's a seperated island. We need it to be updated automatically when we push our commits. We can do this with continuous integration service.

Gitlab's ci service is defined in a special yaml file named .gitlab-ci.yml, you can configure an update routine as a job. Either you can build and generate static files, sync theme, then trigger your server's update job, or you can generate pages on your server too, then on the server you need to 1. pull master; 2. stop service; 3. generate content 4. start service. You can use Makefile to simplify the commands.

One thing worth mentioning is, we ssh to the server as a low privilidge user, but root is required to use systemctl to manage service. We can use sudoers to give a user right to run a specific command, see this answer for your reference.

Now we have a personal blog running in complete customizable way.