Deploy qBittorrent through Proton VPN

This commit is contained in:
ahmza committed 2026-11-01 13:16:14 +00:00
1 parent ef4655086f
commit b0c3d44c78
8 files changed
+247

No files matched your search

+124
View File
@@ -0,0 +1,124 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: qbittorrent
namespace: qbittorrent
spec:
# qBittorrent has one writable configuration volume and one Proton port
# forwarding lease, so upgrades replace the Pod rather than overlap two.
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: qbittorrent
template:
metadata:
labels:
app: qbittorrent
spec:
# The SOPS-managed Secret is read-only, but Hotio writes Proton's current
# forwarded port beside wg0.conf. Copy the secret into a writable emptyDir
# without ever storing the plaintext WireGuard key in Git.
initContainers:
- name: prepare-wireguard-config
image: busybox:1.37.0
command:
- sh
- -ec
- >-
cp /vpn-secret/wg0.conf /wireguard/wg0.conf &&
chmod 0600 /wireguard/wg0.conf
volumeMounts:
- name: wireguard-secret
mountPath: /vpn-secret
readOnly: true
- name: wireguard-runtime
mountPath: /wireguard
containers:
- name: qbittorrent
image: ghcr.io/hotio/qbittorrent:release
imagePullPolicy: Always
securityContext:
# Hotio needs this capability to create the WireGuard interface,
# routes, firewall rules, and VPN kill switch inside the Pod.
capabilities:
add:
- NET_ADMIN
env:
- name: PUID
value: "1000"
- name: PGID
value: "1000"
- name: UMASK
value: "002"
- name: TZ
value: Europe/London
- name: WEBUI_PORTS
value: 8080/tcp
- name: VPN_ENABLED
value: "true"
- name: VPN_CONF
value: wg0
- name: VPN_PROVIDER
value: proton
# Permit ingress-nginx and the media application Pods to reach the
# Web UI/API without allowing ordinary internet traffic to bypass
# the VPN. The LAN range is also retained for cluster-local access.
- name: VPN_LAN_NETWORK
value: 10.10.0.0/16,10.244.0.0/21
- name: VPN_LAN_LEAK_ENABLED
value: "false"
# Proton assigns a dynamic inbound port through NAT-PMP. Hotio
# renews it and updates qBittorrent's listening port automatically.
- name: VPN_AUTO_PORT_FORWARD
value: "true"
- name: VPN_HEALTHCHECK_ENABLED
value: "true"
- name: VPN_NAMESERVERS
value: wg
ports:
- name: http
containerPort: 8080
protocol: TCP
startupProbe:
httpGet:
path: /
port: http
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 36
readinessProbe:
httpGet:
path: /
port: http
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /
port: http
periodSeconds: 30
timeoutSeconds: 10
failureThreshold: 3
volumeMounts:
- name: qbittorrent-config
mountPath: /config
- name: wireguard-runtime
mountPath: /config/wireguard
- name: torrents
mountPath: /data/torrents
volumes:
- name: qbittorrent-config
persistentVolumeClaim:
claimName: qbittorrent-config
- name: wireguard-secret
secret:
secretName: qbittorrent-wireguard
- name: wireguard-runtime
emptyDir: {}
- name: torrents
nfs:
server: nas.ahmza.com
path: /srv/media/torrents
+24
View File
@@ -0,0 +1,24 @@
# Routes qbittorrent.ahmza.com through the cluster's shared ingress-nginx IP.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: qbittorrent
namespace: qbittorrent
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- qbittorrent.ahmza.com
secretName: qbittorrent-tls
rules:
- host: qbittorrent.ahmza.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: qbittorrent
port:
number: 8080
+11
View File
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Namespace
metadata:
name: qbittorrent
# NET_ADMIN is not allowed by Kubernetes' baseline Pod Security profile.
# Scope the exception to this VPN application instead of weakening the
# cluster.
labels:
pod-security.kubernetes.io/enforce: privileged
pod-security.kubernetes.io/audit: privileged
pod-security.kubernetes.io/warn: privileged
+13
View File
@@ -0,0 +1,13 @@
# qBittorrent's database and settings survive Pod replacements on Longhorn.
# Download data is stored separately on the NAS mount in deployment.yaml.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: qbittorrent-config
namespace: qbittorrent
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
+14
View File
@@ -0,0 +1,14 @@
# Only qBittorrent's management UI/API is exposed inside the cluster. Peer
# traffic uses Proton's dynamically forwarded VPN port, not this Service.
apiVersion: v1
kind: Service
metadata:
name: qbittorrent
namespace: qbittorrent
spec:
selector:
app: qbittorrent
ports:
- name: http
port: 8080
targetPort: http
+25
View File
@@ -0,0 +1,25 @@
apiVersion: isindir.github.com/v1alpha3
kind: SopsSecret
metadata:
name: qbittorrent-wireguard
namespace: qbittorrent
spec:
secretTemplates:
- name: qbittorrent-wireguard
stringData:
wg0.conf: ENC[AES256_GCM,data:0zOMbAXi6S+3v95lDxt0FbO2WPbbqmciAzjcXMQ0+yyFmX8yVaxZHwiAbSzGZn8Prn3q1FOE0WtmM7KRg+Unpa5laivSfC9AWT8f3sFjIoWk2jdzUo5uqNGSXpHEi58tgbYqPCdHkwamxycgjll6wO7lG56vJKH/Xs/1EPgqhv1PEg+X7HfDibIYK9PVgvxzZLKB8QhrJmlU9X5IFMFiWC+w3ZGMGUSXip/q5Z22XKRtbcAF9ydWlqfyeRSct2pDO4tgrS3ErCNXe5aMBErQR0DkiKBkFd8D8WL2Z1Qu2pqtOq7rMlcR7kufSk5V+5MHUNAC3hQSk4VDYnVBj3OEhdhaYrLY3uzwpYWKtD5YaiDx2wG9aC+O5qyFAPxxpQo0a6MhEFZMh78dhMzozcpLRzjlfKzjefT2dQ+egSSSVimBXCYVsHKPC5+ODqclpf6cGBWH82m0KXisIQfjAdMUSoULcFH/9ChGy+LFemyA7IkgBJ3fHTVPjC7iWGOFWF6YsCkLZcXAIIoy985ZdY5kyc/e,iv:Y31DyDiNDYtEYTRR1AKqQUtA3SvlhsrPJObJ9lwVXYE=,tag:pvuIFRYKBmjlEVXtkbA1Bw==,type:str]
sops:
age:
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBiV3VUbCtrMUFxeGd4ZVEw
STFhYTNFc0lqdlJQWVpPd3h0UWV3bS8xUG1FClM3NkZvS1g5RkFLWlNYSnVYMnBX
NEExdmNIUnNJUmhxd0tnajgyYWxXbW8KLS0tIHQrWGNMYmx4Tll4aUpTcG9pb0pj
V0NIMStWK2xlODdSVGIxZW9yVkJZR0UKVKky5FJkkGmd5QnNgZBE3Pyxi8+fo6SI
5dSXTwviUo8x/Rp6aSVrty1e1l9uDJ1fD6qagsUpXXbR7GBnpje+yg==
-----END AGE ENCRYPTED FILE-----
recipient: age1udejf5qa66rd6yvj5r8dz0fjnqfh0quf4t339c3cpqr26mkx2ydq3zel07
encrypted_regex: ^(data|stringData)$
lastmodified: "2026-11-01T13:07:18Z"
mac: ENC[AES256_GCM,data:p2x6f9Zslq+ftYjEXIGZZdAmrEPmM2vsgL4gB18RFOnmj9njNqeKCQoXu1A4+FOoEGB0PmwfPFSOo1pLk9LJRpL6F6LS4EP8r8YWwQ4NXUj92cC2Uqps/jwCGmqAbaTlIUsywtFX3SSWXWvf7HoQ2f7WeHtpz5AXGdTjFz3zL1g=,iv:b+N/yhHBHw9cYHPHEPnxbc/tEfYWdeTFNF455YavM5A=,tag:JbotWISa5AGrhWqdDpks9w==,type:str]
version: 3.13.3