Add Security Monitoring to a Next.js App with SecureNow — Traces, Logs, and Body Capture on AWS

Step-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.

Lhoussine
Mar 29, 2026·8 min read
deploy nextjs hacker news aws securenow

Add Security Monitoring to a Next.js App with SecureNow — Traces, Logs, and Body Capture on AWS

Skip the tutorial — paste this into Cursor, Copilot, or any AI assistant and it will wire SecureNow into your Next.js app in one shot:

1. Run: npm install securenow
2. Read the package docs at node_modules/securenow/README.md
3. In next.config.ts, add serverExternalPackages for:
   securenow, @vercel/otel, @opentelemetry/api, @opentelemetry/sdk-node,
   @opentelemetry/exporter-trace-otlp-http, @opentelemetry/exporter-logs-otlp-http,
   @opentelemetry/auto-instrumentations-node
4. Create src/instrumentation.ts:
   - import { registerSecureNow } from "securenow/nextjs" and call it
   - import "securenow/nextjs-auto-capture" for body capture
5. Add these env vars to .env:
   SECURENOW_APPID=<my-app-key>
   SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
   SECURENOW_LOGGING_ENABLED=1
   SECURENOW_CAPTURE_BODY=1
   SECURENOW_NO_UUID=1
6. Rebuild and restart the app

Get your app key by running npx securenow login then npx securenow apps create my-app. Read on for the full walkthrough.

You have a Next.js application running on AWS. Users are logging in, submitting data, calling API routes. But you have no visibility into what those requests contain, who is making them, or whether the patterns look normal.

SecureNow fixes that by plugging into Next.js's built-in instrumentation hook. Every server-side request becomes an OpenTelemetry trace — with full HTTP metadata, client IPs, headers, database timings, and optionally the request and response bodies. Those traces feed into a security analysis engine that lets you run forensic queries, detect anomalies, and trigger alerts.

This guide walks through integrating SecureNow into a real application: a Hacker News clone running on EC2 with PostgreSQL. The same steps apply to any self-hosted Next.js app.

Live demo: https://hn.securenow.ai

...

What SecureNow Captures

Once integrated, every request to your application generates a trace containing:

  • HTTP metadata — method, URL, status code, response time
  • Client identity — IP address (proxy-aware via X-Forwarded-For, X-Real-IP), User-Agent, Referer, Origin
  • Security signals — auth presence, CSRF tokens, request IDs
  • Infrastructure context — protocol, host, port, geographic data
  • Database timings — Prisma/pg query durations via auto-instrumentation
  • Console logsconsole.log, warn, error forwarded as structured OTLP log records
  • Request/response bodies — with automatic redaction of sensitive fields

No code changes to your route handlers. No middleware wrappers. Just one file and a few environment variables.

...

Prerequisites

  • A Next.js 13.4+ application (App Router or Pages Router)
  • Node.js 18+
  • A terminal and a browser (for CLI authentication)
...

Step 1: Install SecureNow

npm install securenow

During installation, the postinstall script detects your Next.js project and offers to create the instrumentation file automatically. You can accept that or set it up manually in the next step.

...

Step 2: Configure next.config.ts

Add serverExternalPackages so webpack does not bundle the OpenTelemetry packages — they need to run as native Node.js requires for runtime instrumentation to work:

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  // If deploying to a VM (EC2, etc.), standalone is recommended
  output: "standalone",
  serverExternalPackages: [
    "securenow",
    "@vercel/otel",
    "@opentelemetry/api",
    "@opentelemetry/sdk-node",
    "@opentelemetry/exporter-trace-otlp-http",
    "@opentelemetry/exporter-logs-otlp-http",
    "@opentelemetry/auto-instrumentations-node",
  ],
};

export default nextConfig;

If you are deploying to Vercel instead of a VM, you can omit output: "standalone" — the rest stays the same.

...

Step 3: Create the Instrumentation File

Create src/instrumentation.ts (or instrumentation.ts at the project root if you do not use a src/ directory):

export async function register() {
  if (process.env.NEXT_RUNTIME === "nodejs") {
    const { registerSecureNow } = await import("securenow/nextjs");
    registerSecureNow();
    await import("securenow/nextjs-auto-capture");
  }
}

This is the standard Next.js instrumentation hook. When the Node.js server starts:

  1. registerSecureNow() initializes the OpenTelemetry SDK with trace and log exporters pointed at your SecureNow instance. On EC2/PM2 it uses the vanilla @opentelemetry/sdk-node; on Vercel it automatically switches to @vercel/otel.
  2. securenow/nextjs-auto-capture patches NextRequest to intercept request and response bodies and attach them as span attributes — no wrapper functions needed around your route handlers.

If you only want traces and logs without body capture, omit the second import.

...

Step 4: Authenticate with the CLI

npx securenow login your@email.com

This opens a browser window. Complete authentication and the CLI stores a session token locally. Verify it worked:

npx securenow whoami
Current Session
  Email    your@email.com
  User ID  abc123...
  API      https://api.securenow.ai
  Expires  in 30 days
...

Step 5: Create an Application

Each monitored app needs an application entry in SecureNow. Create one from the CLI:

npx securenow apps create my-nextjs-app
Application created

  Name      my-nextjs-app
  Key       dc645fcd-ef8a-4b5e-a841-10e6d8a62619
  Instance  Free Trial (https://freetrial.securenow.ai:4318)

The Key is your SECURENOW_APPID. The Instance URL is the OTLP endpoint where traces and logs are sent.

Optionally set it as the default for CLI commands:

npx securenow config set defaultApp dc645fcd-ef8a-4b5e-a841-10e6d8a62619
...

Step 6: Set Environment Variables

Add the following to your .env (or .env.local for local development):

# SecureNow — required
SECURENOW_APPID="dc645fcd-ef8a-4b5e-a841-10e6d8a62619"
SECURENOW_INSTANCE="https://freetrial.securenow.ai:4318"

# SecureNow — enable logs and body capture
SECURENOW_LOGGING_ENABLED=1
SECURENOW_CAPTURE_BODY=1
SECURENOW_NO_UUID=1

What each variable does:

VariablePurpose
SECURENOW_APPIDLinks all telemetry data to your application in the dashboard
SECURENOW_INSTANCEOTLP collector endpoint — the free trial or your own ClickHouse instance
SECURENOW_LOGGING_ENABLED=1Forwards console.log, warn, error as OTLP log records
SECURENOW_CAPTURE_BODY=1Captures request/response JSON bodies on traces (with auto-redaction)
SECURENOW_NO_UUID=1Uses the APPID directly as the OpenTelemetry service name, without appending a random UUID

Optional tuning variables:

VariableDefaultPurpose
SECURENOW_MAX_BODY_SIZE10240Max body size in bytes to capture (larger bodies are truncated)
SECURENOW_SENSITIVE_FIELDSComma-separated extra field names to redact (added to built-in defaults like password, token, secret)
OTEL_LOG_LEVELwarnOpenTelemetry SDK log verbosity (debug, info, warn, error)
SECURENOW_TEST_SPANSet to 1 to emit a test span on startup for connectivity verification
...

Step 7: Build and Deploy

If you are deploying to a self-hosted server (EC2, DigitalOcean, etc.), build the standalone output and copy the env file into it:

npm run build

cp -r .next/static .next/standalone/.next/static
mkdir -p .next/standalone/public && cp -r public/* .next/standalone/public/
cp .env .next/standalone/.env

Start with PM2:

cd .next/standalone
PORT=3000 pm2 start server.js --name my-app

On Vercel, just add the environment variables in the Vercel dashboard and deploy normally.

...

Step 8: Verify the Integration

Check the application logs to confirm SecureNow loaded correctly:

pm2 logs my-app --lines 20 --nostream

You should see output like this:

[securenow] Next.js integration loading (pid=8977)
[securenow] 🖥️  Self-hosted environment detected (EC2/PM2) - using vanilla SDK
[securenow] 🎯 Vanilla SDK initialized for self-hosted environment
[securenow] 📋 Logging: ENABLED → https://freetrial.securenow.ai:4318/v1/logs
[securenow] 📋 HTTP request logging: ENABLED
[securenow] ✅ OpenTelemetry started for Next.js → https://freetrial.securenow.ai:4318/v1/traces
[securenow] 📊 Auto-capturing comprehensive request metadata:
[securenow]    • IP addresses (x-forwarded-for, x-real-ip, socket)
[securenow]    • User-Agent, Referer, Origin, Accept headers
[securenow]    • Protocol, Host, Port (proxy-aware)
[securenow]    • Geographic data (Vercel/Cloudflare)
[securenow]    • Request IDs, CSRF tokens, Auth presence
[securenow]    • Response status, content-type, content-length
[securenow] ✅ Auto-capture: Patched Next.js Request for automatic body capture
[securenow] 📝 Automatic body capture: ENABLED
[securenow] 💡 No code changes needed - bodies captured automatically!

Key lines to confirm:

  • Self-hosted environment detected — SecureNow chose the right SDK mode
  • Logging: ENABLED — console output is being forwarded as OTLP logs
  • OpenTelemetry started — traces are being exported to your endpoint
  • Automatic body capture: ENABLED — request/response bodies are being captured

As requests come in, you will also see per-request log lines:

[securenow] GET / 200 17ms
[securenow] GET /api/stories 200 9ms
[securenow] POST /api/vote 200 23ms
...

Step 9: Explore the Dashboard

Open the SecureNow dashboard to see your data:

  • Traces — every HTTP request with full metadata, timings, and body content
  • Logs — structured log records from console.log/warn/error
  • API Map — auto-discovered endpoints and their traffic patterns
  • Forensics — natural-language queries across your trace data (e.g., "Show me all POST requests to /api/auth with status 401 in the last hour")

You can also use the CLI to inspect data:

# Check dashboard overview
npx securenow status

# View recent traces
npx securenow traces list --limit 10

# View logs
npx securenow logs --limit 10

# Run forensic queries
npx securenow forensics "requests with status 500 in the last 24 hours"
...

Step 10: Set Up Alert Rules

With traces flowing, you can create alert rules that run on a schedule and notify you when something looks wrong.

1. Create a Notification Channel

Go to Dashboard → Notifications and add a channel — Email, Slack, Discord, or a webhook URL. This is where alerts get delivered.

2. Save a Forensic Query

Go to Dashboard → Forensics, write a query, and click Save to Library. Examples:

  • Show me all requests with status code 500 in the last hour
  • IPs making more than 100 requests per minute
  • POST requests to /api/auth/register from the same IP in the last 30 minutes
  • Requests with SQL injection patterns in the request body

3. Create an Alert Rule

Go to Dashboard → Alerting → Rules and create a rule:

  • Query — select one of your saved forensic queries
  • Schedule — how often to check (every 5 min, 15 min, hourly, daily)
  • Channels — which notification channels to alert
  • Applications — scope to specific apps
  • Throttle — minimum minutes between repeated alerts

Example rules worth setting up:

RuleQuerySchedule
Error spikehttp.status_code >= 500Every 5 min
Auth brute forcePOST /api/auth with status 401, grouped by IPEvery 15 min
Suspicious user-agentRequests with bot/scanner/sqlmap in User-AgentEvery 15 min
High request rateIPs with more than 200 requests in 5 minutesEvery 5 min
Unusual payloadRequests containing script tags or SQL keywords in bodyEvery 15 min
...

Troubleshooting

Traces work but no logs appear

Make sure SECURENOW_LOGGING_ENABLED=1 is in your .env. For self-hosted Next.js with standalone output, the .env file must be copied into the .next/standalone/ directory. After changing env vars, clear the build cache and rebuild:

rm -rf .next && npm run build

Body capture shows as disabled

If the logs show Body capture DISABLED at HTTP instrumentation level, make sure you have the auto-capture import in your instrumentation.ts:

await import("securenow/nextjs-auto-capture");

This line must come after registerSecureNow(). The auto-capture module patches NextRequest at the framework level, which is why it works without wrapping individual route handlers.

Sensitive data in body capture

Body capture automatically redacts fields named password, token, secret, authorization, cookie, credit_card, and similar patterns. To add your own:

SECURENOW_SENSITIVE_FIELDS="ssn,date_of_birth,bank_account"

OpenTelemetry debug output

To see detailed SDK diagnostics, set:

OTEL_LOG_LEVEL=debug

This will log every span export, batch flush, and connection attempt — useful for verifying the OTLP endpoint is reachable.

...

Summary

Integrating SecureNow into a Next.js app takes three things:

  1. One npm packagenpm install securenow
  2. One fileinstrumentation.ts with registerSecureNow() and optionally nextjs-auto-capture
  3. A few env varsSECURENOW_APPID, SECURENOW_INSTANCE, and your feature flags

From there, every request is traced with full HTTP metadata, client identity, database timings, and optionally request bodies — all feeding into a dashboard where you can query, alert, and investigate security events without touching your application code.

Frequently Asked Questions

Does SecureNow add latency to my API routes?

No. OpenTelemetry instrumentation adds less than 1% overhead. Traces and logs are exported asynchronously in batches, so request handling is never blocked by telemetry export.

What's the difference between Vercel and self-hosted?

SecureNow auto-detects the environment. On Vercel it uses @vercel/otel under the hood. On EC2 or any self-hosted setup it uses the vanilla @opentelemetry/sdk-node with full auto-instrumentation. The developer-facing API is identical — same instrumentation.ts file, same env vars.

What data does body capture collect?

When SECURENOW_CAPTURE_BODY is enabled, request and response JSON bodies are attached as span attributes. Sensitive fields like password, token, secret, authorization, and credit card numbers are automatically redacted. You can add custom fields to redact via the SECURENOW_SENSITIVE_FIELDS env var.

Can I use this with Express or Fastify instead of Next.js?

Yes. For non-Next.js apps, use the register entry point: node -r securenow/register app.js. It initializes the same OpenTelemetry SDK with auto-instrumentation for HTTP, database clients, and more.

What alerts can I set up with SecureNow?

SecureNow supports query-based alert rules. You can alert on status code spikes (5xx errors), suspicious IPs, unusual request patterns, SQL injection attempts, credential stuffing, high request rates from a single IP, and more. Alerts can be sent to Email, Slack, Discord, and webhooks.

Recommended reading

Getting Started with SecureNow and Nuxt 3 — Add Security Monitoring in Under 2 Minutes

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 2
One Flag to Trace Them All — `-r securenow/register` Now Works for ESM and CJS

Stop 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 2
How to Secure Your Fastify App with SecureNow — Real-Time API Protection via OpenTelemetry

Step-by-step guide to adding security monitoring to your Fastify API with the securenow npm package. Covers CLI setup, instrumentation, body capture caveats, PM2, Docker, and dashboard verification.

Mar 26
getting started securenow fastify