For a long time, my first response to a self-hosted application problem was always the same:
docker ps
If the container appeared in the list, I felt reassured. The application was running—or at least Docker said it was.
That distinction matters more than I expected.
A container can be running while its application cannot reach the database. It can restart every few minutes, serve errors from its API, consume nearly all available memory, or keep running while the disk slowly approaches 100%.
By the time a user tells me that a page is unavailable, the underlying problem may have existed for hours.
This is the problem behind the monitoring and alerts feature in Nitrobase.
Nitrobase has only recently launched and is still in Beta. Its goal here is not to replace a full observability stack. It is to answer a smaller question that matters to people running applications on their own VPS:
Is something happening on this server that needs my attention right now?
“Up” is only one piece of the state
Docker gives us useful lifecycle information, but the state of a container is not the same as the state of the service inside it.
I now think of application health as several layers:
- Is the VPS reachable?
- Is the container running?
- Is it staying running, or repeatedly restarting?
- Is the application responding to its health check?
- Does the server still have enough CPU, memory, and disk space?
Each layer can fail independently.
A server may be online while one service is stopped. A container may be running while its HTTP endpoint returns an error. An application may respond correctly while the server has so little free disk space that the next database write will fail.
Looking at only one signal creates a comforting but incomplete picture.
Restart loops are failures that look like activity
A restart policy is useful because it brings a process back after a transient failure. It can also hide a persistent problem.
Imagine a service that starts, fails to connect to its database, exits, and starts again. A quick docker ps check may catch it during one of its short running periods. From the outside, it looks alive. In reality, it has never remained stable long enough to serve the application reliably.
Nitrobase tracks container restarts and treats repeated restarts as a condition worth surfacing. During deployment, it also waits for services to remain ready for a stable period instead of treating the first successful start as proof that the release worked.
The problem this solves is not that restart counts are difficult to obtain. The problem is remembering to check them, understanding them in context, and noticing the pattern before it becomes an outage.
OOM kills need a better explanation than exit code 137
One of the least helpful experiences in container operations is finding that a process exited with code 137.
That number can be a clue, but it does not immediately answer whether the kernel killed the container because it exceeded its memory limit or whether the process stopped for another reason.
Nitrobase inspects the container state and cgroup memory events to identify out-of-memory kills. When one occurs, the alert can point to the affected service and its configured memory limit.
That context changes the next action.
Without it, I may restart the container and wait for the same failure. With it, I can decide whether the service needs a higher memory limit, whether a workload has grown unexpectedly, or whether the application has a memory leak that needs investigation.
Monitoring is most useful when it does not merely say “something failed,” but helps narrow down why.
Disk space fails slowly, then all at once
CPU spikes are visible and memory pressure often causes an immediate symptom. Disk usage is easier to ignore.
A database grows. Old images accumulate. Logs become larger. Backups are stored locally and never removed. The server continues to work, so there is no obvious moment that demands attention.
Then a write fails.
At that point, the application problem may appear far away from its cause. A database error, a failed deployment, and an incomplete backup can all begin with the same full filesystem.
Nitrobase monitors server disk and memory usage and can raise an alert when configured thresholds are crossed. The value is not a sophisticated graph. It is the chance to act while the server still has enough room to recover safely.
Alerts should travel to where I already look
A monitoring dashboard only helps when I remember to open it.
For a small number of self-hosted applications, I do not want to keep another page open all day. I want important state changes to reach a channel I already check.
Nitrobase can send notifications through:
- email;
- Slack;
- Discord;
- Telegram;
- a signed webhook for custom automation.
This keeps the monitoring loop simple:
- Nitrobase checks the server and its containers.
- A condition changes from normal to something that needs attention.
- An alert is recorded and sent to the selected channel.
- I open the panel or connect to the server with a reason to investigate.
The notification is not the diagnosis. It is the bridge between a problem happening and a person knowing that it happened.
I do not want an alert for every number
More notifications do not automatically mean better monitoring.
If every short CPU spike becomes a message, I will eventually ignore the channel. If an alert repeats continuously while the same problem remains active, the useful signal turns into noise.
The alerts I care about are state changes with operational meaning:
- the server became unreachable;
- a long-running service stopped;
- a container entered a restart loop;
- an OOM kill occurred;
- disk or memory pressure crossed a meaningful threshold;
- the application health check stopped passing.
This is the direction I want Nitrobase monitoring to follow: not every metric deserves an interruption, but every interruption should explain what changed and where to look.
What Nitrobase monitoring is not
I want to be clear about the boundary of this Beta feature.
Nitrobase is not trying to replace Prometheus, Grafana, Loki, OpenTelemetry, or an incident-management platform. Those tools support deeper queries, long-term analysis, distributed tracing, custom dashboards, and complex alert routing.
For a larger system, that level of observability is necessary.
Nitrobase focuses on the operational baseline for applications running on VPS infrastructure it already manages. It knows which server an application belongs to, which containers are expected to stay running, what health check the template defines, and which team should receive the notification.
That context allows it to provide useful defaults without requiring a separate monitoring project before the first application is deployed.
The problem this feature is trying to solve
The hardest part of small-scale self-hosting is often not fixing an issue. It is discovering the issue early enough that the fix remains simple.
I want to know about a restart loop before users experience intermittent failures. I want to see an OOM kill before repeatedly restarting the same container. I want a disk alert while there is still time to remove old data or expand the volume.
Most of all, I want “everything looks fine” to mean more than “the container name appeared in docker ps.”
Nitrobase monitoring tries to turn scattered server signals into a small set of actionable states, visible in one interface and delivered to the channels a team already uses.
It is still a Beta feature and needs more testing across different VPS providers, workloads, and container stacks. Thresholds that work for one application may be noisy for another, and health checks are only as useful as the behavior they actually verify.
But the principle is one I want to keep:
A useful self-hosting platform should not only help deploy an application. It should also tell you when that application quietly stops being healthy.
Nitrobase source code: https://github.com/AydenGroup/nitrobase
Top comments (0)