- JavaScript 78.1%
- CSS 21.5%
- HTML 0.4%
| backend | ||
| frontend | ||
| scripts | ||
| .gitignore | ||
| ecosystem.config.js | ||
| LICENSE | ||
| package.json | ||
| README.md | ||
NeoStatus
A self-hosted, real-time status page for monitoring your services, APIs, and infrastructure.
Warning
This project is no longer in development, the cost of hosting, not having enough time and changes in my life, i decided to stop development and focus on things that i really care about. I going to leave the code up if anyone comes accross it and decides it's useful for them. no support will be given and NeoNeko has change it's focused.
NeoStatus
A free and open source status page you can self-host to monitor uptime, track incidents, and show your users a clean, real-time view of your services. No external database required, everything runs on SQLite.
Features
Real-time monitoring - monitor HTTP/HTTPS endpoints, TCP ports, and ICMP ping with customisable check intervals from 10 seconds to 1 hour.
Live status updates - WebSocket-powered real-time updates pushed to the public status page and admin dashboard as checks complete.
Admin dashboard - add, edit and remove endpoints, manage incidents, configure site settings, manage users, and generate API keys from a single panel.
Public status page - a clean, responsive page showing current status, response times, uptime stats, heatmaps, active incidents, and overall system health.
Incident management - create, update, and resolve incidents with severity levels, link them to affected endpoints, and write post-mortems.
Scheduled maintenance - schedule maintenance windows for endpoints to pause monitoring and display notice to visitors.
Uptime tracking - automatic uptime percentage calculation with SLA tracking over configurable time periods, plus jitter and packet loss metrics for ping checks.
Role-based access - admin and viewer roles with enforced permissions on all protected routes.
Email notifications - SMTP-based notifications with per-user preferences. Subscribe to all endpoints or specific categories. Get notified on downtime, recovery, degradation, or incidents.
API access - generate API keys for programmatic access to your status data. Rate-limited public API with status.json, summary, components, and incidents endpoints.
Custom branding - rename your status page, customize the public URL, and configure SMTP for outgoing notifications.
Zero external dependencies - SQLite database, no Redis or Postgres required. Just Node.js.
Note
See it in action here: https://status.neoneko.org
Note
This project is actively developed. Slack/Discord notifications, detailed analytics, and more are planned for future releases.
Requirements
- Node.js 24 LTS or newer
- A Linux, macOS, or Windows machine
Quick Start
1. Clone and install
git clone https://git.neoneko.org/NeoNeko/NeoStatus
cd NeoStatus
# Install all dependencies (root, backend, and frontend)
npm run install-all
2. Configure
cp backend/.env.example backend/.env
Edit backend/.env and change the JWT secret to a strong random value:
PORT=5000
NODE_ENV=production
JWT_SECRET=replace_with_a_strong_random_string
DATABASE_PATH=../data/status.db
FRONTEND_URL=https://status.example.com
# Background workers (monitoring, maintenance scheduler, webhook retries).
# Leave unset/true to run them inside the API process (simplest).
# Set to false ONLY if you run a separate worker process (see deployment below).
RUN_WORKERS=true
# Required only when RUN_WORKERS=false must match on the API and the worker
# so the worker can forward realtime events to the API.
# WORKER_SECRET=replace_with_a_shared_random_string
Important
Never deploy with the default JWT secret. Generate one with
openssl rand -hex 64or similar.
Important
The background worker drives endpoint monitoring, the scheduled-maintenance start/end webhooks, and webhook delivery retries. If it isn't running, the public page goes stale and maintenance webhooks never fire. Make sure your chosen mode below actually starts it.
3. Run
Development (runs React dev server + backend with hot reload):
npm run dev
Production (builds frontend, serves everything from the backend):
# Build the frontend
npm run build
# Start the server
npm start
Everything runs on a single port in production:
| URL | |
|---|---|
| Status page | http://localhost:5000 |
| Admin panel | http://localhost:5000/admin |
| API | http://localhost:5000/api |
On first launch you'll be guided through a setup wizard to create your admin account and configure site settings.
Public API
NeoStatus exposes a free, rate-limited (60 req/min) public API for integration:
| Endpoint | Description |
|---|---|
/api/v1/status.json |
Full status dump (primary integration) |
/api/v1/summary |
Lightweight summary (page name + overall status) |
/api/v1/components |
All monitored components |
/api/v1/incidents |
Current and past incidents |
/api/v1/scheduled-maintenances |
Upcoming scheduled maintenance |
You can enrich responses by passing an API key via the X-API-Key header.
Production Deployment
Worker modes
The background worker (endpoint monitoring, scheduled-maintenance start/end
scheduler, and webhook delivery retries) can run in one of two modes, controlled
by RUN_WORKERS in backend/.env:
| Mode | RUN_WORKERS |
What runs | Use when |
|---|---|---|---|
| In-process (recommended) | true or unset |
One process serves the API and runs the workers | Single server / VM simplest, nothing to forget |
| Split | false |
API process + a separate worker process | You scale the API separately, run multiple API instances, or want the worker isolated |
Warning
In split mode,
RUN_WORKERS=falsemakes the API start without any workers. You must start the worker process separately, or monitoring and maintenance webhooks silently never run. Manage both with the PM2 ecosystem file below so you can't start one without the other.
Running with PM2, in-process mode (recommended)
With RUN_WORKERS=true (or unset), a single process does everything:
# Install PM2 globally
npm install -g pm2
# Build the frontend first
npm run build
# Start the app (API + workers in one process)
pm2 start "npm start" --name neostatus
# Auto-start on reboot
pm2 startup
pm2 save
# View logs
pm2 logs neostatus
Running with PM2, split mode (separate worker)
With RUN_WORKERS=false, run the API and the worker as two PM2 apps. The repo
ships an ecosystem.config.js that defines both, so a
single command always brings them up together:
npm install -g pm2
npm run build
# Set these in backend/.env:
# RUN_WORKERS=false
# WORKER_SECRET=<same value used by both processes>
# Start BOTH the API and the worker
pm2 start ecosystem.config.js
# Auto-start on reboot
pm2 startup
pm2 save
# Verify both are online
pm2 ls # expect: neostatus (API) AND neostatus-worker
pm2 logs neostatus-worker
Day-to-day, always use pm2 start ecosystem.config.js /
pm2 restart ecosystem.config.js so the worker is never left behind. Starting
only the API (e.g. pm2 start neostatus) will leave monitoring and
maintenance webhooks dead.
Tip
Not sure if the worker is running? If the public page stops updating or scheduled maintenance never fires its webhook, check
pm2 lsthe worker process should beonline, andpm2 logs neostatus-workershould show✓ NeoStatus worker running.
Using a Reverse Proxy (Nginx)
Since everything runs on port 5000 in production, the Nginx config is straightforward:
server {
listen 80;
server_name status.example.com;
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_buffering off;
}
}
Tip
Use Certbot to add HTTPS with a free Let's Encrypt certificate. Update
FRONTEND_URLin your.envto match your domain.
Troubleshooting
Port already in use
lsof -i :5000
lsof -i :3000
kill -9 <PID>
Database issues
Delete the database to reset (this loses all data):
rm data/status.db
npm start
The database will be recreated automatically on startup.
Public page is stale / maintenance webhooks never fire
These are all driven by the background worker. If it isn't running, endpoint
checks stop updating, scheduled maintenance never transitions, and its
maintenance.start / maintenance.end webhooks never fire even though
incident webhooks (triggered by admin actions on the API) still work.
- In-process mode (
RUN_WORKERS=true/unset): restart the apppm2 restart neostatus. - Split mode (
RUN_WORKERS=false): the worker is a separate process. Check it's up withpm2 lsand start both withpm2 start ecosystem.config.js. Restarting only the API does not start the worker.
Confirm the worker is alive: pm2 logs neostatus-worker should show
✓ NeoStatus worker running, and new endpoint checks should appear shortly
after startup.
WebSocket not connecting
Make sure FRONTEND_URL in backend/.env matches your actual frontend URL. If using a reverse proxy, ensure the /socket.io path is proxied correctly.
Ping checks not working
Ping checks require elevated privileges. On Linux, you may need to set the correct capability:
sudo setcap cap_net_raw+ep $(which node)
Or run the backend as root (not recommended for production).
License
MIT
Made with care for anyone who needs a simple, self-hosted status page.