The challenge
What we delivered
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.
The top row answers “is everything all right?” in a second. The rest of the panel answers “what exactly”.
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.
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.
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.
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.
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.
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
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.

