A few months ago I got tired of Portainer.
Not because it's a bad tool — it's excellent at what it does. But for managing my homelab it felt like driving a truck to buy groceries. Too much complexity, too many dependencies, too much noise for what I actually needed.
So I built my own.
What started as a simple panel to see my containers turned into a full ecosystem of tools for managing Docker infrastructure. This is the story of what I built, every technical decision I made, and where it's going.
NEXUS — Docker Manager
NEXUS is a self-hosted Docker management panel. No external database, no cloud dependency. One docker compose up and you're running at http://localhost:9090.
Core features:
- Real-time metrics — CPU & RAM per container with live sparkline history
- Stack view — containers grouped by docker-compose project
-
Integrated terminal —
docker execdirectly from the browser, no SSH needed - Multi-host — manage multiple Docker servers from one panel
- Full management — images, networks, volumes, stacks with built-in YAML editor
- Crash alerts — Telegram notification when a container stops unexpectedly
- Roles — Admin and Viewer, control who can do what
- PWA — installable on desktop and mobile
But the most important technical decision wasn't any of those features. It was how to solve multi-host without compromising security.
The agent architecture
The classic multi-host Docker problem: to manage a remote server you need access to the Docker socket. And the Docker socket is basically root access to the system.
The common solution is to expose the socket over TCP. That's a massive security hole — you're putting root access on the network.
NEXUS solves it differently:
Browser → NEXUS (:9090)
↓
NEXUS Agent (remote host)
↓
Docker socket (never leaves the host)
The agent is a lightweight process running on each remote host. It wraps the socket in its own authenticated API and only exposes the endpoints NEXUS needs. The socket never leaves the host. Communication between NEXUS and the agent uses JWT with 24h expiry.
Result: multi-host management without compromising system security.
# Install NEXUS
curl -O https://raw.githubusercontent.com/Alvarito1983/NEXUS/main/docker-compose.yml
cp .env.example .env
docker compose up -d
# → http://localhost:9090
NEXUS Watcher — Image Update Monitor
Once the panel is running, another problem surfaces: how do I know when updates are available for my images?
The naive solution is tag comparison. If you have nginx:latest and a newer version exists, the tag will have changed. Problem: many images use stable tags that don't change (latest, stable, main) even when the image content has changed.
NEXUS Watcher solves this with manifest digest comparison.
Why digests instead of tags
Every Docker image has a digest — a SHA256 hash of the manifest that describes the image. When a publisher updates an image, the digest changes even if the tag stays the same.
Watcher's flow:
- Gets the local digest of each installed image
- Queries the registry (Docker Hub or GHCR) for the current remote digest
- Compares both — if they differ, there's an update available
For Docker Hub, this requires getting an OAuth token from auth.docker.io first, then querying registry-1.docker.io/v2/{repo}/manifests/{tag} and extracting the docker-content-digest header.
This method detects real updates, not just tag changes.
Real-time update feedback
One issue with earlier versions: you clicked "Update" and had no idea what was happening. Is it downloading? Did it finish? Did it fail?
Dockerode (the Docker wrapper for Node.js) emits progress events during a pull — layer by layer, with percentages. The current version of Watcher exposes those events via Socket.io to the frontend, showing a real-time progress bar with per-layer detail.
It also shows:
- Short digest of the new version (first 12 chars of SHA256)
- Affected containers — which containers will be recreated
- Update history
- Digest-based rollback — one click to go back if something breaks
# Install Watcher
curl -O https://raw.githubusercontent.com/Alvarito1983/nexus-watcher/main/docker-compose.yml
cp .env.example .env
docker compose up -d
# → http://localhost:9091
NEXUS Pulse — Uptime & Health Monitor
Once containers are managed and images are updated, one question remains: are they actually working?
NEXUS Pulse is a self-hosted uptime monitor. It monitors:
- Docker containers — Running/Stopped/Other state
- Web — HTTP/HTTPS with SSL certificate verification and expiry date
- TCP — port availability
- DNS — domain resolution
- Database — connection health check
- API — endpoint response validation
Each monitor has a 30-check history bar — the last 30 results represented as colored vertical bars (green = up, red = down, amber = pending). One glance and you know the recent history of any service.
Alerts go via Telegram with status, response time and timestamp.
# Install Pulse
curl -O https://raw.githubusercontent.com/Alvarito1983/nexus-pulse/main/docker-compose.yml
cp .env.example .env
docker compose up -d
# → http://localhost:9092
The technical stack
All tools share the same architecture:
| Layer | Tech |
|---|---|
| Backend | Node.js + Express + Socket.io + Dockerode |
| Frontend | React 18 + Vite + Lucide React |
| Auth | JWT + scrypt |
| Storage | JSON file (no database) |
| CI/CD | GitHub Actions → Docker Hub + GHCR |
| License | MIT |
Why JSON instead of a database
Deliberate decision. For the use case of these tools (homelab, small teams) a database is overkill and adds a dependency that complicates deployment. The JSON file persists across restarts and is fast enough for the data volume these tools handle.
The design system
The frontend uses a custom Dark Premium design system — inspired by tools like Linear and Vercel. Each tool has its own accent color (green for NEXUS, amber for Watcher, blue for Pulse) but they share the same visual foundation: Inter + JetBrains Mono typography, layered dark backgrounds (#0a0a0f → #111118 → #1a1a24), staggered entry animations.
The goal was that each tool feels like part of the same family while working completely standalone.
What's coming
Each tool works independently but they're designed to integrate:
NEXUS Security (in development)
CVE analysis on installed images, SSL certificate auditing, unnecessary exposed port detection. The goal is security visibility without depending on cloud services.
NEXUS Notify
Unified alert routing. Instead of configuring Telegram in each tool separately, Notify acts as a notification hub — receives events from all tools and distributes them according to configurable rules.
NEXUS Hub
The central panel. SSO for the entire ecosystem — one login, one view of all hosts and all tools. Hub also acts as a shared host directory: add a host once and all tools see it.
Try it
All three tools are MIT licensed, fully open source, and self-contained.
- 🔗 NEXUS: https://github.com/Alvarito1983/NEXUS
- 🔗 Watcher: https://github.com/Alvarito1983/nexus-watcher
- 🔗 Pulse: https://github.com/Alvarito1983/nexus-pulse
- 🌐 Web: https://alvarito1983.github.io/nexus-web/
Happy to answer questions about the architecture, the digest-based detection approach, or the agent security model in the comments.
Tags: docker, selfhosted, opensource, node, react, homelab, devops

Top comments (0)