Kubernetes qBitTorrentWebUI showing only on path '/' - nginx

I am trying to host a qBitTorrent server with Kubernetes. I have composed a YAML for the https://hub.docker.com/r/linuxserver/qbittorrent docker container.
The problem is that it is accessible only from path /. As soon as I move it to /torrent it does not find it anymore: 404 Not Found.
Steps to replicate:
apply following yamls
helm install nginx ingress-nginx/ingress-nginx
go to service_ip:8080, settings, WebUI, uncheck "Enable Host header validation"
go to localhost:nginx_port/torrent
Result:
page not loading
Expected Result:
qBitTorrent WebUi appears and works
What I tried:
adding nginx.ingress.kubernetes.io/rewrite-target: / to annotations
server.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: torrent-deployment
labels:
app: torrent
spec:
replicas: 1
selector:
matchLabels:
pod-label: torrent-pod
template:
metadata:
labels:
pod-label: torrent-pod
spec:
containers:
- name: linuxserver
image: linuxserver/qbittorrent:amd64-latest
---
apiVersion: v1
kind: Service
metadata:
name: torrent-service
labels:
app: torrent
spec:
selector:
pod-label: torrent-pod
ports:
- port: 8080
name: torrent-deployment
ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: torrent-ingress
annotations:
kubernetes.io/ingress.class: nginx
labels:
app: torrent
spec:
rules:
- http:
paths:
- path: /torrent
pathType: Prefix
backend:
service:
name: torrent-service
port:
number: 8080

Thanks to #matt_j I have found a workaround. I wrote and YAML for nginx myself and added the configurations from the post mentioned by matt ( https://github.com/qbittorrent/qBittorrent/wiki/NGINX-Reverse-Proxy-for-Web-UI ) and it worked.
These are the YAMLs I came up with:
server.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
namespace: nginx
spec:
selector:
matchLabels:
pod-label: nginx
template:
metadata:
labels:
pod-label: nginx
spec:
containers:
- name: nginx
image: nginx:latest
volumeMounts:
- name: nginx-conf
mountPath: /etc/nginx/
volumes:
- name: nginx-conf
configMap:
name: nginx-conf
items:
- key: nginx.conf
path: nginx.conf
replicas: 1
# status:
---
apiVersion: v1
kind: Service
metadata:
namespace: nginx
name: nginx
labels:
app: nginx
spec:
selector:
pod-label: nginx
ports:
- port: 80
name: nginx
config.yaml:
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-conf
namespace: nginx
data:
nginx.conf: |
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
http {
server {
server_name 10.152.183.95;
listen 80;
location /torrent/ {
proxy_pass http://torrent-service.qbittorrent:8080/;
#proxy_http_version 1.1;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
#proxy_cookie_path / "/; Secure";
}
}
}
events {
worker_connections 1024;
}

Related

Nginx 503 ingress controller k8s

I have an application running on nginx port 9000, and a service attached to it. If I put service as a LoadBalancer, I can open IP:PORT/app/pages in my browser (ClusterIP and NodePort with nginx doesn't work). Created Ingress controller with ALB, and A record to point to app.mydomain.com, but I keep getting 503 or 404 errors, even 400 sometimes (tried couple of ports/paths etc). Can someone point me to what should I look at? I want to be able to open https://app.mydomain.com/app/pages. cert-manager is complaining with 400 errors also when retrieving the certificate.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-app-dev
namespace: app-dev
annotations:
cert-manager.io/issuer: letsencrypt-nginx
ingress.kubernetes.io/rewrite-target: /
# ingressclass.kubernetes.io/is-default-class: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- app.mydomain.com
secretName: letsencrypt-nginx
rules:
- host: app.mydomain.com
http:
paths:
- pathType: Prefix
backend:
service:
name: app-service
port:
number: 8080
path: /
apiVersion: v1
kind: Service
metadata:
name: app-service
namespace: app-dev
spec:
type: LoadBalancer
ports:
- port: 9090
protocol: TCP
targetPort: 8080
selector:
app: app
IP of Ingress is added as a A record to DNS (app.mydomain.com). This is my nginx conf in the docker image
bash-5.1# cat /etc/nginx/conf.d/default.conf
server {
listen 8080 ssl;
ssl_certificate /ssl/cert;
ssl_certificate_key /ssl/key;
location / {
root /www;
autoindex off;
add_header 'Access-Control-Allow-Origin' '*';
}
location /healthz {
return 200 'ok';
}
}

Proxy Passing to Kubernetes Cluster IP

I have a Kubernetes cluster that's running a API Server deployment and a Nginx deployment. I exposed the Server with a ClusterIP service so the Nginx pods can route to it with a proxy pass then I externalize the nginx pods with a LoadBalancer service. But it's not working. What am I misunderstanding? I get a 404 not found for LOAD_BALANCER_IP/api
Server Deployment:
apiVersion: v1
kind: Service
metadata:
name: league-pool-production-server-service
spec:
type: ClusterIP
selector:
app: league-pool-server
ports:
- protocol: TCP
port: 80
targetPort: 3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: league-pool-server-deployment
spec:
replicas: 3
selector:
matchLabels:
app: league-pool-server
template:
metadata:
labels:
app: league-pool-server
spec:
containers:
- name: league-pool-server-container
image: helloitsian/league-pool-server
ports:
- containerPort: 3000
env:
- name: MONGO_URL
value: mongodb://mongo-0.mongo,mongo-1.mongo,mongo-2.mongo:27017/player-pools
imagePullPolicy: Always
Nginx Deployment:
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: league-pool-nginx-deployment
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: league-pool-nginx-deployment
minReplicas: 2
maxReplicas: 5
metrics:
- type: Resource
resource:
name: cpu
targetAverageUtilization: 80
---
apiVersion: v1
kind: Service
metadata:
name: league-pool-nginx-service
spec:
type: LoadBalancer
externalTrafficPolicy: Local
selector:
app: league-pool-nginx-production
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
- name: https
protocol: TCP
port: 443
targetPort: 443
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: league-pool-nginx-deployment
labels:
app: league-pool-nginx-production
spec:
replicas: 1
selector:
matchLabels:
app: league-pool-nginx-production
template:
metadata:
labels:
app: league-pool-nginx-production
spec:
containers:
- name: league-pool-nginx-production
image: helloitsian/league-pool-nginx
imagePullPolicy: Always
resources:
limits:
cpu: 300m
requests:
cpu: 100m
memory: 200Mi
ports:
- containerPort: 443
- containerPort: 80
Nginx site conf:
server {
listen 80;
root /usr/share/nginx/html;
location / {
try_files $uri $uri/ =404;
}
location /api {
proxy_pass http://league-pool-server;
}
}

How can I define the `limit_req_zone`?

I am working with nginx-ingress-controller (this is not the same that ingress-nginx )
I have this ingress file
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-test"
acme.cert-manager.io/http01-edit-in-place: "true"
nginx.org/location-snippets: |
limit_req zone=by_web;
spec:
ingressClassName: nginx
rules:
- host: my.domain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80
tls:
- hosts:
- my.domain.com
secretName: quickstart-example-tls
I was able to define a limit_req using nginx.org/location-snippets.
How can I define the limit_req_zone?
limit_req_zone $request_uri zone=by_web:10m rate=60r/m;
Regards.
According to this article from official documentation, you can define limit_req_zone by adding following ConfigMap keys to location-snippets and server-snippets annotations:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-test"
acme.cert-manager.io/http01-edit-in-place: "true"
nginx.org/location-snippets: |
geo $limit {
default 1;
10.0.0.0/8 0;
192.168.0.0/24 0;
}
map $limit $request_uri {
default '';
'1' $binary_remote_addr;
}
limit_req_zone $request_uri zone=by_web:10m rate=1r/s;
nginx.org/server-snippets: |
location / {
limit_req zone=by_web burst=10 nodelay;
}
spec:
ingressClassName: nginx
rules:
- host: my.domain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80
tls:
- hosts:
- my.domain.com
secretName: quickstart-example-tls
So this will let you rate limit to be defined on requests from anyone who is not on an “allowlist”

Nginx ingress kubernetes Proxy Pass

I need configure a proxy pass in a nginx ingress.
The rule must be:
%USER%.test.domain.com to app.test.domain.com/%USER%
*It must be a proxy pass NOT a redirect
I created this Ingress but it does not work
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test02-ingress
annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: 'true'
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/server-snippet: |
server_name ~^(?<subdomain>.+)\.test\.domain\.it;
location = / {
proxy_pass https://app.test.domain.it/$subdomain/;
proxy_set_header Host $subdomain.test.domain.it;
}
spec:
rules:
- host: "*.test.domain.it"
http:
paths:
- path: /
backend:
serviceName: test01-svc
servicePort: 80
``

Is there a point of having pod-level nginx when using nginx ingress?

I was wondering if I should have the pod level nginx in the implementations below:
I was previously using a normal ingress and kube-lego after migrating from VMs and now I am using cert-manager and GKE.
My Ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: myapp-static-ip
kubernetes.io/ingress.class: nginx
kubernetes.io/ingress.allow-http: "false"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
ingress.kubernetes.io/rewrite-target: /
certmanager.k8s.io/cluster-issuer: letsencrypt
namespace: default
spec:
tls:
- hosts:
- myapp.com
secretName: myapp-crt
rules:
- host:
http:
paths:
- path: /
backend:
serviceName: myapp
servicePort: http
My service:
apiVersion: v1
kind: Service
metadata:
name: myapp
labels:
app: myapp
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 32111
protocol: "TCP"
name: http
selector:
app: myapp
My Deployment
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: myapp
labels:
app: myapp
spec:
replicas: 3
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: gcr.io/myapp-1/myapp:latest
imagePullPolicy: Always
env:
- name: DB_USER
valueFrom:
secretKeyRef:
name: cloudsql
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: cloudsql
key: password
-
name: STATIC_ROOT
value: https://storage.googleapis.com/myapp-api/static/
-
name: STATIC_URL
value: https://storage.googleapis.com/myapp-api/static/
-
name: MEDIA_ROOT
value: /myapp/media
-
name: MEDIA_URL
value: http://myapp.com/media/
-
name: nginx
image: nginx
command: [nginx, -g,'daemon off;']
imagePullPolicy: Always
volumeMounts:
-
name: api-nginx-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
-
name: myapp-media
mountPath: /myapp/media/
ports:
- containerPort: 80
- image: b.gcr.io/cloudsql-docker/gce-proxy:1.05
name: cloudsql-proxy
command: ["/cloud_sql_proxy", "--dir=/cloudsql",
"-instances=myapp-1:europe-west1:myapp-api=tcp:5432",
"-credential_file=/secrets/cloudsql/credentials.json"]
volumeMounts:
- name: cloudsql-oauth-credentials
mountPath: /secrets/cloudsql
readOnly: true
- name: ssl-certs
mountPath: /etc/ssl/certs
- name: cloudsql
mountPath: /cloudsql
- name: myapp-media
mountPath: /myapp/media
volumes:
- name: cloudsql-oauth-credentials
secret:
secretName: cloudsql-oauth-credentials
- name: cloudsql
emptyDir:
- name: api-nginx-config
configMap:
name: api-nginx-config
-
name: myapp-media
persistentVolumeClaim:
claimName: myapp-media
my nginx conf:
apiVersion: v1
kind: ConfigMap
metadata:
name: api-nginx-config
data:
nginx.conf: |
events {
worker_connections 1024;
}
http {
upstream api {
server 127.0.0.1:8080 fail_timeout=0;
}
server {
access_log /var/log/nginx/http-access.log;
error_log /var/log/nginx/http-error.log;
listen 80;
listen [::]:80;
server_name myapp.com;
location /media/ {
alias /myapp/media;
}
location = /favicon.ico {
access_log off;
log_not_found off;
}
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://127.0.0.1:8080/;
}
}
}
Is it serving any major purpose given I could directly map the myapp/media directly to /media in the volume mount and my tls is handled by ingress. My major concern is with the pod-level nginx as I highlighted earlier, is it useless in this case? Is it just a baggage I am carrying over from previous implementations?
Generally, there is not really a point to have an extra nginx pod. If you do, you would have something of a double ingress. An nginx ingress controller pod already has nginx in it and you can scale that up/down.
One reason you would want to keep it is for backward compatibility, if for example, you want to use an ingress but want to gradually roll it out in this sort of fashion: create new nginx ingress -> flip traffic from your own nginx only through the new nginx ingress and your own nginx, until you have flipped all your pods -> remove your own nginx gradually until you have removed them all.
Another reason is to support a very specific nginx configuration that is not supported by the nginx ingress controller yet.
You may need to run your own nginx as deployment , for the reasons listed in the above answer , plus , you may need to scale the nginx deployment , let say 10 replicas. you cant scale ingress like that. But in any case , you just need one of them.

Resources