terminal: cut over to multi-session lobby on terminal.viktorbarzin.me

Promotes the staged multi-session UX from term.viktorbarzin.me to the
primary terminal.viktorbarzin.me hostname. `ttyd.service` on the DevVM
moves to the same ExecStart that `ttyd-multi.service` was running:
`/usr/local/bin/ttyd -W -a -t enableClipboard=true -I
/usr/local/share/ttyd/index.html -p 7681 /usr/local/bin/tmux-attach.sh`.
The lobby HTML supersedes the old per-user-attach index.html
(ttyd-session.sh wrapper retired alongside).

Terraform: retires the `terminal-multi` Service+Endpoints and the
term.viktorbarzin.me ingress (Cloudflare DNS record for `term` is
released by module deletion). The tmux-api Service+Endpoints stay, but
its IngressRoute now matches terminal.viktorbarzin.me — same path-prefix
specificity wins against the catch-all ingress.

DevVM follow-up (applied manually as before — see files/devvm/README.md):
restart ttyd to pick up the new unit, stop+disable ttyd-multi.service.
This commit is contained in:
Viktor Barzin 2026-05-13 16:34:11 +00:00 committed by Viktor Barzin
parent cb37db4e7e
commit e88ce131f1
5 changed files with 257 additions and 627 deletions

View file

@ -217,49 +217,15 @@ module "ingress_ro" {
}
}
# === Multi-session terminal: term.viktorbarzin.me ===
# === Multi-session lobby cutover on terminal.viktorbarzin.me ===
#
# Additive lobby UX on a fresh hostname + ports does not touch the existing
# terminal.viktorbarzin.me (7681), terminal-ro.viktorbarzin.me (7682) or
# /clipboard/* (7683) wiring above. DevVM-side units (ttyd-multi.service on
# port 7685, tmux-api.service on port 7684) ship from
# files/devvm/ see files/devvm/README.md.
# Service+Endpoints ttyd-multi on the DevVM (port 7685).
resource "kubernetes_service" "terminal_multi" {
metadata {
name = "terminal-multi"
namespace = kubernetes_namespace.terminal.metadata[0].name
labels = {
app = "terminal-multi"
}
}
spec {
port {
name = "http"
port = 80
target_port = 7685
}
}
}
resource "kubernetes_endpoints" "terminal_multi" {
metadata {
name = "terminal-multi"
namespace = kubernetes_namespace.terminal.metadata[0].name
}
subset {
address {
ip = "10.0.10.10"
}
port {
name = "http"
port = 7685
}
}
}
# The `terminal` Service+Endpoints (port 7681) above now backs the
# multi-session lobby ttyd.service on the DevVM runs tmux-attach.sh with
# `-a`, serving index.html (the lobby HTML, ex-index-multi.html). DevVM-side
# units ship from files/devvm/ see files/devvm/README.md.
#
# The lobby's REST API (`/api/sessions/*`) is reverse-proxied to a small Go
# binary on port 7684 via the IngressRoute below.
# Service+Endpoints tmux-api on the DevVM (port 7684).
resource "kubernetes_service" "tmux_api" {
@ -297,30 +263,10 @@ resource "kubernetes_endpoints" "tmux_api" {
}
}
# Public ingress for the lobby + per-session attach.
# Hostname: term.viktorbarzin.me (via `host = "term"` override).
module "ingress_multi" {
source = "../../modules/kubernetes/ingress_factory"
dns_type = "proxied"
namespace = kubernetes_namespace.terminal.metadata[0].name
name = "terminal-multi"
host = "term"
tls_secret_name = var.tls_secret_name
auth = "required"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Terminal (Multi)"
"gethomepage.dev/description" = "Multi-session tmux lobby (ttyd)"
"gethomepage.dev/icon" = "mdi-console"
"gethomepage.dev/group" = "Infrastructure"
"gethomepage.dev/pod-selector" = ""
}
}
# IngressRoute: /api/sessions/* on term.viktorbarzin.me tmux-api service.
# Path-prefixed routes beat the catch-all module ingress above by
# specificity, so the lobby HTML reaches tmux-api directly while everything
# else flows to ttyd-multi.
# IngressRoute: /api/sessions/* on terminal.viktorbarzin.me tmux-api
# service. Path-prefix specificity beats the catch-all `module.ingress`
# (terminal.viktorbarzin.me ttyd) above, so the lobby HTML reaches
# tmux-api directly while everything else flows to ttyd.
resource "kubernetes_manifest" "tmux_api_ingressroute" {
manifest = {
apiVersion = "traefik.io/v1alpha1"
@ -332,7 +278,7 @@ resource "kubernetes_manifest" "tmux_api_ingressroute" {
spec = {
entryPoints = ["websecure"]
routes = [{
match = "Host(`term.viktorbarzin.me`) && PathPrefix(`/api/sessions/`)"
match = "Host(`terminal.viktorbarzin.me`) && PathPrefix(`/api/sessions/`)"
kind = "Rule"
middlewares = [
{