Legacy Labs 2026
Intro
This is a short build log for my LegacyLabs experiment: taking an old, abandoned search engine and seeing whether it can still be useful in a modern small web app. The constraint is deliberate: modern OS, tiny VPS, old-school search stack, and no heavyweight Elasticsearch/SOLR style of machinery.
Day 1: Swish-e
For my LegacyLabs pick, I want to revive an abandoned piece of software: Swish-e.
I used Swish-e on a customer project many years ago, but only at a surface level. It did some basic site-search work, and I remember admiring the idea of it, but I never really had the chance to understand it properly.
That makes it a good candidate for this project. This is not random retro software for me, it is unfinished business.
The motivation is simple: I want adequate website search, and possibly document search, without needing a large modern search stack sitting there with 32GB of RAM allocated to it. Swish-e comes from a time when search had to be smaller, simpler, and more directly operated by the sysadmin.
So let’s begin.
The first decision: this will not run on an entirely retro platform.
I briefly considered running an old Linux distribution, but running a 20-year-old operating system on the public Internet, with decades of unpatched security holes, gives me hives. I also do not have physical server hardware or an adequate home connection for hosting it myself.
Instead, I will use a small paid VPS: one CPU, 512MB RAM, and Debian 12 Bookworm.
That feels like the right compromise. The operating system will be modern and patched, but the application layer will still be deliberately small and old-school. Debian also makes sense because I will need build tools and compatibility with older C software. A minimal distribution like Alpine is attractive in general, but for this particular task it creates the wrong kind of difficulty.
Day 2: Actual sysadmin
I found the archived GitHub repo: https://github.com/swish-e/swish-e. Well, actually before that, I found there's a Debian package for swish-e, but I decided not to use it but rather compile the latest source code. I tried to build it on the freshly installed Debian 12 bookworm and immediately ran into build issues. Name clash, don't mind it, nothing that sed can't fix.
Just for the record, name clash on uncompress2 function.
find src -type f \( -name '*.c' -o -name '*.h' \) -exec perl -pi -e 's/\buncompress2\b/swish_uncompress2/g' {} \;
I managed to index a couple of docs and query them back, confirming that it's actually working. Next step I'll need to harness it somehow to use programmatically. There are standard libs for C and Perl, I have no intention using of either so I'll have to think about that.
Day 3: Docs
Reading the Swish-e documentation. It may as well be French. I am no longer used to documentation like that and I don't usually shy away from man pages. The capabilities that I want to achieve are as follows:
- My documents will live in database, not flat files
- I want to have them converted and consumed by the search engine.
- I want to programmatically query it and return relevant information back to scripts.
- I want to be able to index one document at a time
- I want to be able to index everything in bulk
- I want to be able to update / delete index if document changed or removed.
Finally, once I have all that, I'd like to proliferate documents to something uncomfortable (like at least 100,000) and see if it still stands on 1CPU / 512RAM and whether the results I get from it are adequate.
Day 4: Armature
I like thinking with my hands, and to properly play with the search engine, I need real-ish data.
So today I put together a small app: a hobby web app for posting memories about old computers. It is a hybrid of two apps I worked on before but never published. The important part is that the search layer will rely on user-generated content, not carefully prepared test fixtures.
In the spirit of keeping it economical, I went with FlightPHP and SQLite for a simple backend, ported over some of my slick PixiJS components, and started planning the search document structure.
The search documents will look something like this:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Apple IIe</title>
<meta name="computer_id" content="2">
<meta name="user_id" content="1">
<meta name="username" content="demo">
<meta name="slug" content="apple-iie">
<meta name="url" content="/u/demo/apple-iie">
</head>
<body>
<h1>Apple IIe</h1>
<div class="story">
The Apple IIe was the workhorse of our school computer lab.
We learned Logo programming and played Oregon Trail.
The green screen and the satisfying click of the keyboard are forever
etched in my memory.</div>
</body>
</html>
The idea is simple: Swish-e indexes the full text, while the metadata gives the app enough pointers to route search results back to the right computer, user, and URL.
For the first iteration, I will be happy with basic full-text search, as long as it works reliably.
Day 5: Local environment
I got all machinery for the indexing and search to run on my FlightPHP app. I hit a few obstacles, like I couldn't get Swish-e to work on my MacBook, as it was failing with segfaults. I asked ChatGPT for help and it paid off. Basically, ignore the library soup provided by brew and build it without libxml2
./configure --prefix="$HOME/local/swish-e" --disable-libxml2
Now full text works, indexing works, deletions / insertions / updates are working too. Next thing is to host it on my underpowered machine and stress test.