feat(admin): ask the panel to restart, from verdande's own settings
Release / Build and publish image (push) Failing after 10m2s
Release / Build and publish image (push) Failing after 10m2s
A container cannot replace its own image from the inside, so "update" is really "ask whoever owns the container to recreate it" — Yggdrasil pulls `:latest` on the way, which is what makes a restart an update at all. This removes the second browser tab, not the panel's authority: the panel still does the work and still records who asked. Three settings, needed together, and the page names whichever are missing — an operator reading "not configured" should not have to go and find out which of three. The token is never sent to a browser; the page is told only whether it is set. Answers 202 rather than waiting. The panel stops this container as part of answering, so the reply may never arrive, and a request cut off mid-flight is the successful case wearing a failure's clothes. The interface believes neither answer and polls /healthz until it responds. Administrators only, and sessions only. A leaked API token that could restart the server is a denial of service in one request. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
19aa02e80c
commit
2b45aa33e1
@@ -60,6 +60,18 @@ own mailbox from **Settings → Gmail**. The redirect URI is derived from
|
||||
| Variable | Default | What it does |
|
||||
|---|---|---|
|
||||
| `VERDANDE_UPDATE_CHECK` | `false` | Ask GitHub whether a newer release exists. |
|
||||
| `VERDANDE_PANEL_URL` | — | The Yggdrasil panel this instance runs under. |
|
||||
| `VERDANDE_PANEL_TOKEN` | — | An API token from that panel, belonging to somebody with control of this server. |
|
||||
| `VERDANDE_PANEL_SERVER_ID` | — | Which server to restart — the id in the panel's URL. |
|
||||
|
||||
All three together let **Indstillinger → Notifikationer** restart this instance,
|
||||
which is also how it picks up a new version: a container cannot replace its own
|
||||
image, so the panel recreates it and pulls `:latest` on the way. Any one of the
|
||||
three alone does nothing, and the page names the ones that are missing.
|
||||
|
||||
The token is a panel credential with control over that server. Anybody who can
|
||||
read this environment can restart it — which is true of anybody with the host
|
||||
anyway — and it is never sent to a browser.
|
||||
|
||||
Off unless you turn it on. When on, verdande asks the public GitHub releases API
|
||||
at most every six hours and sends nothing about your instance — no identifier, no
|
||||
|
||||
@@ -1337,6 +1337,67 @@ paths:
|
||||
"403": { $ref: "#/components/responses/Forbidden" }
|
||||
"404": { $ref: "#/components/responses/NotFound" }
|
||||
|
||||
/api/v1/panel:
|
||||
get:
|
||||
tags: [auth]
|
||||
summary: Whether this instance can restart itself. Administrators only.
|
||||
description: |
|
||||
A container cannot replace its own image from the inside, so "update" is
|
||||
really "ask whoever owns the container to recreate it" — Yggdrasil pulls
|
||||
`:latest` on the way, which is what makes a restart an update at all.
|
||||
|
||||
This says whether the three settings are present. The token is never sent:
|
||||
the page needs to know whether the button can work, not what the credential
|
||||
is. When it cannot, the missing variables are named — an operator reading
|
||||
"not configured" should not have to go and find out which of three.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
configured: { type: boolean }
|
||||
panel_url: { type: string }
|
||||
missing:
|
||||
type: array
|
||||
items: { type: string }
|
||||
description: The environment variables that are not set.
|
||||
"403": { $ref: "#/components/responses/Forbidden" }
|
||||
|
||||
/api/v1/panel/restart:
|
||||
post:
|
||||
tags: [auth]
|
||||
summary: Ask the panel to recreate this container. Administrators only.
|
||||
description: |
|
||||
The panel does the work and records who asked; this removes the second
|
||||
browser tab, not the panel's authority.
|
||||
|
||||
Answers 202 rather than waiting: the panel stops this container as part of
|
||||
answering, so the reply may never arrive. A request cut off mid-flight is
|
||||
the successful case wearing a failure's clothes — the interface polls
|
||||
`/healthz` rather than believing either answer.
|
||||
|
||||
Sessions only, like the rest of this group. A leaked API token that could
|
||||
restart the server is a denial of service in one request.
|
||||
responses:
|
||||
"202":
|
||||
description: The panel accepted, or was already restarting this container.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
restarting: { type: boolean }
|
||||
note: { type: string }
|
||||
"403": { $ref: "#/components/responses/Forbidden" }
|
||||
"502":
|
||||
description: |
|
||||
The panel refused. Usually a token without control of this server.
|
||||
"503":
|
||||
description: The three settings are not all present.
|
||||
|
||||
/api/v1/errors:
|
||||
get:
|
||||
tags: [auth]
|
||||
|
||||
Reference in New Issue
Block a user