Drop the external demo: the Widgets tab is the demo
The hamlab-demo site, its Widgets-tab button, the demo_url config key and the make publish target that fed it are all gone, along with the public read-only token it needed. The example stays in examples/external-demo as something to read. The installer one-liner already comes from Gitea releases. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
b5454c1022
commit
363ff02bda
@@ -2,7 +2,6 @@
|
||||
VERSION ?= $(shell git describe --tags --always 2>/dev/null || echo dev)
|
||||
GO ?= go
|
||||
PREFIX ?= /usr/local/bin
|
||||
PUBLISH ?= /home/core/apps/hamlab-demo/site
|
||||
|
||||
# every architecture a release carries; arm is ARMv6 hard-float, so it covers every Raspberry Pi
|
||||
ARCHES ?= amd64 arm64 arm 386 riscv64
|
||||
@@ -10,7 +9,7 @@ LDFLAGS = -s -w -X main.version=$(VERSION)
|
||||
# static, no cgo: the same file runs on glibc, musl (Alpine) and anything else with a Linux kernel
|
||||
GOBUILD = CGO_ENABLED=0 GOOS=linux GOARM=6 $(GO) build -trimpath -ldflags "$(LDFLAGS)"
|
||||
|
||||
.PHONY: all web build go dev cross release publish gitea-release deploy push-nodes push-nodes-force test clean
|
||||
.PHONY: all web build go dev cross release gitea-release deploy push-nodes push-nodes-force test clean
|
||||
|
||||
all: build
|
||||
|
||||
@@ -61,9 +60,7 @@ gitea-release: release
|
||||
deploy: build cross
|
||||
./bin/hamlab install --prefix $(PREFIX)
|
||||
@sleep 1; $(PREFIX)/hamlab push-nodes || true
|
||||
@# The public installer must never lag the fleet: it would offer everyone an older build, and
|
||||
@# "upgrade" a current machine backwards. Publish only where this hub serves the download site.
|
||||
@if [ -d $(PUBLISH) ]; then $(MAKE) --no-print-directory publish; fi
|
||||
@echo "deployed $(VERSION); 'make gitea-release' publishes it for everyone else"
|
||||
|
||||
# push the installed binary to every managed machine (what deploy does last)
|
||||
push-nodes:
|
||||
@@ -75,13 +72,3 @@ push-nodes-force:
|
||||
|
||||
clean:
|
||||
rm -rf bin dist internal/web/dist web/dist
|
||||
|
||||
# Put the release where `curl -fsSL https://hamlab-demo.bigham.dev/install.sh | sh` finds it:
|
||||
# the static site beside the demo page (nginx, public through NPM). Binaries first, VERSION
|
||||
# last, so nobody is ever pointed at files that aren't there yet.
|
||||
publish: release
|
||||
mkdir -p $(PUBLISH)/dl
|
||||
cp dist/hamlab-linux-* dist/SHA256SUMS $(PUBLISH)/dl/
|
||||
cp dist/install.sh $(PUBLISH)/dl/install.sh && cp dist/install.sh $(PUBLISH)/install.sh
|
||||
cp dist/VERSION $(PUBLISH)/dl/VERSION
|
||||
@echo "published $(VERSION): curl -fsSL https://hamlab-demo.bigham.dev/install.sh | sh"
|
||||
|
||||
@@ -186,7 +186,12 @@ something long in one, switch away and back, refresh — it's all still there.
|
||||
a URL), status sensors (services, updates, ZFS, SMART), a widget library, custom widgets
|
||||
on the Dashboard tab (briefly renamed "Monitors" 2026-09-19, back to "Dashboard"
|
||||
2026-09-20 at Mitchell's request; the view id and URL were always `dashboard`), and a
|
||||
frameable `/embed/widget` for Glance and friends. The stock Dashboard modules and the Disks
|
||||
frameable `/embed/widget` for Glance and friends. (An external demo page was deployed at
|
||||
`hamlab-demo.bigham.dev` and linked from the Widgets tab 2026-09-19; **both removed
|
||||
2026-09-23** at Mitchell's request — the Widgets tab shows the same thing against the
|
||||
machine you are signed in to, so the second copy earned nothing and cost a public
|
||||
read-only token, which was revoked with it. `examples/external-demo/` stays as an example
|
||||
to read.) The stock Dashboard modules and the Disks
|
||||
tab read the sensor API too (`sampleAdapter.ts`); `/api/metrics` is retired.
|
||||
Also per-service and per-container sensors (memory and CPU from cgroups), tokens limited
|
||||
to ID patterns, and `/api/fleet/sensors/query` for the whole fleet in one request.
|
||||
@@ -406,8 +411,7 @@ something long in one, switch away and back, refresh — it's all still there.
|
||||
still default to private. No token is needed by anything any more (the read-only one was
|
||||
revoked; only `hamlab-publish`, which creates releases, remains). Gitea resolves
|
||||
`releases/download/latest/<asset>`, so `install.sh` and `HAMLAB_URL` now point straight
|
||||
at the newest release and never need changing; the rolling copy on
|
||||
`hamlab-demo.bigham.dev` stays as a mirror. What is public is the source, the history,
|
||||
at the newest release and never need changing. What is public is the source, the history,
|
||||
`BUGS.md` and this file — which describes the lab and names the console's hostname.
|
||||
- **Auth hardening** — WebAuthn passkeys (phone Face ID), TOTP fallback, optional NPM
|
||||
access list restricting to WireGuard/LAN.
|
||||
|
||||
@@ -12,10 +12,10 @@ window.HAMLAB = { base: 'http://10.0.0.234:8100', token: '<read-only sensor toke
|
||||
```
|
||||
|
||||
Anyone who can load the page can read the token. If the page is public, limit the token to
|
||||
patterns that name nothing you'd mind the world reading (the `hamlab-demo` one shows
|
||||
hardware numbers and counts, not container or service names). Deployed on `core` as the `hamlab-demo` stack —
|
||||
see Hamlet `docs/docker.md`. Update it with
|
||||
`cp examples/external-demo/index.html /home/core/apps/hamlab-demo/site/`.
|
||||
patterns that name nothing you'd mind the world reading — hardware numbers and counts,
|
||||
not container or service names.
|
||||
|
||||
To link it from the Widgets tab, set `"demo_url": "http://…"` in the hub's `config.json`
|
||||
and restart Ham Lab.
|
||||
This is an example to read and copy, not something that runs anywhere. It was deployed on
|
||||
`core` as the `hamlab-demo` stack and linked from the Widgets tab until 2026-09-23, when
|
||||
both were removed: the Widgets tab shows the same widgets against the machine you are
|
||||
already signed in to, so a second public copy earned nothing and cost a public token.
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
# Ham Lab installer.
|
||||
#
|
||||
# curl -fsSL https://hamlab-demo.bigham.dev/install.sh | sh
|
||||
# curl -fsSL https://git.bigham.dev/mitchell/hamlab/releases/download/latest/install.sh | sh
|
||||
#
|
||||
# With a terminal it walks you through it: who the console runs as, where it listens,
|
||||
# HTTPS, the firewall, the password — then downloads the build for this machine, checks
|
||||
|
||||
@@ -1013,9 +1013,8 @@ func (s *Server) me(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
_, rebootErr := os.Stat("/run/reboot-required")
|
||||
updateVersion, _ := s.behind()
|
||||
var demoURL, addr string
|
||||
var addr string
|
||||
s.cfg.View(func(c *config.Config) {
|
||||
demoURL = c.DemoURL
|
||||
if h, _, err := net.SplitHostPort(c.Listen); err == nil && h != "" && h != "0.0.0.0" && h != "::" {
|
||||
addr = h // the address this console listens on, for the machine menu
|
||||
}
|
||||
@@ -1023,7 +1022,7 @@ func (s *Server) me(w http.ResponseWriter, r *http.Request) {
|
||||
jsonOK(w, 200, map[string]any{
|
||||
"host": s.hostName(), "user": s.user, "account": actorOf(r).User, "version": s.version,
|
||||
"load": load, "uptime": uptime, "service_started": s.started,
|
||||
"reboot_needed": rebootErr == nil, "fingerprint": s.fingerprint, "arch": runtime.GOARCH, "demo_url": demoURL, "addr": addr,
|
||||
"reboot_needed": rebootErr == nil, "fingerprint": s.fingerprint, "arch": runtime.GOARCH, "addr": addr,
|
||||
"update_available": updateVersion,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -70,9 +70,6 @@ type Config struct {
|
||||
TLS string `json:"tls,omitempty"` // "auto" → self-signed cert in the data dir; "" → plain HTTP
|
||||
Tokens []Token `json:"tokens,omitempty"`
|
||||
Nodes []Node `json:"nodes,omitempty"`
|
||||
// DemoURL, when set, is linked from the Widgets tab: a page outside Ham Lab that
|
||||
// shows the sensor API being used (examples/external-demo).
|
||||
DemoURL string `json:"demo_url,omitempty"`
|
||||
// Updates: where a newer build comes from. See UpdateSource.
|
||||
Updates UpdateSource `json:"update,omitempty"`
|
||||
|
||||
|
||||
+1
-2
@@ -31,7 +31,7 @@ function Tile({ spec, data, note }: { spec: WidgetSpec; data: WidgetData; note:
|
||||
)
|
||||
}
|
||||
|
||||
export default function Gallery({ demoUrl }: { demoUrl?: string }) {
|
||||
export default function Gallery() {
|
||||
const [cat, setCat] = useState<Sensor[] | null>(null)
|
||||
const [err, setErr] = useState('')
|
||||
const rate = useRefreshMs()
|
||||
@@ -61,7 +61,6 @@ export default function Gallery({ demoUrl }: { demoUrl?: string }) {
|
||||
<span className="hint">{needle ? `${shown.length} of ${sensors.length}` : sensors.length} sensors on this machine · live · tap a tile to copy its ID</span>
|
||||
<input className="gallery-find" value={find} onChange={(e) => setFind(e.target.value)} placeholder="find — gitea, temp, enp3s0…" spellCheck={false} autoCapitalize="off" />
|
||||
<span className="spacer" />
|
||||
{demoUrl && <a className="btn" href={demoUrl} target="_blank" rel="noreferrer" title="a page outside Ham Lab, built on the same sensor API">External demo ↗</a>}
|
||||
</div>
|
||||
|
||||
{!needle && <h2 className="section">Widget types</h2>}
|
||||
|
||||
+1
-1
@@ -269,7 +269,7 @@ export default function Shell({ me: hubMe, onLoggedOut }: { me: Me; onLoggedOut:
|
||||
{view === 'space' && <Space key={machine ?? ''} />}
|
||||
{view === 'machines' && <Machines hub={hubMe} onChanged={loadMachines} onOpen={(n) => { switchMachine(n); setView('dashboard') }} />}
|
||||
{view === 'dashboard' && <Dashboard />}
|
||||
{view === 'widgets' && <Gallery demoUrl={hubMe.demo_url} />}
|
||||
{view === 'widgets' && <Gallery />}
|
||||
{view === 'docker' && <Docker />}
|
||||
{view === 'alerts' && <Alerts machines={machines.map((m) => m.name)} titleOf={(n) => titleOf(n === hubMe.host ? null : n, machines, hubMe.host)} />}
|
||||
{view === 'top' && <Top />}
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ async function req<T>(method: string, path: string, body?: unknown, local = fals
|
||||
}
|
||||
|
||||
export interface UpdateStatus { current: string; latest: string; arch: string; behind: boolean; checking: boolean; installing: boolean; enabled: boolean; auto: boolean; url: string; notes?: string; published?: string; checked?: string; error?: string }
|
||||
export interface Me { demo_url?: string; addr?: string; host: string; user: string; account?: string; update_available?: string; version: string; load: string; uptime: number; reboot_needed?: boolean; fingerprint?: string; arch?: string }
|
||||
export interface Me { addr?: string; host: string; user: string; account?: string; update_available?: string; version: string; load: string; uptime: number; reboot_needed?: boolean; fingerprint?: string; arch?: string }
|
||||
export interface PushResult { name: string; ok: boolean; version?: string; error?: string }
|
||||
// What a machine is called on screen: the hostname it reports, which follows a rename within
|
||||
// a poll. The name it was added under stays its identity — the URL, its accent colour, and
|
||||
|
||||
Reference in New Issue
Block a user