Modulo is a Java/Jetty-based reverse proxy for WebObjects and
ng-objects applications. It replaces Apache's mod_WebObjects
adaptor with a small, modern, easier-to-understand piece of software.
A modern WO deployment historically required Apache + mod_WebObjects
in front, with all the operational baggage that brings: compiling an
Apache module, dark configuration chants, and an HTTP stack that
didn't speak HTTP/2.
Some avoid this by replacing the adaptor with mod_proxy or another
generic proxy, but that means losing many of the management benefits provided by
JavaMonitor and wotaskd.
Modulo is a small reverse proxy that:
wotaskd:1085 like mod_WebObjects does./Apps/WebObjects/*) to the appropriate WO app instance.x-webobjects-* headers WO/ng apps expect.Since modulo is written in Java, it's easier than mod_WebObjects for
most WO developers to understand, maintain, debug and extend. And
since it's a standalone application, it works behind any web server
that can act as a reverse proxy — nginx, Caddy, Apache, HAProxy.
Modulo has been running in production behind Apache for over a year, serving real WO/ng-objects sites without issue. This is the core, mature part of the project.
A front-end mode is being developed alongside it — TLS termination, HTTP/2, SNI across many sites, automatic certificates via ACME, HTTP→HTTPS redirects, compression. The goal is for modulo to fully replace the Apache + certbot layer. The front-end is in production use for a real fleet of sites and now has its own configuration format (a single TOML config file) and native ACME issuance/renewal — but it's still young: the ACME path is fresh out of development, and a handful of operator-facing rough edges remain. See SETUP.md for setting it up.
See ROADMAP.md for where modulo is heading and BRAINSTORMING.md for ideas being considered.
wotaskd, sets WO-specific request
headers. This is the mature, production-tested part.Modulo is packaged as a WO-style application and run via its launcher
script. It needs to know how to reach wotaskd so it can discover
your WO apps:
./modulo-runner \
-Dmodulo.wotaskd.host=[yourhost] \
-Dmodulo.wotaskd.port=[yourport] \
-Dmodulo.wotaskd.password=[yourpass]
By default modulo listens on port 1400 and serves as a plain reverse proxy behind another web server.
If you're using Apache, add the following to your config (assuming
modulo is on the default port 1400 and your adaptor URL is
/Apps/WebObjects):
ProxyPreserveHost On
ProxyPass /Apps/WebObjects http://proxyhost:1400/Apps/WebObjects
ProxyPassReverse /Apps/WebObjects http://proxyhost:1400/Apps/WebObjects
Modulo's TLS front-end can run alongside the plain proxy when
configured. This lets you incrementally move sites off Apache without
breaking the rest. SETUP.md covers the full setup — the
modulo.toml config, automatic certificates, and migrating an
existing Apache + certbot deployment.
Modulo tunnels WebSockets to your apps with zero configuration —
something Apache + mod_WebObjects never could (mod_WebObjects
requires the prefork MPM, which is mutually exclusive with Apache's
own WebSocket-capable modules). An upgrade request is routed exactly
like any HTTP request (hostname mapping, instance pinning,
round-robin), then both sides switch to a raw byte tunnel: no frame
parsing, so subprotocols and extensions pass through untouched.
On the app side, wo-adaptor-jetty provides the WebSocket server
support — register a handler and go:
WOWebSocketRegistry.register( "/ws/chat", ChatWebSocketHandler.class );
Live demo, served through modulo: www.skoffin.com/websocket — an echo endpoint with a small test page, from the AjaxPlayground test app.
Design discussions live in the issue tracker.