# websurfx: a self-hosted meta search engine written in Rust

> websurfx is an AGPL-3.0 Rust meta search engine and Searx alternative that queries upstream engines, filters and reranks the results, and caches them, with a Lua configuration file, Redis as an optional cache layer and a Docker image that publishes port 8080.

**neon-mmd/websurfx** — :rocket: An open source alternative to searx which provides a modern-looking :sparkles:, lightning-fast :zap:, privacy respecting :disguised_face:, secure :lock: meta search engine

- Repository: https://github.com/neon-mmd/websurfx
- Website: https://github.com/neon-mmd/websurfx/tree/rolling/docs
- Stars: 1,220 · Forks: 129
- Language: Rust
- License: AGPL-3.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/neon-mmd-websurfx

## A meta search engine with the upstream engines hidden

websurfx is a meta search engine written in Rust, described in the repository as an open source alternative to Searx. The name is pronounced as websurface or web-surface.

The mechanism is the standard one for this class of tool. websurfx does not index the web itself. It takes your query, sends it to a set of upstream search engines, parses the results with the `scraper` crate, and presents them as one list. The privacy claim in the README is that the searching happens on your own infrastructure rather than through a search provider that profiles you, and the results are ad-free and clean.

The Rust stack is visible in the manifest. `actix-web` is the HTTP server, `reqwest` is the HTTP client with rustls-tls, brotli, gzip, http2 and socks enabled, which is the feature set that lets it talk to engines and to a proxy. `tokio` provides the async runtime, `scraper` does the HTML parsing, and `maud` is the HTML templating layer wired into actix-web.

Two dependencies stand out as design decisions rather than defaults. `mlua` is embedded with the async, luajit and vendored features, which is how a Lua configuration file can drive a Rust binary. And `redis` is present but optional, gated behind a feature flag, which is what makes the cache layer a choice rather than a requirement.

The licence is AGPL-3.0, the default branch is `rolling`, and the last push was on 2026-10-18 with v1.29.9 tagged on 2026-05-13.

## Building and running it on bare metal

The README's installation route is the manual one, and it assumes Cargo is already installed.

```shell
git clone https://github.com/neon-mmd/websurfx.git
cd websurfx
git checkout stable
cargo build -r
redis-server --port 8082 &
./target/release/websurfx
```

The `git checkout stable` step is worth noticing, because the repository's default branch is `rolling` and the manual instructions deliberately move you off it. A rolling branch is where the newest work lands, and a first build is not the moment to pick it up.

Redis is started on port 8082 in the background, and the binary is then run directly from `target/release/`. Once the server is up, you browse to http://127.0.0.1:8080 to use it.

That Redis line is unconditional in the instructions even though the Redis dependency is optional in the manifest, because the caching feature is what the configuration file enables by default. If you do not want a Redis process, the config is where you switch the cache type, and the Dockerfile has a matching build-time switch.

The project is also Gitpod-ready, with a `.gitpod.yml` and a `.gitpod.Dockerfile` in the tree, so an editor-in-the-browser setup is possible if you would rather not install Rust locally.

## The Dockerfile and the compose file both switch on the cache type

The container route is the one a self-hoster will actually use, and the cache choice is threaded through the build rather than hidden.

The Dockerfile is a multi-stage build on `rust:1.94.1-alpine`, with a chef stage that installs the build toolchain and then `cargo-chef`, a planner stage that prepares a recipe file, and a builder stage that cooks the dependencies. The cook step branches on a `CACHE` build argument with four values:

```dockerfile
ARG CACHE=memory
ENV CACHE=${CACHE}
```

With `memory`, the default, the build uses the default features. With `redis`, it adds `--no-default-features --features redis-cache`. With `hybrid`, it adds the redis-cache feature on top of the defaults. With `no-cache`, it drops the default features entirely. The same four-way branch appears again in the actual `cargo build` step, so the choice is consistent between the dependency cook and the source build.

That is a well-designed build, and it means the image you pull matches the cache behaviour you asked for, rather than shipping Redis support to everyone whether or not they use it.

The compose file is minimal. The app service maps port 8080 to 8080, builds from the local Dockerfile, and mounts `./websurfx/` to `/etc/xdg/websurfx/`, which is where the configuration lives inside the container. The Redis service is present but commented out, with a note to uncomment the `depends_on` and `links` lines if you use the `hybrid` or `redis` caching feature.

## Configuration in Lua, and a default that has to be edited

The configuration is a Lua file, `config.lua`, located in the `websurfx/` directory, and the full instructions live in `docs/configuration.md`.

Using Lua as the configuration language is the choice that follows from embedding `mlua` with the luajit feature. It means the configuration is a real program rather than a declarative file, so logic is possible, and it means the configuration is a file you can read as code. It also means a configuration mistake can fail in ways a YAML file cannot, which is worth keeping in mind before you point a script at a production instance.

The installation section tells you to edit the config file as part of getting started, which tells you something about the defaults. A meta search engine has to know which upstream engines to query, and that list is something you have to supply, because sending your queries to a set of engines you did not choose is exactly the privacy property this class of tool is supposed to give you back.

The docs directory also holds `instances.md`, a list of publicly available community-driven websurfx instances to test or use daily. That list is worth reading before you deploy your own, because it tells you what other people have configured, and it is also the fastest way to try the software without installing anything.

## Filtering, reranking, caching and the Tor option

The feature list describes what the engine does with the results it collects.

Filtering is the first: search filtering on four different levels. The levels are not enumerated in the README, so the configuration documentation is where you find out what they are.

Organic results come next, with a built-in ranking algorithm to rerank the search results according to the user's query. That is a meaningful addition for a meta search engine, since the upstream engines return results in their own order and their own quality, and without a reranking step the merged list is a mishmash.

Caching is described as different caching levels focusing on reliability, speed and resiliency, and the four cache types in the Dockerfile build switch map onto that: memory for speed, redis for a shared cache across instances, hybrid for both, and no-cache when you want every query to go out fresh. The redis option exists because a multi-instance deployment behind a load balancer with a per-instance memory cache gets a cold cache on every instance, and the redis feature plus the `tcp_nodelay` and `connection-manager` features on the redis crate is the answer to that.

On the fetching side, there is custom proxy and Tor support for reaching the upstream engines, which is the obvious requirement for a privacy-focused search tool. There is also an experimental IO-uring feature for Linux systems, described as focused on the performance of the engine.

Compression and encryption are listed as different levels focusing on speed and privacy, which covers both what is sent upstream and what is served to your browser.

## The limits the project states plainly

websurfx lists its own gaps, and they are the facts that decide whether it suits you.

On the feature side, the README notes that many features are still missing, with image search, different categories and quick apps named as examples, to be added in future releases. Categories and quick apps are search-engine features websurfx does not offer yet, and if your use of a meta search engine is category browsing rather than a single query, that is a visible difference.

On language, the answer is currently blunt: other languages are not supported, though contributions on language support will be accepted in the future, on the stated grounds that language should never be a barrier to entry.

On architecture, only x86_64 is supported at present, with contributions to extend to other architectures welcomed. An ARM home server is therefore out of reach without work.

Two other details are worth knowing. The FAQ explains the project's reason for existing in terms of other meta search engines not guaranteeing the security of their search engines, with memory flaws given as an example of what can expose private information, which is an argument about the implementation of the tools rather than about the search engines themselves. And the note under the installation instructions says the project is no longer in the testing phase and is now ready for production use, while still listing the missing features above.

The licence is AGPL-3.0, which for a self-hosted service means the source of any modified version you expose to users has to be available, and that is a consideration for anyone planning to run a modified instance as a public service.

## Conclusion

websurfx suits a self-hosting user who wants a search front end that queries upstream engines on their own infrastructure, with their own filtering and cache settings, and who is willing to accept that the tool sends queries to third-party engines. It does not suit a user who needs image search, quick apps or category filters today, since those are listed as still missing, and it does not support languages other than English yet. Before deploying it, build with `cargo build -r`, start Redis on port 8082 if you want the redis or hybrid cache, and read the configuration documentation for `config.lua` before changing the upstream engine list.

## FAQ

### What is websurfx?

It is a meta search engine written in Rust, described as an open source alternative to Searx, with clean, ad-free results and a focus on privacy and security. It queries upstream search engines and reranks the results, and it is licensed AGPL-3.0.

### How do I build and run websurfx?

Clone the repository, check out the stable branch, run `cargo build -r`, start Redis with `redis-server --port 8082 &`, and run `./target/release/websurfx`, then open http://127.0.0.1:8080. There are also Docker and Docker-Compose options documented in the installation docs.

### What caching options does websurfx have?

Four, selected through the config file and matching the Docker build argument: memory, redis, hybrid and no-cache. The redis and hybrid modes use the optional redis-cache feature, and the compose file includes a commented-out Redis service for them.

### How is websurfx configured?

Through a `config.lua` file in the `websurfx/` directory, with full instructions in docs/configuration.md. The project embeds the mlua Lua runtime, so the configuration is a Lua program rather than a plain settings file.

### What features does websurfx still lack?

The README names image search, different categories and quick apps as still missing. Only x86_64 is supported, and languages other than the default are not yet supported, though contributions in both areas are invited.

## Sources

- [License: AGPL-3.0](https://github.com/neon-mmd/websurfx/blob/rolling/LICENSE)
- [neon-mmd/websurfx on GitHub](https://github.com/neon-mmd/websurfx)
- [Project website](https://github.com/neon-mmd/websurfx/tree/rolling/docs)
- [README](https://github.com/neon-mmd/websurfx/blob/rolling/README.md)
- [Releases](https://github.com/neon-mmd/websurfx/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/neon-mmd-websurfx
