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.
This commit is contained in:
9
app/serterm/schema/schema.cue
Normal file
9
app/serterm/schema/schema.cue
Normal file
@@ -0,0 +1,9 @@
|
||||
package schema
|
||||
|
||||
#SerTermSsh: {
|
||||
authorized_keys: [...string]
|
||||
}
|
||||
|
||||
#SerTerm: {
|
||||
ssh: #SerTermSsh
|
||||
}
|
||||
41
app/serterm/templates.cue
Normal file
41
app/serterm/templates.cue
Normal file
@@ -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},
|
||||
]
|
||||
}
|
||||
},
|
||||
]
|
||||
10
env/prod/serterm.cue
vendored
Normal file
10
env/prod/serterm.cue
vendored
Normal file
@@ -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
|
||||
|
||||
promtail: prod.#promtail
|
||||
|
||||
serterm: prod.serterm
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"du5t1n.me/cfg/app/collectd"
|
||||
"du5t1n.me/cfg/app/promtail"
|
||||
"du5t1n.me/cfg/app/serterm"
|
||||
"du5t1n.me/cfg/env/prod"
|
||||
)
|
||||
|
||||
@@ -12,4 +13,5 @@ render: list.Concat([
|
||||
prod.templates,
|
||||
collectd.templates,
|
||||
promtail.templates,
|
||||
serterm.templates,
|
||||
])
|
||||
|
||||
3
templates/serterm/95-serial-terminal.rules
Normal file
3
templates/serterm/95-serial-terminal.rules
Normal file
@@ -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"
|
||||
3
templates/serterm/authorized_keys
Normal file
3
templates/serterm/authorized_keys
Normal file
@@ -0,0 +1,3 @@
|
||||
{% for key in serterm.ssh.authorized_keys -%}
|
||||
{{ key }}
|
||||
{% endfor -%}
|
||||
7
templates/serterm/serial-terminal-server-window@.service
Normal file
7
templates/serterm/serial-terminal-server-window@.service
Normal file
@@ -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
|
||||
30
templates/serterm/serial-terminal-server.container
Normal file
30
templates/serterm/serial-terminal-server.container
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user