Skip to content

Repository files navigation

Homelab Automation Dashboard

Homelab Automation Dashboard

Overview

Homelab Automation Dashboard is an Express-based backend with a React + Vite single-page application for day-to-day homelab operations. It centralizes service automation, infrastructure lookups, and inventory reconciliation workflows behind one API and one UI.

Recent project changes are now part of the shipped application:

  • The legacy static frontend has been replaced with a React 19 + Vite SPA under client/.
  • The production server serves the built SPA from dist/ when a client build is present.
  • The inventory area has expanded from basic network CRUD into a configuration-aware import workflow with preview, apply, relationship tracing, and operator notes.

Current Capabilities

  • GitLab pipeline status monitoring, recurring refresh, automerge, on-demand assigned merge request refresh, and MR diff review
  • GitHub pull request lookup and file diff inspection
  • Azure DNS zone lookup plus lazy-loaded Azure inventory for resource groups, web apps, function apps, storage accounts, Service Bus namespaces, and Application Insights
  • Microsoft 365 tenant inventory for users, subscribed licenses, standard distribution groups, and Graph-discovered shared mailboxes
  • Namecheap domain inventory with registrar metadata
  • Wave customer listing and paginated invoice lookup
  • RabbitMQ queue snapshot collection and grouped message-shape inspection
  • Inventory import, preview, apply, relationship exploration, and note-taking for imported entities
  • Scheduled security and analytics reporting with durable configuration, encrypted write-only secrets, child-process execution, and run-history visibility

Architecture

  • src/ contains the Express API, organized into routes, controllers, services, middleware, and utils.
  • client/ contains the React + Vite frontend, organized by app shell, shared components, and feature modules.
  • dist/ contains the production SPA build generated by Vite at the repository root.
  • data/inventory.json stores the normalized inventory state. Inventory writes create a data/inventory.json.bak backup before replacement.
  • data/scheduled-jobs.json, data/scheduled-job-runs.json, and data/scheduled-job-secrets.enc.json store scheduled-job configuration, recent run metadata, and encrypted secrets.
  • Helmet-based security middleware remains enabled on the backend.

Requirements

  • Node.js 22+
  • npm 10+
  • Docker is optional for containerized runs

Installation

  1. Clone the repository.

    git clone https://github.com/Robotti-io/Homelab-Automation-Dashboard.git
    cd homelab-automation-dashboard
  2. Install dependencies for the root project and the frontend workspace.

    npm install
  3. Copy .env.example to .env and add the credentials required for the integrations you plan to use.

Local Development

Run the backend and frontend in separate terminals.

Backend:

npm run dev:server

Frontend:

npm run dev:client

Development URLs:

  • React SPA: http://localhost:5173
  • Express API: http://localhost:3000
  • Health check: http://localhost:3000/health

During frontend development, Vite proxies /api and /health requests to the Express server.

Production Build And Run

Build the SPA:

npm run build

Start the backend:

node src/server.js

When dist/index.html exists, Express serves the built SPA and falls back to index.html for non-API routes. If dist/ is absent, the server runs as an API-only backend.

Docker

The Docker image uses a multi-stage build:

  • Stage 1 installs client dependencies and builds the Vite app into dist/
  • Stage 2 installs production backend dependencies and serves the built SPA from Express

Build and run:

docker build -t homelab-dashboard .
docker run --env-file .env -p 3000:3000 homelab-dashboard

Scripts

Root scripts:

  • npm start starts the backend with nodemon
  • npm run dev:server starts the backend with nodemon
  • npm run dev:client starts the Vite dev server from client/
  • npm run build builds the frontend into dist/
  • npm run lint runs ESLint and Markdown linting
  • npm run test runs backend tests, frontend tests, and merges coverage into the root coverage/ folder

Frontend workspace scripts:

  • npm run dev --workspace client
  • npm run build --workspace client
  • npm run preview --workspace client
  • npm run test --workspace client

Environment Variables

Server:

  • PORT optional HTTP port for Express, default 3000
  • JSON_BODY_LIMIT optional JSON request limit, default 5mb

Scheduled Jobs:

  • SCHEDULED_JOBS_SECRET_PASSPHRASE required to save or decrypt scheduled-job secrets
  • SCHEDULED_JOBS_RUN_HISTORY_LIMIT optional retained run count per job, default 25
  • SCHEDULED_JOBS_DEFAULT_TIMEOUT_MS optional default per-job timeout, default 600000

GitLab:

  • GITLAB_API_URL or GITLAB_API GitLab API base URL
  • GITLAB_ACCESS_TOKEN personal access token used for GitLab API calls
  • GITLAB_ASSIGNEE_ID optional default assignee ID used by automerge-created merge requests

Azure:

  • AZURE_SUBSCRIPTION_ID Azure subscription ID
  • Azure authentication must also be available to DefaultAzureCredential
  • A typical local service-principal setup uses AZURE_TENANT_ID, AZURE_CLIENT_ID, and AZURE_CLIENT_SECRET

Microsoft 365:

  • M365_TENANT_ID optional explicit Entra tenant ID for Microsoft Graph, falls back to AZURE_TENANT_ID
  • M365_CLIENT_ID optional explicit app registration client ID for Microsoft Graph, falls back to AZURE_CLIENT_ID
  • M365_CLIENT_SECRET optional explicit client secret for Microsoft Graph, falls back to AZURE_CLIENT_SECRET
  • The configured app registration must have Microsoft Graph application permissions with admin consent for at least User.Read.All, GroupMember.Read.All, LicenseAssignment.Read.All, and MailboxSettings.Read.

Microsoft 365 Setup

The M365 integration uses an Entra app registration with application permissions, similar in operating model to the Azure resource integration.

Recommended setup:

  1. Create or reuse an Entra app registration for the dashboard.
  2. Create a client secret for that app registration.
  3. Grant Microsoft Graph application permissions: User.Read.All, GroupMember.Read.All, LicenseAssignment.Read.All, and MailboxSettings.Read.
  4. Grant admin consent for the tenant.
  5. Set either the dedicated M365_* environment variables or reuse the existing AZURE_* service principal variables if the same app registration is used for both Azure and M365 access.

Current M365 scope and limitations:

  • Included in this implementation: users, subscribed licenses / SKUs, standard mail-enabled distribution groups, and shared mailboxes discovered through Microsoft Graph mailbox settings.
  • License rows are enriched with human-readable product names using an embedded Microsoft SKU catalog that ships with the application.
  • Excluded in this implementation: dynamic distribution groups.
  • Shared mailbox discovery may omit mailbox types that are not reliably exposed through the Graph mailboxSettings/userPurpose path.

Namecheap:

  • NAMECHEAP_API_USER
  • NAMECHEAP_API_KEY
  • NAMECHEAP_USERNAME
  • NAMECHEAP_CLIENT_IP

Wave:

  • WAVE_API_KEY
  • WAVE_BUSINESS_ID

RabbitMQ:

  • RABBITMQ_HOST
  • RABBITMQ_PORT optional, default 5672
  • RABBITMQ_USERNAME
  • RABBITMQ_PASSWORD
  • RABBITMQ_VHOST optional, default /

GitHub:

  • No GitHub token is currently required by the implemented backend routes. The GitHub feature uses public GitHub API requests.

Scheduled Reporting Workflow

The scheduled-jobs feature adds two built-in operator-managed jobs:

  • security-report for request and bot-scan reporting against the logger schema
  • analytics-report for analytics and refresh-pipeline reporting against the analytics schema

Operator workflow:

  1. Open the Scheduled Jobs page in the SPA navigation.
  2. Configure each job's schedule, email delivery settings, database connection details, and report parameters.
  3. Save the required database and SMTP passwords through the write-only secret form.
  4. Confirm the job shows Ready before enabling or manually running it.
  5. Use Run now for an on-demand execution and monitor recent status in the run history table.

Important behavior:

  • Secrets are encrypted at rest with AES-256-GCM and are never returned in plaintext by the API.
  • Enabled jobs refresh their in-memory node-cron registration immediately after configuration or secret changes.
  • Jobs run in child processes and do not overlap for the same job ID.
  • Changing the scheduled-jobs passphrase requires operators to re-enter stored secrets.

Inventory Import Workflow

The inventory feature now supports configuration-derived datasets instead of only manual network records.

Implemented workflow:

  1. Select a source type in the React inventory page.
  2. Choose a local export file in the browser.
  3. The browser reads the file and submits JSON to the backend.
  4. Preview the normalized changes before applying, or apply directly.
  5. Inspect the resulting entities, warnings, conflicts, and relationships.
  6. Add operator notes without overriding imported authoritative values.

Supported import sources:

  • opnsense for OPNsense firewall exports, accepted extensions .xml, limit 2 MB
  • windows-dns for Windows DNS zone exports, accepted extensions .dns and .txt, limit 1 MB
  • nginx for NGINX config exports, accepted extensions .conf and .txt, limit 1 MB

Inventory data includes:

  • Networks
  • Hosts
  • DNS records
  • Firewall rules
  • Websites
  • Relationships between imported entities
  • Source snapshot metadata
  • User-authored notes

Legacy /api/inventory/networks CRUD endpoints still exist for compatibility with earlier data, but the current frontend centers inventory around authoritative imports, preview/apply flows, and read-only derived entities.

Testing

Backend tests use Jest. Frontend tests use Vitest with Testing Library. Coverage is generated separately and merged by scripts/mergeCoverage.js into the root coverage/ directory.

Generated coverage artifacts include:

  • coverage/coverage-summary.json merged backend + frontend summary
  • coverage/lcov.info merged backend + frontend LCOV report
  • coverage/cobertura-coverage.xml merged backend + frontend Cobertura report for CI artifacts such as GitLab coverage ingestion
  • coverage/backend/cobertura-coverage.xml backend-only Cobertura output
  • client/coverage/cobertura-coverage.xml frontend-only Cobertura output

Useful commands:

npm run test
npm run test:backend
npm run test:frontend

API Endpoints

Core endpoints currently exposed by the server:

GitLab:

  • GET /api/gitlab/users
  • GET /api/gitlab/pipeline-status
  • POST /api/gitlab/automerge
  • GET /api/gitlab/assigned-mrs
  • GET /api/gitlab/mr-diff

GitHub:

  • GET /api/github/prs
  • GET /api/github/pr-diff

Azure:

  • GET /api/azure/dns-zones
  • GET /api/azure/dns-zones/records
  • GET /api/azure/inventory/resource-groups
  • GET /api/azure/inventory/web-apps
  • GET /api/azure/inventory/function-apps
  • GET /api/azure/inventory/storage-accounts
  • GET /api/azure/inventory/service-bus-namespaces
  • GET /api/azure/inventory/application-insights

Microsoft 365:

  • GET /api/m365/users
  • GET /api/m365/licenses
  • GET /api/m365/distribution-groups
  • GET /api/m365/shared-mailboxes

Namecheap:

  • GET /api/namecheap/domains

Wave:

  • GET /api/wave/customers
  • GET /api/wave/customers/:customerId/invoices

RabbitMQ:

  • GET /api/rabbitmq/snapshot

Inventory:

  • GET /api/inventory/networks
  • GET /api/inventory/networks/:id
  • POST /api/inventory/networks
  • PUT /api/inventory/networks/:id
  • DELETE /api/inventory/networks/:id
  • GET /api/inventory/summary
  • GET /api/inventory/relationships
  • GET /api/inventory/import-sources
  • POST /api/inventory/imports/preview
  • POST /api/inventory/imports/apply
  • DELETE /api/inventory/imports/:sourceType
  • PUT /api/inventory/notes

Health:

  • GET /health

Project Structure

homelab-automation-dashboard/
|-- client/                 # React + Vite SPA
|   |-- public/images/      # Frontend image assets
|   `-- src/
|       |-- app/            # App shell, routing, layout
|       |-- components/     # Shared UI primitives
|       |-- features/       # Feature modules by service area
|       `-- lib/            # Shared API and formatting helpers
|-- data/                   # Inventory data and sample import files
|-- dist/                   # Production frontend build output
|-- scripts/                # Repo automation helpers
|-- src/
|   |-- controllers/        # HTTP handlers
|   |-- middleware/         # Security and validation middleware
|   |-- routes/             # Express route definitions
|   |-- services/           # Business logic and integrations
|   `-- utils/              # Pure helper logic and parsers
|-- tests/                  # Backend test suite
`-- README.md

Extending The Application

To add a new service area:

  1. Add a feature module under client/src/features/.
  2. Register its route in client/src/app/App.jsx.
  3. Add navigation in client/src/app/layout/AppLayout.jsx when needed.
  4. Reuse the shared client API helpers in client/src/lib/api.js.
  5. Add or extend backend routes, controllers, and services under src/ only when the UI needs backend support.

License

ISC (c) Robotti Tech Services

Do not commit secrets or production exports that should remain private. Use a proper secret-management workflow for real deployments.

About

Homelab Automation Dashboard is an Express-based backend with a React + Vite single-page application for day-to-day homelab operations. It centralizes service automation, infrastructure lookups, and inventory reconciliation workflows behind one API and one UI.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages