Files
Homelab-manager/INTEGRATIONS.md
T
bobbanandClaude Sonnet 5 1a2dd19736 Add an Uptime Kuma integration: monitor status and which server each one watches
New integration, following the existing pattern: config in-app (URL +
API key, credentials encrypted at rest), its own Uptime Kuma page, an
Integrations list entry, a Dashboard widget, and diagnostic-log/
integration-down-alert coverage for free via the shared withDiagLogging
wrapper. Read-only -- no start/stop equivalent exists for a monitor.

Uptime Kuma has no conventional REST API (the dashboard talks to it over
Socket.IO); researched before writing any code, since guessing wrong here
would have cost real time. The one machine-readable, authenticated
endpoint that lists every monitor is its Prometheus exporter at
GET /metrics, gated by HTTP Basic auth -- an API key as the password with
the username left blank on current installs, or the real dashboard
login on installs from before the API-key feature existed. This adapter
authenticates the same way and parses that endpoint's text-exposition
format itself (metrics: monitor_status, monitor_response_time,
monitor_cert_days_remaining, monitor_uptime_ratio; labels: monitor_id,
monitor_name, monitor_type, monitor_url, monitor_hostname, monitor_port),
verified against the documented metric/label set and the actual upstream
source (server/prometheus.js). A malformed line is skipped rather than
failing the whole scrape.

"What server is being monitored for what": each monitor's target (an IP
for TCP checks, or the hostname out of the URL for HTTP/keyword checks)
is matched against your servers' own IPs and hostnames -- reusing the
same kind of match already used in the consistency report -- and linked
to that server's page. Monitors with no single network target (groups,
push monitors, DNS/keyword checks with a complex URL) are left unmatched
rather than guessed at. Uptime Kuma's tags aren't read, since the
Prometheus endpoint doesn't reliably distinguish a tag label from any
other label it might add later.

The username field is the first genuinely optional integration config
field this app has had; IntegrationField gained an `optional` flag
(server validation and both the add/edit web forms honor it) rather than
special-casing Uptime Kuma.

Verified with 48 backend checks (Prometheus text parsing including
escaped quotes, decimals, negative numbers, and malformed lines; TCP vs.
HTTP target/port extraction; every documented status code; server
matching by IP, hostname, and short name, including no-match cases; the
route's real HTTP round trip against a fake Uptime Kuma server, wrong
credentials, upstream failures, roles, wrong/disabled/missing
integration, diagnostic-log entries; the optional-field validation rule)
and by driving the real page and the real Dashboard widget in a browser
against the real routers, including CSV export and column sorting. Real
dev database mtime untouched.

Not verified: a real Uptime Kuma instance. Everything here was checked
against Uptime Kuma's documented metric format, its actual upstream
source, and a fake server built to match both -- not against a live
installation. If your instance's /metrics output differs from what's
documented (older version, unusual monitor types), the parser should
degrade to an empty or partial monitor list rather than error, but that
degradation itself hasn't been observed against the real thing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 18:50:27 +02:00

121 lines
8.8 KiB
Markdown

# Integration & DNS provider access requirements
What credential to create in each target system, and the minimum
access it needs, when adding an integration or DNS provider in
Homelab Manager (Integrations → Add integration, or DNS → Add
provider). All credentials are entered in-app and encrypted at rest —
nothing is read from environment variables.
Every adapter listed here performs write actions (starting/stopping
things, editing DNS records, etc.), not just reads — a read-only
credential will fail as soon as you use one of those actions, even if
the dashboard views themselves load fine.
## Integrations
### Tailscale
- **Config fields:** Tailnet, API key
- **Auth:** Bearer token against `api.tailscale.com`
- **Actions used:** list devices, remove a device, authorize/deauthorize a device
- **Required access:** An API access token (or OAuth client) with **Devices Core: Read + Write** — create one under the admin console → Settings → Keys. Read-only isn't enough since remove/authorize are write calls.
### Proxmox VE
- **Config fields:** Proxmox URL, API token ID, API token secret, allow self-signed certificate
- **Auth:** `PVEAPIToken=<tokenId>=<tokenSecret>` header
- **Actions used:** list nodes/VMs/LXCs, read guest config and live status, read node host stats and storage usage, start/stop/reboot/shutdown a guest, read backup job schedules and recent `vzdump` task history
- **Required access:** A dedicated API token (Datacenter → Permissions → API Tokens) with a role granting **VM.Audit + VM.PowerMgmt** (e.g. `PVEVMAdmin`) on the VMs/LXCs to manage, **plus Sys.Audit and Datastore.Audit** on the node(s) for the host CPU/RAM/storage cards to populate. A token scoped to VM management only will still work for the guest list and power actions — it'll just show an error on the per-node hardware card instead of failing outright. Backup job schedules and run history need that same **Sys.Audit** — no separate permission to grant if the node-stats card already works.
- **Notes:** self-signed certificates are supported via the "Allow self-signed certificate" checkbox — common for an internal PVE host.
### Synology DSM
- **Config fields:** Synology DSM URL, Username, Password, allow self-signed certificate
- **Auth:** DSM session login (`SYNO.API.Auth`), session id reused until it expires
- **Actions used:** read-only — storage/volume/disk health, system info, network info. No writes.
- **Required access:** A DSM user account that can view **Storage Manager** and **System Information** (a regular admin-group account is simplest; a dedicated read-only user works too since nothing is ever changed). **2FA/OTP on the account is not supported** — use an account without it enabled, or DSM's application-specific password if your setup requires 2FA elsewhere.
- **Notes:** works over plain HTTP or HTTPS depending on the URL you enter; self-signed certs supported.
### Semaphore (Ansible Semaphore / Semaphore UI)
- **Config fields:** Semaphore URL, API token
- **Auth:** Bearer token
- **Actions used:** list projects, list templates, run a template (creates a task)
- **Required access:** A user API token with access to every project you want visible, and **permission to run templates** in those projects — a viewer/guest-level project role can list templates but will fail on "Run", so the account needs at least the operator-equivalent role Semaphore's own project permissions define.
### Gitea
- **Config fields:** Gitea URL, API token
- **Auth:** `Authorization: token <token>` header
- **Actions used:** list repos, list Actions workflow runs, re-run failed jobs in a run
- **Required access:** A personal access token with **`repo`** scope (read access to repos, including private ones you want tracked) and Actions read/write — generate it under the account → Settings → Applications → Generate New Token, with the `repository` and `write:repository`/Actions permission groups enabled (exact grouping depends on your Gitea version's token scope UI). Read-only Actions access isn't enough since re-running jobs is a write call.
### Dockhand
- **Config fields:** Dockhand URL, API token
- **Auth:** Bearer token against Dockhand's own API
- **Actions used:** list environments/containers, check for image updates, start/stop/restart a container
- **Required access:** A Dockhand API token belonging to a user with access to every environment (Docker host) you want visible, with permission to **start/stop/restart containers and trigger update checks** in each — not just view them.
### Uptime Kuma
- **Config fields:** Uptime Kuma URL, username (leave blank — see below), API key
- **Auth:** HTTP Basic, with the API key as the password and the username left empty. Uptime Kuma has no
conventional REST API — the dashboard talks to it over Socket.IO — so this integration reads its
Prometheus-metrics endpoint (`GET /metrics`) instead and parses that. On installs from before the API-key
feature existed (Uptime Kuma < 1.23), that endpoint instead checks your real dashboard login, so put your
Uptime Kuma username and password in those two fields rather than leaving the username blank.
- **Required access:** In Uptime Kuma, go to Settings → API Keys → **Add API Key**, and paste the value it
shows you (once — it isn't shown again) into this integration's "API key" field. No other permission is
needed; the metrics endpoint is read-only.
- **What you get:** every monitor's status (up/down/pending/maintenance), response time, uptime over 24
hours/30 days, and certificate days remaining where applicable. A monitor is linked to one of your servers
when its target — an IP, or a TCP/HTTP hostname — matches that server's own address or hostname; monitors
with no single network target (groups, push monitors, keyword checks with a complex URL) are shown
unmatched rather than guessed at. Uptime Kuma's tags aren't read, since the metrics endpoint doesn't
reliably distinguish a tag from any other label.
## DNS providers
### Cloudflare
- **Config fields:** API Token
- **Auth:** Bearer token against the Cloudflare v4 API
- **Actions used:** list zones, list/create/update/delete DNS records
- **Required access:** A scoped API token (My Profile → API Tokens → Create Token) with **Zone → Zone → Read** and **Zone → DNS → Edit**, restricted to the zone(s) you want managed. `DNS Read` alone isn't enough — record add/update/delete need `Edit`.
### Loopia
- **Config fields:** Username, Password
- **Auth:** Full account credentials sent on every XML-RPC call — Loopia's API has no scoped API-key concept
- **Actions used:** list domains/subdomains/zone records, add/remove zone records and subdomains
- **Required access:** The full Loopia account username and password. There's no way to scope this down at the API level — the credential has the same access as logging into the Loopia customer portal.
### Pi-hole
- **Config fields:** Pi-hole URL, Web password
- **Auth:** Session login against the Pi-hole v6 API (`/api/auth`) using the admin web password, session id cached until it expires
- **Actions used:** read/add/update/delete local DNS "hosts" (A/AAAA) and CNAME records
- **Required access:** The Pi-hole admin web interface password — Pi-hole v6 doesn't have per-feature roles, so this is effectively full admin access to that Pi-hole instance.
### Azure DNS
- **Config fields:** Tenant ID, Client (application) ID, Client secret, Subscription ID
- **Auth:** OAuth2 client-credentials (Azure AD app registration / service principal), then Bearer token against Azure Resource Manager
- **Actions used:** list DNS zones, list/read/create/update/delete record sets
- **Required access:** The service principal needs the **DNS Zone Contributor** role (or higher) on the subscription or resource group containing the DNS zone(s) — assign it under Azure Portal → the zone or resource group → Access control (IAM) → Add role assignment.
### cPanel
- **Config fields:** cPanel URL, Username, API Token, allow self-signed certificate
- **Auth:** `Authorization: cpanel <username>:<apiToken>` header (UAPI for reads, API 2 for record writes)
- **Actions used:** list zones/domains, read a zone's records, add/remove a zone record
- **Required access:** An API token generated under cPanel → Security → Manage API Tokens for the account that **owns** the domain(s) being managed. cPanel tokens inherit the full account's permissions — there's no separate DNS-only scope to grant.
### Technitium DNS Server
- **Config fields:** Technitium URL, API Token
- **Auth:** Bearer token
- **Actions used:** list zones, read zone records, add/delete records (an "update" is implemented as delete + add)
- **Required access:** A token tied to a Technitium user account with **Zones: View + Modify** permission — view-only will fail on record changes since updates are add/delete calls under the hood.