Home » Portfolio » Status panel — server and site monitoring that became a product
CRM Monitoring / In-house product

Status panel — server and site monitoring that became a product

Seganiko
Client Seganiko
Industry Monitoring / In-house product
Type CRM
Technologies used PHP, SQLite, hand-drawn SVG charts, Ed25519 licences, update channel, VPS and shared-hosting profiles
Context

The challenge

Run monitoring where it has no right to exist: on shared hosting, with no root, no system counters and no SSH to push an update onto the client’s server.
Our approach

What we delivered

A root collector separated from the interface, SQLite between them, charts drawn by hand in SVG. Domains polled straight at the IP so a DNS failure is told apart from a site failure, and logs read incrementally through a noise filter. On the product side: signed licences verified offline, a two-week buffer, and updates pulled by the installation itself.
Project details

Monitoring that had to learn to live without root

We built the panel to see our own server: load, disk, network, site availability, errors in the logs and the bills from cloud services. Then clients asked for it — and the panel became a product.

The hard part was not the charts. The hard part is that half the clients sit on shared hosting, where there is no root, no access to system counters and no SSH to push an update through.

Status panel: tiles for processor, memory, disk and site availability

The top row answers “is everything all right?” in a second. The rest of the panel answers “what exactly”.

What it is

  • Product: built in-house at Seganiko
  • Purpose: monitoring for a server and its sites
  • Installations: eight, five of them on client domains
  • Environments: VPS and shared hosting

Objectives

  • Show the state of server and sites so it reads without a manual.
  • Work where system metrics are simply not available.
  • Update client installations without access to their servers.
  • Tell a real outage apart from noise in the logs.

What is inside

  • A collector that runs as root on a schedule.
  • A panel with no external libraries: charts are drawn in SVG.
  • Signed licences and an update channel.
  • Cost modules: storage, API, traffic.

Two halves of one panel

The collector and the web panel are deliberately separated. The collector runs once a minute as root — otherwise it sees neither the system counters, nor the web server logs, nor the domain configs. The panel runs as an ordinary user and has access to nothing but a single database.

Between them sits SQLite. Metrics live for thirty-five days, errors for seven. It is not an archive; it is a window showing what has changed over the past month.

Why no charting library: the panel has to open quickly and over a weak connection, and every third-party library is another few hundred kilobytes plus one more dependency that will one day update badly. Every chart is drawn by hand in SVG.

Load you can see whole

Processor, memory, swap, disk, I/O, IOPS, network, process count and PHP workers — all on one screen, with a period from thirty minutes to thirty days. Where there is a hard ceiling, the dashed line shows it: not “a lot or a little”, but how much headroom is left.

Grid of charts: disk, load average, PHP workers, swap, IOPS, network

Sites are polled around DNS

Every domain is checked once a minute — but the request goes straight to the server’s IP rather than through public DNS. A small detail with large consequences: if a site answers by IP and not by name, the problem is not the site but the DNS record. The panel tells those apart and says so plainly.

Things that do not change by the minute are checked separately and less often: DNS every quarter of an hour, certificates every six hours. The table shows the response code, response time, availability over the last day, certificate expiry and the error count.

Site table: response code, response time, 24-hour availability, DNS, SSL and errors

Errors without the noise

The web server log is read incrementally: the panel remembers where it stopped and does not re-read the file after rotation. But the real work is in the filter.

Domains that are closed on purpose write “access denied” into the log every minute — that is the protection working, not an outage. Entries from our own monitoring are not errors either. Warnings and notices do not count as failures. Without that cleaning, the error list turns into a feed people stop looking at.

Money next to the metrics

A server goes down not only from load — sometimes from the invoice. So the panel carries monthly traffic as a share of the quota, storage spend with a forecast to month end, and API spend broken down by model. The forecast is calculated from the actual rate, not from the monthly average.

Cost blocks: Cloudflare R2 and OpenAI API with a forecast to month end

A public page separate from the panel

What the owner sees and what can be shown to customers are different things. The panel sits behind a password, and beside it there is a public status page: ninety days of availability bars, average response time, and one line at the top — working or not.

Public status page with ninety days of availability history

Updates without access to someone else’s server

We have no SSH to client servers, and should not have. So the connection runs the other way: once a day the installation calls our panel, confirms its licence and pulls an update if there is one.

The licence is signed and verified offline on every request, not by asking us — if our server is down, client panels keep working. For a long outage there is a two-week buffer: our failure must not switch off someone else’s installation.

Small updates install themselves, large ones on a button. From our panel a version can be rolled out by force, but only to installations whose code already contains a receiver for that order. That is an honest limit of the architecture, and it is visible in the interface.

How it was done

1
Phase 1
Collector
System metrics, domain polling around DNS, certificate checks, incremental log reading with a noise filter.
2
Phase 2
Panel
SVG charts with no libraries, ceilings drawn on the charts, period selection, the site table, and a public status page separate from the private one.
3
Phase 3
Product
Signed licences with offline verification, an update channel, a mother panel holding releases and installations, two environment profiles.
4
Phase 4
Shared hosting
A profile where system metrics are simply absent while availability, DNS, certificates and errors remain. Detected by probing at install time.

Under the hood

Collector

Scheduled PHP running as root, reading system counters, polling domains straight at the IP, incremental log reading with a saved position. Storage is SQLite: metrics for 35 days, errors for 7.

Panel

No external libraries: charts are drawn in SVG on the server. Administrator and viewer roles, with the public status page as a separate layer.

Product

Ed25519-signed licences, offline verification on every request, a daily check-in, a two-week buffer. The installation pulls the update itself — no SSH to the client is needed.

How it turned out

The panel we wrote for ourselves now runs on eight installations, five of them on client domains. It behaves the same on a VPS with full access and on shared hosting where half the metrics are out of reach: in the second case it simply does not show what it cannot know, rather than drawing zeros.

And the main architectural decision proved right: in all that time not one update has required logging into someone else’s server.


Have a similar project?

Let's discuss your goals and see how we can help.

Request a free quote →
Any questions?

Let's discuss
your project.

Free first consultation, no strings attached.