{"id":51633026,"url":"https://github.com/ashishjsharda/opstatus","last_synced_at":"2026-07-13T10:31:03.709Z","repository":{"id":369309309,"uuid":"1289199602","full_name":"ashishjsharda/opstatus","owner":"ashishjsharda","description":"Self-hosted open source status page. Track service uptime, communicate incidents, schedule maintenance \u0026 notify subscribers — beautiful dark/light UI, zero config, single SQLite file. Drop-in alternative to Atlassian Statuspage.","archived":false,"fork":false,"pushed_at":"2026-07-04T15:16:05.000Z","size":414,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-04T17:07:03.946Z","etag":null,"topics":["devops","incident-management","incident-response","infrastructure","monitoring","nextjs","open-source","self-hosted","self-hosting","sre","status","status-dashboard","status-page","status-page-ui","statuspage","uptime-monitoring"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ashishjsharda.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-07-04T12:54:28.000Z","updated_at":"2026-07-04T15:16:08.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ashishjsharda/opstatus","commit_stats":null,"previous_names":["ashishjsharda/opstatus"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/ashishjsharda/opstatus","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashishjsharda%2Fopstatus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashishjsharda%2Fopstatus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashishjsharda%2Fopstatus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashishjsharda%2Fopstatus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ashishjsharda","download_url":"https://codeload.github.com/ashishjsharda/opstatus/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashishjsharda%2Fopstatus/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35420322,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-13T02:00:06.543Z","response_time":119,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["devops","incident-management","incident-response","infrastructure","monitoring","nextjs","open-source","self-hosted","self-hosting","sre","status","status-dashboard","status-page","status-page-ui","statuspage","uptime-monitoring"],"created_at":"2026-07-13T10:31:03.613Z","updated_at":"2026-07-13T10:31:03.702Z","avatar_url":"https://github.com/ashishjsharda.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Opstatus\n\nA beautiful, self-hosted open source status page. Track services, communicate incidents, schedule maintenance, and keep your users subscribed — all from a single SQLite file. No external database. No native compilation. Works on Windows, Mac, and Linux.\n\n![Dark mode](https://img.shields.io/badge/theme-dark%20%2F%20light-brightgreen)\n![Next.js](https://img.shields.io/badge/Next.js-14-black)\n![Node](https://img.shields.io/badge/Node.js-22%2B-339933)\n![SQLite](https://img.shields.io/badge/database-SQLite-blue)\n![License](https://img.shields.io/badge/license-MIT-purple)\n\n---\n\n## Screenshots\n\n### Dark Mode\n![Opstatus dark mode — service uptime grid](docs/dark-services.png)\n\n### Light Mode\n![Opstatus light mode — service uptime grid](docs/light-services.png)\n\n### Incident Timeline\n![Opstatus incident timeline with update history](docs/dark-incidents.png)\n\n---\n\n## Features\n\n- **Service health tracking** — operational / degraded / partial outage / major outage / maintenance\n- **90-day uptime bars** — visual history per service, grouped by category\n- **Incident management** — create incidents, post timestamped updates (investigating → identified → monitoring → resolved)\n- **Maintenance windows** — schedule, track, and complete planned maintenance\n- **Email subscribers** — visitors subscribe to status updates; confirm / unsubscribe via token\n- **Dark + light mode** — gorgeous on both, three-way toggle (light / dark / system)\n- **Zero native dependencies** — uses Node's built-in `node:sqlite` — no node-gyp, no build tools needed\n- **Admin panel** — full CRUD via `/admin`, protected by session-based auth\n- **Docker ready** — multi-stage Dockerfile + `docker-compose.yml` included\n\n---\n\n## Requirements\n\n- **Node.js 22+** — Opstatus uses Node's built-in `node:sqlite` module (introduced in Node 22). Node 20 will not work.\n\nCheck your version:\n```bash\nnode --version   # must be v22.x or higher\n```\n\nDownload Node 22 from [nodejs.org](https://nodejs.org) if needed.\n\n---\n\n## Quick Start\n\n```bash\n# 1. Clone\ngit clone https://github.com/your-org/opstatus\ncd opstatus\n\n# 2. Install dependencies\nnpm install\n\n# 3. Configure\ncp .env.example .env.local\n# Edit .env.local — at minimum change ADMIN_PASSWORD and SESSION_SECRET\n\n# 4. Run\nnpm run dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000) — public status page.  \nOpen [http://localhost:3000/admin](http://localhost:3000/admin) — admin panel.\n\nDefault admin password: `password` — **change this before going live**.\n\n\u003e **Windows users:** Clone or copy the project to a short path like `C:\\opstatus` to avoid Windows' 260-character MAX_PATH limit during `npm install`.\n\n---\n\n## Load Demo Data\n\nAfter running the dev server at least once (to initialise the database), populate it with realistic demo data:\n\n```bash\n# Run from inside the opstatus project folder\nnode --experimental-sqlite scripts/seed.mjs\n```\n\nThis seeds:\n- 10 services across 3 groups (Core, Infrastructure, Integrations)\n- 90 days of uptime history per service (with realistic blips)\n- 1 active incident with a 3-step timeline\n- 1 scheduled maintenance window\n\nThen restart the dev server and refresh your browser to see everything.\n\n---\n\n## Docker\n\n```bash\n# Using Docker Compose (recommended)\ncp .env.example .env\n# Edit .env with your values\n\ndocker compose up -d\n```\n\nOr with plain Docker:\n```bash\ndocker build -t opstatus .\ndocker run -p 3000:3000 \\\n  -v opstatus_data:/app/data \\\n  -e ADMIN_PASSWORD=your-secure-password \\\n  -e SESSION_SECRET=your-32-char-random-secret \\\n  opstatus\n```\n\n---\n\n## Configuration\n\nAll config lives in `.env.local` (development) or environment variables (production/Docker).\n\n| Variable | Description | Default |\n|---|---|---|\n| `NEXT_PUBLIC_SITE_NAME` | Site name in header + tab title | `My Status Page` |\n| `NEXT_PUBLIC_SITE_URL` | Public URL of your status page | `http://localhost:3000` |\n| `NEXT_PUBLIC_SUPPORT_URL` | Link to your support page (optional) | — |\n| `ADMIN_PASSWORD` | Admin panel password | `password` |\n| `SESSION_SECRET` | 32+ char random string for session encryption | ⚠️ required in prod |\n| `DATABASE_PATH` | Path to SQLite DB file | `./data/opstatus.db` |\n| `SMTP_HOST` | SMTP server for email notifications | — |\n| `SMTP_PORT` | SMTP port | `587` |\n| `SMTP_USER` | SMTP username | — |\n| `SMTP_PASS` | SMTP password | — |\n| `SMTP_FROM` | From address for emails | — |\n\n---\n\n## Deployment\n\nOpstatus runs anywhere Node.js 22+ runs.\n\n**VPS (Recommended for production):**\n```bash\n# Install Node 22\ncurl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -\nsudo apt install nodejs\n\n# Clone and build\ngit clone https://github.com/your-org/opstatus /opt/opstatus\ncd /opt/opstatus\nnpm install \u0026\u0026 npm run build\n\n# Run with PM2\nnpm install -g pm2\npm2 start npm --name opstatus -- start\npm2 save \u0026\u0026 pm2 startup\n\n# Nginx reverse proxy\n# server { listen 80; location / { proxy_pass http://localhost:3000; } }\n```\n\n**Railway / Render:**  \nDeploy directly from GitHub. Set environment variables in the dashboard. Mount a persistent volume at `/app/data` for the SQLite file.\n\n**Vercel:**  \nNot recommended — serverless functions don't persist the SQLite file between invocations. Use a VPS or Railway instead.\n\n---\n\n## Admin Panel\n\nNavigate to `/admin` — you'll be redirected to `/login` if not authenticated.\n\n- **Overview** — system status at a glance, stats for services / incidents / maintenance / subscribers\n- **Services** — add/edit/delete services, one-click status changes, drag to reorder\n- **Incidents** — create incidents, post timestamped updates, track through to resolution\n- **Maintenance** — schedule and manage maintenance windows\n- **Subscribers** — view confirmed and pending email subscribers\n\n---\n\n## API\n\nAll endpoints return JSON. Admin endpoints require an active session cookie (set via `POST /api/auth`).\n\n| Method | Endpoint | Auth | Description |\n|---|---|---|---|\n| `GET` | `/api/services` | Public | List all services |\n| `POST` | `/api/services` | Admin | Create service |\n| `PATCH` | `/api/services/:id` | Admin | Update service |\n| `DELETE` | `/api/services/:id` | Admin | Delete service |\n| `GET` | `/api/incidents` | Public | List incidents |\n| `POST` | `/api/incidents` | Admin | Create incident |\n| `POST` | `/api/incidents/:id/updates` | Admin | Add incident update |\n| `DELETE` | `/api/incidents/:id` | Admin | Delete incident |\n| `GET` | `/api/maintenance` | Public | List maintenance |\n| `POST` | `/api/maintenance` | Admin | Schedule maintenance |\n| `PATCH` | `/api/maintenance/:id` | Admin | Update maintenance |\n| `DELETE` | `/api/maintenance/:id` | Admin | Delete maintenance |\n| `POST` | `/api/subscribers` | Public | Subscribe to updates |\n| `DELETE` | `/api/subscribers?token=` | Public | Unsubscribe |\n| `POST` | `/api/auth` | — | Log in (returns session cookie) |\n| `DELETE` | `/api/auth` | — | Log out |\n\n---\n\n## Tech Stack\n\n- **[Next.js 14](https://nextjs.org)** — App Router, server components, ISR\n- **[node:sqlite](https://nodejs.org/api/sqlite.html)** — built-in Node 22 SQLite (zero native compilation)\n- **[iron-session](https://github.com/vvo/iron-session)** — encrypted session cookies\n- **[Tailwind CSS](https://tailwindcss.com)** — utility-first styling\n- **[next-themes](https://github.com/pacocoursey/next-themes)** — dark/light/system theme toggle\n- **[bcryptjs](https://github.com/dcodeIO/bcrypt.js)** — password hashing\n\n---\n\n## License\n\nMIT — use it, fork it, ship it.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fashishjsharda%2Fopstatus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fashishjsharda%2Fopstatus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fashishjsharda%2Fopstatus/lists"}