Replace binary-exists check with .jmri_installed_version marker pattern.
- Reads marker on each run; skips install if version matches
- On version mismatch: stops JMRI, wipes /opt/JMRI, downloads new archive
- Separates build hash into jmri_build_hash var (templated into download URL)
- Config is preserved — lives in git-managed .jmri symlink
To upgrade: bump jmri_version + jmri_build_hash, re-run playbook.
- Stable udev device symlinks (/dev/jmri/nce, /dev/jmri/loconet, /dev/jmri/lcc)
- jmri-monitor: polls Leviton Decora Smart switch to start/stop JMRI automatically
- Quiet hours 1-10 AM (no polling)
- 30s off-delay before shutdown
- LCRR config cloned from Gitea (ssh://gitea.mk-labs.cloud:2221/rblundon/LCRR.git)
- ~/.jmri symlinked to LCRR repo for GitOps config management
- jmri-gui: X11 remote GUI access (PanelPro/DecoderPro) via ssh -X as jmri user
- Stops daemon, launches GUI, restarts daemon on exit if layout still on
- jmri user gets login shell + SSH key for GUI sessions
- Full JRE installed (openjdk-21-jre) for AWT/X11 support
- minecraft-prometheus-exporter v3.1.2 plugin (port 9225)
- ServiceMonitor for Prometheus scraping
- Grafana dashboard ConfigMap (ID 20659, Minecraft server stats)
- metrics port added to Service and Deployment containerPorts
- PaperMC 26.1.2 via itzg/minecraft-server:2026.7.0
- Namespace: minecraft, Service: journey-into-imagination
- TCP port 10182 (non-standard) via ingress-nginx tcp forwarding
- Pure Storage CSI PVC (pure-block, 50Gi) for world data
- World seed hardcoded: -5177989977648707969
- RCON password via ExternalSecret + 1Password Connect
- SleepMost v5.6.2 plugin for single-player sleep
- Whitelist off at launch, toggle-ready
- ExternalDNS annotations for internal Technitium record
- Manual steps: UniFi port forward WAN:10182→10.1.71.80:10182,
Cloudflare A record + SRV for journey-into-imagination.mk-labs.cloud
- New ansible/roles/jmri role: installs OpenJDK 21 headless, creates
jmri service user, downloads JMRI 5.10, deploys JmriFaceless systemd unit
- Handles dialout group membership for serial device access
- Config restore task for post-reinstall recovery from GitHub backup
- host_vars/main-street-station: profile_id and serial device (TODO: fill in)
- Inventory: jmri_server group with main-street-station at 192.168.10.45
- Playbook: day1_deploy_jmri.yml (linux-baseline + jmri)
Fixes 413 Entity Too Large error in Obsidian LiveSync sync operations.
Applies to both internal (communicore.local) and public (communicore.mk-labs.cloud) ingress routes.
Successfully writes /system/etc/multipath.conf but cannot write to /etc
due to Talos read-only filesystem restrictions.
Attempts made:
- nsenter with sh/cat/ln - commands don't exist in Talos minimal env
- Mount /proc/1/root/etc - still read-only
- Bind mount - invalid argument
Blocker: Talos /etc is truly read-only post-boot. PX-CSI also fails
with same nsenter/command issues when trying to validate multipath.conf.
Next: Investigate PX-CSI configuration options or Talos machine config alternatives.
Use nsenter to write multipath.conf in host's mount namespace instead
of trying to write to /host/etc which is read-only in containers.
Talos mounts /etc as read-only in container namespaces but allows writes
in the host mount namespace. This fix uses nsenter to access PID 1's
mount namespace where /etc is writable.
Also removed unnecessary volumeMounts and volumes since we're using
nsenter instead of hostPath mounts.
Fixes: Init:Error - 'can't create /host/etc/multipath.conf: Read-only file system'
Comprehensive summary of diagnosis, fix, and recovery status.
Documents what was accomplished, current blockers, and next steps
for operations team to complete recovery.