diff --git a/public/icons/services/backrest-dark.svg b/public/icons/services/backrest-dark.svg new file mode 100644 index 0000000..5ff59f8 --- /dev/null +++ b/public/icons/services/backrest-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/services/backrest-light.svg b/public/icons/services/backrest-light.svg new file mode 100644 index 0000000..15ea945 --- /dev/null +++ b/public/icons/services/backrest-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/services/proxmox-dark.svg b/public/icons/services/proxmox-dark.svg new file mode 100644 index 0000000..af63010 --- /dev/null +++ b/public/icons/services/proxmox-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/services/proxmox-light.svg b/public/icons/services/proxmox-light.svg new file mode 100644 index 0000000..3c0eb19 --- /dev/null +++ b/public/icons/services/proxmox-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/content/docs/docs/create-a-widget/data.md b/src/content/docs/docs/create-a-widget/data.md index 32802e7..cd955ab 100644 --- a/src/content/docs/docs/create-a-widget/data.md +++ b/src/content/docs/docs/create-a-widget/data.md @@ -29,7 +29,7 @@ A widget that renders entirely in the browser, like [Clock](/docs/widgets/clock/ | `ctx.endpoint` | The endpoint name, set for an `optionsFrom` fetch or a multi-view widget. | | `ctx.row` | For an `optionsFrom` fetch from a field in a `group`, that row's values. Otherwise `null`. | | `ctx.params` | The query parameters the manifest lists in [`params`](/docs/create-a-widget/manifest/#query-parameters), plus `endpoint`, as `URLSearchParams`. | -| `ctx.fetchJSON(url, opts)` | Fetches a URL and parses the body. Returns `{ status, data }` or throws. JSON is returned as-is. Prometheus text and XML are parsed. Pass `{ raw: true }` for the untouched text. | +| `ctx.fetchJSON(url, opts)` | Fetches a URL and parses the body. Returns `{ status, data }` or throws. JSON is returned as-is. Prometheus text and XML are parsed. Pass `{ raw: true }` for the untouched text. At most six requests to one service run at once. The rest wait in order. | | `ctx.parsePrometheus(text)` | Parses a Prometheus metrics body. Non-string input gives an empty object. | | `ctx.normalizeBase(raw)` | Tidies a user-entered base URL: adds a scheme, drops a trailing slash. | | `ctx.metrics` | Host metrics: `cpuSample`, `ramPercent`, `cpuTemp`, `diskStats`, `procCount`, `uptimeSeconds`. Each is a function. `cpuSample()` is async and returns `{ cpu, iowait }`. They read `/proc` and `/sys`, so they report the host, not the container limits. | diff --git a/src/content/docs/docs/create-a-widget/manifest.md b/src/content/docs/docs/create-a-widget/manifest.md index 778c503..9d4eadd 100644 --- a/src/content/docs/docs/create-a-widget/manifest.md +++ b/src/content/docs/docs/create-a-widget/manifest.md @@ -177,7 +177,7 @@ That saves `{ "vpn": { "url": "...", "apiKey": "..." } }`. A sub-field `showIf` ## Options from the service -When a `select` can only be filled after the user enters a URL and key, give it `"optionsFrom": ""`. The form shows a **Fetch** button, which calls `data.js` with `ctx.endpoint` set to that name. Return `{ options: [{ value, label }, ...] }`. +When a `select` can only be filled after the user enters a URL and key, give it `"optionsFrom": ""`. The form shows a **Fetch** button, which calls `data.js` with `ctx.endpoint` set to that name. Return `{ options: [{ value, label }, ...] }`. If the service listed more than you return, add `truncated: true`. The form then says the list was cut short. The fetch receives the current form values, `transient` fields included. diff --git a/src/content/docs/docs/widgets/backup.mdx b/src/content/docs/docs/widgets/backup.mdx index 344d186..778c920 100644 --- a/src/content/docs/docs/widgets/backup.mdx +++ b/src/content/docs/docs/widgets/backup.mdx @@ -1,6 +1,6 @@ --- title: Backup widget -description: Last run, next run and live status of Duplicati and Kopia backup jobs on your Stackyard dashboard. +description: Last run, next run and live status of Duplicati, Kopia, Proxmox Backup Server and Backrest backup jobs on your Stackyard dashboard. --- import WidgetGroup from '../../../../components/WidgetGroup.astro'; @@ -42,10 +42,51 @@ Small holds one slot. Medium holds three. Each slot reads one job. ], links: [{ label: 'kopia/kopia', href: 'https://github.com/kopia/kopia' }], }, + { + name: 'Proxmox Backup Server', icon: 'proxmox', + kind: 'Backup server', + needs: 'URL, API token', + fields: [ + ['URL', 'The server address, for example `https://pbs.local:8007`.'], + ['Token ID', 'The API token, for example `stackyard@pbs!dashboard`.'], + ['Token Secret', 'Stored as a secret.'], + ['Allow Self-Signed Certificate', 'Turn on if the server uses its default certificate.'], + ['Backup Group', 'Optional. Enter the URL and token, then load the groups and pick one. Lists up to 20 datastores, and up to 20 namespaces in each.'], + ], + links: [{ label: 'Proxmox Backup Server', href: 'https://www.proxmox.com/en/products/proxmox-backup-server/overview' }], + }, + { + name: 'Backrest', icon: 'backrest', + kind: 'Backup software', + needs: 'URL, login if set', + fields: [ + ['URL', 'The Backrest address, for example `http://backrest:9898`.'], + ['Username', 'Optional. Leave blank if sign-in is off.'], + ['Password', 'Optional. Stored as a secret.'], + ['Plan', 'Optional. Enter the URL and credentials, then load the plans and pick one.'], + ], + links: [{ label: 'garethgeorge/backrest', href: 'https://github.com/garethgeorge/backrest' }], + }, ]} /> + + +## Proxmox Backup Server + +A slot reads one backup group, such as `vm/100`. The card is named from the newest backup's notes, else the group. + +- Give the token the Audit role. On the datastore, the card shows the last backup, and failed if the newest backup failed verification. On `/`, it also shows running and failed backup tasks. +- A backup older than 25 hours shows a warning. +- Proxmox Backup Server does not hold the backup schedule, so the card shows no next run. +- A group moved to another namespace of its datastore is found again when exactly one namespace holds it. Pick the group again if two do. + +## Backrest + +A slot reads one plan. The card shows the last run, the next run, and missed when Backrest marks the plan overdue. Missed needs Backrest 1.14 or newer. + +Backrest has no read-only user. Any Backrest login has full control of Backrest. Stackyard only reads from it. diff --git a/src/content/docs/docs/widgets/index.mdx b/src/content/docs/docs/widgets/index.mdx index 3b3bf3f..c1a0199 100644 --- a/src/content/docs/docs/widgets/index.mdx +++ b/src/content/docs/docs/widgets/index.mdx @@ -22,7 +22,7 @@ Widgets reorder in the same list as apps and folders. See [Apps and folders](/do ## The widgets