Run the server and dashboard
The DL Sentinel server is one Node.js process that serves an HTTP API and a web dashboard. It adds a scan queue, scheduled scans, scan history and trends, user roles and optional notifications. It keeps its data in plain files, with no database.
You do not need the server to scan. It is for teams that want scans and results in one place.
Start the server with Node.js
Build DL Sentinel from source as on the install page.
Choose a long random token and the folder that holds the projects you want to scan. From the
dl-sentinelfolder, start the server:bashSENTINEL_API_TOKEN=change-me \ SENTINEL_SCAN_ROOT=/srv/repos \ SENTINEL_DATA_DIR=/var/lib/dl-sentinel \ node apps/api/dist/main.jsReplace
change-mewith your own token.The server prints a line starting with
[dl-sentinel:api] listening on http://localhost:8752.
If you leave out SENTINEL_API_TOKEN, the server makes up a token for that run and prints it once at startup. It changes every time the server restarts.
SENTINEL_SCAN_ROOT limits what can be scanned: a scan request for a path outside that folder is refused.
Start the server with Docker
The repository includes a Dockerfile and a compose.yaml. No ready-made image is published; Docker builds it on your machine.
Open
compose.yamland, undervolumes:, add one read-only line per folder you want to scan, below/scans. For example:yaml- /home/you/projects:/scans/projects:roStart it with your token:
bashSENTINEL_API_TOKEN=change-me docker compose up -d
Inside the container, scan paths start with /scans, for example /scans/projects/my-app. Results are kept in the sentinel-data volume.
Open the dashboard
Open
http://localhost:8752/in a browser.Select the Settings button.
Paste your token into API Token and select Save. Test Connection checks that it works.
The token is stored only in that browser's local storage. API Base URL is needed only if the dashboard is served from a different address than the API.
The dashboard has these pages:
| Page | What it shows |
|---|---|
| Dashboard | Security Overview: recent scans, risk by scanner, the findings trend and top findings |
| Scans | Every scan and its status, and a form to start a new one |
| Schedules | Scans that repeat at a fixed interval |
| Findings | Findings across completed scans, filtered by severity and scanner |
| Trends | Severity counts over time |
| Rules | Every rule, with its CWE and OWASP mapping |
| Reports | A completed scan's report as JSON, Markdown or SARIF |
| Users | Users and their roles (admins only) |
| Notifications | Webhook and Slack channels (admins only) |
Run a scan from the dashboard
Open Scans.
In Path, type the absolute path of a folder inside the scan root.
Optional: in Scanners, list scanner ids separated by commas, such as
secrets,source.Select Run Scan.
The scan is queued and runs in the background. Its page updates by itself until it finishes. By default two scans run at a time; more wait in the queue.
Users and roles
The token you started the server with is the root admin and always works. Admins can add users, each with their own token and one role:
| Role | Can |
|---|---|
viewer | Read scans, findings, rules, reports, schedules, history and trends |
operator | Everything a viewer can, and start scans |
admin | Everything, including schedules, users and notifications |
A new user's token is shown once, when the user is created. The server stores only a hash of it. If it is lost, rotate it to get a new one.
Call the API
Every API request sends the token in a header:
curl -H "Authorization: Bearer $SENTINEL_TOKEN" http://localhost:8752/api/scansQueue a scan, then fetch its findings when it has finished:
curl -X POST -H "Authorization: Bearer $SENTINEL_TOKEN" \
-H "Content-Type: application/json" \
-d '{"path": "/srv/repos/my-app"}' \
http://localhost:8752/api/scansThe answer is 202 with the new scan's id and "status": "queued". Check progress with GET /api/scans/<id>. A scan moves from queued to running to completed or failed. GET /api/scans/<id>/findings returns 409 until the scan is completed.
Main endpoints:
| Method and path | What it does |
|---|---|
POST /api/scans | Queue a scan. Body: path, and optionally scanners |
GET /api/scans | List scans and their status |
GET /api/scans/:id | One scan, with its report when completed |
GET /api/scans/:id/findings | Findings of one scan. Filters: ?severity= and ?scanner= |
GET /api/findings | Findings across completed scans |
GET /api/reports/:id | A rendered report. ?format=json, markdown or sarif |
GET /api/rules | Every rule |
POST /api/schedules | Repeat a scan every intervalMs milliseconds (at least 60000) |
GET /api/history, GET /api/trends | Past results, oldest first |
GET /api/me | Your name and role |
GET /health | Health check, no token needed |
Users (/api/users) and notifications (/api/notifications) are admin-only. Errors come back as JSON with a code and a message. Requests are limited to 60 per minute per token by default. New to APIs? Start with What is an API.
Notifications
Admins can add a webhook or Slack channel that receives an event when a scan completes or fails, when a scan breaks the policy, or when a schedule fails. Notifications carry counts and ids only, never findings or code. The address must use https, except for localhost. With no channel configured, the server makes no outgoing requests.
Exposing the server
The server speaks plain HTTP. If anyone outside your own network can reach it, put a TLS reverse proxy (such as Caddy or nginx) in front of it and keep tokens secret.
DANGER
The server can read every file under SENTINEL_SCAN_ROOT. Set it to the folder of projects you mean to scan, not to / or your home folder, and mount folders read-only in Docker.