How to Secure Your h3 App with SecureNow — Nitro-Ready Observability Guide
Complete walkthrough for adding security monitoring to your h3 / Nitro application with the securenow npm package. Covers CLI setup, body capture, instrumentation, PM2, and Docker.

How to Secure Your h3 App with SecureNow — Nitro-Ready Observability Guide
h3 is the minimal, high-performance HTTP framework from the UnJS ecosystem. It powers Nitro — and by extension Nuxt 3's entire server engine — which means a huge number of production APIs run on h3 without developers even realizing it. If you are building directly on h3 (or Nitro), you get blazing-fast event handlers. What you don't get is built-in security observability.
SecureNow changes that. A single require() line auto-instruments your h3 application with OpenTelemetry-powered tracing, so SQL injection probes, credential stuffing, API abuse, and anomalous traffic are surfaced in real time — without adding middleware or rewriting handlers.
This guide walks you through the full integration: install, CLI authentication, app creation, environment configuration, instrumentation, and production deployment with PM2 and Docker.
Prerequisites
- Node.js 18+ installed
- An existing h3 project (or willingness to scaffold a quick one)
- A terminal and a browser
No SecureNow account yet? No problem — the CLI will open a browser-based signup/login flow for you.
Step 1: Install the Package
Open your project directory and install securenow:
npm install securenow
This single package bundles the OpenTelemetry SDK, auto-instrumentations for Node.js, an OTLP exporter, the SecureNow CLI, and optional console-log forwarding. There is nothing else to install.
Step 2: Log In via the CLI
SecureNow ships a CLI as securenow (or npx securenow if you installed it locally). Authenticate with one command:
npx securenow login
A browser tab opens at app.securenow.ai where you can sign up or log in. Once authenticated, the token is saved to ~/.securenow/credentials.json and every subsequent CLI command is authorized.
Prefer a non-interactive flow? Generate a CLI token from your dashboard at Settings → CLI Token, then run:
npx securenow login --token YOUR_TOKEN
Verify you are logged in:
npx securenow whoami
You should see your email and account details printed in the terminal.
Step 3: Create an Application (Free Trial)
Every application you monitor in SecureNow gets a unique identifier (the app key). Create one from the CLI:
npx securenow apps create my-h3-api
The CLI will prompt you to pick a ClickHouse instance. Choose Free Trial — this provisions a managed OTLP collector at https://freetrial.securenow.ai:4318 at no cost and with no credit card.
After creation you will see output like:
✔ Application created
SECURENOW_APPID=a1b2c3d4-e5f6-7890-abcd-ef1234567890
SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
Add these to your .env file.
Copy those two values — you will need them in the next step.
Optionally, set the new app as your default so CLI commands like securenow traces and securenow status target it automatically:
npx securenow config set defaultApp a1b2c3d4-e5f6-7890-abcd-ef1234567890
Step 4: Configure Environment Variables
Create (or update) a .env file in your project root:
SECURENOW_APPID=a1b2c3d4-e5f6-7890-abcd-ef1234567890
SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
SECURENOW_LOGGING_ENABLED=1
SECURENOW_CAPTURE_BODY=1
| Variable | Purpose |
|---|---|
SECURENOW_APPID | Identifies your app in the dashboard. Use the key from Step 3. |
SECURENOW_INSTANCE | OTLP collector URL. Free trial default shown above. |
SECURENOW_LOGGING_ENABLED | Set to 1 to forward console.log/warn/error as OTel logs. |
SECURENOW_CAPTURE_BODY | Set to 1 to attach request bodies to trace spans. h3's readBody works alongside the capture hook, so body capture is fully supported. Sensitive fields are automatically redacted. |
Step 5: Instrument Your h3 App
You have two options — pick whichever fits your workflow.
Option A: Two Lines at the Top of Your Entry File (Recommended)
Add these lines before any other require or import:
require('securenow/register');
require('securenow/console-instrumentation');
const http = require('http');
const { createApp, createRouter, defineEventHandler, readBody, toNodeListener } = require('h3');
const app = createApp();
const router = createRouter();
router.get('/health', defineEventHandler(() => {
return { status: 'ok', timestamp: new Date().toISOString() };
}));
router.post('/tasks', defineEventHandler(async (event) => {
const body = await readBody(event);
console.log('Creating task', { title: body.title, priority: body.priority });
const task = {
id: Date.now(),
title: body.title,
priority: body.priority || 'medium',
createdAt: new Date().toISOString(),
};
event.node.res.statusCode = 201;
return task;
}));
app.use(router);
const PORT = process.env.PORT || 3000;
http.createServer(toNodeListener(app)).listen(PORT, () => {
console.log(`h3 server running on http://localhost:${PORT}`);
});
securenow/register starts the OpenTelemetry SDK, reads your .env, and auto-instruments HTTP, database drivers, and more. securenow/console-instrumentation forwards console.* calls as OTel log records so they appear alongside your traces in the dashboard.
Option B: Zero Code Changes with NODE_OPTIONS
If you prefer not to touch your source files at all, preload the modules via NODE_OPTIONS:
NODE_OPTIONS="-r securenow/register -r securenow/console-instrumentation" node app.js
Or add it to your package.json scripts:
{
"scripts": {
"start": "node app.js",
"start:observe": "NODE_OPTIONS='-r securenow/register -r securenow/console-instrumentation' node app.js"
}
}
Then run:
npm run start:observe
Step 6: Start and Verify
Run your app:
node app.js
You should see confirmation in your terminal:
[securenow] OTel SDK started → https://freetrial.securenow.ai:4318/v1/traces
[securenow] 📋 Logging: ENABLED → https://freetrial.securenow.ai:4318/v1/logs
[securenow] Console instrumentation installed
h3 server running on http://localhost:3000
Generate some traffic — curl http://localhost:3000/health a few times — then check your dashboard:
npx securenow status
You should see your app listed as protected. You can also browse traces directly from the terminal:
npx securenow traces
Or open the full dashboard at app.securenow.ai to explore traces, logs, security issues, and analytics.
Bonus: Useful CLI Commands
Once your app is instrumented, the CLI becomes your terminal-based control plane:
| Command | What It Does |
|---|---|
securenow traces | List recent traces |
securenow traces show <traceId> | Inspect a single trace |
securenow traces analyze <traceId> | AI-powered trace analysis |
securenow logs | List recent logs |
securenow issues | View detected security issues |
securenow analytics | Traffic and performance analytics |
securenow ip <address> | Look up an IP address |
securenow blocklist add <ip> | Block a malicious IP |
securenow alerts rules | Manage alert rules |
securenow forensics | Run natural-language forensic queries |
Production Deployment with PM2
For production, use PM2 with an ecosystem config:
// ecosystem.config.js
module.exports = {
apps: [{
name: 'my-h3-api',
script: './app.js',
instances: 4,
exec_mode: 'cluster',
node_args: '-r securenow/register -r securenow/console-instrumentation',
env: {
SECURENOW_APPID: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
SECURENOW_INSTANCE: 'https://freetrial.securenow.ai:4318',
SECURENOW_LOGGING_ENABLED: '1',
SECURENOW_CAPTURE_BODY: '1',
SECURENOW_NO_UUID: '1',
NODE_ENV: 'production',
}
}]
};
pm2 start ecosystem.config.js
Setting SECURENOW_NO_UUID=1 ensures all cluster workers report under the same service name.
Docker Deployment
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
ENV SECURENOW_APPID=my-h3-api
ENV SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
ENV SECURENOW_LOGGING_ENABLED=1
ENV SECURENOW_CAPTURE_BODY=1
ENV NODE_ENV=production
EXPOSE 3000
CMD ["node", "app.js"]
What SecureNow Detects Automatically
Once traces are flowing, SecureNow watches for:
- SQL injection — malicious patterns in query parameters and request bodies
- XSS attempts — script injection in user input
- Credential stuffing — high-velocity failed authentication attempts
- API abuse — unusual request patterns, rate-limit evasion, unauthorized endpoint access
- Anomalous traffic — AI-powered detection of behavioral outliers
- Supply-chain signals — unexpected outbound calls from your service
- Performance degradation — slow queries, high error rates, latency spikes
All of this happens without writing a single detection rule. Security issues surface in the dashboard and can trigger alerts via email, Slack, or custom webhooks.
A Note on Nitro and Nuxt 3
h3 is the HTTP layer inside Nitro, and Nitro is the server engine inside Nuxt 3. If you are building a standalone h3 or Nitro server (outside of Nuxt), the integration above works as-is. If you are running a full Nuxt 3 application, SecureNow still works — but you will instrument the Nitro build output (the .output/server/index.mjs file) rather than a hand-written app.js. Point NODE_OPTIONS or PM2's node_args at the Nitro entry and everything else stays the same.
Recap
| Step | Command / Action | Time |
|---|---|---|
| Install | npm install securenow | 10 s |
| Login | npx securenow login | 20 s |
| Create app | npx securenow apps create my-h3-api | 15 s |
| Configure | Add env vars to .env (body capture on) | 30 s |
| Instrument | Add two require() lines or use NODE_OPTIONS | 30 s |
| Verify | npx securenow status | 10 s |
Six steps, five minutes, zero handler changes. Your h3 API is now observable and protected.
Next Steps
- Explore the SecureNow dashboard to view traces, logs, and security issues
- Set up alert rules for critical security events
- Run
npx securenow forensicsto ask natural-language questions about your traffic - Read the full environment variable reference for advanced tuning
Happy shipping — and happy securing.
Frequently Asked Questions
Does SecureNow work with Nitro and Nuxt 3 server routes?
Yes. h3 is the HTTP framework that powers Nitro, which is Nuxt 3's server engine. SecureNow's auto-instrumentation hooks into the underlying Node.js HTTP layer, so it captures every h3/Nitro handler — including Nuxt server routes, API routes, and middleware — without any Nuxt-specific configuration.
Can I enable request body capture with h3?
Yes. Unlike some frameworks that consume the request stream during parsing, h3's readBody function works alongside SecureNow's body capture hook. Set SECURENOW_CAPTURE_BODY=1 and request payloads will be attached to trace spans with sensitive fields automatically redacted.
Do I need to install any h3-specific plugin for SecureNow?
No. SecureNow auto-instruments via Node.js preload and hooks into the standard HTTP layer that h3 builds on. No plugins, no defineNitroPlugin, and no changes to your event handlers are needed.
Does SecureNow work with PM2 cluster mode and h3?
Yes. Pass the preload via node_args in your ecosystem.config.js and set SECURENOW_NO_UUID=1 so all workers report under the same service name. h3 runs on a plain Node.js HTTP server, so clustering behaves identically to any other Node.js app.
Recommended reading
A hands-on walkthrough for adding security observability to a Nuxt 3 app using the securenow npm package and official Nuxt module. Covers installation, nuxt.config.ts setup, environment variables, optional tuning, deployment targets, CLI verification, and troubleshooting.
Apr 2Stop juggling --require and --import flags. securenow/register now auto-registers the ESM loader hook via module.register() on Node >=20.6, so a single -r flag is all you need for both CommonJS and ESM apps.
Apr 2Step-by-step guide to integrating SecureNow into a self-hosted Next.js application on AWS EC2. Covers installation, instrumentation, environment configuration, verifying traces and logs, enabling request body capture, and creating alert rules.
Mar 29