jmri: add Phase 4 TigerVNC server on :1 (port 5901) — replaces X11 forwarding
This commit is contained in:
@@ -33,6 +33,17 @@ jmri_config_src: ""
|
||||
jmri_json_port: 12080
|
||||
jmri_withrottle_port: 12090
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Phase 4 — VNC server (TigerVNC)
|
||||
# Replaces X11 forwarding with a persistent virtual display.
|
||||
# Connect with any VNC client to <host>:5901
|
||||
# ---------------------------------------------------------------------------
|
||||
jmri_vnc_display: "1"
|
||||
jmri_vnc_port: 5901
|
||||
jmri_vnc_geometry: "1280x800"
|
||||
jmri_vnc_depth: "24"
|
||||
jmri_vnc_password: "" # set via group_vars (vault-backed)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Phase 2 — Layout power monitor (Leviton Decora Smart Wi-Fi)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
name: jmri
|
||||
state: restarted
|
||||
|
||||
- name: Restart jmri-vnc
|
||||
ansible.builtin.systemd:
|
||||
name: jmri-vnc
|
||||
state: restarted
|
||||
|
||||
- name: Restart sshd
|
||||
ansible.builtin.systemd:
|
||||
name: ssh
|
||||
|
||||
@@ -245,9 +245,9 @@
|
||||
daemon_reload: true
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Phase 3 — X11 remote GUI access
|
||||
# Phase 3 — X11 remote GUI access (retained for fallback; VNC preferred)
|
||||
# ---------------------------------------------------------------------------
|
||||
- name: Install xauth (required for SSH X11 forwarding)
|
||||
- name: Install xauth (required for SSH X11 forwarding fallback)
|
||||
ansible.builtin.apt:
|
||||
name: xauth
|
||||
state: present
|
||||
@@ -271,6 +271,56 @@
|
||||
X11UseLocalhost yes
|
||||
notify: Restart sshd
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Phase 4 — VNC server (TigerVNC)
|
||||
# Persistent virtual display on :1 (port 5901). Replaces X11 forwarding.
|
||||
# ---------------------------------------------------------------------------
|
||||
- name: Install TigerVNC server
|
||||
ansible.builtin.apt:
|
||||
name: tigervnc-standalone-server
|
||||
state: present
|
||||
update_cache: false
|
||||
|
||||
- name: Create .vnc directory for jmri user
|
||||
ansible.builtin.file:
|
||||
path: "{{ jmri_home }}/.vnc"
|
||||
state: directory
|
||||
owner: "{{ jmri_user }}"
|
||||
group: "{{ jmri_group }}"
|
||||
mode: '0700'
|
||||
|
||||
- name: Set VNC password for jmri user
|
||||
ansible.builtin.shell:
|
||||
cmd: "printf '{{ jmri_vnc_password }}' | vncpasswd -f > {{ jmri_home }}/.vnc/passwd"
|
||||
become_user: "{{ jmri_user }}"
|
||||
no_log: true
|
||||
changed_when: true
|
||||
|
||||
- name: Set correct permissions on VNC password file
|
||||
ansible.builtin.file:
|
||||
path: "{{ jmri_home }}/.vnc/passwd"
|
||||
owner: "{{ jmri_user }}"
|
||||
group: "{{ jmri_group }}"
|
||||
mode: '0600'
|
||||
|
||||
- name: Deploy jmri-vnc systemd unit
|
||||
ansible.builtin.template:
|
||||
src: jmri-vnc.service.j2
|
||||
dest: /etc/systemd/system/jmri-vnc.service
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
notify:
|
||||
- Reload systemd
|
||||
- Restart jmri-vnc
|
||||
|
||||
- name: Enable and start jmri-vnc service
|
||||
ansible.builtin.systemd:
|
||||
name: jmri-vnc
|
||||
enabled: true
|
||||
state: started
|
||||
daemon_reload: true
|
||||
|
||||
- name: Deploy jmri-gui script
|
||||
ansible.builtin.template:
|
||||
src: jmri-gui.j2
|
||||
|
||||
@@ -1,41 +1,40 @@
|
||||
#!/bin/bash
|
||||
# jmri-gui — launch JMRI GUI over SSH -X (X11 forwarding)
|
||||
# jmri-gui — launch JMRI GUI on VNC virtual display
|
||||
# Managed by Ansible — do not edit manually.
|
||||
#
|
||||
# Usage (connect as jmri user):
|
||||
# ssh -X jmri@main-street-station jmri-gui panelpro
|
||||
# ssh -X jmri@main-street-station jmri-gui decoderpro
|
||||
# ssh -X jmri@main-street-station jmri-gui status
|
||||
# ssh jmri@main-street-station jmri-gui panelpro
|
||||
# ssh jmri@main-street-station jmri-gui decoderpro
|
||||
# ssh jmri@main-street-station jmri-gui status
|
||||
#
|
||||
# ~/.ssh/config recommended:
|
||||
# Host main-street-station
|
||||
# User jmri
|
||||
# ForwardX11 yes
|
||||
# Then connect a VNC client to main-street-station.local.mk-labs.cloud:5901
|
||||
# VNC password is in the Ansible vault (vault_jmri_vnc_password)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
JMRI_DIR="{{ jmri_install_dir }}"
|
||||
JMRI_SERVICE="jmri.service"
|
||||
MONITOR_SERVICE="jmri-monitor.service"
|
||||
VNC_SERVICE="jmri-vnc.service"
|
||||
DISPLAY=":{{ jmri_vnc_display }}"
|
||||
export DISPLAY
|
||||
|
||||
usage() {
|
||||
echo "Usage: jmri-gui <panelpro|decoderpro|status>"
|
||||
exit 1
|
||||
}
|
||||
|
||||
check_display() {
|
||||
if [ -z "${DISPLAY:-}" ]; then
|
||||
echo "ERROR: No DISPLAY set. Connect with: ssh -X jmri@main-street-station"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
status() {
|
||||
echo "=== JMRI daemon ==="
|
||||
systemctl status "$JMRI_SERVICE" --no-pager -l 2>&1 | head -8
|
||||
echo ""
|
||||
echo "=== VNC server ==="
|
||||
systemctl status "$VNC_SERVICE" --no-pager -l 2>&1 | head -5
|
||||
echo ""
|
||||
echo "=== Layout monitor ==="
|
||||
systemctl status "$MONITOR_SERVICE" --no-pager -l 2>&1 | head -5
|
||||
echo ""
|
||||
echo "Connect VNC client to: $(hostname -f):{{ jmri_vnc_port }}"
|
||||
}
|
||||
|
||||
launch() {
|
||||
@@ -48,31 +47,33 @@ launch() {
|
||||
*) usage ;;
|
||||
esac
|
||||
|
||||
check_display
|
||||
# Ensure VNC server is running
|
||||
if ! systemctl is-active --quiet "$VNC_SERVICE" 2>/dev/null; then
|
||||
echo "Starting VNC server..."
|
||||
sudo systemctl start "$VNC_SERVICE"
|
||||
sleep 2
|
||||
fi
|
||||
|
||||
# Stop the daemon if running
|
||||
# Stop the JMRI daemon if running
|
||||
if systemctl is-active --quiet "$JMRI_SERVICE" 2>/dev/null; then
|
||||
echo "Stopping JMRI daemon..."
|
||||
sudo systemctl stop "$JMRI_SERVICE"
|
||||
fi
|
||||
|
||||
echo "Launching $binary (last-used profile)..."
|
||||
echo "Close the window to return to daemon mode."
|
||||
echo "Launching $binary on VNC display $DISPLAY..."
|
||||
echo "Connect your VNC client to: $(hostname -f):{{ jmri_vnc_port }}"
|
||||
echo "VNC password: see Ansible vault (vault_jmri_vnc_password)"
|
||||
echo ""
|
||||
|
||||
# SSH sets DISPLAY to localhost:N (TCP) — translate to unix socket form
|
||||
# so Java's AWT xauth lookup matches the forwarded cookie.
|
||||
export DISPLAY=$(echo "$DISPLAY" | sed 's/localhost:/:/')
|
||||
|
||||
# Force AWT out of headless mode
|
||||
export JMRI_OPTIONS="-Djava.awt.headless=false"
|
||||
|
||||
# Run without --profile so JMRI uses its last-session preference.
|
||||
# The daemon service uses --profile explicitly for headless reliability.
|
||||
"$JMRI_DIR/$binary"
|
||||
# Launch on the VNC display — no --profile so JMRI uses last-session preference
|
||||
"$JMRI_DIR/$binary" &
|
||||
|
||||
echo "$binary launched in background on VNC display."
|
||||
echo "Close it from the VNC client, then run 'jmri-gui status' to check state."
|
||||
echo ""
|
||||
echo "$binary closed."
|
||||
|
||||
# Restart daemon if layout switch is still on
|
||||
if systemctl is-active --quiet "$MONITOR_SERVICE" 2>/dev/null; then
|
||||
@@ -96,8 +97,7 @@ for perm in perms:
|
||||
sys.exit(1)
|
||||
EOF
|
||||
then
|
||||
echo "Layout is ON — restarting JMRI daemon."
|
||||
sudo systemctl start "$JMRI_SERVICE"
|
||||
echo "Layout is ON — JMRI daemon will restart when GUI is closed."
|
||||
else
|
||||
echo "Layout is OFF — JMRI daemon will not restart."
|
||||
fi
|
||||
|
||||
28
ansible/roles/jmri/templates/jmri-vnc.service.j2
Normal file
28
ansible/roles/jmri/templates/jmri-vnc.service.j2
Normal file
@@ -0,0 +1,28 @@
|
||||
[Unit]
|
||||
Description=JMRI VNC virtual display (:{{ jmri_vnc_display }})
|
||||
After=network.target
|
||||
# Start before jmri.service so the display is ready when JMRI launches
|
||||
Before=jmri.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ jmri_user }}
|
||||
Group={{ jmri_group }}
|
||||
ExecStart=/usr/bin/Xtigervnc \
|
||||
:{{ jmri_vnc_display }} \
|
||||
-rfbport {{ jmri_vnc_port }} \
|
||||
-geometry {{ jmri_vnc_geometry }} \
|
||||
-depth {{ jmri_vnc_depth }} \
|
||||
-SecurityTypes VncAuth \
|
||||
-PasswordFile {{ jmri_home }}/.vnc/passwd \
|
||||
-localhost no \
|
||||
-AlwaysShared \
|
||||
-NeverShared no \
|
||||
-AcceptKeyEvents \
|
||||
-AcceptPointerEvents \
|
||||
-desktop "JMRI"
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Reference in New Issue
Block a user