# 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==` 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 ` 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. - **Maintenance import:** the Maintenance page can read which monitors are currently in maintenance in Uptime Kuma and start (or extend) a maintenance window here for the matching server, for a duration you pick — the metrics endpoint only exposes current status, not a monitor's scheduled start/end time, so this reflects what's in maintenance right now rather than mirroring Uptime Kuma's own schedule. ### Proxmox Backup Server - **Config fields:** Proxmox Backup Server URL, API token ID, API token secret, allow self-signed certificate - **Auth:** `PBSAPIToken=:` header — note the **colon** between the token id and secret; Proxmox VE's own token header uses `=` there instead, so a PVE token/secret pair copied verbatim into this integration's fields will still format correctly (the adapter supplies the colon itself) as long as the id/secret values themselves are right. - **Actions used:** read-only — list datastores and their usage, read every stored snapshot's verification status, read the PBS host's own CPU/RAM/disk. No writes; nothing here can prune, delete, or re-verify a backup. - **Required access:** A dedicated API token (Configuration → Access Control → API Token) belonging to a user with **Datastore.Audit** on the datastore(s) to show, and **Sys.Audit** for the node status card to populate. A token scoped to just `Datastore.Audit` on one datastore will still work — other datastores it can't read are shown with an error rather than failing the whole page. - **What you get, and why it's separate from the Proxmox VE integration:** Proxmox VE (the "Proxmox" integration above) already shows whether the last `vzdump` push to PBS succeeded, but has no visibility at all into PBS's own backup **verification** — whether the data PBS actually stored still passes an integrity check, run separately by PBS's verify jobs. This integration reads that directly from PBS (`verification.state` on each stored snapshot), and a daily check (mirroring the Proxmox backup-failure check) sends a notification when a snapshot has failed verification or a datastore couldn't be read at all — the "Notify on" section in Settings → Notifications has a dedicated toggle for it, sharing the same daily reminder time as the other daily checks. - **Not verified against a live instance** — built from PBS's own published API documentation (endpoints, the `PBSAPIToken` header format, and the datastore/snapshot field names all cross-checked there), but nobody has run it against a real Proxmox Backup Server yet. If a datastore comes back empty or with the wrong fields, tell us what your instance actually returned and we'll adjust. ### osTicket - **Config fields:** Database host, Database port (optional, default 3306), Database name, Database username, Database password, Table prefix (optional, default `ost_` — only needed if you changed it at install time) - **Auth:** a plain MySQL/MariaDB connection (host/port/database/username/password) — not HTTP, and not osTicket's own API. - **Why this one reads the database directly:** osTicket's official REST API only supports **creating** tickets (`POST /api/tickets.json`) — there is no documented endpoint to list or read existing ones (osTicket's own developer docs say as much: *"For now, only ticket creation is supported..."*). Listing tickets therefore means reading osTicket's own MySQL/MariaDB database directly, the same way osTicket's own admin panel does internally. This makes it the only integration in this app that isn't a REST API. - **Actions used:** read-only — a single `SELECT` joining the ticket, status, priority, department, staff, team, and requester tables for every ticket whose status is in the "open" state. Nothing here can create, update, or close a ticket. - **Required access:** a MySQL/MariaDB user with **read-only (`SELECT`) access to the osTicket database only** — never reuse osTicket's own application database user, which has full read/write access. Create one with something like: ```sql CREATE USER 'homelab_manager'@'%' IDENTIFIED BY 'a-strong-password'; GRANT SELECT ON osticket.* TO 'homelab_manager'@'%'; FLUSH PRIVILEGES; ``` (narrow the host part — `'%'` — to this app's actual server address if your MySQL/MariaDB setup allows it, and make sure the database's own network/firewall rules allow that connection in the first place; this integration connects over plain TCP, unencrypted, so it's meant for a same-host or same-LAN database, not one reachable over the internet). - **What you get:** every currently-open ticket's number, subject, status, priority, department, assigned staff member or team (or "Unassigned"), requester name/email, source, created/last-activity/due dates, and two flags osTicket already tracks natively — **overdue** and **awaiting our reply** (i.e. the customer replied last and nobody on staff has answered yet) — which are the two things most worth a glance on a dashboard. - **A reliability note on subject/priority specifically:** those two fields aren't columns on osTicket's main ticket table — osTicket normalizes them into its dynamic custom-fields system, and reads them back here from `ost_ticket__cdata`, a cache table osTicket's own admin panel also uses for ticket lists (faster than joining the generic form-fields tables). osTicket's own GitHub issue tracker documents that cache occasionally going stale or briefly missing right after a custom-field change; this integration's query is written so a ticket with no matching cache row still shows up in the list, just with an empty subject/priority instead of being silently dropped. - **Not verified against a live instance** — built from osTicket's own published database schema and developer docs (table/column names, the ticket status `state` classification, and the cdata-cache mechanism all cross-checked there), but this could not be run against a real osTicket database in this environment either (no MySQL/MariaDB server was available to test against). If a query comes back empty, errors on a missing column, or a field looks wrong, tell us what happened and we'll adjust — this one has had less real-world exposure than every other integration listed here. ### phpIPAM - **Config fields:** phpIPAM URL, API app ID, App token - **Auth:** the `token` header (and `phpipam-token`, in case your version expects that name instead), set to a static per-app code. In phpIPAM, go to **Administration → API**, create (or edit) an API app, and set its **App security** to **"SSL with App token"** (or "App token" if the install isn't served over HTTPS). Saving it shows the app's code once — that's what goes in this integration's "App token" field, and the app's own short id (chosen when you created it) goes in "API app ID". phpIPAM's other auth method — logging in as a real user to get a short-lived token — isn't supported; use an App-token app instead. - **Required access:** the API app just needs read access to whichever sections/subnets you want imported. - **What it does:** this is import-only, not a full integration page — on the **IP Addresses** page, "Sync from phpIPAM" reads every subnet and the addresses in each, and adds or updates an IPAM entry per address (label from its hostname or description, the subnet's own description as its location, description/note/MAC folded into notes), the same way "Sync from Tailscale"/"Sync from Proxmox" already work: an address you entered by hand, or that a different sync source owns, is never overwritten. - **Not verified against a live instance** — built from phpIPAM's own published API documentation (endpoints, the `token` header, and the address/subnet field names all cross-checked there), but nobody has run it against a real phpIPAM yet. If a sync comes back empty or with the wrong fields, tell us what your instance actually returned and we'll adjust. ## 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 :` 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.