Building from source

A Cargo workspace, so building it is one command once the prerequisites are there. The prerequisites are the interesting part: LuaJIT and the TLS backend both compile C.

The short version

shell

git clone https://gitlab.hacking.hu/szabolcs/sslb3.git
cd sslb3
cargo build --release

That builds every crate in the workspace. For just the balancer, which is the only one most people want:

shell

cargo build --release -p sslb3

Prerequisites

A current stable Rust toolchain, and a C compiler — two dependencies vendor C sources rather than linking a system library, which is what makes the resulting binary portable but does mean a compiler has to be present.

PlatformWhat you need

Debian / Ubuntu

shell

apt install build-essential pkg-config cmake

Fedora / RHEL

shell

dnf install gcc gcc-c++ make cmake pkgconf

macOS

shell

xcode-select --install
brew install cmake

The two C dependencies are LuaJIT, through mlua with its vendored feature, and aws-lc-rs, the cryptography backend rustls uses. Neither needs anything installed beyond a compiler on Linux or macOS.

Tests and lints

The test suite is mostly pure logic and runs in seconds. It is worth running before anything else, because a failure in it points at a real problem rather than a build one.

shell

cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
cargo fmt --all --check

Container images

Each crate has a Dockerfile producing a distroless image with one static-ish binary in it. The platform is fixed to linux/amd64: development machines are often Apple Silicon, and the default would build arm64 images that fail with exec format error after a clean push.

shell

docker build --platform linux/amd64 \
  -f crates/sslb3/Dockerfile -t sslb3:dev .

./build-images.sh does all three and verifies each binary reports the version its tag claims — typing the version separately is how an image ends up tagged one way and reporting another.

The statistics page

The page is a React application built with Vite and embedded in the balancer binary as a single HTML file, so there is nothing to serve separately. It lives in web/stats and is built with yarn:

shell

cd web/stats
yarn install
yarn build      # writes crates/sslb3/assets/stats.html

The built asset is committed, so a Rust-only build does not need Node. Rebuild it when you change the page, and commit the result.

Windows
Not supported yet

There is no Windows build today, and I have not yet tried one on a Windows host. What follows is my assessment of the work, not a result.

The netlink helper will never work there and does not need to: it programs nftables and IPVS, which are Linux. It already refuses to start elsewhere, and the balancer already treats a missing helper as ordinary — every service is reported ineligible for the fast path and served by SSLB3 itself. A Windows build would simply have no fast path.

The balancer itself has no inherent obstacle. Everything on the request path — tokio, hyper, rustls, the HTTP module, balancing, affinity, the detector — is portable. What is unix-bound is startup and operating system integration, and it is concentrated in a handful of places:

WhatWindows

Privilege dropping

getpwnam, setuid, setgid, initgroups. Windows has no "bind as root then drop" model — and no restriction on ports below 1024, so the whole dance may simply be unnecessary there.

Signals

SIGINT and SIGTERM map to tokio::signal::windows. SIGHUP has no equivalent, so configuration reload needs another trigger — the admin API is the likely answer, and needs no new mechanism.

Socket options

IPV6_V6ONLY and SO_LINGER are set through raw libc calls. Both exist on Windows; the socket2 crate covers both platforms and removes two unsafe blocks on the way.

Unix domain sockets

Windows 10 and later support AF_UNIX, but tokio’s listener type is unix-only. UDS listeners would be unavailable at first.

Syslog

No equivalent. The Windows Event Log is the analogue; the setting would report that it cannot be honoured rather than silently doing nothing.

File mode checks

The session store and a configuration holding secrets are checked for 0600. Windows uses ACLs, so these do not translate.

LuaJIT

The open question. See below.

The one that decides it

Whether mlua builds LuaJIT with its vendored feature under MSVC. LuaJIT supports Windows, but the vendored build may not be wired for it. If it does, the rest is a day or two of platform modules. If it does not, the options are a different Lua on Windows — which changes script behaviour and performance, and is a product decision rather than a build flag — or no Lua there, which removes the session script and the Lua layer 7 module.

I tried cross-compiling from macOS and it answers none of this: it fails in the crypto backend's build script for want of NASM and a target C toolchain, which is an environment limitation and says nothing about portability. I have written the assessment and its open questions up in doc/windows-port.md in the repository, if you want to take it further.