BLIS.exe, soup to nuts
What is BLIS? You can read about it here.
BLIS was originally designed to run on Windows computers, because when BLIS was originally written, they were the dominant platform of the intended users. The great thing about using a program that has been the subject of multiple theses and scholarly articles is that the design decisions are documented.
…BLIS required a stable solution that would work with minimal or no installation steps needed on the laboratory computer. The portable offline version of BLIS is built using the Server2Go Framework which enables packaging of Apache web server, PHP runtime, and MySQL database engine into a single entity requiring no installation. This enables use of the system in a portable manner on local hard disk or flash drives.
Server2Go has served BLIS well, but over the years, there have been situations where I wanted more from the desktop application that we run. What if our desktop application had the ability to perform basic MySQL diagnostics without manual intervention? What if we could distribute updates to users within the application? What if we could recover a broken installation? Server2Go was not designed for any of that, and without the ability to modify the binary1, I knew that the day would come that I would have to rewrite it.
Design Decisions
In a professional software development team, it’s common to read and write design documents that outline the context for a particular decision. It’s useful to frame a technical choice in terms of requirements and the tradeoffs that are needed to meet them.
Here’s what I knew we needed for a solution, if we were to maintain parity with Server2Go:
- No external dependencies. It’s going to be a major bummer if we have to require everyone to install the Java SRE to run our wrapper first.
- Runs on Windows. This requirement has not changed from the early days.
- Accessible for student developers. With every project, you have to consider not only your users, but also your other developers. I can’t expect a project like this to be maintained if the language or build process to be complicated or finicky.
- No command line. The application itself should present all of its functions via a GUI. If necessary, command line tools can be written, but they shouldn’t be the default (unlike Linux.)
First attempt: Write it in Rust
In my heart, I am a systems programmer, even if, in my brain, I am a sad web developer. I have only played around with a Rust a little bit, and thought, why not? I really just need a process manager for an initial version: to run a web server, database, and (maybe) a PHP process.
Here are the characteristics that made Rust desirable:
- Runs on Windows
- Rich library ecosystem
- Several choices of GUI libraries (more on this later)
- Ability to compiles to single binary
Some drawbacks become immediately apparent:
- No standard GUI library. This isn’t a dealbreaker, but it did raise the question, what do I use? What’s going to compile on Windows? What’s going to be easy to learn, and easy to maintain?
- It’s a pretty big paradigm shift. The memory safety guarantees of Rust are certainly interesting, but they come at the cost of a new paradigm.
In my first attempt, I tried to use some native Windows GUI library (Win32) bindings for Rust, but I found that to be pretty complicated for what I wanted to do. I ended up using GTK3 bindings for Rust, which were much more intuitive. Unfortunately, it was also a lot more difficult to set up a development environment for these.
One early, cool thing I did here was use a template library (based on the Handlebars syntax) for “rendering” the configuration files. This was kind of overkill, but it was very simple (Server2Go does a similar thing, but I think it uses plain string replacement).
After several hours over a few months on the project, which still wasn’t able to boot BLIS, I abandoned it. Unfortunately, I found that it was taking me too long to get to the “fun part” - running BLIS and iterating on improvements to the desktop app, rather than building it.
Second attempt: .NET
In September, I started working on a team within Microsoft, and as such, have had to pick up C# as my primary (business) language. Modern C#/.NET has a lot of surprising benefits: the core .NET code is MIT-licensed, it has a lot of syntax sugar that make it very ergonomic, and importantly - you can compile it to a self-contained binary.
I sat down to make a C# version of BLIS.exe, and it only took me a few hours to get to the “fun part” of running the processes and tweaking things to get BLIS running.
Here are some of the interesting design decisions that I made:
- I enabled all the single file options. Under the hood it seems like a pretty complicated mishmash of techniques to get this to work, but hey - it does work!
- I used a logging framework (Serilog) in conjunction with the Microsoft.Extensions.Logging library to dump all application logs and stdout/stderr from the processes to a log file in the same place as the BLIS logs.
- I used Avalonia UI. It’s surprisingly nice to use and I was able to replicate the splash screen PNG file as a GUI layout. The View/ViewModel/Model structure is still a little weird to me (read: I’m definitely using it a little wrong.)
- I used a template engine based on Liquid called Fluid. Even better, the configuration file templates for each process are bundled with the executable and written to the file system every time BLIS starts, so it truly is a single binary.
One fun thing I got to do was reverse engineer Server2Go! At one point, Apache2 just was not starting when I enabled PHP. Something had to be configured wrong, but I couldn’t figure out what. I used Ghidra to open up BLIS.exe (Server2Go) and did a string search for php.exe
. There it was! Server2Go was setting the PHPRC
environment variable, so I did too. That got it running!
The repository for BLIS-NG is here. This will make it much easier for me to ship updates in the future, and make the application more resilient. No more one-off batch scripts - I can build it into the application!
The Future
Writing my own BLIS.exe has also allowed me to finally start updating to PHP 7 (and beyond) because I have more control over the environment BLIS is running in. I hope that in the next month or so, I can get a PHP 7 version of BLIS assembled for testing. Unfortunately, the thing that blocks that will be a rewrite of some of the core encryption features, which rely on some old and never-seemed-to-be-really-recommended PHP encryption functions.
The real killer feature would be the ability to update the launcher itself. If I can do that, I can roll out new features gradually - including the ability to update BLIS itself through the launcher.
My (admittedly sporadic) posts can show you that I do really enjoy working on BLIS. The most interesting challenges to me2 are the human ones - how do I make this system easy to use? How do I make it easy to explain, and for future students to maintain? I hope that the attitude is clear in my writing, and more importantly, I hope it’s clear to the BLIS users out there in the world.
- Server2Go was never open-source, making it the only closed-source component of BLIS. I reached out to the original author, who was very nice, but he wasn’t able to find and provide me the original C++ source code. It’s been about 15 years since the last release, after all - I couldn’t blame him!
- Aside from working on “old” tech which is just Mitchell catnip