r/serterm: Deploy serial terminal multiplexer

Using `tmux`, we can spawn a bunch of `picocom` processes for the serial
ports connected to other server's console ports.  The
_serial-terminal-server_ service manages the `tmux` server process,
while the individual _serial-terminal-server-window@.service_ units
create a window in the `tmux` session.

The serial terminal server runs as a dedicated user.  The SSH server is
configured to force this user to connect to the `tmux` session.  This
should help ensure the serial consoles are accessible, even if the
Active Directory server is unavailable.
dynamic-inventory
Dustin 2024-11-07 21:36:07 -06:00
parent 8b9cf1985a
commit 6115762847
16 changed files with 280 additions and 0 deletions

View File

@ -0,0 +1,2 @@
serterm_static_windows: []
serterm_authorized_keys: []

View File

@ -0,0 +1,6 @@
#!/bin/sh
# vim: set sw=4 ts=4 sts=4 et :
port="$1"
exec tmux new-window -a -t 'serial:{end}' -n "${port##*/}" /usr/local/libexec/serterm/connect-serial /dev/"${port}"

View File

@ -0,0 +1,8 @@
#!/bin/sh
# vim: set sw=4 ts=4 sts=4 et :
: "${LOG_DIR:=/var/log/serial}"
port="$1"
exec picocom -b 115200 -g "${LOG_DIR%/}"/"${port##*/}".log "${port}"

View File

@ -0,0 +1,6 @@
#!/bin/sh
# vim: set sw=4 ts=4 sts=4 et :
port="$1"
exec tmux kill-window -t "${port##*/}"

View File

@ -0,0 +1,16 @@
# vim: set ft=systemd :
[Unit]
Description=Add serial terminal window for %I
Requires=serial-terminal-server.service
After=serial-terminal-server.service
[Service]
Type=oneshot
ExecStart=/usr/local/libexec/serterm/add-window %I
ExecStop=/usr/local/libexec/serterm/remove-window %I
RemainAfterExit=yes
User=serterm
Group=serterm
[Install]
WantedBy=serial-terminal-server.service

View File

@ -0,0 +1,14 @@
# vim: set ft=systemd :
[Unit]
Description=Serial Terminal
[Service]
Type=forking
ExecStart=/usr/local/libexec/serterm/start-server
User=serterm
Group=serterm
Restart=always
RestartSec=1s
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,16 @@
#!/bin/sh
# vim: set sw=4 ts=4 sts=4 et :
if [ -z "${TMUX}" ]; then
exec tmux new-session -s serial -d "$0"
fi
tmux \
set-option -t serial:0 -w remain-on-exit on \; \
rename-window -t serial:0 info
cat <<'EOF'
This window must remain open to keep the tmux server/session running.
If all windows are closed, tmux will exit and will not be able to
receive commands to add new windows for hotplugged devices.
EOF

View File

@ -0,0 +1,18 @@
#!/bin/sh
# vim: set sw=4 ts=4 sts=4 et :
if [ -z "${TMUX}" ]; then
exec tmux new-session -s serial -d "$0"
fi
tmux \
set-option -t serial:0 -w remain-on-exit on \; \
rename-window -t serial:0 info
cat <<'EOF'
This window must remain open to keep the tmux server/session running.
If all windows are closed, tmux will exit and will not be able to
receive commands to add new windows for hotplugged devices.
Use `respawn-window` to restart all serial terminal windows.
EOF

View File

@ -0,0 +1,18 @@
#!/bin/sh
# vim: set sw=4 ts=4 sts=4 et :
if [ -z "${TMUX}" ]; then
exec tmux new-session -s serial -d "$0"
fi
tmux \
set-option -t serial:0 -w remain-on-exit on \; \
rename-window -t serial:0 info
cat <<'EOF'
This window must remain open to keep the tmux server/session running.
If all windows are closed, tmux will exit and will not be able to
receive commands to add new windows for hotplugged devices.
Use `respawn-window` to restart all serial terminal windows.
EOF

View File

@ -0,0 +1,9 @@
- name: restart serial-terminal-server
service:
name: serial-terminal-server
state: restarted
- name: reload sshd
service:
name: sshd
state: reloaded

View File

@ -0,0 +1,2 @@
dependencies:
- systemd-base

View File

@ -0,0 +1,153 @@
- name: ensure serial terminal packages are instaled
package:
name:
- picocom
- tmux
state: present
tags:
- install
- name: ensure serterm group exists
group:
name: serterm
state: present
tags:
- group
- user
- name: ensure serterm user exists
user:
name: serterm
create_home: false
home: /
group: serterm
groups:
- dialout
state: present
tags:
- user
- name: ensure serial log directory exists
file:
path: /var/log/serial
owner: root
group: serterm
mode: ug=rwx,o=
state: directory
tags:
- logs
- name: ensure serterm configuration directory exists
file:
path: /etc/serterm
owner: root
group: root
mode: u=rwx,go=rx
state: directory
tags:
- config
- name: ensure serterm is configured
template:
src: tmux.conf.j2
dest: /etc/serterm/tmux.conf
owner: root
group: root
mode: u=rw,go=r
tags:
- config
- name: ensure serterm script directory exists
file:
path: /usr/local/libexec/serterm
owner: root
group: root
mode: u=rwx,go=rx
state: directory
tags:
- script
- name: ensure serterm scripts are installed
copy:
src: '{{ item }}.sh'
dest: /usr/local/libexec/serterm/{{ item }}
mode: u=rwx,go=rx
owner: root
group: root
loop:
- add-window
- connect-serial
- remove-window
- start-server
notify:
- restart serial-terminal-server
- name: ensure serterm systemd units are installed
copy:
src: '{{ item }}'
dest: /etc/systemd/system/
mode: u=rw,go=r
owner: root
group: root
notify:
- reload systemd
- restart serial-terminal-server
loop:
- serial-terminal-server.service
- serial-terminal-server-window@.service
tags:
- systemd
- name: ensure serial-terminal-server is enabled
service:
name: serial-terminal-server
enabled: true
tags:
- service
- name: ensure static serial-terminal-server-window units are enabled
service:
name: serial-terminal-server-window@{{ item }}
enabled: true
loop: '{{ serterm_static_windows }}'
tags:
- service
- name: flush handlers
meta: flush_handlers
tags:
- always
- name: ensure serial-terminal-server is running
service:
name: serial-terminal-server
state: started
tags:
- service
- name: ensure static serial-terminal-server-window units are started
service:
name: serial-terminal-server-window@{{ item }}
state: started
loop: '{{ serterm_static_windows }}'
tags:
- service
- name: ensure serterm user ssh keys are authorized
template:
src: authorized_keys.j2
dest: /etc/serterm/authorized_keys
owner: root
group: root
mode: u=rw,go=r
tags:
- ssh
- authorized_keys
- name: ensure sshd is configured for serterm
template:
src: sshd_config.j2
dest: /etc/ssh/sshd_config.d/80-serterm.conf
owner: root
group: root
mode: u=rw,go=r
notify:
- reload sshd
tags:
- ssh
- sshd_config

View File

@ -0,0 +1,3 @@
{% for key in serterm_authorized_keys %}
{{ key }}
{% endfor %}

View File

@ -0,0 +1,3 @@
Match user serterm
ForceCommand tmux attach
AuthorizedKeysFile /etc/serterm/authorized_keys

View File

@ -0,0 +1 @@
set -g remain-on-exit on

5
serterm.yml Normal file
View File

@ -0,0 +1,5 @@
- hosts: serterm
roles:
- role: serterm
tags:
- serterm