This article describes the reasoning behind designing my self-hosted blog infrastructure.
Table of Contents
Introduction
The idea of starting a personal blog is exciting. Making it happen, however, requires careful consideration of which technologies to use and how to set up the infrastructure. These decisions are rarely straightforward, as there are so many alternatives available today, and without a clear understanding of the priorities, choosing the right one becomes complicated.
My initial goal was to find a tool that, without requiring excessive technical effort, would allow me to focus directly on writing articles and effectively managing content.
Choosing the Right CMS
What better solution than using an existing Content Management System (CMS)? The other option I had, as a software engineer, would have been to design and implement a custom web platform. However, this would have been over-engineering, introducing significant technical overhead and, in a sense, reinventing the wheel to create a personal blog.
Among the various options, I was drawn to Drupal, as I already had experience using it and, especially, customizing its components. Building a blog with Drupal was certainly possible, but it would have taken more time; furthermore, Drupal is a platform designed primarily for corporate websites and highly complex projects.
Consequently, my final choice was WordPress: one of the best-known CMSs for building blogs. Its simplicity made it the ideal choice for my initial goal. If I ever wanted to expand the functionality of my personal space, I would always be free to explore other options by migrating, but as a starting solution, WordPress was excellent.
From Managed Hosting to Self-Hosting
The next step was choosing a hosting method. The hosting landscape, of course, is a world of its own, as, in addition to using WordPress, there were many options I needed to consider: from Managed Web Hosting to Self-Hosting on a VPS.
Here, I encountered my first deviation from the initial goal of having the least possible technical overhead. Indeed, having control of the infrastructure without limitations and the possibility of reusing and extending it for other projects in the future became an important goal. Complete control, however, came at the cost of taking full responsibility for managing the system.
I had decided on self-hosting, but I preferred to wait before choosing a VPS provider, as I first wanted to decide how to install and configure the WordPress environment and, finally, understand and estimate hardware resource usage.
Why I Chose Docker
The most straightforward approach would have been to install all the CMS components directly on the host that would eventually become the VPS. Direct installation, however, had significant implications. First, it would create a tight coupling between the software and the host environment, with a strong dependency on the operating system and its configurations. Such coupling would have made it difficult to reproduce the WordPress stack on another host in the future, requiring everything to be configured again.
Security was another critical aspect: a compromise of the CMS would also directly affect the hosting environment, potentially requiring the entire VPS operating system to be reinstalled.
Additionally, I wanted maximum flexibility and portability for my applications on the host server, as the projects to be hosted were not limited to just the WordPress blog.
Last but not least, the entire infrastructure could be version-controlled alongside the project, making every configuration change traceable and reproducible.
All these reasons were decisive in choosing one of the most well-known containerization systems: Docker.
Deploying the applications in an isolated, reproducible, portable, and version-controlled environment was truly a great solution.
Building the Docker Compose Stack
Moreover, using Docker Compose, I built a set of coordinated containers so that the various CMS components could talk to each other. The simple yet effective idea was: one service = one responsibility.
From this point on, the approach was incremental but above all exploratory. In addition to the basic services required for WordPress to function, the idea was also to add others, such as utility services, to automate certain processes, including database initialization, synchronization, and backups.
Automation was also made possible thanks to the use of shell scripts executed within the various containers.
I performed the implementation and testing on my local computer, where I had installed Docker Desktop. The strategy was to split the Docker Compose configuration into three files. The first would contain the base configuration. The second would add everything needed for local development. Finally, the third file would include the production-specific configuration for the VPS.
I opted for these environment overrides because the production environment is much more demanding, requiring resource management, logging, and specific configurations for the various services and their interactions.
An optional but very useful tool was a Makefile. Instead of typing out all the Docker Compose commands each time, I simply mapped the various targets with their specific commands in a separate file. The Makefile allowed me to automate multiple operations both on my local computer and on the host.
Adding Continuous Integration was another optional step to perform a basic validation with each push or pull request. The checks were intentionally minimal and included linting the Docker Compose files, POSIX shell scripts, the Makefile, and Markdown files.
Separating the Reverse Proxy
At a certain point, I realized that, from an architectural perspective, it would be better to create another repository alongside this one, extracting all the Nginx reverse proxy logic and certificate management. The separation added complexity, but from an extensibility and modularity perspective, it was a sound choice. Indeed, if I wanted to install another web application on my server in the future, it would have been enough to reuse the same repository as the single entry point capable of routing requests to the specific application while centrally managing SSL/TLS certificates.
Choosing the VPS Provider
The final step was to decide on a domain name and, more importantly, a VPS provider. After some research, I concluded that OVHcloud met both my needs. What immediately stood out to me was the availability of more resources at the same price. Furthermore, the provider enjoyed a good reputation among users, making the decision straightforward.
After purchasing, I applied the basic security configurations by following the excellent documentation provided. I also really appreciated the VPS’s daily backup feature: in case of errors or specific needs, it allowed me to quickly and easily restore a previous state.
Final Thoughts
In conclusion, this whole process was a great experiment for me. I admit that initially I wanted to save technical time on the CMS side, but then, ironically, I spent much more time on the DevOps side, giving in to over-engineering. There are certainly existing solutions on GitHub that could have reduced the amount of work involved.
That said, I invite you to take a look at my two repositories for this project, covering the Nginx reverse proxy and the WordPress stack, respectively.
- Nginx Reverse Proxy: Reverse proxy configuration and certificate management.
- WordPress Docker Stack: Docker Compose configuration for the WordPress environment.
Thanks for reading.

