Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions public/icons/services/backrest-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/icons/services/backrest-light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/icons/services/proxmox-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/icons/services/proxmox-light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/content/docs/docs/create-a-widget/data.md
Original file line number Diff line number Diff line change
Expand Up @@ -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. |
Expand Down
2 changes: 1 addition & 1 deletion src/content/docs/docs/create-a-widget/manifest.md
Original file line number Diff line number Diff line change
Expand Up @@ -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": "<endpoint>"`. 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": "<endpoint>"`. 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.

Expand Down
47 changes: 44 additions & 3 deletions src/content/docs/docs/widgets/backup.mdx
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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' }],
},
]} />


<SettingList title="Settings for each slot" items={[
{ name: 'Provider', text: 'Duplicati, Kopia, or None for an empty slot.' },
{ name: 'Provider', text: 'Duplicati, Kopia, Proxmox Backup Server, Backrest, or None for an empty slot.' },
{ name: 'Display name', text: 'Replaces the job name shown on the card.', optional: true },
{ name: 'Link URL', text: 'Where clicking the slot opens. Duplicati opens the job log and Kopia the snapshot list under it. Leave blank to use the service address, if your browser can reach it.', optional: true },
{ name: 'Link URL', text: 'Where clicking the slot opens. Duplicati opens the job log, Kopia the snapshot list and Backrest the plan under it. Proxmox Backup Server opens the address itself. Leave blank to use the service address, if your browser can reach it.', optional: true },
]} />

## 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.
2 changes: 1 addition & 1 deletion src/content/docs/docs/widgets/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Widgets reorder in the same list as apps and folders. See [Apps and folders](/do
## The widgets

<LinkList title="12 widgets" items={[
{ href: '/docs/widgets/backup/', name: 'Backup', text: 'Last and next run of backup jobs.', value: 'Duplicati, Kopia' },
{ href: '/docs/widgets/backup/', name: 'Backup', text: 'Last and next run of backup jobs.', value: 'Duplicati, Kopia, Proxmox Backup Server, Backrest' },
{ href: '/docs/widgets/books/', name: 'Books', text: 'Reading progress and shelves.', value: 'Audiobookshelf, Komga, Kavita' },
{ href: '/docs/widgets/clock/', name: 'Clock', text: 'A digital or analog clock.', value: 'No service' },
{ href: '/docs/widgets/connections/', name: 'Connections', text: 'A VPN tile, or services on a world map.', value: 'Gluetun, NetBird, Conduit, Plausible, Umami' },
Expand Down
Loading