NaaS
Deprecated: NaaS is no longer maintained. Use YESorNOaaS instead:
npm install -g @ravidor/yesornoaasfor Yes!, No!, and random answers in one service.
No as a Service.
Every request returns:
No!
Requirements
- Node.js 22 or newer
- npm
Install
Install globally from npm:
npm install -g @ravidor/naas
Or clone and run locally:
git clone https://github.com/ravidorr/no-as-a-service.git
cd no-as-a-service
npm install
Run
npm start
The API listens on http://localhost:3000 by default.
The UI is available at http://localhost:3000.
Use ?request= to open a shareable NaaS flow that types and submits the request automatically.
Health check:
curl http://localhost:3000/health
Output:
{"status":"No!","version":"0.6.2"}
Prometheus metrics:
curl http://localhost:3000/metrics
Output is Prometheus text format (text/plain; charset=utf-8; version=0.0.4).
The endpoint is public, exempt from rate limiting, and remains available during
graceful shutdown.
Custom HTTP metrics:
naas_http_requests_total{route,method,status_code}naas_http_request_duration_seconds{route,method,status_code}naas_http_requests_in_flight{route,method}
Route labels are normalized to version, health, metrics, api_no, or
fallback. Scrape traffic to /metrics is not counted in the custom HTTP
metrics.
Standard Node.js process and runtime metrics (CPU, memory, event loop, GC) are also included.
Treat /metrics as an internal operations endpoint. On the public internet,
bind to a private network, restrict access at your reverse proxy, or scrape
from an internal URL only. See SECURITY.md for deployment
guidance.
Version:
curl http://localhost:3000/version
Output:
0.6.2
OpenAPI specification:
curl http://localhost:3000/openapi.yaml
curl -X POST http://localhost:3000/anything \
-H 'content-type: application/json' \
-d '{"question":"Can I?"}'
Output:
No!
Use a different port:
PORT=8080 npm start
Rate limiting applies to /api/no and fallback routes. Static assets,
GET /health, and GET /metrics are exempt. Throttled requests return 429
with the body No!.
Configure the limit with environment variables:
RATE_LIMIT_WINDOW_MS=900000 RATE_LIMIT_MAX=100 npm start
Defaults are 100 requests per client IP every 15 minutes. Limits are stored in process memory, so multiple instances do not share quota state. With N replicas, the effective limit is roughly N times the configured maximum unless you use a shared store (for example Redis; see ROADMAP.md).
Behind a reverse proxy or ingress, set TRUST_PROXY so limits key on the
client IP from X-Forwarded-For instead of the proxy IP:
TRUST_PROXY=1 npm start
Accepted values are true, false, or a non-negative integer hop count. When
unset, Express trust proxy stays disabled.
Graceful shutdown applies when the process receives SIGTERM or SIGINT, such
as docker stop or local Ctrl+C. The server marks itself as draining and
continues accepting connections briefly so orchestrators can observe 503 on
GET /health with the same JSON body. After a readiness grace period, it stops
accepting new connections, reaps idle keep-alive sockets, and waits for active
requests to finish.
Configure the drain deadline and readiness grace with:
SHUTDOWN_TIMEOUT_MS=30000 SHUTDOWN_READINESS_GRACE_MS=1000 npm start
The default drain deadline is 30 seconds. The default readiness grace is 1 second. After the deadline, remaining HTTP connections are force-closed before exit. A second signal during shutdown exits immediately with a non-zero status.
Docker
Pull the published release image:
docker pull ghcr.io/ravidorr/no-as-a-service:0.6.2
Run the container:
docker run --rm -p 3000:3000 ghcr.io/ravidorr/no-as-a-service:0.6.2
The version tag is immutable. latest tracks the newest release:
docker pull ghcr.io/ravidorr/no-as-a-service:latest
docker run --rm -p 3000:3000 ghcr.io/ravidorr/no-as-a-service:latest
Build the image locally:
docker build -t naas .
docker run --rm -p 3000:3000 naas
Verify the health check:
curl http://localhost:3000/health
Inspect container health status:
docker inspect --format='{{.State.Health.Status}}' "$(docker ps -q --filter ancestor=naas)"
Use a different port:
docker run --rm -e PORT=8080 -p 8080:8080 naas
The image runs Node directly as PID 1 so container stop signals reach the HTTP
server. docker stop triggers bounded graceful draining using the same
SHUTDOWN_TIMEOUT_MS behavior as local runs.
CLI
After a global install:
naas anything at all
For local development:
npm link
naas anything at all
Output:
No!
MCP
Run the stdio MCP server:
npm run mcp
After a global install or npm link, MCP clients can use:
naas-mcp
It exposes one tool:
no: returnsNo!and ignores all arguments.
Test
npm test
Contributors should also run the coverage gate before opening a pull request:
npm run test:coverage
Roadmap
See ROADMAP.md for completed work and the release process.
Community
Release policy: every merged change must bump the version in package.json and add a matching entry to CHANGELOG.md. See Contributing for details.
License
MIT
Social icons are from Font Awesome Free.