Running a single web server is a gamble. No matter how stable your hardware is, maintenance updates, accidental misconfigurations, or hardware failures can take your site offline instantly. In a professional environment, we solve this with High Availability (HA)—running multiple copies of the server so that if one goes down, the others pick up the slack and share the workload.
Typically, setting up HA for dynamic CMS sites like WordPress is complex because you have to synchronize two things: the database and the files (uploads, plugins, themes, core files).
In this guide, we are tackling the file synchronization and traffic routing aspect. We will transform a standalone Nginx web server into a resilient cluster using Proxmox for virtualization, OPNsense (HAProxy) for load balancing, and Syncthing for real-time, peer-to-peer file replication. By the end of this tutorial, you will have a setup where you can reboot one server while your website stays online, with file uploads syncing between nodes automatically.
Initial situation
- One web server VM running nginx with a PHP module that supports running WordPress sites.
- WP Core files will be managed via another solution (Gitea source version control), we will only tackle the ‘/uploads’ folder.
- VM runs on a headless Debian 12 or 13.
- You have OPNSense with HAProxy installed as a plugin OR a separate HAProxy server that you know how to handle already (screenshots provided are from OPNSense).
Where are we trying to get
- Have two or more web server VM instances running on preferably different hardware (such as two Proxmox hosts).
- We want to split traffic that reaches HAProxy between the two or more web server instances.
- If a user uploads a file, it will become almost immediately available on the other web server VM(s).
What we will do in a nutshell
- Clone a VM from one proxmox node to another and change its network configuration on OPNSense.
- Set up HAPRoxy on OPNSense (new back-end, new front-end, rules, etc.).
- Verify that traffic goes between the nodes correctly while there is no sync between them.
- Set up syncthing on each web server VM to transfer files whenever there is a change. Verify it by uploading a file in WordPress.
- Consider limitations of syncthing to justify using Gitea for WP core files, plugins and themes.
What we are NOT addressing in this article:
- VM web server security hardening / nginx set up – it is assumed you have that handled already.
- DB high availability – check out my other article on that one.
- The deployment of Gitea for WP core, plugins and themes – a separate tutorial will be needed for this.