blackscope
v1.0.5
Published
BlackScope — self-hosted server dashboard (Docker, PM2, nginx, system monitoring).
Readme
BlackScope
Self-hosted server command center. Real-time monitoring and management for Ubuntu/Debian servers: CPU/RAM/disk/network, PM2, Docker, systemd services, storage, firewall, SSL certs, CrowdSec, APT updates, journal logs, and WebAuthn/passkey login.
Install
1. Install the CLI
npm install -g blackscopeOr clone and install locally:
git clone https://github.com/YOUR_USERNAME/blackscope.git
cd blackscope
npm install2. Create the environment file
cp .env.example .env.localEdit .env.local:
| Variable | What to set |
|---|---|
| ADMIN_USERNAME | Dashboard login username |
| ADMIN_PASSWORD_HASH | Base64-encoded bcrypt hash of your password |
| SESSION_SECRET | Random 64-byte hex string |
| WEBAUTHN_RP_ID | Domain you serve the dashboard from (e.g. dash.yourdomain.com) |
| DISCORD_WEBHOOK_URL | Optional Discord webhook for alerts |
Generate values:
# bcrypt hash, base64-encoded
node -e "console.log(Buffer.from(require('bcryptjs').hashSync('YOUR_PASSWORD',10)).toString('base64'))"
# session secret
openssl rand -hex 643. Sudoers rules (server-side features)
Create /etc/sudoers.d/blackscope:
${USER} ALL=(ALL) NOPASSWD: /usr/sbin/reboot
${USER} ALL=(ALL) NOPASSWD: /usr/sbin/shutdown
${USER} ALL=(ALL) NOPASSWD: /usr/bin/apt-get install --only-upgrade -y *
${USER} ALL=(ALL) NOPASSWD: /usr/bin/cscli decisions *
${USER} ALL=(ALL) NOPASSWD: /usr/bin/certbot certificates
${USER} ALL=(ALL) NOPASSWD: /usr/bin/certbot renew
${USER} ALL=(ALL) NOPASSWD: /usr/bin/certbot certonly
${USER} ALL=(ALL) NOPASSWD: /usr/bin/certbot delete
${USER} ALL=(ALL) NOPASSWD: /usr/sbin/ufw status verbose
${USER} ALL=(ALL) NOPASSWD: /usr/bin/systemctl start *
${USER} ALL=(ALL) NOPASSWD: /usr/bin/systemctl stop *
${USER} ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart *Lock it:
sudo chmod 0440 /etc/sudoers.d/blackscopeFor the System Journal page, add your user to the systemd-journal group:
sudo usermod -aG systemd-journal ${USER}4. Run
Development:
blackscope init
blackscope dev --port 3003Production with PM2:
blackscope build
blackscope start --port 3003
blackscope stopOr without the CLI:
npm run build
npm run startThe dashboard listens on 127.0.0.1:3003 by default. Put it behind nginx with HTTPS in production.
Pages
| Page | Purpose | |---|---| | Dashboard | Overview, KPI cards, live charts, machine info, process counts | | PM2 Processes | Live table, start/stop/restart/delete, streaming logs | | Docker | Container list with start/stop/restart | | Process Explorer | All system processes sorted by CPU/memory, signal/kill | | System Services | systemd units, filter by state, start/stop/restart | | Service Uptime | HTTP reachability checks, latency, availability | | Storage | Per-filesystem usage, inodes, block devices, disk I/O | | Network & Firewall | UFW rules, listening sockets, exposed-port warnings | | System Journal | journalctl viewer with severity filters | | System Updates | APT upgradable packages with bulk install | | Security Radar | CrowdSec bans, fail2ban status, SSH audit | | SSL Certificates | Let's Encrypt expiry tracking and renew/delete | | Passkeys | WebAuthn passkey registration/management |
Security notes
- Bind to
127.0.0.1and run behind a reverse proxy with HTTPS. - Set a strong
SESSION_SECRETand keepADMIN_PASSWORD_HASHout of git. TRUST_PROXY=1only when behind a trusted reverse proxy.- WebAuthn RP ID cannot change after passkeys are registered without re-enrolling them.
- Commands use argument arrays, not string concatenation, to prevent shell injection.
- Firewall rules are read-only in the UI.
Development
npm run dev
npx tsc --noEmit
npm run build