feat(userbot): add Kubernetes control panel

Manage Telegram instances through Kubernetes with legacy adoption for forust and anna. Build and deploy the panel image alongside the runtime.
This commit is contained in:
2026-07-26 19:39:09 +02:00
parent 30e7d1b65f
commit 96de2d2573
39 changed files with 8188 additions and 5 deletions
+1 -3
View File
@@ -3,7 +3,5 @@ kind: Kustomization
resources:
- userbots.yaml
- common-secret.yaml
- panel.yaml
- common-config.yaml
- forust-secrets.yaml
- anna-secrets.yaml
+264
View File
@@ -0,0 +1,264 @@
apiVersion: v1
kind: Namespace
metadata:
name: userbot
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: userbot-panel
namespace: userbot
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: userbot-runtime
namespace: userbot
automountServiceAccountToken: false
---
apiVersion: v1
kind: ConfigMap
metadata:
name: userbot-common-config
namespace: userbot
data:
DATABASE_TYPE: ""
DATABASE_NAME: ""
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: userbot-panel
namespace: userbot
rules:
- apiGroups:
- apps
resources:
- deployments
verbs:
- get
- list
- watch
- create
- patch
- delete
- apiGroups:
- apps
resources:
- deployments/scale
verbs:
- get
- patch
- update
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods/log
verbs:
- get
- apiGroups:
- ""
resources:
- persistentvolumeclaims
verbs:
- get
- list
- watch
- create
- delete
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- create
- delete
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- apiGroups:
- metrics.k8s.io
resources:
- pods
verbs:
- get
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: userbot-panel
namespace: userbot
subjects:
- kind: ServiceAccount
name: userbot-panel
namespace: userbot
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: userbot-panel
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: userbot-panel-legacy
namespace: default
rules:
- apiGroups:
- apps
resources:
- deployments
verbs:
- get
- list
- watch
- patch
- apiGroups:
- apps
resources:
- deployments/scale
verbs:
- get
- patch
- update
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods/log
verbs:
- get
- apiGroups:
- ""
resources:
- persistentvolumeclaims
verbs:
- get
- list
- apiGroups:
- metrics.k8s.io
resources:
- pods
verbs:
- get
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: userbot-panel-legacy
namespace: default
subjects:
- kind: ServiceAccount
name: userbot-panel
namespace: userbot
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: userbot-panel-legacy
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: userbot-panel
namespace: userbot
labels:
app: userbot-panel
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: userbot-panel
template:
metadata:
labels:
app: userbot-panel
spec:
serviceAccountName: userbot-panel
containers:
- name: userbot-panel
image: gcr.forust.xyz/forust/userbot-panel:latest
imagePullPolicy: Always
ports:
- name: http
containerPort: 8080
env:
- name: USERBOT_NAMESPACE
value: userbot
- name: USERBOT_LEGACY_NAMESPACES
value: default
- name: USERBOT_IMAGE
value: gcr.forust.xyz/forust/userbot:latest
- name: USERBOT_STORAGE_CLASS
value: local-path-retain
- name: USERBOT_DOWNLOADS_HOST_PATH
value: /srv/homelab/userbot/Downloads
resources:
requests:
cpu: 20m
memory: 96Mi
limits:
cpu: 300m
memory: 384Mi
readinessProbe:
httpGet:
path: /api/health
port: http
initialDelaySeconds: 3
periodSeconds: 10
livenessProbe:
httpGet:
path: /api/health
port: http
initialDelaySeconds: 10
periodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
name: userbot-panel
namespace: userbot
spec:
type: ClusterIP
selector:
app: userbot-panel
ports:
- name: http
port: 8080
targetPort: http
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: userbot-panel-route
namespace: userbot
spec:
entryPoints:
- websecure
routes:
- match: Host(`userbot.workstation.internal`)
kind: Rule
services:
- name: userbot-panel
port: 8080
+30 -2
View File
@@ -4,8 +4,14 @@ metadata:
name: forust-userbot-deployment
labels:
app: forust-userbot
app.kubernetes.io/name: userbot
app.kubernetes.io/instance: forust
annotations:
userbot.forust.xyz/display-name: forust
userbot.forust.xyz/legacy: "true"
userbot.forust.xyz/credentials-secret: userbot-forust-secrets
userbot.forust.xyz/pvc: forust-pvc
spec:
replicas: 1
selector:
matchLabels:
app: forust-userbot
@@ -13,6 +19,8 @@ spec:
metadata:
labels:
app: forust-userbot
annotations:
kubectl.kubernetes.io/restartedAt: "2026-07-25T20:24:51+02:00"
spec:
containers:
- name: forust-userbot
@@ -33,6 +41,8 @@ spec:
- secretRef:
name: userbot-forust-secrets
volumeMounts:
- name: downloads
mountPath: /app/downloads
- name: forust-storage
mountPath: /app/data
subPath: data
@@ -40,6 +50,10 @@ spec:
mountPath: /app/logs
subPath: logs
volumes:
- name: downloads
hostPath:
path: /srv/homelab/userbot/Downloads
type: DirectoryOrCreate
- name: forust-storage
persistentVolumeClaim:
claimName: forust-pvc
@@ -62,8 +76,14 @@ metadata:
name: anna-userbot-deployment
labels:
app: anna-userbot
app.kubernetes.io/name: userbot
app.kubernetes.io/instance: anna
annotations:
userbot.forust.xyz/display-name: anna
userbot.forust.xyz/legacy: "true"
userbot.forust.xyz/credentials-secret: userbot-anna-secrets
userbot.forust.xyz/pvc: anna-pvc
spec:
replicas: 1
selector:
matchLabels:
app: anna-userbot
@@ -71,6 +91,8 @@ spec:
metadata:
labels:
app: anna-userbot
annotations:
kubectl.kubernetes.io/restartedAt: "2026-07-25T20:24:51+02:00"
spec:
containers:
- name: anna-userbot
@@ -91,6 +113,8 @@ spec:
- secretRef:
name: userbot-anna-secrets
volumeMounts:
- name: downloads
mountPath: /app/downloads
- name: anna-storage
mountPath: /app/data
subPath: data
@@ -98,6 +122,10 @@ spec:
mountPath: /app/logs
subPath: logs
volumes:
- name: downloads
hostPath:
path: /srv/homelab/userbot/Downloads
type: DirectoryOrCreate
- name: anna-storage
persistentVolumeClaim:
claimName: anna-pvc