qbittorrentvpn.yaml 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  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. # qbit_manage to auto-tag by tracker URL
  293. ---
  294. apiVersion: batch/v1
  295. kind: CronJob
  296. metadata:
  297. name: qbittorrentvpn-manage
  298. namespace: plex
  299. spec:
  300. schedule: "*/10 * * * *"
  301. successfulJobsHistoryLimit: 1
  302. failedJobsHistoryLimit: 1
  303. concurrencyPolicy: Forbid
  304. jobTemplate:
  305. spec:
  306. activeDeadlineSeconds: 60
  307. template:
  308. metadata:
  309. labels:
  310. app: qbittorrentvpn-manage
  311. spec:
  312. restartPolicy: OnFailure
  313. containers:
  314. - name: qbittorrentvpn-manage
  315. image: ghcr.io/stuffanthings/qbit_manage:v4.6.5@sha256:4f36632a138b4e5aeab3b765b7f389087bfb140c80dbbec1343eca74dc351245
  316. command:
  317. - python3
  318. - qbit_manage.py
  319. - "--run"
  320. volumeMounts:
  321. - name: config
  322. mountPath: /config/config.yml
  323. subPath: config.yml
  324. volumes:
  325. - name: config
  326. secret:
  327. secretName: qbittorrentvpn-manage
  328. items:
  329. - key: config.yml
  330. path: config.yml
  331. #configMap:
  332. # name: qbittorrentvpn-manage-config
  333. # configMap:
  334. # items:
  335. # - key: config.yml
  336. # path: config.yml
  337. ---
  338. apiVersion: external-secrets.io/v1
  339. kind: ExternalSecret
  340. metadata:
  341. name: qbittorrentvpn-manage
  342. namespace: plex
  343. spec:
  344. target:
  345. name: qbittorrentvpn-manage
  346. deletionPolicy: Delete
  347. template:
  348. type: Opaque
  349. data:
  350. config.yml: |-
  351. {{ .trackertags }}
  352. qbt:
  353. host: https://qbittorrentvpn.lan.jibby.org
  354. user: {{ .username }}
  355. pass: {{ .password }}
  356. commands:
  357. recheck: false
  358. cat_update: false
  359. tag_update: true
  360. rem_unregistered: false
  361. rem_orphaned: false
  362. tag_tracker_error: false
  363. tag_nohardlinks: false
  364. share_limits: false
  365. skip_cleanup: false
  366. dry_run: false
  367. skip_qb_version_check: false
  368. # Not using any of these fields, but they're required for qbit_manage
  369. cat:
  370. tv-sonarr: Uncategorized
  371. completed: /not/using/cat
  372. recyclebin:
  373. enabled: false
  374. save_torrents: false
  375. split_by_category: false
  376. empty_after_x_days:
  377. directory:
  378. root_dir: /not/using/rootdir
  379. torrents_dir:
  380. orphaned:
  381. max_orphaned_files_to_delete: 50
  382. min_file_age_minutes: 0
  383. empty_after_x_days:
  384. exclude_patterns:
  385. settings:
  386. force_auto_tmm: false
  387. tracker_error_tag: issue
  388. nohardlinks_tag: noHL
  389. stalled_tag: stalledDL
  390. share_limits_tag: ~share_limit
  391. share_limits_min_seeding_time_tag: MinSeedTimeNotReached
  392. share_limits_min_num_seeds_tag: MinSeedsNotMet
  393. share_limits_last_active_tag: LastActiveLimitNotReached
  394. cat_filter_completed: true
  395. share_limits_filter_completed: true
  396. tag_nohardlinks_filter_completed: true
  397. rem_unregistered_filter_completed: false
  398. cat_update_all: true
  399. disable_qbt_default_share_limits: true
  400. tag_stalled_torrents: true
  401. rem_unregistered_grace_minutes: 10
  402. rem_unregistered_max_torrents: 10
  403. private_tag:
  404. force_auto_tmm_ignore_tags: []
  405. rem_unregistered_ignore_list: []
  406. webhooks:
  407. error:
  408. run_start:
  409. run_end:
  410. function:
  411. tag_tracker_error:
  412. share_limits:
  413. data:
  414. - secretKey: username
  415. sourceRef:
  416. storeRef:
  417. name: bitwarden-login
  418. kind: ClusterSecretStore
  419. remoteRef:
  420. key: 8dd7dfc3-800d-4af5-8a45-b23f0132806c
  421. property: username
  422. - secretKey: password
  423. sourceRef:
  424. storeRef:
  425. name: bitwarden-login
  426. kind: ClusterSecretStore
  427. remoteRef:
  428. key: 8dd7dfc3-800d-4af5-8a45-b23f0132806c
  429. property: password
  430. - secretKey: trackertags
  431. sourceRef:
  432. storeRef:
  433. name: bitwarden-notes
  434. kind: ClusterSecretStore
  435. remoteRef:
  436. key: 54c175aa-aa4f-4a28-a8f6-b3f80146e440
  437. # Restart qbittorrentvpn reguarly. Sometimes VPN throughput slows down & a restart helps.
  438. #---
  439. #apiVersion: batch/v1
  440. #kind: CronJob
  441. #metadata:
  442. # name: qbittorrentvpn-restart
  443. # namespace: plex
  444. #spec:
  445. # schedule: "*/30 * * * *"
  446. # successfulJobsHistoryLimit: 1
  447. # failedJobsHistoryLimit: 1
  448. # concurrencyPolicy: Forbid
  449. # jobTemplate:
  450. # spec:
  451. # template:
  452. # metadata:
  453. # labels:
  454. # app: qbittorrentvpn-restart
  455. # spec:
  456. # serviceAccountName: qbittorrentvpn-restart-serviceaccount
  457. # securityContext:
  458. # runAsUser: 1000
  459. # runAsGroup: 1000
  460. # restartPolicy: OnFailure
  461. # containers:
  462. # - name: qbittorrentvpn-restart
  463. # image: python:3.14
  464. # command:
  465. # - python3
  466. # - -c
  467. # - |
  468. # import subprocess
  469. # import json
  470. # import pprint
  471. # import urllib.parse
  472. # import sys
  473. # import datetime
  474. #
  475. # # Vars to configure
  476. # namespace = 'plex'
  477. # qparams = {'labelSelector': 'app=qbittorrentvpn'}
  478. # max_runtime = datetime.timedelta(days=3)
  479. #
  480. # # serviceaccount/k8s specific vars. Likely don't need to edit these.
  481. # serviceaccount_dir = '/var/run/secrets/kubernetes.io/serviceaccount'
  482. # apiserver = 'https://kubernetes.default.svc'
  483. #
  484. # token = open(f'{serviceaccount_dir}/token').read()
  485. # result = subprocess.run([
  486. # 'curl',
  487. # '--cacert', f'{serviceaccount_dir}/ca.crt',
  488. # '--header', f'Authorization: Bearer {token}',
  489. # '-X', 'GET',
  490. # f'{apiserver}/api/v1/namespaces/{namespace}/pods?{urllib.parse.urlencode(qparams)}'
  491. # ],
  492. # capture_output=True,
  493. # check=True,
  494. # )
  495. #
  496. # pod_list = json.loads(result.stdout)
  497. # items = pod_list.get('items')
  498. # if items is None or len(items) < 1:
  499. # print(f'No pod found? Exiting. {pod_list=}')
  500. # sys.exit(1)
  501. # if len(items) > 1:
  502. # print(f'>1 pod? Exiting. {items=}, {len(items)=}')
  503. # sys.exit(1)
  504. #
  505. # pod = items[0]
  506. # container_statuses = pod['status']['containerStatuses']
  507. # if len(container_statuses) != 1:
  508. # print(f'len(containerStatuses) != 1? Exiting. {container_statuses=}')
  509. # sys.exit(1)
  510. # running = container_statuses[0]['state'].get('running')
  511. # if not running:
  512. # print(f'Pod not running? Exiting. {container_statuses["state"]=}')
  513. #
  514. # started_at = datetime.datetime.fromisoformat(running["startedAt"])
  515. # runtime = datetime.datetime.now(tz=datetime.UTC) - started_at
  516. # print(f'{runtime=} > {max_runtime=} ? {runtime > max_runtime}')
  517. # if runtime > max_runtime:
  518. # pod_name = pod['metadata']['name']
  519. # print(f'Deleting pod {pod_name}')
  520. # result = subprocess.run([
  521. # 'curl',
  522. # '--cacert', f'{serviceaccount_dir}/ca.crt',
  523. # '--header', f'Authorization: Bearer {token}',
  524. # '-X', 'DELETE',
  525. # f'{apiserver}/api/v1/namespaces/{namespace}/pods/{pod_name}'
  526. # ],
  527. # capture_output=True,
  528. # check=True,
  529. # )
  530. #---
  531. #apiVersion: v1
  532. #kind: ServiceAccount
  533. #metadata:
  534. # name: qbittorrentvpn-restart-serviceaccount
  535. # namespace: plex
  536. #---
  537. #apiVersion: rbac.authorization.k8s.io/v1
  538. #kind: RoleBinding
  539. #metadata:
  540. # name: qbittorrentvpn-restart-serviceaccount-edit
  541. # namespace: plex
  542. #roleRef:
  543. # apiGroup: rbac.authorization.k8s.io
  544. # kind: ClusterRole
  545. # name: edit
  546. #subjects:
  547. #- kind: ServiceAccount
  548. # name: qbittorrentvpn-restart-serviceaccount
  549. # namespace: plex