SQLite as an encrypted, portable, file-system!
At quite an early age, I had heard and remembered “need is the mother of invention”. Chamber’s journey is that of fulfilling a need that I had and hoped that someone else would have too. It was sort of an itch. And you know what happens when you scratch one: it gets worse. The original need was simple. And unlike many people, and unlike myself in many other cases, I scratched. I tried to fix my needs using existing tools; but it was like I had square and round pegs but the hole I wanted to fill was triangular and no matter how I tried to arrange those pegs, there were always some gaps left.
The Itch
For the last decade or so, a MacBook has been my primary device (though I am gradually going back to my old, original love - Linux). Like anyone else, I had my workflows setup according to the operating system. Part of that workflow was an encrypted DMG file where I kept things which I was not comfortable giving away to a cloud service provider for any cost. Things like some documents but mostly the code that I did not want to just hand over to Microsoft (GitHub). It had the raw algos, some code, the plans, the pitch deck etc. of my “moonshot project” (which is very much on the cards, still). Hence, I encrypted it all inside the DMG and uploaded it to my cloud storage provider.
One day I visited a relative and wanted to show a few files and talk about related things. But she… had… a… Windows laptop! I downloaded the DMG file on her computer, totally forgetting that I won’t be able to open it on Windows. But Windows reminded me of the reality.
The Scratch
“Surely there has to be a way. It’s 2025” was my thought. I started looking for a solution that allowed me to keep my files and folders encrypted in a single file and worked on all the operating systems I cared about (macOS on ARM64, Windows on AMD64, Linux on AMD64 and Linux on ARM64). There were numerous projects but all of them had something or the other that I had an issue with. 7-Zip’s tooling did not feel right because the support for non-Windows platforms is not first-party. Cryptomator wanted to work only if I had some kind of cloud storage backing. VeraCrypt was too complicated for my taste to be setup on all the platforms. Gocryptfs only did a 1-1 mapping of each plaintext file to an encrypted version into its target storage. OpenSSL and GPG were complicated too - I had to either carry my encryption keys and/or remember long commands; the GUI apps were not consistent in features and support across platforms. BitLocker and LUKS are Windows and Linux specific so not cross-platform. Then there were some “folder lock” software that worked either on Windows or on Windows and Mac only and most of them were paid and none of them made me feel confident to trust either.
I actually started using VeraCrypt but once I took the vault I created using it to Windows, I realised that I had accidentally created a file system which was mac specific (don’t remember if it was HFS+ or APFS). So that was also a let-down. The deeper I looked, the more frustrated I got. I wanted to solve the original problem.
I wanted to be able to download a vault file from my cloud storage, download the tool that could open it and just be able to work with those files using a password that I could remember (no key management stuff). And I wanted this experience on all my machines.
By the end of the month after trying multiple things and researching around it, the itch became a wound. I was getting anxious about “how come, there is no tool that does this simple stuff?”.
The Ointment
I once read “Action kills anxiety” and I thought I needed to act. So I went into a “dreamy” state. What would I want from a software that I would use for this purpose? And I laid out a set of features. I did not worry about whether or not those things were possible or not. For this project though, I had decided to make things in open and upload the videos of me doing things.
Once the requirements list was done, I realised that the data format was the biggest issue. For about 4 days I was planning and thinking about implementing my own file system inside another file and researching if it was possible. Back in my college days, I had studied NTFS in significant detail (out of curiosity) and was planning the on-disk structures and layout. Trees, the clusters, space allocations and whatnot. And then one day while walking on the road, I read something about “Turso DB” on the mobile. I remembered it from ThePrimeagen’s video that it was something based on SQLite. And in a flash I remembered “SQLite”. For some reason, as if exploding out of my subconscious, a memory returned from the days when I was trying to build C-Integration (now-defunct).
Like many others before me (and after me), I had once wondered and tried to use my database (PostgreSQL btw) to store my web-assets and user file uploads. So I had already been there. I had done a basic implementation too, though the code was not there now. In the next 5 minutes or so before I reached my home, my brain had already planned out most of the DB structure. 2 days of raw coding and research proved that it was possible, the bare minimum happy path was done. Sometime during this time I uploaded the second video of the series too.
The healing power of Go and SQLite
I was already using Go. I loved the language and had some setup on it already. Go was capable of taking care of two glaring problems - distribution (single binary, very simple docker images) and cross-platform requirement.
SQLite was already known to have a portable on-disk structure for both little and big endian systems. I would have loved to implement all those trees, free-space-map calculations and clustered space management and what not. But SQLite made more sense than anything else. This was not a research project, it was an actual product that I was imagining. SQLite could give me a well-built search, filters, aggregations, locks, integrity guarantees, indexes and an ability to store more than just file data.
The best part? SQLite allowed me to build the one feature I really worried about in the beginning - being able to work with files without mounting them. This would allow me to keep anything on any VPS provider and they would not be able to peek into my private stuff. I know there are privacy policies but I have read complaints about some hosts that if they “detect” some software on your VM then they can block your account and kill the instance and I always wondered “how do they detect without looking inside in one way or the other?”.
Thou art health
It took me almost 4 months of coding and testing to finally release Chamber. About 2 out of those 4 months went into redoing the UI so that it could be accessible on my mobile as well as on my laptop. After all, I wanted to be able to utilize the spare space on my VPS, my 15 year old laptop and the Raspberry Pi’s.
But as I kept working, the old adage of “You walk 4 steps and then you can see the next 4” showed up automatically. My brain right now is flooded with what all can be done in and with Chamber. While I move forward with Advanced features, there is a couple of anecdotes about my choices when it comes to Chamber.
HTMX + Not really SQLite + No Desktop App (yet)
Not a dedicated desktop app yet: There are a few things that people on Discord asked me about my choices related to having a Desktop app. The first thing is - Chamber is not (not yet, at least) a mass-market product and I expect that someone willing to use Chamber would be at least a semi-technical person who would be able to follow basic instructions, can launch a program and maybe even launch a Docker container if required. For a person like that, it should not be a big ask to open a web browser and navigate to http://localhost:24262. Creating a separate desktop app for all platform invites a lot more work for too little a gain as of now. However, I did try setting up an Electron-based setup where I launched the web server and showed the web page in the browser window. It worked but I needed to navigate around some security restrictions. I have decided to take that up later.
Not the original SQLite: SQLite in its original form is a C program and compiling or interacting with a C program in Go can not only mean that I would lose the ability to cross compile, but it might also invite a lot of bugs that are really difficult to detect and work around. The internet has some examples of such pesky ones. I came across gitlab.com/cznic/sqlite and it made sense to me. My tests proved that the behavior and resulting file format was indeed compatible with the original SQLite project and since this one was CGO-free, I decided to use it instead of the original one.
The React vs HTMX debate: I avoided making a dedicated/separate desktop app because I wanted to focus on the integrity, the features and stability of Chamber. As a single developer, I think that having to maintain multiple codebases comes in the way of that goal. In addition, I have only used Vue in the past and that was like 6 years ago. To learn and work with a whole ecosystem and make a codebase which also needed to be maintained separately was not something I wanted to invest my time and energy into. In addition, I have seen React codebases where one single error can make the whole app crash. At the same time I come from a time when AJAX was a hot keyword. And I know that it is very much possible to create a system where each page gets rendered from the backend, carries minimal javascript to make that one page work and can still be very fast. I already knew about HTMX. And hence, I chose to use HTMX as the rendering system because it helps me to:
- avoid a whole new framework and ecosystem
- is very lightweight and stable
- works with the basics and that means it’s fast (faster than I can imagine React to be)
- allowed me to progressively refactor my codebase in a way that it becomes more and more PWA-like (the very essense of PWA lies in there)
The end result was a system where the page reloaded before my eyes could catch.
Honorable Mention - Plush: Go is my favorite programming language as of today and the one thing I cannot stand in Go is its templating system. I hate it, despise it, abhor it. It is one of the ugliest I have ever encountered. Templating systems in Go are a whole research topic in itself. When looking at the reviews of The Compiler Book by Thorsten Ball, I remember coming across Plush and I also remembered its templating system which looked closer to RoR whose templating I do like. Hence I chose Plush for Chamber as I think it’s the best templating system there is for Golang.
A note about Chamber Advanced
If I could, I would give away all my creations for free and keep them open too. But I can’t. I have bills to pay and smiles to nurture. I love and respect projects like Redis and Minio and I totally understand why they change the licenses. I don’t want to do that. Hence I would be developing new features mostly in a new edition called “Chamber Advanced” and as I progress, I will put back some of those features (approx one out of 3) into the open edition. I do not want to make the open edition feel abandoned but at the same time I want to offer some paid features too.
As of now, I have decided to keep Chamber Advanced in either “Pay in Kind” or “Pay by Money” mode. That’s because I do not want to lock down people behind a paywall. So in case someone who creates a vault using Chamber Advanced is unable to pay money tomorrow, they can at least pay in kind to keep getting those features. After all, these are all the features that I want to have. I being the first user of Chamber would never want to lock myself out.
List of Articles
Before I wrote this document/page, I wrote some other pages. You can view the list of articles below. It is very much recommended to read them in that order, but that’s not a necessity.
- Inspiration
- Expectations
- Data Storage
- The CLI
- Encryption in Chamber
- Being PRAGMAtic
- License
- The GUI
- Editions (and Planned Features)
- Final Release
I hope you would love reading through these pages and using Chamber just as much as I enjoyed building it all and writing all of it.