DIY multi-regional uptime monitoring with and Uptime Kuma

Two things happened recently that led to this post:

  • Heroku had a DNS problem (incident#2453, and many websites went down.
  • Heroku announced their next chapter (spoiler: no more free cookies dynos).

I was affected by both (well, the second one has not come into effect yet). And I found this set of circumstances an excellent opportunity to try something new.

Introducing Uptime Kuma

The first event made me think of setting up an uptime monitoring (with DNS checks support), and an OSS project bubbled in my mind—Uptime Kuma.

Uptime Kuma calls itself a “fancy monitoring tool”. And I absolutely agree with that. It has both a great feature set and a slick UI. Here is my dashboard:

Uptime Kuma dashboard

You can find the complete list of features in the repo; I was only interested in the basic HTTP and DNS checks. As for notifications, there are dozens of integrations. I chose Slack for simplicity and plan to add a Telegram integration for personal projects later.

What about deployment? There is an official Docker image (louislam/uptime-kuma), so all you need is a platform capable of spinning up Docker containers and taking care of them. Heroku could be a candidate, but I prefer not to pay for pet/research projects. So, I turned to the alternatives.

Deploying Uptime Kuma to Fly is a modern deployment platform focused on multi-regional availability (“close to your users”, their main page says). By “modern”, I mean providing a great developer experience: CLI-first, sensible defaults and configuration, and a generous free tier.

You can deploy a Docker image to Fly with a single command:

flyctl launch --image louislam/uptime-kuma:1

That could be it for some apps, but for Uptime Kuma we need persistent storage to keep configuration and application settings (such as admin username and password). For that, we can use volumes.

Let’s first create an application to generate the default fly.toml file:

fly create
# answer the questions, don't install PostgreSQL 🙂 

In the resulting fly.toml file, update the service port (Uptime Kuma uses 3001 by default):

  http_checks = []
  internal_port = 3001

And add the mounts section:

  source="kuma_data" # choose whatever name you want

Now we need to create a volume manually:

fly volumes create kuma_data --region lhr --size 1

We use the smallest possible size (1 GB), which is too much for Uptime Kuma, but fly doesn’t allow passing floats 🤷‍♂️

Now, we’re ready to deploy our application!

fly deploy

After the app has been deployed, you can open it and configure the monitors:

fly open

Going multi-regional

I decided to go further and turn my DIY monitoring into a high-available solution by creating a second application instance in another region.

The tricky part here is dealing with volumes: a volume could only be attached to a single application instance. So it’s just a private storage, non-shared.

If we want to deploy more instances, we must create new volumes. Let’s create one in Chicago:

fly volumes create kuma_data --region lhr --size 0.1

We can check the status of our volumes by running the following command:

$ fly volumes list

vol_xxxx  created  kuma_data 1GB   lhr     abc123    
vol_yyyy  created  kuma_data 1GB   yyz     

Now, we need to add a new region to our application. First, I tried to follow the documentation and add a new region to the pool but failed:

$ fly regions add yyz

Error App 'uptime_kuma' uses volumes to control regions. Add or remove volumes to change region placement.

The error message itself wasn’t really helpful (I created a volume, what’s wrong?), but it led me to the community discussion which explains that you don’t need to add regions manually when using volumes. All you need is to scale the app, and Fly will choose a proper region based on the free volume:

fly scale count 2

Awesome! Now we have two apps. But they are independent; how can we sync the configuration?

To deal with configuration syncing, I decided to use the built-in Backups features of Uptime Kuma: export in one region and import into another.

It turned out that there is no way to access an app deployed in the specific region, Fly takes care of geolocation-based routing itself, and you have no control over it. Solution? VPN!

So, here is the step-by-step instruction on how to “sync” Uptime Kuma instances:

  • Open the app closest to your current location: fly open.
  • Download the configuration backup.
  • Connect to a VPN server closer to the second location and run fly open again.
  • During the first launch, a fresh Uptime Kuma instance prompts you to enter admin login details again—just use the same as for the first app.
  • Go to Backups, choose the “Overwrite” option and upload a dump from the first app. That’s it!

It took me about ~30 minutes to run a multi-regional monitoring system on, and I hope it will last for years until Fly hits its next chapter forcing me to look for an alternative 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post

What are No-Code Platforms?

Next Post

How to become a self taught developer

Related Posts