Portable install: the binary installs itself; static builds on five architectures; root via sudo, doas or uid 0; every package manager; older systemd; no lsblk
- hamlab install / uninstall (internal/setup): systemd or OpenRC, elevates through sudo or doas, runs as the invoking user, sets or generates the password, names only journal groups that exist, waits for /healthz, reports an active firewalld/ufw. --purge and the data chown never touch a directory that isn't Ham Lab's alone. - install.sh: curl-able bootstrap (arch detection, SHA256SUMS, offline beside the binaries, noexec /tmp fallback). make release builds dist/ for amd64, arm64, arm (ARMv6), 386, riscv64. Every build is CGO_ENABLED=0; the native one used to link glibc. - internal/priv replaces every literal `sudo -n`: uid 0, sudo or doas. - Updates acts on dnf, zypper, pacman and apk as well as apt; dnf shows installed versions. - Services falls back to the plain systemctl table before systemd 246 and says so on hosts without systemd. Disks falls back to /sys/block without lsblk. - Listener binds with IP_FREEBIND, so a LAN address that isn't up at boot is no failure. - Self-update: the new build must pass `check` against the live config, is put in place by atomic rename, and the daemon re-execs itself (same under any supervisor). - State and config writes are fsynced; a corrupt state.json is set aside, not fatal. - Terminal shutdown no longer empties the saved list, so names come back after a restart by design rather than by winning a race. - Config default is ~/.config/hamlab; an existing ~/apps/hamlab is still found. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
91b7f4f009
commit
488d929733
@@ -1,6 +1,6 @@
|
||||
# Ham Lab
|
||||
|
||||
Web-based Linux management console for bare-metal Debian, in the style of the Proxmox
|
||||
Web-based Linux management console for bare-metal Linux, in the style of the Proxmox
|
||||
web UI. Named after Ham the cat (see also HamTV).
|
||||
|
||||
Status: **v0.1** — persistent web terminals and a live Dashboard tab. Scope and roadmap in
|
||||
@@ -8,27 +8,62 @@ Status: **v0.1** — persistent web terminals and a live Dashboard tab. Scope an
|
||||
|
||||
## Runs on any Linux box
|
||||
|
||||
One static Go binary with the UI embedded; no cgo, no Node at runtime, no agents. The
|
||||
Dashboard reads `/proc` and `/sys` directly (CPU, memory, hwmon or thermal-zone temps,
|
||||
fans, NICs, block devices, mounts) so it works the same on x86 and ARM, bare metal or VM,
|
||||
and just leaves a section empty when the hardware has nothing to report. UPS status is
|
||||
optional and picked up from whichever of `pwrstat`, NUT (`upsc`) or `apcupsd` is
|
||||
installed.
|
||||
One static Go binary with the UI embedded: no cgo, no libc, no Node at runtime, no agents.
|
||||
The same file runs on Debian, Ubuntu, Fedora, RHEL/Rocky/Alma, openSUSE, Arch and Alpine
|
||||
(musl), on bare metal, VMs and containers. Builds: `amd64`, `arm64`, `arm` (ARMv6
|
||||
hard-float and up, so every Raspberry Pi), `386`, `riscv64`.
|
||||
|
||||
```sh
|
||||
make build # web + Go, or: make build-arm64 for a cross-compile
|
||||
./deploy/install.sh # installs the binary + a systemd unit for the invoking user
|
||||
hamlab passwd # set the login password (config in ~/apps/hamlab/)
|
||||
sudo systemctl start hamlab # listens on 127.0.0.1:8100 by default; set "listen" in config.json
|
||||
sudo ./hamlab-linux-amd64 install # that's the whole install
|
||||
```
|
||||
|
||||
or, from wherever `make release` output is served:
|
||||
|
||||
```sh
|
||||
curl -fsSL "$HAMLAB_URL/install.sh" | sh
|
||||
curl -fsSL "$HAMLAB_URL/install.sh" | sh -s -- --listen 0.0.0.0:8100 --tls auto
|
||||
```
|
||||
|
||||
`install.sh` only picks the build for `uname -m`, checks it against `SHA256SUMS` and runs
|
||||
`hamlab install`; run it beside the `hamlab-linux-*` files and it installs offline.
|
||||
`hamlab install`:
|
||||
|
||||
- copies the binary to `/usr/local/bin` (`--prefix`), atomically;
|
||||
- gets root through `sudo` or `doas` if you aren't root already, and runs the console as
|
||||
**you** (`--user`), so terminals are your login shell with your rights;
|
||||
- writes the config to `~/.config/hamlab/` (`--data`; an existing `~/apps/hamlab/` is kept)
|
||||
and asks for the login password, or generates one and prints it once
|
||||
(`--password-stdin` for scripts);
|
||||
- registers a boot-time service with **systemd** or **OpenRC**, naming only groups that
|
||||
exist on the host, and waits for `/healthz`; with neither init it prints the one line
|
||||
to put under your own supervisor;
|
||||
- says so when firewalld or ufw will block the port (`--open-firewall` opens it).
|
||||
|
||||
Re-running it upgrades in place and keeps config, user and password. `hamlab uninstall
|
||||
[--purge]` reverses it.
|
||||
|
||||
What adapts to the host, rather than assuming Debian:
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Root | already root, else passwordless `sudo`, else passwordless `doas`; without any, the console is read-only where root is needed and says so |
|
||||
| Updates tab | apt, dnf, zypper, pacman, apk: list, refresh, upgrade, install (pacman: all or nothing) |
|
||||
| Services / timers | systemd of any age (JSON output where it exists, the plain table before v246); a clear message on hosts without systemd |
|
||||
| Disks | `lsblk`, or `/sys/block` when it's missing (busybox) or too old; SMART and ZFS only when their tools are there |
|
||||
| Dashboard | `/proc` and `/sys` only: hwmon or thermal-zone temps, fans, NICs, disks, mounts; empty sections where the hardware has nothing to report. UPS from whichever of `pwrstat`, NUT (`upsc`) or `apcupsd` is installed |
|
||||
| Listen address | bound with `IP_FREEBIND`, so a LAN address that isn't up yet at boot doesn't fail the start |
|
||||
| Self-update | the new build must run and load this host's config before it replaces the old one; atomic rename; the daemon then re-execs itself, so it restarts the same way under systemd, OpenRC or nothing; `hamlab.prev` kept |
|
||||
|
||||
Building: `make build` (web + Go), `make release` (every architecture, `install.sh` and
|
||||
`SHA256SUMS` in `dist/`), `make test`.
|
||||
|
||||
Terminals run as the user the service runs as, with that user's login shell.
|
||||
|
||||
## Managing several machines
|
||||
|
||||
Install Ham Lab on each host. On the ones the hub should reach, add `"tls": "auto"` and a
|
||||
LAN `listen` address to `config.json` (a self-signed certificate is generated on first
|
||||
start). Then on the hub, open **Machines**, enter a name, the address
|
||||
Install Ham Lab on each host; on the ones the hub should reach:
|
||||
`hamlab install --listen <lan-ip>:8100 --tls auto` (a self-signed certificate is generated
|
||||
on first start). Then on the hub, open **Machines**, enter a name, the address
|
||||
(`https://host:8100`) and that machine's Ham Lab password once. The hub pins the
|
||||
certificate, keeps an access token, and every tab works against the chosen machine
|
||||
through the switcher at the top of the rail.
|
||||
@@ -36,8 +71,8 @@ through the switcher at the top of the rail.
|
||||
Updating: `make deploy` on the hub installs the new build there and then pushes it to
|
||||
every managed machine (`hamlab push-nodes`), which install it and restart. The Machines
|
||||
page flags machines running an older version and offers the same push per machine.
|
||||
Mixed architectures are fine: `make deploy` also cross-compiles arm64, and the hub sends
|
||||
each machine the build for its own architecture.
|
||||
Mixed architectures are fine: `make deploy` also cross-compiles every other architecture,
|
||||
and the hub sends each machine the build for its own.
|
||||
|
||||
- On `core` it is public at `https://hamlab.bigham.dev` behind Nginx Proxy Manager.
|
||||
- Installable as a PWA.
|
||||
|
||||
Reference in New Issue
Block a user