Hey all! You asked for it, so here it is. I’ma drop a diagram here and will refer to it throughout the rest of this post:

Our infrastructure
In simple terms, the way it all works is we have our protected servers in the backend.
PERSISTENCE
We run our postgres database defensively with 3 dedicated (metal) servers, the main servers each have 2× 1.92TB enterprise-grade NVMe drives mirrored (RAID-1).
We use patroni + percona postgres to manage the cluster. Each instance has a software watchdog to trip-wire a failure.
Scripts automate promotion to make sure under normal circumstances (healthy cluster) that the main server, our big EPYC 7401P 128GiB DDR4(ECC) i350 NIC is the primary.
We have a second server which is a less-powerful i9-12900K 128Gib DDR4(non-ECC) i219v NIC that acts as a read-only secondary, and gets promoted to primary on failover.
Then there’s the little server that replicates for backups and potential dual-failure disaster scenarios, a meager Ryzen 7 3700X 64GiB DDR4(ECC) i210 NIC and it has 2× 8TB enterprise-grade spinny disks striped (RAID-0), to keep the DB and backups safe.
It will become primary if the other 2 servers cannot.
The database servers are not connected to directly by any of our services, there’s instead a load balancer in front which targets the 3× server’s HAProxy instances that have one port directed at the current primary and another port for the current secondary.
This database infrastructure is the biggest, costliest and most engineered part of our setup (which is very frugal for what it is). It’s taken me through a near catastrauphic situation (double server failure). You can ask Ada… I was freaking the fuck out.
Additionally we have a single Redis instance which runs on a quad CPU ARM (Ampere) 8GiB RAM 80GB SSD.
- Primary server: €83.70/m
- Secondary server: €61.70/m
- Backup server: €40.70/m
- Load balancer: €5.39/m
- Redis: €6.49/m
- Total: €197.98/m (AUD ~$350) for the persistence layer.
APPLICATION
We then have a prometheus/grafana monitoring box at another €6.49/m.
Then we have the services which run just like everyone else on various pieces of hardware, in docker containers for most, but some run standalone on their own hosts. Sharkey €24.49, Lemmy €12.49/m, Synapse €12.49/m, everything else smaller (pyfedi, pixelfed, friendica, photon frontend, various different static frontends, Ada’s latest project of the week) runs on a single dedicated docker host costing €38.70/m.
That brings us to another €101.15/m for the application layer.
EDGE
Then under that we now have the edge nodes, which are completely standalone and do not have internal VPCs etc, it’s TLS in, TLS out for these machines.
Each node is generally around 2× vCPU 1GB RAM 25GB SSD 2TB bandwidth for around €6/m. We have 4, so that’s around €24/m all up.
End user flow
So when you vist the site, you will first typically hit our DNS server. Our DNS server uses the requesting IP, or EDNS client subnet provided to work out which healthy node is closest to your region, and gives you back that IP address.
Side note: It’s important to realise that up until this point, what domain you requested is known to yourself and the DNS provider you used. If you care about privacy, you should install a pihole (you can install it in a docker container, you don’t need a raspberry pi), and set it’s upstream DNS to Quad9 with ECS and DNSSEC enabled (or if you’re really adventurous, install your own unbound server and bypass intermediaries completely).
We run a dual-stack IPv4/IPv6 network all the way through so if you’re on IPv6, you’ll get our v6 IPs, and hopefully enjoy a less NATted, wider MTU’d, packet un-fragmented journey through the internet.
Once you have the IP address from the DNS server, you will connect to the caching caddy server on the closest healthy node to your geographical location and it will terminate your TLS session, decrypting your request.
At this point we’ll see if we have the asset to the request you made cached locally, if so we can send it straight back to you, super quickly!
If not then it will connect to the upstream server in our core location over a (presumably) much larger, less latent and more resilient trunk pipe than most consumer-grade bandwidth will provide. (Unless you run your own redundant-path dark fibre into your house, which I’m not discounting entirely… I know people.)
The returned response will then be evaluated for cacheability and sent back to you.
The build
We wanted to make sure that if one of these endpoints degrade / get attacked / shut down / die, that we can spin up a new one really quick. So the deployment and configuration is completely managed by an Ansible configuration. The deployment of a single node or even a complete replacement of all nodes takes about 10 minutes.
Our nodes run 2 pieces of third party software, and a few scripts to manage things.
DNS
For the DNS resolution we run gdnsd with 2 plugins, http_status and geoip.
The http_status plugin monitors the health of the other nodes to make sure it’s not sending people to nodes that don’t respond.
The geoip plugin uses the requesting IP to determine what region/country you’re from, and select a priority list of nodes closes to that region. The first healthy node in that list is the node that’s selected.
CACHING REVERSE-PROXY
For the web-serving component, we run a custom xcaddy compiled caddy server with a few modules included: cache-handler, otter storage, coraza WAF, ratelimit, layer4, maxmind and crowdsec.
At the moment only the first 3 are in use, but the other 4 are included in case we need to mitigate attacks or other edge cases in the future.
And that’s pretty much it!
If anyone wants any help with setting up their own version of this, or needs more details, let me know. I’d be happy to help.
If a lot of people are interested (which I doubt at this stage, but who knows?) I’d even be willing to create a project or make it dockerisable etc, but I suspect that it’s something that most people would just use Cloudflare et. al. for, if the privacy aspect wasn’t such a concern.
I am not computer smart enough to understand most of this, but big thanks to you and the rest of the Blahaj team for donating your time, skills, and being so open about how things work! 🩷🩵🤍
Do you have your db setup in ansible playbooks. If so I’d love to take a look at those.
Also goddamn that’s an impressive amount of engineering. Well done.
No, patroni is literally like a dozen commands to run for a new server, and I have those in a text file. It takes me maybe 10 minutes and a few hours of waiting for replication to start up/sync if I need to create a new one. I’m up to our 6th db server through incremental upgrades now (the current secondary used to be the primary, then a new server replaced its primacy).
Why not run those commands via ansible though?
At one point I would have said the same thing… but these days my spare time is so low and ROI on creating and debugging and replaying over and over again until it works flawlessly then maintaining that when I next have to do it and they have changed the process (again)…
I find as I get older I lack the enthusiasm for perfecting these things unless it’s truly going to make my life better, it’s needed for a time critical or replicable/repeatable install or it needs to be run by
complete idiotsclients.As an addition to db0’s points here, I would be utilizing any/all information about this to test/deploy onto the anarchist.nexus site as well. I try to help out where I can with the div0 systems, and db0 has nudged my thoughts in the correct directions more than a few times.
More to the point, while most of my psql knowledge is 18~ years old, I do have some experience working with clusters of them (including the EnterpriseDB variants). I would be more than happy to work at adapting the commands and lessons-learned you might have into basics for db0 and I to hammer into proper ansible.
And add my own “Thank you!” to the pile. Any and all information you feel up for providing would be considered a wealth.
I mean, fair enough. I’m mostly in the same boat, but ansible is my personal stickler. I refuse to do any manual config changes anymore. I’m not a perfectionist though. I don’t keep replaying for perfection usually. Just until it works. Future me can fix if ansible fails in the future :D
Honestly I wasn’t aware of the percona dist until now. We just run a vanilla postgresql and I’d be interested in copying your design for HA. Would you be able to assist in us switching to percona? I am more of an infra/automation guy and whenever I tried to HA databases, I keep fucking it up >_<
I’ll get together my scraps of notes and text files and put together something for you tomorrow. I’ve been meaning to setup a tech blog for a while now and this sounds like a good reason to spin it up. :D
See here for my blog post, hopefully you can make something out of this:
https://pen.blahaj.zone/supakaity/installing-a-patroni-cluster-on-ubuntu
This was the image I sent to her describing myself at the same time :P

That’s a really impressive setup, thx for sharing!
Blåhaj zone is best zone.
Thank you for running lovely instances!
It’s a lot of money every month, but I’m really impressed at what it buys! That’s a lot of infrastructure for that price. I know a few companies that could take a page from this particular book.
Thank you for the details. What application did you use to make that diagram? It looks awesome and I’d like mine to look like that.
Ahh, that’s just Figma (a FigJam to be precise).








