feat(signage): scaffold bare Debian VM module

New src/apps/signage: Debian 13 VM, 1 core / 1G / 16G (vmid 816), deps cluster:vm + templates:debian + backup:vm. update.sh confirms the VM is up and records a version marker; signage software layered on in a later pass. Registered in module-catalog.json.
This commit is contained in:
Lars Rossen 2026-09-01 22:14:54 +02:00
parent be50a7d900
commit 8b981ecdea
6 changed files with 203 additions and 0 deletions

View file

@ -0,0 +1,26 @@
# signage — digital signage host
A Debian 13 VM intended to run digital-signage software. **Current state: bare
VM scaffold** — the VM shape and module plumbing are in place; the signage
service itself is not chosen/installed yet.
| | |
|---|---|
| VM | 1 core · 1024 MB · 16 G disk · `tanka1` · `lan` bridge |
| Image | `debian-13-generic-amd64.qcow2` (cloud-init) |
| vmid | 816 |
| Depends on | `cluster:vm`, `templates:debian`, `backup:vm` |
| Target env | `omStaging` (installs as `signage-omStaging`) |
## Files
- `signage.json` — module config (VM shape + dependencies)
- `install.sh` — thin wrapper → `update.sh`
- `update.sh` — confirms the VM is up, records a version marker (no service yet)
- `test.sh` — checks the VM resolves, is reachable, and carries the marker
## Next steps
Pick the signage software and extend `update.sh`/`test.sh` accordingly. If it
exposes a web UI, add `network:proxy` (and `identity:identity` for OIDC login)
to `dependsOn` and a matching `config` block.

15
src/apps/signage/install.sh Executable file
View file

@ -0,0 +1,15 @@
#!/usr/bin/env bash
#
# signage module install — thin wrapper.
#
# The VM is created by the cluster:vm provider (Debian 13 cloud image) and
# OS-prepped by templates:debian. This script applies the module-specific step;
# all real work lives in update.sh (install == update for this module).
#
# Usage: install.sh <module-name>
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
exec "${SCRIPT_DIR}/update.sh" "$@"

View file

@ -0,0 +1,29 @@
{
"description": "Digital signage host — bare Debian VM scaffold (signage software TBD)",
"version": "0.0.1",
"appVersion": "TBD",
"releaseDate": "2026-09-01",
"maintainer": "@larsrossen",
"status": "Development",
"vmname": "signage",
"vmid": 816,
"vmtag": "TAPPaaS,MakerFLOSS",
"ports": [],
"dependsOn": ["cluster:vm", "templates:debian", "backup:vm"],
"provides": [],
"config": {
"cluster:vm": {
"bios": "seabios",
"ostype": "l26",
"cores": 1,
"memory": "1024",
"diskSize": "16G",
"storage": "tanka1",
"imageType": "img",
"image": "debian-13-generic-amd64.qcow2",
"imageLocation": "https://cdimage.debian.org/cdimage/cloud/trixie/latest",
"cloudInit": "true",
"bridge0": "lan"
}
}
}

66
src/apps/signage/test.sh Executable file
View file

@ -0,0 +1,66 @@
#!/usr/bin/env bash
#
# signage module test — health checks for the bare Debian VM.
#
# Verifies (from tappaas-cicd, over the Proxmox guest agent + SSH):
# - the VM's IP resolves via the guest agent
# - the VM is reachable over SSH
# - the version marker written by update.sh is present
#
# As the signage software is layered on later, add its checks here.
#
# Usage: test.sh <module-name>
#
set -uo pipefail
. /home/tappaas/bin/common-install-routines.sh
MODULE="${1:-signage}"
readonly MGMT="mgmt"
readonly MARKER="/etc/tappaas-signage.version"
VMID="$(get_config_value 'vmid')"
VMNAME="$(get_config_value 'vmname' "${MODULE}")"
PASS=0; FAIL=0
ok() { info " ${GN}✓${CL} $1"; PASS=$((PASS+1)); }
no() { error " ✗ $1"; FAIL=$((FAIL+1)); }
[[ -n "${VMID}" && "${VMID}" != "null" ]] || die "no vmid for ${MODULE}"
PRIMARY="$(get_primary_node_fqdn 2>/dev/null || echo "tappaas1.${MGMT}.internal")"
NODE="$(ssh -o BatchMode=yes -o StrictHostKeyChecking=accept-new "root@${PRIMARY}" \
"pvesh get /cluster/resources --type vm --output-format json 2>/dev/null" \
| jq -r --arg v "${VMID}" '.[] | select(.vmid==($v|tonumber)) | .node' 2>/dev/null | head -1)"
[[ -n "${NODE}" ]] || NODE="$(get_config_value 'node' "$(get_node_hostname 0)")"
IP="$(ssh -o BatchMode=yes "root@${NODE}.${MGMT}.internal" \
"qm guest cmd ${VMID} network-get-interfaces" 2>/dev/null \
| jq -r '.[] | select(.name | test("^lo$") | not) | ."ip-addresses"[]? | select(."ip-address-type"=="ipv4") | ."ip-address"' 2>/dev/null \
| grep -v '^127\.' | head -1)"
info "${BOLD}signage test${CL} (${VMNAME}, VM ${VMID} on ${NODE})"
if [[ -z "${IP}" ]]; then
no "could not resolve VM IP via guest agent"
info "Result: ${PASS} passed, ${FAIL} failed"
exit 1
fi
ok "VM IP resolved (${IP})"
vm() { ssh -o StrictHostKeyChecking=accept-new -o ConnectTimeout=10 "tappaas@${IP}" "$@"; }
if vm "true"; then
ok "VM reachable over SSH"
else
no "VM not reachable over SSH"
fi
if vm "test -f ${MARKER}"; then
ok "version marker present ($(vm "cat ${MARKER} 2>/dev/null" | tr -d '\r'))"
else
no "version marker ${MARKER} missing (update.sh did not run?)"
fi
echo ""
info "Result: ${PASS} passed, ${FAIL} failed"
[[ "${FAIL}" -eq 0 ]]

58
src/apps/signage/update.sh Executable file
View file

@ -0,0 +1,58 @@
#!/usr/bin/env bash
#
# signage module update — a bare Debian VM (scaffold).
#
# The VM is created by the cluster:vm provider (Debian 13 cloud image) and
# OS-prepped by templates:debian. This module currently only confirms the VM is
# up and records a version marker — the signage software will be layered on in a
# later pass. install == update for this module.
#
# Runs on tappaas-cicd: resolves the VM's IP via the Proxmox guest agent, then
# drives the VM over SSH. Idempotent.
#
# Usage: update.sh <module-name>
#
set -euo pipefail
. /home/tappaas/bin/common-install-routines.sh
MODULE="${1:-signage}"
readonly MGMT="mgmt"
readonly MARKER="/etc/tappaas-signage.version" # on the VM: module version we applied
VMNAME="$(get_config_value 'vmname' "${MODULE}")"
VMID="$(get_config_value 'vmid')"
VERSION="$(get_config_value 'version' '0.0.1')"
[[ -n "${VMID}" && "${VMID}" != "null" ]] || die "no vmid for ${MODULE}"
# ── Locate the node hosting the VM (HA-safe) and resolve its IP ───────
PRIMARY="$(get_primary_node_fqdn 2>/dev/null || echo "tappaas1.${MGMT}.internal")"
NODE="$(ssh -o BatchMode=yes -o StrictHostKeyChecking=accept-new "root@${PRIMARY}" \
"pvesh get /cluster/resources --type vm --output-format json 2>/dev/null" \
| jq -r --arg v "${VMID}" '.[] | select(.vmid==($v|tonumber)) | .node' 2>/dev/null | head -1)"
[[ -n "${NODE}" ]] || NODE="$(get_config_value 'node' "$(get_node_hostname 0)")"
[[ -n "${NODE}" ]] || die "could not locate the node hosting VM ${VMID}"
get_vm_ip() {
ssh -o BatchMode=yes "root@${NODE}.${MGMT}.internal" \
"qm guest cmd ${VMID} network-get-interfaces" 2>/dev/null \
| jq -r '.[] | select(.name | test("^lo$") | not) | ."ip-addresses"[]? | select(."ip-address-type"=="ipv4") | ."ip-address"' 2>/dev/null \
| grep -v '^127\.' | head -1
}
info "${BOLD}Updating signage${CL} on ${VMNAME} (VM ${VMID}, node ${NODE})"
IP=""
for _ in $(seq 1 18); do IP="$(get_vm_ip)"; [[ -n "${IP}" ]] && break; sleep 10; done
[[ -n "${IP}" ]] || die "could not resolve an IPv4 for VM ${VMID} via the guest agent"
info " VM IP: ${IP}"
vm() { ssh -o BatchMode=yes -o StrictHostKeyChecking=accept-new -o ConnectTimeout=10 "tappaas@${IP}" "$@"; }
# Confirm SSH is up and record the version marker. Nothing else to install yet —
# this is a bare Debian scaffold; the signage service comes in a later pass.
vm "true" || die "VM ${VMNAME} (${IP}) not reachable over SSH"
vm "echo '${VERSION}' | sudo tee ${MARKER} >/dev/null" || warn "could not write version marker"
info " ${GN}✓${CL} signage VM is up (bare Debian scaffold — no service installed yet)"

View file

@ -19,6 +19,15 @@
"stack": "infrastructure",
"category": "containers",
"status": "incomplete"
},
{
"moduleName": "signage",
"repo": "community",
"moduleJson": "src/apps/signage/signage.json",
"vmid": 816,
"stack": "application",
"category": "signage",
"status": "incomplete"
}
],
"proxmoxTemplates": [],