Backupbox

Why a backup solution?

My wife has filled her third phone and Google account with pictures and if she ever loses one of those phones a third of our family memories are gone. In Montenegro you cannot simply purchase a Google One subscription, you only have the free tier. I do not understand specifically why, but like for most things, big corporations simply do not care about small markets. So I decided to build a simple backup solution for her.

Immich

I first looked at existing open source solutions and found Immich. Immich is a self-hosted photo and video backup solution. It provides apps for Android and iOS and a web interface. It looked promising, it has many features and a nice clean UI. I deployed it on my living room PC and it worked almost out off the box, until I tried uploading my photo collection. After a few hundred photos it started blocking and not resuming. I had to keep my phone on and it was pretty slow. In addition Immich was using 3-4GB, so I decided to look for more lightweight solutions.

Fleabox

Recently I have been working on my own backend framework called Fleabox. Fleabox is a minimalistic backend framework for building web and mobile applications. It is like a mini Firebase/Supabase. It provides user authentication and CRUD operations over files. Every user gets their own private storage space on the server. The server is written in Rust and takes only 4MB of RAM no matter how many users or apps you deploy. I decided to test the versatility of Fleabox by building a backup solution for my wife. I decided to use my minimalistic backend framework to implement the solution. Fleabox is like a mini Firebase. It provides user authentication and file storage and its footprint is 4MB!

PWA vs Native App

Firebase can be used by both web apps or native apps. The interface is just a very simple REST API. I wanted to build a native Android app at first, but since moving to Linux, I had issues running the Android emulator, so I decided to go with a web app, more specifically a PWA. PWA stands for Progressive Web App. It is a web application that can be installed on your device and run like a native app. It can work offline and has access to some native features like notifications and background processing. Developing a web application certainly has a faster development cycle, but the question is can a PWA provide enough features to implement a backup solution?

Background Processing

The first thing I needed was to process backups in the background. There are several ways to do this in a PWA, but the most reliable way is to use service workers. Service workers provide a way to run scripts in the background without a web page or user interaction. There are no guarantees that a service worker will run at a specific time, but they are good enough for a backup solution. The important bit is that I can resume the backup where it left off.

Acessing Entire Folders

The other problem is that web apps do not have general access to the file system. Users can only select files using the file input element. This is a problem for a backup solution because users need to select entire folders to back up their photos. Luckily there is a relatively new function called the showDirectoryPicker() that allows users to select entire folders. The showDirectoryPicker() function provides a way to select a folder and get access to its contents. The function is still not supported by older browsers, but it worked on my Pixel 7a. Be aware that if you need to implement folder picking in your PWA make sure to serve it over HTTPS otherwise the folder picker API will not be available.

Fitting it all together

With Fleabox providing the backend and the PWA providing the frontend, I was able to implement a simple backup solution. Unfortunately since Android 11 the camera stores photos in a protected folder that cannot be accessed by web apps, so I can backup everything except those photos. In the future I might try to implement a native app that can access those photos as well.

Backupbox Screenshot

If you want to set it up yourself, the source code is available on GitHub.

© 2025 Jaksa Vuckovic. Built with SvelteKit