Samizdat

How I self-host my blog with Docker & Ansible

I have always wanted to build a blog, but for a long time, I have been postponing it.

Well, I guess I thought it was difficult to build a blog. Turns out, even if you self-host it, it’s not that hard.

I decided to finally create it one day, and I had a few criteria:

Considered options

Self-hosting

Self-hosting has never been so easy, the only hard requirement is to have a Linux server costing $5 a month for 25GB SSD, 1GB RAM and 1vCPU.

I have selected Hugo for site generation because it is very popular, has a large supportive community, uses markdown, and has a lot of free themes.

Packaging

Packaging and distribution is done using Docker. This is how tiny my Dockerfile looks:

FROM alpine as build
RUN apk add --update --no-cache hugo
WORKDIR /srv/http/
COPY . /srv/http/
RUN hugo -e production

FROM nginx:alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /srv/http/public /srv/http/
WORKDIR /srv/http/

This ends up as a Docker container with Nginx and static HTML and CSS files.. The docker image is approximately 52MB in size.

Just two commands and the blog is ready for deployment:

$ docker build -t kovetskiy/my-blog .
$ docker push kovetskiy/my-blog

Deployment

A manual way of deployment and an automatic way are available.

Manual way

Manually, on the remote host, you would end up with commands like:

Automation with Ansible

A playbook is a list of tasks that should be executed to accomplish the desired status. In my case, it is pulling of the Docker image and starting a Docker container.

The playbook is saved as a file called my-blog.yaml:

- hosts: my-server
  tasks:
    - name: Pull image
      docker_image:
        name: kovetskiy/my-blog

    - name: Start container
      docker_container:
        name: my-blog
        detach: true
        image: kovetskiy/my-blog
        restart_policy: always
        state: started

Ansible needs a bit of project-wide configuration, it just has to understand how to connect to this my-server server.

To tell Ansible where the list of server is, put the following content into ansible.cfg:

[defaults]
inventory = hosts

Add your server into the hosts file and replace 123.123.123.123 with the host’s IP address:

[my-server]
123.123.123.123

The deployment will be done with one small command from now on:

$ ansible-playbook my-blog.yaml

Recap

I also self-host an open source comments system without sacrificing any privacy. 👇


Comments