diff --git a/deploy/k8s/rustdesk/rustdesk.yaml b/deploy/k8s/rustdesk/rustdesk.yaml new file mode 100644 index 0000000..4dcfa4c --- /dev/null +++ b/deploy/k8s/rustdesk/rustdesk.yaml @@ -0,0 +1,112 @@ +# RustDesk-Server (ID-Server hbbs + Relay hbbr) in k3s, Umzug vom Portainer-Stack „rustdesk“ auf appsrv08 +# (Phase 6.0, 15.10.2026). Schlüsselpaar id_ed25519 kommt aus dem Secret rustdesk-keys (legt +# playbooks/rustdesk-k3s.yml aus /root/.config/knaster/rustdesk/ auf ops an; nicht im Repo). Mit demselben +# Schlüssel bleiben die in den Clients hinterlegten Public Keys gültig. +# +# Erreichbar über Service-Typ LoadBalancer (k3s ServiceLB): Ports 21115–21119/tcp und 21116/udp auf jeder +# Knoten-Adresse. Die Clients tragen als ID-Server die Adresse ein, die das Playbook als Relay-Adresse setzt +# (rustdesk_public_host, Standard: die k3s-VM). Erst mit fester Adresse/DNS-Namen für die Clients umstellen. +apiVersion: v1 +kind: Namespace +metadata: + name: rustdesk + labels: + knaster.app: rustdesk +--- +# Datenbank (ID-Registrierungen) auf local-path: bindet den Pod an den Knoten, auf dem er zuerst lief. +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: rustdesk-data + namespace: rustdesk +spec: + accessModes: [ReadWriteOnce] + storageClassName: local-path + resources: + requests: + storage: 1Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: rustdesk + namespace: rustdesk + labels: {app: rustdesk} +spec: + replicas: 1 + strategy: {type: Recreate} # ein Datenverzeichnis, ein Pod + selector: + matchLabels: {app: rustdesk} + template: + metadata: + labels: {app: rustdesk} + spec: + nodeSelector: + knaster.gpu: "true" # nicht auf die kleine k3s-VM (2 Kerne, 3 GB) + containers: + - name: hbbs + image: rustdesk/rustdesk-server:1.1.14 + # Relay-Adresse, die hbbs den Clients nennt; setzt das Playbook (RELAY_HOST) – muss von den Clients erreichbar sein + command: ["sh", "-c", "exec hbbs -r ${RELAY_HOST}:21117 -k _"] + env: + - {name: RELAY_HOST, value: "__RELAY_HOST__"} + workingDir: /root + ports: + - {name: nat-test, containerPort: 21115, protocol: TCP} + - {name: id-tcp, containerPort: 21116, protocol: TCP} + - {name: id-udp, containerPort: 21116, protocol: UDP} + - {name: web, containerPort: 21118, protocol: TCP} + resources: + requests: {cpu: 50m, memory: 64Mi} + limits: {memory: 256Mi} + volumeMounts: + - {name: data, mountPath: /root} + - {name: keys, mountPath: /root/id_ed25519, subPath: id_ed25519, readOnly: true} + - {name: keys, mountPath: /root/id_ed25519.pub, subPath: id_ed25519.pub, readOnly: true} + readinessProbe: + tcpSocket: {port: id-tcp} + periodSeconds: 10 + livenessProbe: + tcpSocket: {port: id-tcp} + periodSeconds: 30 + failureThreshold: 3 + - name: hbbr + image: rustdesk/rustdesk-server:1.1.14 + command: ["hbbr", "-k", "_"] + workingDir: /root + ports: + - {name: relay, containerPort: 21117, protocol: TCP} + - {name: relay-web, containerPort: 21119, protocol: TCP} + resources: + requests: {cpu: 50m, memory: 64Mi} + limits: {memory: 256Mi} + volumeMounts: + - {name: keys, mountPath: /root/id_ed25519, subPath: id_ed25519, readOnly: true} + - {name: keys, mountPath: /root/id_ed25519.pub, subPath: id_ed25519.pub, readOnly: true} + readinessProbe: + tcpSocket: {port: relay} + periodSeconds: 10 + volumes: + - name: data + persistentVolumeClaim: {claimName: rustdesk-data} + - name: keys + secret: + secretName: rustdesk-keys + defaultMode: 0400 +--- +apiVersion: v1 +kind: Service +metadata: + name: rustdesk + namespace: rustdesk + labels: {app: rustdesk} +spec: + type: LoadBalancer + selector: {app: rustdesk} + ports: + - {name: nat-test, port: 21115, targetPort: 21115, protocol: TCP} + - {name: id-tcp, port: 21116, targetPort: 21116, protocol: TCP} + - {name: id-udp, port: 21116, targetPort: 21116, protocol: UDP} + - {name: relay, port: 21117, targetPort: 21117, protocol: TCP} + - {name: web, port: 21118, targetPort: 21118, protocol: TCP} + - {name: relay-web, port: 21119, targetPort: 21119, protocol: TCP} diff --git a/platform/proxmox/ansible/playbooks/rustdesk-k3s.yml b/platform/proxmox/ansible/playbooks/rustdesk-k3s.yml new file mode 100644 index 0000000..61242d0 --- /dev/null +++ b/platform/proxmox/ansible/playbooks/rustdesk-k3s.yml @@ -0,0 +1,71 @@ +# RustDesk-Server (hbbs/hbbr) in k3s, Umzug vom Portainer-Stack „rustdesk“ auf appsrv08 (15.10.2026). +# Läuft auf ops: ansible-playbook playbooks/rustdesk-k3s.yml [-e rustdesk_public_host=] +# +# Voraussetzung: Schlüsselpaar des bisherigen Servers unter /root/.config/knaster/rustdesk/{id_ed25519,id_ed25519.pub} +# auf ops (aus dem Docker-Volume rustdesk_rustdesk-data von appsrv08, Pfad /root). Damit bleiben die in den +# Clients hinterlegten Public Keys gültig. Die Clients selbst zeigen weiter auf appsrv08, bis ihre +# Server-Adresse umgestellt wird (Installer-Name im Stack rustdesk-updater und bestehende Installationen). +- name: RustDesk nach k3s + hosts: localhost + connection: local + gather_facts: false + vars: + manifest: "{{ playbook_dir }}/../../../../deploy/k8s/rustdesk/rustdesk.yaml" + key_dir: /root/.config/knaster/rustdesk + # Adresse, die hbbs den Clients als Relay nennt (Port 21117). Standard: die k3s-VM; ServiceLB stellt die Ports + # auf jeder Knoten-Adresse bereit. Nach DHCP-Reservierung/DNS-Name hier bzw. per -e anpassen. + rustdesk_public_host: "{{ hostvars['k3s'].ansible_host }}" + tasks: + - name: Schlüsseldateien vorhanden? + ansible.builtin.stat: + path: "{{ key_dir }}/{{ item }}" + loop: [id_ed25519, id_ed25519.pub] + register: keys + failed_when: not keys.stat.exists + + - name: Namespace + ansible.builtin.shell: > + kubectl create namespace rustdesk --dry-run=client -o yaml | kubectl apply -f - + register: ns + changed_when: "'created' in ns.stdout" + + - name: Secret rustdesk-keys aus den Schlüsseldateien + ansible.builtin.shell: > + kubectl -n rustdesk create secret generic rustdesk-keys + --from-file=id_ed25519={{ key_dir }}/id_ed25519 --from-file=id_ed25519.pub={{ key_dir }}/id_ed25519.pub + --dry-run=client -o yaml | kubectl apply -f - + register: secret + changed_when: "'configured' in secret.stdout or 'created' in secret.stdout" + no_log: true + + - name: Manifest mit Relay-Adresse anwenden + ansible.builtin.shell: > + sed 's/__RELAY_HOST__/{{ rustdesk_public_host }}/' {{ manifest }} | kubectl apply -f - + register: dep + changed_when: "'configured' in dep.stdout or 'created' in dep.stdout" + + - name: Neustart, wenn sich nur das Secret geändert hat + ansible.builtin.command: kubectl -n rustdesk rollout restart deployment/rustdesk + when: secret.changed and not dep.changed + + - name: Warten, bis bereit + ansible.builtin.command: kubectl -n rustdesk rollout status deployment/rustdesk --timeout=300s + changed_when: false + + - name: Public Key im Cluster entspricht der Datei + ansible.builtin.shell: > + set -o pipefail; + kubectl -n rustdesk exec deploy/rustdesk -c hbbs -- cat /root/id_ed25519.pub | tr -d '\n' | cmp - <(tr -d '\n' < {{ key_dir }}/id_ed25519.pub) + args: {executable: /bin/bash} + changed_when: false + + - name: Ports von außen erreichbar (ID-Server 21116/tcp, Relay 21117/tcp auf {{ rustdesk_public_host }}) + ansible.builtin.wait_for: + host: "{{ rustdesk_public_host }}" + port: "{{ item }}" + timeout: 30 + loop: [21115, 21116, 21117, 21118, 21119] + + - name: Ergebnis + ansible.builtin.debug: + msg: "RustDesk in k3s bereit: ID-Server/Relay {{ rustdesk_public_host }}, Public Key {{ lookup('file', key_dir + '/id_ed25519.pub') }}"