A Deno-based web server for secure execution of JavaScript modular applications ("mod-apps") with SSL management, static file serving, process isolation, and a comprehensive authentication framework.
JSMAWS follows an inside-out design philosophy: rather than an application that contains a web server, JSMAWS is a web server that contains independently deployable mod-apps. The server is the stable platform; mod-apps are the independently hot-swappable units running inside it — analogous to Apache Tomcat for Java servlets or PHP-FPM for PHP scripts, but for JavaScript mod-apps with stronger process isolation.
- HTTP to HTTPS Redirect — Automatic redirection with ACME challenge bypass
- SSL Certificate Management — Integration with Let's Encrypt / certbot; automatic reload on certificate renewal; expiry warnings at 30 days
- Static File Serving — Efficient delivery of static content with range request support, MIME type mapping, and directory traversal prevention
- JavaScript Mod-App Execution — Sub-process-based execution with full process isolation; supports regular responses, SSE streaming, and WebSocket bidirectional connections
- Privilege Separation — Operator process runs as root (to bind ports 80/443); all request-handling sub-processes run as an unprivileged user
- User-Configurable Process Pools — Named pools capable of independent scaling strategies, per-pool timeouts, and request limits (inspired by PHP-FPM)
- Authentication Framework — Built-in providers (
@jwt,@api-key,@basic,@test-identity); optional auth sub-process pool for external providers; TTL-based caching; provider-level cache key extraction - Route Groups and Host-Based Routing — Named reusable route groups with per-group auth/role overrides; multi-host SNI routing via
hostRoutes - Header and Cookie Filtering — Allowlist/denylist filtering of request and response headers/cookies at global or route-group level
- Environment and Secrets Injection —
:env:,:file:,:kv:value references resolved at config load time; per-pool and per-routeappEnvinjection into mod-apps - SLID Configuration — Human-readable configuration format using NANOS; hot-reloaded on file change or SIGHUP
- Graceful Shutdown — SIGTERM triggers a configurable deadline with spread across process layers; mod-apps receive
JSMAWS.shutdownDeadlinepromise - WebSocket Support — Full bidirectional communication via PolyTransport
- Deno 2.0 or later
# Clone the repository
git clone https://github.com/your-org/jsmaws.git
cd jsmaws
# Run the test suite to verify your installation
./deno-test
# Start the server (HTTP-only development mode)
deno run \
--allow-read \
--allow-net \
--allow-run \
--allow-env \
--allow-sys \
--unstable-worker-options \
src/operator.esm.js \
--config jsmaws.slidJSMAWS uses SLID format (.slid files) for configuration. The file is monitored for changes and reloaded automatically; a SIGHUP signal also triggers a reload.
[(
noSSL=@t /* Run without SSL */
httpPort=8080
hostname=localhost
root=/var/www/html
appRoot=/var/www/apps
routes=[
[path=/static/:* pool=fast app=@static method=read]
[path=/api/:* pool=standard app=./apps/api.esm.js]
[regex='^/.*' response=404]
]
)]
[(
hostname=0.0.0.0
httpPort=80
httpsPort=443
certFile=/etc/letsencrypt/live/example.com/fullchain.pem
keyFile=/etc/letsencrypt/live/example.com/privkey.pem
acmeChallengeDir=/var/www/acme-challenge
uid=33
gid=33
shutdownDelay=30
shutdownSpread=0.1
authn=[
[provider=@jwt secret=:env:JWT_SECRET algorithm=HS256]
]
pools=[
fast=[minProcs=2 maxProcs=10 maxWorkers=8 maxReqs=1000 reqTimeout=5]
standard=[minProcs=1 maxProcs=20 maxWorkers=4 maxReqs=100 reqTimeout=60]
stream=[minProcs=0 maxProcs=50 maxWorkers=1 maxReqs=1 reqTimeout=0 idleTimeout=60 conTimeout=3600 resType=[stream bidi]]
]
routes=[
[path=/static/:* pool=fast app=@static method=read]
[path=/api/:* pool=standard app=./apps/api.esm.js]
[path=/ws/:* pool=stream app=./apps/ws.esm.js method=any]
[regex='^/.*' response=404]
]
)]
See docs/configuration.md for the complete configuration reference.
jsmaws/
├── src/
│ ├── operator.esm.js # Main entry point (privileged process bootstrap)
│ ├── operator-process.esm.js # OperatorProcess class (lifecycle, pools, config)
│ ├── operator-request-state.esm.js# Request state machine
│ ├── responder-process.esm.js # Responder sub-process (executes mod-apps)
│ ├── router-worker.esm.js # Router worker implementation
│ ├── pool-manager.esm.js # Generic process pool manager
│ ├── process-manager.esm.js # Sub-process lifecycle management
│ ├── ssl-manager.esm.js # SSL certificate monitoring and expiry checks
│ ├── configuration.esm.js # System-wide configuration class
│ ├── file-monitor.esm.js # Generic file-change monitor
│ ├── logger.esm.js # Centralized logging (console and syslog)
│ ├── operator-authn.esm.js # Authentication chain (operator-resident providers)
│ ├── auth-process.esm.js # Auth sub-process (external providers)
│ ├── value-resolver.esm.js # :env:/:file:/:kv: value reference resolution
│ ├── apps/
│ │ ├── bootstrap.esm.js # Mod-app bootstrap (JSMAWS namespace, channels)
│ │ └── static-content.esm.js # Static file serving mod-app
│ └── auth/
│ ├── jwt.esm.js # @jwt provider
│ ├── api-key.esm.js # @api-key provider
│ ├── basic.esm.js # @basic provider
│ └── test-identity.esm.js # @test-identity provider (dev/testing only)
├── test/ # Unit tests
├── test-e2e/ # End-to-end tests
├── examples/
│ ├── apps/ # Example mod-apps (hello-world, SSE clock, WebSocket echo)
│ └── clients/ # Example test clients
├── docs/
│ ├── configuration.md # Full configuration reference
│ ├── deployment.md # Production deployment guide
│ ├── mod-app-development.md # Writing mod-apps for JSMAWS
│ └── client-bidi-integration.md # Client-side WebSocket/bidi integration
├── arch/ # Architecture and design documents
├── jsmaws.slid # Default configuration file
└── deno-test # Test runner script
# All unit tests
./deno-test test
# End-to-end tests (requires a running server; starts/stops automatically)
./deno-test test-e2e# Start the server with the example configuration
deno run --allow-all --unstable-worker-options \
src/operator.esm.js --config examples/jsmaws-examples.slid
# In another terminal, run an example client
deno run --allow-net examples/clients/http-hello.esm.js
deno run --allow-net examples/clients/sse-clock.esm.js
deno run --allow-net examples/clients/ws-echo.esm.jsSee examples/README.md for details on the example mod-apps.
A mod-app is an ES module that exports a default handler function. JSMAWS bootstraps the mod-app in a Web Worker and exposes a frozen globalThis.JSMAWS namespace:
// Copyright 2026 Kappa Computer Solutions, LLC and Brian Katzung
// my-app.esm.js — simple JSON response mod-app
export default async function handler () {
const { server } = globalThis.JSMAWS;
const req = await server.read({ only: 'req', decode: true });
if (!req) return;
const { method, url } = JSON.parse(req.text);
await req.done();
const body = JSON.stringify({ hello: 'world', method, url });
await server.write('res', JSON.stringify({
status: 200,
headers: { 'content-type': 'application/json' },
body,
}));
}See docs/mod-app-development.md for the complete mod-app development guide, including streaming (SSE) and bidirectional (WebSocket) patterns.
See docs/deployment.md for the full production deployment guide, including:
- System requirements and Deno installation
- Directory layout and privilege setup
- systemd unit file
- Let's Encrypt / certbot integration
- Log rotation
- Pool sizing recommendations
- Upgrade procedure
| Document | Description |
|---|---|
docs/configuration.md |
Complete configuration reference |
docs/deployment.md |
Production deployment guide |
docs/mod-app-development.md |
Writing mod-apps for JSMAWS |
docs/client-bidi-integration.md |
Client-side WebSocket/bidi integration |
examples/README.md |
Example mod-apps and clients |
JSMAWS uses a multi-process architecture with privilege separation:
Privileged Operator Process (root)
├── Binds ports 80 / 443
├── Reads configuration (SLID)
├── Runs authentication chain (operator-resident providers)
└── Manages process pools
├── "fast" pool — short-duration, high-frequency requests
├── "standard" pool — general application requests
└── "stream" pool — WebSocket / SSE connections
└── Responder sub-processes (uid: www-data)
└── Mod-app Web Workers
Key design documents are in the arch/ directory.
MIT License
Copyright 2025–2026 Kappa Computer Solutions, LLC and Brian Katzung