Glkvm Health
fi.gy's scheduled GL.iNet KVM health and TLS: check the out-of-band KVM on my LAN every 15 minutes, forward its verdict to the swamp-managed OpenTelemetry collector, and give its web UI a publicly trusted Let's Encrypt certificate.
WHAT IT DOES
Adds the missing reporting half to @sntxrr/glinet-kvm: that model can check a
GL.iNet KVM (Comet GL-RM1 / GL-RM1PE) but cannot report it. This extension
adds an emit method (health to OTel) and a cert method (install a TLS
certificate onto the KVM) to the type — the same shape @svendowideit/nanokvm
ships — and a scheduled workflow that runs health then emit every 15
minutes. An unreachable KVM is a fail sample rather than a silent gap. A
second workflow, @figy/glkvm-dns, publishes the KVM's address as an A
record (glkvm.fi.gy) and declares the name as a TLS subject, so the shared
Caddy issues and renews a Let's Encrypt certificate for it. A third,
@figy/glkvm-cert, installs that certificate onto the KVM (over SSH, since
the device has no cert-upload API) so its web UI serves a trusted
certificate.
INSTALL
swamp extension pull @figy/glkvm-healthDEPENDENCIES
@sntxrr/glinet-kvm (the model this extends, pulled automatically), a GL.iNet
KVM reachable at the configured address, its login password in the glkvm
vault (swamp vault create @svendowideit/systemd-creds glkvm then
swamp vault put glkvm GLKVM_PASSWORD), and a running OTLP gateway listening
on 127.0.0.1:4318 (the @svendowideit/otel-gateway). Without the gateway the
emit step still runs and records why it skipped.
RUN
# Run the pipeline once now, instead of waiting for the 15-minute trigger.
swamp workflow run @figy/glkvm-health
# Check a different GL.iNet KVM on the same LAN (any input can be overridden).
swamp workflow run @figy/glkvm-health --input host=10.10.6.151
# Validate the DAG before running it (no device contact).
swamp workflow validate @figy/glkvm-health
# Read the last emit result back (endpoint, HTTP statuses, verdict).
swamp data get glkvm emit --json
# Publish the KVM's address and declare it for a certificate: reconcile
# glkvm.fi.gy -> the KVM into the shared Caddy (run after changing the
# address or the caddy model). Caddy then issues and renews a Let's
# Encrypt certificate for glkvm.fi.gy.
swamp workflow run @figy/glkvm-dns
# Install that certificate onto the KVM's web UI (scheduled daily; the
# device has no cert-upload API, so it is written over SSH).
swamp workflow run @figy/glkvm-certCONFIGURE
Inputs (all overridable per run; the defaults are my repo): device, host,
port, username, vaultName, passwordRef, timeoutMs, otelModel, otelEndpoint,
otelMesh, otelVaultName, otelTokenRef. host and vaultName are the ones
that matter — the KVM's address and the vault holding its password. The
trigger is read-only inside an extension; change the schedule from the host
with swamp workflow trigger set @figy/glkvm-health --schedule "…". See the
README for the full table.
@figy/glkvm-dns drives a @svendowideit/caddy model named glkvm-caddy that
must be a repo model (under models/) — the caddy mixin ignores
workflow/auto-created models. Create it once, declaring only the KVM's A
record plus the settings shared with the Caddy's other models (my-caddy),
then reconcile it:
# One-time: create the repo model declaring glkvm.fi.gy -> the KVM. Its
# serviceName/target share my-caddy's Caddy by default; baseDomain, the
# ACME email, plugins and environmentFile must match my-caddy's too.
swamp model create @svendowideit/caddy glkvm-caddy \
--global-arg baseDomain=fi.gy \
--global-arg letsEncryptEmail=SvenDowideit@home.org.au \
--global-arg environmentFile=$HOME/.config/caddy/dns.env \
--global-arg 'plugins:json=["github.com/caddy-dns/gandi"]' \
--global-arg 'dnsRecords:json=[{"name":"glkvm.fi.gy","type":"A","value":["10.10.6.150"],"zone":"fi.gy"}]'
# Reconcile it into the shared Caddy (re-run after changing the address).
swamp workflow run @figy/glkvm-dns To move the KVM, edit the model's dnsRecords and re-run the DNS workflow.
See the README for the full input table.
UPGRADE
This extension installs nothing on the host, so an upgrade has nothing to rebuild or reconcile. Refresh the pulled copy with one idempotent command:
swamp extension update The @sntxrr/glinet-kvm model it extends is upgraded by that extension's own
upgrades entry on the next method run.
WHAT IT INSTALLS
Nothing on the host — no services, cron triggers, daemons or webhooks. The
schedule is a swamp trigger evaluated by swamp serve; it runs the
@sntxrr/glinet-kvm model with the added emit method, which talks to the
device and the collector and writes swamp data.
fi.gy's scheduled GL.iNet KVM health: check the out-of-band KVM at 10.10.6.150, forward its health to the swamp-managed OpenTelemetry collector, and require the run to leave a health record. This is the concrete, site-specific half. The portable model that knows how to talk to a GL.iNet KVM (the kvmd fork, self-signed TLS, viewer-driven snapshots) is @sntxrr/glinet-kvm; this workflow pins it to my device and my collector. Every 15 minutes it runs `health`, then the `emit` method added by @figy/
fi.gy's GL.iNet KVM DNS and certificate: reconcile glkvm.fi.gy -> the KVM into the shared Caddy, and declare the name as a TLS subject so Caddy issues and renews a Let's Encrypt certificate for it (via DNS-01), without giving the KVM its own Caddy. The A record lives on its own @svendowideit/caddy model, `glkvm-caddy`, whose only desired state is that one record — plus the shared settings (base domain fi.gy, ACME email, the Gandi DNS provider via the shared environment file) the caddy extension
fi.gy's GL.iNet KVM TLS: install the Let's Encrypt certificate Caddy issued for glkvm.fi.gy onto the KVM and keep it current. The GLKVM has no certificate-upload API, so this drives the `cert install` method @figy/glkvm-health adds to @sntxrr/glinet-kvm, which writes /etc/kvmd/user/ssl/server.crt and .key over SSH (root, the device password) and reloads nginx. The certificate files are taken from Caddy's store (~/.local/share/caddy/certificates), where Caddy issued them and renews them automati
- Has README or module doc2/2earned
- README has a code example1/1earned
- README is substantive1/1earned
- Most symbols documented1/1earned
- No slow types (deprecated)1/1earned
- Dependencies pass trust audit2/2earned
- Has description1/1earned
- Platform support declared (or universal)2/2earned
- License2/2earned
- Verified public repository2/2earned
Spawns a subprocess with Deno.Command().
- models/glkvm_emit.ts:685 — reading the certificate the KVM serves needs a TLS handshake openssl s_client provides; the arguments are fixed and validated, never raw caller input.
- models/glkvm_emit.ts:704 — reading a certificate serial needs openssl x509; the argument is a path this method resolved, never raw caller text.
- models/glkvm_emit.ts:742 — ssh is the only transport the GLKVM exposes for writing a certificate (it has no cert-upload API); the password goes via SSH_ASKPASS env, never argv.