serterm: Deploy serial terminal server
The serial terminal server ("serterm") is a collection of scripts that automate launching multiple `picocom` processes, one per USB-serial adapter connected to the system. Each `picocom` process has its own window in a `tmux` session, which is accessible via SSH on a dedicated port (20022). Clients connecting to that SSH server will be automatically attached to the `tmux` session, allowing them to access the serial terminal server quickly and easily. The SSH server only allows public-key authentication, so the authorized keys have to be pre-configured. In addition to automatically launching `picocom` windows for each serial port when the terminal server starts, ports that are added (hot-plugged) while the server is running will have windows created for them automatically, by way of a udev rule. Each `picocom` process is configured to log communications with its respective serial port. This may be useful, for example, to find diagnostic messages that may not be captured by the `tmux` scrollback buffer.master
parent
9779ac795d
commit
d989994f25
|
@ -0,0 +1,9 @@
|
||||||
|
package schema
|
||||||
|
|
||||||
|
#SerTermSsh: {
|
||||||
|
authorized_keys: [...string]
|
||||||
|
}
|
||||||
|
|
||||||
|
#SerTerm: {
|
||||||
|
ssh: #SerTermSsh
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package serterm
|
||||||
|
|
||||||
|
import "du5t1n.me/cfg/base/schema/instructions"
|
||||||
|
|
||||||
|
templates: [...instructions.#RenderInstruction] & [
|
||||||
|
{
|
||||||
|
template: "serterm/authorized_keys"
|
||||||
|
dest: "/etc/serterm/authorized_keys"
|
||||||
|
hooks: {
|
||||||
|
changed: [
|
||||||
|
{run: "systemctl restart serial-terminal-server"},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
template: "serterm/95-serial-terminal.rules"
|
||||||
|
dest: "/etc/udev/rules.d/95-serial-terminal.rules"
|
||||||
|
hooks: {
|
||||||
|
changed: [{run: "udevadm control --reload"}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
template: "serterm/serial-terminal-server.container"
|
||||||
|
dest: "/etc/containers/systemd/serial-terminal-server.container"
|
||||||
|
hooks: {
|
||||||
|
changed: [
|
||||||
|
{run: "systemctl daemon-reload", immediate: true},
|
||||||
|
{run: "systemctl restart serial-terminal-server"},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
template: "serterm/serial-terminal-server-window@.service"
|
||||||
|
dest: "/etc/systemd/system/serial-terminal-server-window@.service"
|
||||||
|
hooks: {
|
||||||
|
changed: [
|
||||||
|
{run: "systemctl daemon-reload", immediate: true},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
|
@ -0,0 +1,10 @@
|
||||||
|
package prod
|
||||||
|
|
||||||
|
import "du5t1n.me/cfg/app/serterm/schema"
|
||||||
|
|
||||||
|
serterm: schema.#SerTerm
|
||||||
|
|
||||||
|
serterm: ssh: authorized_keys: [
|
||||||
|
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAINZCN2cxMDwedJ1Ke23Z3CZRcOYjqW8fFqsooRus7RK0AAAABHNzaDo= dustin@rosalina.pyrocufflink.blue",
|
||||||
|
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIAB6xTCSNz+AcQCWcyVKs84tThXN4wpLgCo2Lc48L6EsAAAABHNzaDo= dustin@luma.pyrocufflink.blue",
|
||||||
|
]
|
|
@ -8,3 +8,5 @@ ssh: prod.ssh
|
||||||
sudo: prod.sudo
|
sudo: prod.sudo
|
||||||
|
|
||||||
promtail: prod.#promtail
|
promtail: prod.#promtail
|
||||||
|
|
||||||
|
serterm: prod.serterm
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
|
|
||||||
"du5t1n.me/cfg/app/collectd"
|
"du5t1n.me/cfg/app/collectd"
|
||||||
"du5t1n.me/cfg/app/promtail"
|
"du5t1n.me/cfg/app/promtail"
|
||||||
|
"du5t1n.me/cfg/app/serterm"
|
||||||
"du5t1n.me/cfg/env/prod"
|
"du5t1n.me/cfg/env/prod"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -12,4 +13,5 @@ render: list.Concat([
|
||||||
prod.templates,
|
prod.templates,
|
||||||
collectd.templates,
|
collectd.templates,
|
||||||
promtail.templates,
|
promtail.templates,
|
||||||
|
serterm.templates,
|
||||||
])
|
])
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
# udev worker process does not have permissions/capabilities to run
|
||||||
|
# `podman exec` directly, so a systemd unit is necessary
|
||||||
|
ACTION=="add", SUBSYSTEM=="tty", SUBSYSTEMS=="usb-serial", TAG+="systemd", ENV{SYSTEMD_WANTS}+="serial-terminal-server-window@%k.service"
|
|
@ -0,0 +1,3 @@
|
||||||
|
{% for key in serterm.ssh.authorized_keys -%}
|
||||||
|
{{ key }}
|
||||||
|
{% endfor -%}
|
|
@ -0,0 +1,7 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Add serial terminal window for %I
|
||||||
|
After=serial-terminal-server.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/usr/bin/podman exec serial-terminal-server add-window /dev/%I
|
|
@ -0,0 +1,30 @@
|
||||||
|
[Unit]
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Container]
|
||||||
|
ContainerName=serial-terminal-server
|
||||||
|
Image=git.pyrocufflink.net/containerimages/serial-terminal-server
|
||||||
|
Pull=newer
|
||||||
|
ReadOnly=true
|
||||||
|
VolatileTmp=true
|
||||||
|
Volume=serial-logs:/var/log/serial:rw,z,U
|
||||||
|
Volume=serial-ssh:/etc/ssh:rw,z,U
|
||||||
|
Volume=/dev:/dev:rw
|
||||||
|
Volume=/etc/serterm/authorized_keys:/run/serial/.ssh/authorized_keys:ro,z,U
|
||||||
|
PublishPort=20022:20022
|
||||||
|
RunInit=true
|
||||||
|
# SELinux does not allow container_t access to devpts_t (for tmux)
|
||||||
|
SecurityLabelDisable=true
|
||||||
|
PodmanArgs=--device-cgroup-rule='c 188:* rw'
|
||||||
|
# This must be the GID of the "dialout" group on the host
|
||||||
|
# Using the group name would resolve the GID inside the container,
|
||||||
|
# which would not give the correct permissions.
|
||||||
|
PodmanArgs=--group-add=18
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Restart=always
|
||||||
|
RestartSec=2s
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
Loading…
Reference in New Issue