feat(terminal): add clipboard paste support for text and images

- Custom index.html with xterm.js for reliable Ctrl+V text paste
- Go clipboard-upload service saves pasted images to /tmp/clipboard-images/
- Traefik IngressRoute routes /clipboard/* to upload service (same-origin)
- Authentik-protected upload path with strip-prefix middleware
This commit is contained in:
Viktor Barzin 2026-04-06 16:57:18 +03:00
parent cbed5423ec
commit 15e45b95a9
4 changed files with 416 additions and 0 deletions

View file

@ -107,6 +107,94 @@ resource "kubernetes_endpoints" "terminal_ro" {
}
}
# Clipboard image upload service (same-origin path routing)
resource "kubernetes_service" "clipboard_upload" {
metadata {
name = "clipboard-upload"
namespace = kubernetes_namespace.terminal.metadata[0].name
labels = {
app = "clipboard-upload"
}
}
spec {
port {
name = "http"
port = 80
target_port = 7683
}
}
}
resource "kubernetes_endpoints" "clipboard_upload" {
metadata {
name = "clipboard-upload"
namespace = kubernetes_namespace.terminal.metadata[0].name
}
subset {
address {
ip = "10.0.10.10"
}
port {
name = "http"
port = 7683
}
}
}
# IngressRoute for /clipboard/* on terminal.viktorbarzin.me clipboard-upload service
resource "kubernetes_manifest" "clipboard_ingressroute" {
manifest = {
apiVersion = "traefik.io/v1alpha1"
kind = "IngressRoute"
metadata = {
name = "clipboard-upload"
namespace = kubernetes_namespace.terminal.metadata[0].name
}
spec = {
entryPoints = ["websecure"]
routes = [{
match = "Host(`terminal.viktorbarzin.me`) && PathPrefix(`/clipboard/`)"
kind = "Rule"
middlewares = [
{
name = "authentik-forward-auth"
namespace = "traefik"
},
{
name = "clipboard-strip-prefix"
namespace = kubernetes_namespace.terminal.metadata[0].name
}
]
services = [{
name = "clipboard-upload"
port = 80
}]
}]
tls = {
secretName = var.tls_secret_name
}
}
}
}
resource "kubernetes_manifest" "clipboard_strip_prefix" {
manifest = {
apiVersion = "traefik.io/v1alpha1"
kind = "Middleware"
metadata = {
name = "clipboard-strip-prefix"
namespace = kubernetes_namespace.terminal.metadata[0].name
}
spec = {
stripPrefix = {
prefixes = ["/clipboard"]
}
}
}
}
module "ingress_ro" {
source = "../../modules/kubernetes/ingress_factory"
namespace = kubernetes_namespace.terminal.metadata[0].name