Skip to content

Latest commit

 

History

History
327 lines (259 loc) · 16.3 KB

File metadata and controls

327 lines (259 loc) · 16.3 KB

Sentinel TD

Self-hosted monitoring and maintenance for WordPress and Joomla sites — one dashboard that checks your sites, applies updates, watches renewals and tells you what happened. Your server, your data, your branding.

🇮🇹 Leggi in italiano


Features

Monitoring

  • Availability checks with confirmation before crying wolf: an outage is announced only when the site stays unreachable for the minutes you choose (5 by default), so a slow server does not wake you up

  • Core, plugin, theme and translation versions for every site, through the included connectors

  • Visual preview of each site, refreshed on a schedule, with thumbnails in the list (independent timer checked every minute; frequency from Settings, even for unchanged pages). Enabled sites with missing or overdue previews are queued at startup too. Failed or blocked attempts retry after the configured interval; the last good image retains its real date. Actual execution may be delayed by the queue

  • Folders (clients), tags, quick filters, search and CSV export

  • WordPress core check against the official wordpress.org checksums: modified, missing and extra files in wp-admin and wp-includes, with a notification when the result changes

Updates

  • Update one site, a selection or the whole fleet — by hand or with the hourly automatic cycle (AUTOUPDATE_ENABLED=true), which retries failed items after a pause (24 hours by default)
  • Update buttons are explicit requests: they run even when automatic updates are off for the site or an item is paused after a failure, and the panel follows the update and shows the outcome — "2 updated, 1 failed", "nothing to update", "the site does not answer: HTTP 401"
  • Bulk install and remove across many sites, guided step by step: pick the platform, the package or the extension, then the target sites by folder. Removal only reaches the sites that actually have that extension
  • Bulk install runs in the background: one job per site with live progress, it carries on if you close the browser (and the page picks it up again), and timeouts or server errors are retried a minute later; real errors (rejected token, broken zip) stop at once
  • Brake for weak servers: sites are grouped by server (the IP address of their domain), shown by client folder with the server's name. On the servers you brake you choose how many sites at a time, how long the server rests after a site and the pause between updates on the same site; the other servers work as always
  • Update history with, for every component, how many times it was updated and from which version to which
  • Homepage check: a snapshot before and after every update; the report says whether the site looks the same, changed noticeably (snapshots attached) or broke
  • Copy before the update, restore with one click (WordPress): before updating a plugin or theme the connector zips the current version into uploads/sentinel-backups/ (last two per item, 14 days). The site history shows Restore x.y on every update that has a copy. And if the homepage breaks after an update — an error or a 5xx that was not there before — Sentinel rolls back by itself, locks those components to the restored version and tells you
  • Licensed products (e.g. Elementor Pro) are updated from inside the WordPress admin; when a site cannot download them, Sentinel installs the zip you uploaded once in Packages
  • Take a licensed package from a site: search a plugin or theme by name across your WordPress sites and take the zip of the highest version installed, ready to install on the sites the vendor does not reach
  • Elementor and Elementor Pro move together: Elementor never jumps to a new major version while Pro is left behind
  • Lock a single plugin or theme to the version installed (site page → Extensions → Lock): it is never updated, automatically or by hand, nor counted as pending, while the rest of the site keeps updating
  • After any plugin, theme or core update the WordPress connector clears the site's caches by itself, each with its own official command and only if present: CSS generated by page builders (Elementor, Essential Addons, Beaver Builder, Divi, Avada), page caches (WP Rocket, W3 Total Cache, LiteSpeed, WP Super Cache, WP Fastest Cache, SiteGround, Breeze, Cache Enabler, Hummingbird, Nginx Helper, Autoptimize) and the cached options in the object cache — the cause of pages that hang or lose their styles after an update
  • YOOtheme Pro, on WordPress and Joomla: after any update the connector clears YOOtheme's configuration cache (builder, elements, dynamic sources) — the folder its Clear cache button empties — before YOOtheme reads it again. The image cache is left alone: regenerating every resized image is not needed after an update and would weigh on weak servers
  • Readable errors: no HTML entities, no download links with tokens, no progress lines — just the sentence that matters, with a hint when the likely cause is a full disk

Security and renewals

  • Vulnerability feed matched against the extensions actually installed, with severity and the version that fixes each issue
  • Abandoned plugins: every WordPress plugin of the fleet with the author's last update, the tested-up-to version and the closures taken from wordpress.org (refreshed weekly) — closed plugins and plugins idle for years, with the sites that still run them
  • Domain expiry through RDAP with WHOIS fallback, with reminders at your own thresholds
  • For every domain: where it is registered (registrar and nameservers) and a renewal decision — to decide, renew, do not renew — set one by one or in bulk, with folders and an early reminder so there is time to ask the client
  • Licence and subscription renewals (themes, plugins, hosting) with recurring periods and a Renewed button that moves the date forward by one period

Reports and notifications

  • Email and Telegram messages per event, with editable templates, live preview and a test send
  • One summary per automatic cycle on Telegram: one block per site with its folder, core and major components first, long lists folded, and on top what needs a look — failures with their reason, items waiting, homepages that changed. Long summaries are split between sites, never inside one. By email: one message per site (result and folder in the subject, handy for mail rules) or one summary per cycle
  • Monthly PDF report, global or one per folder, sent automatically on the day and at the time you choose (hours and minutes)
  • Site status in every report: for each site CMS and version, PHP with its support state, domain expiry and current warnings
  • Client reports: every client receives each month the report of their own sites only, at their own addresses — never yours, never Telegram — signed "Report by" your company. Sites and clients are many-to-many: usually one site per client, but a group (for example every site of an agency) gets one report for all its sites, with one address. Clients are created from the sites (one per site, or one group for a whole folder), merged, deleted in bulk; sites are added to or removed from a group, with autocomplete on groups, clients and folders. The client reports have their own settings — automatic sending, day and time, sections, texts and PDF layout — separate from your monthly report, with a live preview on any client
  • Detailed reports on demand (PDF or CSV) for one site, a selection or everything, over any range of months, with the full history of every update
  • Statistics with daily, monthly and month-against-month views, rankings of the most updated sites and components
  • The panel updates itself: dots, badges and the open site page follow the real state within a few seconds, without reloading. Every 6 seconds the browser asks for a one-line fingerprint of the fleet (an empty 304 when nothing changed) and downloads the list only when it did
  • Password sign-in with TOTP and passkeys
  • Branding: your logo and favicon in the panel, in the PDFs and in the emails
  • Interface in Italian, English, French and German, connectors included
  • Connector packages built by the panel itself, already carrying your address and key
  • Connector kept up to date by itself: every night the panel installs the connector it ships on the sites that run an older one (one site at a time on braked servers), and Settings → Connectors shows which sites are behind, with Update on the sites for right now

Requirements

  • A Linux server with Docker and the Docker Compose plugin
  • A reverse proxy with HTTPS in front of the panel (Nginx Proxy Manager, Traefik, Caddy, Nginx…)
  • Outbound internet access, to reach the monitored sites and the vulnerability feeds
  • RAM for Chromium and PDF rendering: 2 GB are comfortable for a few dozen sites
Port Protocol What
HOST_PORT (default 8810) TCP Web panel — behind your reverse proxy

Everything else (PostgreSQL, Redis, the screenshot service) stays on the internal Docker network and is never exposed.


Installation

git clone https://github.com/Giuseppe-TD/sentinel-td.git
cd sentinel-td

# 1. Configuration
cp .env.example .env
nano .env        # at least: POSTGRES_PASSWORD, JWT_SECRET, ADMIN_PASSWORD, TZ

# 2. Start
docker compose up -d --build
docker compose logs -f api worker

Generate the secrets with:

docker run --rm python:3.12-slim python -c "import secrets; print(secrets.token_hex(32))"

ADMIN_PASSWORD must be at least 12 characters: it only bootstraps the first administrator, after that the password lives in the database and is changed from the panel.

Then open the panel (http://localhost:8810 for a local check) and sign in as admin.

Behind a reverse proxy on another machine

The port is bound to loopback by default. If the proxy runs elsewhere on your network:

BIND_ADDRESS=0.0.0.0    # then restrict port 8810 to the proxy address with a firewall
TZ=Europe/Rome          # nightly updates, reports and month boundaries follow this zone
DEFAULT_UI_LANGUAGE=it  # language of emails and PDFs generated by the server

For passkeys, WEBAUTHN_RP_ID is the bare hostname and WEBAUTHN_ORIGIN the exact HTTPS origin:

WEBAUTHN_RP_ID=sentinel.example.com
WEBAUTHN_ORIGIN=https://sentinel.example.com

Connecting your sites

Each site talks to the panel through a small connector. You do not build it: the packages ship with the application.

  1. Settings → Connectors → set Public address of this panel (the Use this one button fills in the address you are browsing from)
  2. Press Download next to WordPress or Joomla. The WordPress package is generated with your address and registration key inside
  3. Install it on the site and activate it. On WordPress open Settings → Sentinel TD, pick the folder and press Connect: the site appears in the panel, already paired

A site can also be added by hand: install the package, copy the token the connector shows and paste it when adding the site in the panel. The sources live in connectors/ and are neutral — no address, no key — so anyone can build their own; see connectors/README.md.

WordPress package export (Take from a site) needs connector 2.19 or later. Additional site diagnostics have been removed in 2.28.15.


What goes where

What Where
Logo, favicon, panel name Settings → Branding
Rename a folder pencil next to the folder in the sidebar
Zip of a licensed plugin to install everywhere Settings → Packages
Take the zip of a licensed plugin or theme from one of your sites Settings → Packages → Take from a site
After how many minutes a silent site is reported Settings → Report a site as unreachable after
Expiry thresholds, scan frequency, preview refresh, history retention Settings
Panel address and registration key for the connectors Settings → Connectors
One email per site or one summary per automatic cycle Settings → Update report emails
Writable space, PHP, permissions, core files, size history of a site site page → Diagnostics, Site size
Text, HTML and channels of every notification Notifications
Monthly report: day and time, recipient, content, layout Monthly report
Clients, their sites and addresses, automatic report to the client Client reports
Client reports: day, hour, sections, texts, PDF layout (one set for all clients) Client reports → Settings
Text of the email sent to clients with their report Notifications → Monthly report to the client
Brake on weak servers (sites at a time, rests, pause between updates) Settings → Site servers
Database credentials, SMTP, Telegram, secrets, ports .env

Server resource monitoring and its nightly summary have been removed in 2.28.14.

Updates

git pull --ff-only
docker compose up -d --build
docker compose ps

Database migrations run by themselves at startup. If you replace files by hand instead of using Git, rebuild both services that share the same build context:

docker compose up -d --build api worker

Backups

Back up together:

  • the PostgreSQL data (pg_data)
  • the branding, connectors and screenshots volumes
  • your private .env
docker compose exec -T postgres pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" > sentinel-$(date +%F).sql

A plain docker compose down keeps the volumes. docker compose down -v deletes them, and with them your history and settings.


Troubleshooting

  • A site shows as offline but it works (HTTP 401 rest_forbidden) — the site answers but the connector rejects the token, usually because the connector was removed and reinstalled. On the site, Settings → Sentinel TD → Connect this site to Sentinel TD realigns the token by itself; otherwise copy it into Edit. Hosts that drop the Authorization header are covered since connector 2.18.2, which also accepts the token in X-Sentinel-Token.
  • Updates fail on several sites at once — it is almost always DNS or the filesystem, not the panel. docker compose logs worker | grep "UPDATE FALLITO" shows the real reason returned by each site.
  • An update fails with PCLZIP_ERR_BAD_FORMAT or "not enough space" — the hosting quota is probably full, even if the server disk is not. Check the account quota in the hosting control panel. Synthetic write probes have been removed.
  • Updates time out on a cheap shared hosting — put the brake on that server in Settings → Site servers: fewer sites at a time, a rest after each site and a longer pause between updates on the same site.
  • No preview, or a blank rectangle where a video is — the screenshot service needs Google Chrome for H.264 background videos: docker compose logs shooter | grep pronto should mention Chrome. Rebuild with docker compose build shooter if it fell back to Chromium.
  • Emails or PDFs come out in the wrong language — they follow DEFAULT_UI_LANGUAGE, not the language chosen in the browser.
  • Scheduled things happen at the wrong hour — set TZ in .env; without it the containers run in UTC.

Documentation

  • CHANGELOG.md — release notes
  • SECURITY.md — how to report a vulnerability
  • THIRD-PARTY.md — third-party components and their licences
  • connectors/README.md — the WordPress and Joomla connectors
  • docs/LANGUAGES.md — translation maintenance
  • docs/PUBLISHING.md — publishing this project on GitHub

Licence

Sentinel TD is free software released under the GNU Affero General Public License v3.0 or later — see LICENSE.

In short: you can use, modify and redistribute it, including commercially. If you run a modified version as a network service for other people, you must offer its source code to those users.

Third-party components and their licences are listed in THIRD-PARTY.md.

Copyright © Giuseppe Sciarra — Tastiere Digitali


Support the project

If Sentinel TD is useful to you, you can support its development with a donation:

paypal.me/raxiel87

Bug reports and pull requests are welcome.