DEV Community

Cover image for I built a self-hosted Docker management ecosystem — NEXUS, Watcher and Pulse (open source, MIT)
Alvarito1983
Alvarito1983

Posted on

I built a self-hosted Docker management ecosystem — NEXUS, Watcher and Pulse (open source, MIT)

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 terminaldocker exec directly 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)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

  1. Gets the local digest of each installed image
  2. Queries the registry (Docker Hub or GHCR) for the current remote digest
  3. 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.

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)