| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447 |
- ---
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: qbittorrentvpn
- namespace: plex
- spec:
- strategy:
- type: Recreate
- selector:
- matchLabels:
- app: qbittorrentvpn
- replicas: 1
- template:
- metadata:
- labels:
- app: qbittorrentvpn
- annotations:
- backup.velero.io/backup-volumes-excludes: seedbox,media,media2,data-ec,scratch
- spec:
- affinity:
- nodeAffinity:
- requiredDuringSchedulingIgnoredDuringExecution:
- nodeSelectorTerms:
- - matchExpressions:
- - key: seedbox
- operator: In
- values:
- - "true"
- containers:
- - name: qbittorrentvpn
- image: binhex/arch-qbittorrentvpn:5.1.4-1-01
- ports:
- - containerPort: 8080
- name: http-web-svc
- securityContext:
- privileged: true
- env:
- - name: DEBUG
- value: "true"
- - name: ENABLE_PRIVOXY
- value: "no"
- - name: LAN_NETWORK
- value: "172.16.69.0/24,10.42.0.0/16"
- - name: NAME_SERVERS
- value: "209.244.0.3,209.244.0.4"
- - name: PGID
- value: "1000"
- - name: PUID
- value: "1000"
- - name: STRICT_PORT_FORWARD
- value: "yes"
- - name: VPN_CLIENT
- value: "wireguard"
- - name: VPN_ENABLED
- value: "yes"
- - name: VPN_PROV
- value: "airvpn"
- - name: VPN_USER
- valueFrom:
- secretKeyRef:
- name: qbittorrentvpn
- key: VPN_USER
- - name: VPN_PASS
- valueFrom:
- secretKeyRef:
- name: qbittorrentvpn
- key: VPN_PASS
- livenessProbe:
- exec:
- command: ["curl", "--fail", "localhost:8080"]
- volumeMounts:
- - mountPath: "/media"
- name: media
- - mountPath: "/media2"
- name: media2
- - mountPath: "/dataec"
- name: data-ec
- - mountPath: "/config"
- name: config
- - mountPath: "/scratch"
- name: seedbox
- volumes:
- - name: media
- persistentVolumeClaim:
- claimName: plex-pvc
- - name: media2
- persistentVolumeClaim:
- claimName: media2-pvc
- - name: data-ec
- persistentVolumeClaim:
- claimName: data-ec-pvc
- - name: config
- persistentVolumeClaim:
- claimName: qbittorrentvpn-pvc
- - name: seedbox
- hostPath:
- path: /seedbox/torrents
- type: Directory
- ---
- apiVersion: v1
- kind: Service
- metadata:
- name: qbittorrentvpn-service
- namespace: plex
- spec:
- selector:
- app: qbittorrentvpn
- type: ClusterIP
- ports:
- - name: qbittorrentvpn-web-port
- protocol: TCP
- port: 8080
- targetPort: http-web-svc
- ---
- apiVersion: networking.k8s.io/v1
- kind: Ingress
- metadata:
- name: qbittorrentvpn
- namespace: plex
- annotations:
- traefik.ingress.kubernetes.io/router.entrypoints: websecure
- traefik.ingress.kubernetes.io/router.middlewares: kube-system-lanonly@kubernetescrd
- spec:
- rules:
- - host: qbittorrentvpn.lan.jibby.org
- http:
- paths:
- - path: /
- pathType: Prefix
- backend:
- service:
- name: qbittorrentvpn-service
- port:
- number: 8080
- ---
- apiVersion: external-secrets.io/v1
- kind: ExternalSecret
- metadata:
- name: qbittorrentvpn
- namespace: plex
- spec:
- target:
- name: qbittorrentvpn
- deletionPolicy: Delete
- template:
- type: Opaque
- data:
- VPN_USER: |-
- {{ .username }}
- VPN_PASS: |-
- {{ .password }}
- data:
- - secretKey: username
- sourceRef:
- storeRef:
- name: bitwarden-login
- kind: ClusterSecretStore
- remoteRef:
- key: 19b0020e-51d3-42eb-b78b-b1d7012d1a8a
- property: username
- - secretKey: password
- sourceRef:
- storeRef:
- name: bitwarden-login
- kind: ClusterSecretStore
- remoteRef:
- key: 19b0020e-51d3-42eb-b78b-b1d7012d1a8a
- property: password
- ---
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: qbittorrentvpn-exporter
- namespace: plex
- spec:
- strategy:
- type: Recreate
- selector:
- matchLabels:
- app: qbittorrentvpn-exporter
- replicas: 1
- template:
- metadata:
- labels:
- app: qbittorrentvpn-exporter
- spec:
- containers:
- - name: qbittorrentvpn-exporter
- image: ghcr.io/esanchezm/prometheus-qbittorrent-exporter:latest
- ports:
- - containerPort: 8000
- name: metrics
- env:
- - name: QBITTORRENT_HOST
- value: qbittorrentvpn.lan.jibby.org
- - name: QBITTORRENT_PORT
- value: "443"
- - name: QBITTORRENT_SSL
- value: "True"
- - name: QBITTORRENT_USER
- valueFrom:
- secretKeyRef:
- name: qbittorrentvpn-exporter
- key: QBITTORRENT_USER
- - name: QBITTORRENT_PASS
- valueFrom:
- secretKeyRef:
- name: qbittorrentvpn-exporter
- key: QBITTORRENT_PASS
- livenessProbe:
- exec:
- command:
- - "/bin/sh"
- - "-c"
- - 'wget -O - 0.0.0.0:8000 | grep -E "qbittorrent_up\{.* 1.0"'
- initialDelaySeconds: 3
- timeoutSeconds: 5
- periodSeconds: 3
- failureThreshold: 15
- resources:
- requests:
- memory: "0"
- limits:
- memory: "256Mi"
- ---
- apiVersion: v1
- kind: Service
- metadata:
- name: qbittorrentvpn-exporter-service
- namespace: plex
- labels:
- app: qbittorrentvpn-exporter
- spec:
- selector:
- app: qbittorrentvpn-exporter
- type: ClusterIP
- ports:
- - name: metrics
- protocol: TCP
- port: 8000
- targetPort: metrics
- ---
- apiVersion: monitoring.coreos.com/v1
- kind: PrometheusRule
- metadata:
- labels:
- prometheus: qbittorrent
- role: alert-rules
- name: prometheus-qbittorrent-rules
- namespace: plex
- spec:
- groups:
- - name: ./qbittorrent.rules
- rules:
- - alert: QbittorrentErroredTorrents
- expr: sum(qbittorrent_torrents_count{status="error"}) > 0
- ---
- apiVersion: external-secrets.io/v1
- kind: ExternalSecret
- metadata:
- name: qbittorrentvpn-exporter
- namespace: plex
- spec:
- target:
- name: qbittorrentvpn-exporter
- deletionPolicy: Delete
- template:
- type: Opaque
- data:
- QBITTORRENT_USER: |-
- {{ .username }}
- QBITTORRENT_PASS: |-
- {{ .password }}
- data:
- - secretKey: username
- sourceRef:
- storeRef:
- name: bitwarden-login
- kind: ClusterSecretStore
- remoteRef:
- key: 8dd7dfc3-800d-4af5-8a45-b23f0132806c
- property: username
- - secretKey: password
- sourceRef:
- storeRef:
- name: bitwarden-login
- kind: ClusterSecretStore
- remoteRef:
- key: 8dd7dfc3-800d-4af5-8a45-b23f0132806c
- property: password
- # Restart qbittorrentvpn reguarly. Sometimes VPN throughput slows down & a restart helps.
- #---
- #apiVersion: batch/v1
- #kind: CronJob
- #metadata:
- # name: qbittorrentvpn-restart
- # namespace: plex
- #spec:
- # schedule: "*/30 * * * *"
- # successfulJobsHistoryLimit: 1
- # failedJobsHistoryLimit: 1
- # concurrencyPolicy: Forbid
- # jobTemplate:
- # spec:
- # template:
- # metadata:
- # labels:
- # app: qbittorrentvpn-restart
- # spec:
- # serviceAccountName: qbittorrentvpn-restart-serviceaccount
- # securityContext:
- # runAsUser: 1000
- # runAsGroup: 1000
- # restartPolicy: OnFailure
- # containers:
- # - name: qbittorrentvpn-restart
- # image: python:3.14
- # command:
- # - python3
- # - -c
- # - |
- # import subprocess
- # import json
- # import pprint
- # import urllib.parse
- # import sys
- # import datetime
- #
- # # Vars to configure
- # namespace = 'plex'
- # qparams = {'labelSelector': 'app=qbittorrentvpn'}
- # max_runtime = datetime.timedelta(days=3)
- #
- # # serviceaccount/k8s specific vars. Likely don't need to edit these.
- # serviceaccount_dir = '/var/run/secrets/kubernetes.io/serviceaccount'
- # apiserver = 'https://kubernetes.default.svc'
- #
- # token = open(f'{serviceaccount_dir}/token').read()
- # result = subprocess.run([
- # 'curl',
- # '--cacert', f'{serviceaccount_dir}/ca.crt',
- # '--header', f'Authorization: Bearer {token}',
- # '-X', 'GET',
- # f'{apiserver}/api/v1/namespaces/{namespace}/pods?{urllib.parse.urlencode(qparams)}'
- # ],
- # capture_output=True,
- # check=True,
- # )
- #
- # pod_list = json.loads(result.stdout)
- # items = pod_list.get('items')
- # if items is None or len(items) < 1:
- # print(f'No pod found? Exiting. {pod_list=}')
- # sys.exit(1)
- # if len(items) > 1:
- # print(f'>1 pod? Exiting. {items=}, {len(items)=}')
- # sys.exit(1)
- #
- # pod = items[0]
- # container_statuses = pod['status']['containerStatuses']
- # if len(container_statuses) != 1:
- # print(f'len(containerStatuses) != 1? Exiting. {container_statuses=}')
- # sys.exit(1)
- # running = container_statuses[0]['state'].get('running')
- # if not running:
- # print(f'Pod not running? Exiting. {container_statuses["state"]=}')
- #
- # started_at = datetime.datetime.fromisoformat(running["startedAt"])
- # runtime = datetime.datetime.now(tz=datetime.UTC) - started_at
- # print(f'{runtime=} > {max_runtime=} ? {runtime > max_runtime}')
- # if runtime > max_runtime:
- # pod_name = pod['metadata']['name']
- # print(f'Deleting pod {pod_name}')
- # result = subprocess.run([
- # 'curl',
- # '--cacert', f'{serviceaccount_dir}/ca.crt',
- # '--header', f'Authorization: Bearer {token}',
- # '-X', 'DELETE',
- # f'{apiserver}/api/v1/namespaces/{namespace}/pods/{pod_name}'
- # ],
- # capture_output=True,
- # check=True,
- # )
- #---
- #apiVersion: v1
- #kind: ServiceAccount
- #metadata:
- # name: qbittorrentvpn-restart-serviceaccount
- # namespace: plex
- #---
- #apiVersion: rbac.authorization.k8s.io/v1
- #kind: RoleBinding
- #metadata:
- # name: qbittorrentvpn-restart-serviceaccount-edit
- # namespace: plex
- #roleRef:
- # apiGroup: rbac.authorization.k8s.io
- # kind: ClusterRole
- # name: edit
- #subjects:
- #- kind: ServiceAccount
- # name: qbittorrentvpn-restart-serviceaccount
- # namespace: plex
- # qbit_manage to auto-tag by tracker URL
- ---
- apiVersion: batch/v1
- kind: CronJob
- metadata:
- name: qbittorrentvpn-manage
- namespace: plex
- spec:
- schedule: "*/10 * * * *"
- successfulJobsHistoryLimit: 1
- failedJobsHistoryLimit: 1
- concurrencyPolicy: Forbid
- jobTemplate:
- spec:
- activeDeadlineSeconds: 60
- template:
- metadata:
- labels:
- app: qbittorrentvpn-manage
- spec:
- restartPolicy: OnFailure
- containers:
- - name: qbittorrentvpn-manage
- image: ghcr.io/stuffanthings/qbit_manage:v4.6.5@sha256:4f36632a138b4e5aeab3b765b7f389087bfb140c80dbbec1343eca74dc351245
- command:
- - python3
- - qbit_manage.py
- - "--run"
- volumeMounts:
- - name: config
- mountPath: /config/config.yml
- subPath: config.yml
- volumes:
- - name: config
- configMap:
- name: qbittorrentvpn-manage-config
- configMap:
- items:
- - key: config.yml
- path: config.yml
|