qbittorrentvpn.yaml 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. ---
  2. apiVersion: apps/v1
  3. kind: Deployment
  4. metadata:
  5. name: qbittorrentvpn
  6. namespace: plex
  7. spec:
  8. strategy:
  9. type: Recreate
  10. selector:
  11. matchLabels:
  12. app: qbittorrentvpn
  13. replicas: 1
  14. template:
  15. metadata:
  16. labels:
  17. app: qbittorrentvpn
  18. annotations:
  19. backup.velero.io/backup-volumes-excludes: seedbox,media,media2,data-ec,scratch
  20. spec:
  21. affinity:
  22. nodeAffinity:
  23. requiredDuringSchedulingIgnoredDuringExecution:
  24. nodeSelectorTerms:
  25. - matchExpressions:
  26. - key: seedbox
  27. operator: In
  28. values:
  29. - "true"
  30. containers:
  31. - name: qbittorrentvpn
  32. image: binhex/arch-qbittorrentvpn:5.1.4-1-01
  33. ports:
  34. - containerPort: 8080
  35. name: http-web-svc
  36. securityContext:
  37. privileged: true
  38. env:
  39. - name: DEBUG
  40. value: "true"
  41. - name: ENABLE_PRIVOXY
  42. value: "no"
  43. - name: LAN_NETWORK
  44. value: "172.16.69.0/24,10.42.0.0/16"
  45. - name: NAME_SERVERS
  46. value: "209.244.0.3,209.244.0.4"
  47. - name: PGID
  48. value: "1000"
  49. - name: PUID
  50. value: "1000"
  51. - name: STRICT_PORT_FORWARD
  52. value: "yes"
  53. - name: VPN_CLIENT
  54. value: "wireguard"
  55. - name: VPN_ENABLED
  56. value: "yes"
  57. - name: VPN_PROV
  58. value: "airvpn"
  59. - name: VPN_USER
  60. valueFrom:
  61. secretKeyRef:
  62. name: qbittorrentvpn
  63. key: VPN_USER
  64. - name: VPN_PASS
  65. valueFrom:
  66. secretKeyRef:
  67. name: qbittorrentvpn
  68. key: VPN_PASS
  69. livenessProbe:
  70. exec:
  71. command: ["curl", "--fail", "localhost:8080"]
  72. volumeMounts:
  73. - mountPath: "/media"
  74. name: media
  75. - mountPath: "/media2"
  76. name: media2
  77. - mountPath: "/dataec"
  78. name: data-ec
  79. - mountPath: "/config"
  80. name: config
  81. - mountPath: "/scratch"
  82. name: seedbox
  83. volumes:
  84. - name: media
  85. persistentVolumeClaim:
  86. claimName: plex-pvc
  87. - name: media2
  88. persistentVolumeClaim:
  89. claimName: media2-pvc
  90. - name: data-ec
  91. persistentVolumeClaim:
  92. claimName: data-ec-pvc
  93. - name: config
  94. persistentVolumeClaim:
  95. claimName: qbittorrentvpn-pvc
  96. - name: seedbox
  97. hostPath:
  98. path: /seedbox/torrents
  99. type: Directory
  100. ---
  101. apiVersion: v1
  102. kind: Service
  103. metadata:
  104. name: qbittorrentvpn-service
  105. namespace: plex
  106. spec:
  107. selector:
  108. app: qbittorrentvpn
  109. type: ClusterIP
  110. ports:
  111. - name: qbittorrentvpn-web-port
  112. protocol: TCP
  113. port: 8080
  114. targetPort: http-web-svc
  115. ---
  116. apiVersion: networking.k8s.io/v1
  117. kind: Ingress
  118. metadata:
  119. name: qbittorrentvpn
  120. namespace: plex
  121. annotations:
  122. traefik.ingress.kubernetes.io/router.entrypoints: websecure
  123. traefik.ingress.kubernetes.io/router.middlewares: kube-system-lanonly@kubernetescrd
  124. spec:
  125. rules:
  126. - host: qbittorrentvpn.lan.jibby.org
  127. http:
  128. paths:
  129. - path: /
  130. pathType: Prefix
  131. backend:
  132. service:
  133. name: qbittorrentvpn-service
  134. port:
  135. number: 8080
  136. ---
  137. apiVersion: external-secrets.io/v1
  138. kind: ExternalSecret
  139. metadata:
  140. name: qbittorrentvpn
  141. namespace: plex
  142. spec:
  143. target:
  144. name: qbittorrentvpn
  145. deletionPolicy: Delete
  146. template:
  147. type: Opaque
  148. data:
  149. VPN_USER: |-
  150. {{ .username }}
  151. VPN_PASS: |-
  152. {{ .password }}
  153. data:
  154. - secretKey: username
  155. sourceRef:
  156. storeRef:
  157. name: bitwarden-login
  158. kind: ClusterSecretStore
  159. remoteRef:
  160. key: 19b0020e-51d3-42eb-b78b-b1d7012d1a8a
  161. property: username
  162. - secretKey: password
  163. sourceRef:
  164. storeRef:
  165. name: bitwarden-login
  166. kind: ClusterSecretStore
  167. remoteRef:
  168. key: 19b0020e-51d3-42eb-b78b-b1d7012d1a8a
  169. property: password
  170. ---
  171. apiVersion: apps/v1
  172. kind: Deployment
  173. metadata:
  174. name: qbittorrentvpn-exporter
  175. namespace: plex
  176. spec:
  177. strategy:
  178. type: Recreate
  179. selector:
  180. matchLabels:
  181. app: qbittorrentvpn-exporter
  182. replicas: 1
  183. template:
  184. metadata:
  185. labels:
  186. app: qbittorrentvpn-exporter
  187. spec:
  188. containers:
  189. - name: qbittorrentvpn-exporter
  190. image: ghcr.io/esanchezm/prometheus-qbittorrent-exporter:latest
  191. ports:
  192. - containerPort: 8000
  193. name: metrics
  194. env:
  195. - name: QBITTORRENT_HOST
  196. value: qbittorrentvpn.lan.jibby.org
  197. - name: QBITTORRENT_PORT
  198. value: "443"
  199. - name: QBITTORRENT_SSL
  200. value: "True"
  201. - name: QBITTORRENT_USER
  202. valueFrom:
  203. secretKeyRef:
  204. name: qbittorrentvpn-exporter
  205. key: QBITTORRENT_USER
  206. - name: QBITTORRENT_PASS
  207. valueFrom:
  208. secretKeyRef:
  209. name: qbittorrentvpn-exporter
  210. key: QBITTORRENT_PASS
  211. livenessProbe:
  212. exec:
  213. command:
  214. - "/bin/sh"
  215. - "-c"
  216. - 'wget -O - 0.0.0.0:8000 | grep -E "qbittorrent_up\{.* 1.0"'
  217. initialDelaySeconds: 3
  218. timeoutSeconds: 5
  219. periodSeconds: 3
  220. failureThreshold: 15
  221. resources:
  222. requests:
  223. memory: "0"
  224. limits:
  225. memory: "256Mi"
  226. ---
  227. apiVersion: v1
  228. kind: Service
  229. metadata:
  230. name: qbittorrentvpn-exporter-service
  231. namespace: plex
  232. labels:
  233. app: qbittorrentvpn-exporter
  234. spec:
  235. selector:
  236. app: qbittorrentvpn-exporter
  237. type: ClusterIP
  238. ports:
  239. - name: metrics
  240. protocol: TCP
  241. port: 8000
  242. targetPort: metrics
  243. ---
  244. apiVersion: monitoring.coreos.com/v1
  245. kind: PrometheusRule
  246. metadata:
  247. labels:
  248. prometheus: qbittorrent
  249. role: alert-rules
  250. name: prometheus-qbittorrent-rules
  251. namespace: plex
  252. spec:
  253. groups:
  254. - name: ./qbittorrent.rules
  255. rules:
  256. - alert: QbittorrentErroredTorrents
  257. expr: sum(qbittorrent_torrents_count{status="error"}) > 0
  258. ---
  259. apiVersion: external-secrets.io/v1
  260. kind: ExternalSecret
  261. metadata:
  262. name: qbittorrentvpn-exporter
  263. namespace: plex
  264. spec:
  265. target:
  266. name: qbittorrentvpn-exporter
  267. deletionPolicy: Delete
  268. template:
  269. type: Opaque
  270. data:
  271. QBITTORRENT_USER: |-
  272. {{ .username }}
  273. QBITTORRENT_PASS: |-
  274. {{ .password }}
  275. data:
  276. - secretKey: username
  277. sourceRef:
  278. storeRef:
  279. name: bitwarden-login
  280. kind: ClusterSecretStore
  281. remoteRef:
  282. key: 8dd7dfc3-800d-4af5-8a45-b23f0132806c
  283. property: username
  284. - secretKey: password
  285. sourceRef:
  286. storeRef:
  287. name: bitwarden-login
  288. kind: ClusterSecretStore
  289. remoteRef:
  290. key: 8dd7dfc3-800d-4af5-8a45-b23f0132806c
  291. property: password
  292. # Restart qbittorrentvpn reguarly. Sometimes VPN throughput slows down & a restart helps.
  293. #---
  294. #apiVersion: batch/v1
  295. #kind: CronJob
  296. #metadata:
  297. # name: qbittorrentvpn-restart
  298. # namespace: plex
  299. #spec:
  300. # schedule: "*/30 * * * *"
  301. # successfulJobsHistoryLimit: 1
  302. # failedJobsHistoryLimit: 1
  303. # concurrencyPolicy: Forbid
  304. # jobTemplate:
  305. # spec:
  306. # template:
  307. # metadata:
  308. # labels:
  309. # app: qbittorrentvpn-restart
  310. # spec:
  311. # serviceAccountName: qbittorrentvpn-restart-serviceaccount
  312. # securityContext:
  313. # runAsUser: 1000
  314. # runAsGroup: 1000
  315. # restartPolicy: OnFailure
  316. # containers:
  317. # - name: qbittorrentvpn-restart
  318. # image: python:3.14
  319. # command:
  320. # - python3
  321. # - -c
  322. # - |
  323. # import subprocess
  324. # import json
  325. # import pprint
  326. # import urllib.parse
  327. # import sys
  328. # import datetime
  329. #
  330. # # Vars to configure
  331. # namespace = 'plex'
  332. # qparams = {'labelSelector': 'app=qbittorrentvpn'}
  333. # max_runtime = datetime.timedelta(days=3)
  334. #
  335. # # serviceaccount/k8s specific vars. Likely don't need to edit these.
  336. # serviceaccount_dir = '/var/run/secrets/kubernetes.io/serviceaccount'
  337. # apiserver = 'https://kubernetes.default.svc'
  338. #
  339. # token = open(f'{serviceaccount_dir}/token').read()
  340. # result = subprocess.run([
  341. # 'curl',
  342. # '--cacert', f'{serviceaccount_dir}/ca.crt',
  343. # '--header', f'Authorization: Bearer {token}',
  344. # '-X', 'GET',
  345. # f'{apiserver}/api/v1/namespaces/{namespace}/pods?{urllib.parse.urlencode(qparams)}'
  346. # ],
  347. # capture_output=True,
  348. # check=True,
  349. # )
  350. #
  351. # pod_list = json.loads(result.stdout)
  352. # items = pod_list.get('items')
  353. # if items is None or len(items) < 1:
  354. # print(f'No pod found? Exiting. {pod_list=}')
  355. # sys.exit(1)
  356. # if len(items) > 1:
  357. # print(f'>1 pod? Exiting. {items=}, {len(items)=}')
  358. # sys.exit(1)
  359. #
  360. # pod = items[0]
  361. # container_statuses = pod['status']['containerStatuses']
  362. # if len(container_statuses) != 1:
  363. # print(f'len(containerStatuses) != 1? Exiting. {container_statuses=}')
  364. # sys.exit(1)
  365. # running = container_statuses[0]['state'].get('running')
  366. # if not running:
  367. # print(f'Pod not running? Exiting. {container_statuses["state"]=}')
  368. #
  369. # started_at = datetime.datetime.fromisoformat(running["startedAt"])
  370. # runtime = datetime.datetime.now(tz=datetime.UTC) - started_at
  371. # print(f'{runtime=} > {max_runtime=} ? {runtime > max_runtime}')
  372. # if runtime > max_runtime:
  373. # pod_name = pod['metadata']['name']
  374. # print(f'Deleting pod {pod_name}')
  375. # result = subprocess.run([
  376. # 'curl',
  377. # '--cacert', f'{serviceaccount_dir}/ca.crt',
  378. # '--header', f'Authorization: Bearer {token}',
  379. # '-X', 'DELETE',
  380. # f'{apiserver}/api/v1/namespaces/{namespace}/pods/{pod_name}'
  381. # ],
  382. # capture_output=True,
  383. # check=True,
  384. # )
  385. #---
  386. #apiVersion: v1
  387. #kind: ServiceAccount
  388. #metadata:
  389. # name: qbittorrentvpn-restart-serviceaccount
  390. # namespace: plex
  391. #---
  392. #apiVersion: rbac.authorization.k8s.io/v1
  393. #kind: RoleBinding
  394. #metadata:
  395. # name: qbittorrentvpn-restart-serviceaccount-edit
  396. # namespace: plex
  397. #roleRef:
  398. # apiGroup: rbac.authorization.k8s.io
  399. # kind: ClusterRole
  400. # name: edit
  401. #subjects:
  402. #- kind: ServiceAccount
  403. # name: qbittorrentvpn-restart-serviceaccount
  404. # namespace: plex
  405. # qbit_manage to auto-tag by tracker URL
  406. ---
  407. apiVersion: batch/v1
  408. kind: CronJob
  409. metadata:
  410. name: qbittorrentvpn-manage
  411. namespace: plex
  412. spec:
  413. schedule: "*/10 * * * *"
  414. successfulJobsHistoryLimit: 1
  415. failedJobsHistoryLimit: 1
  416. concurrencyPolicy: Forbid
  417. jobTemplate:
  418. spec:
  419. activeDeadlineSeconds: 60
  420. template:
  421. metadata:
  422. labels:
  423. app: qbittorrentvpn-manage
  424. spec:
  425. restartPolicy: OnFailure
  426. containers:
  427. - name: qbittorrentvpn-manage
  428. image: ghcr.io/stuffanthings/qbit_manage:v4.6.5@sha256:4f36632a138b4e5aeab3b765b7f389087bfb140c80dbbec1343eca74dc351245
  429. command:
  430. - python3
  431. - qbit_manage.py
  432. - "--run"
  433. volumeMounts:
  434. - name: config
  435. mountPath: /config/config.yml
  436. subPath: config.yml
  437. volumes:
  438. - name: config
  439. configMap:
  440. name: qbittorrentvpn-manage-config
  441. configMap:
  442. items:
  443. - key: config.yml
  444. path: config.yml