diff --git a/k8s/celery-beat/deployment.yml b/k8s/celery-beat/deployment.yml new file mode 100644 index 000000000..eb403dff9 --- /dev/null +++ b/k8s/celery-beat/deployment.yml @@ -0,0 +1,79 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: celery-beat +spec: + replicas: 1 + selector: + matchLabels: + app: celery-beat + template: + metadata: + labels: + app: celery-beat + spec: + containers: + - name: celery-beat + image: ghcr.io/0xtejas/rengine/celery-beat:latest + command: ["celery", "-A", "reNgine", "beat", "-l", "INFO", "--scheduler", "django_celery_beat.schedulers:DatabaseScheduler"] + env: + - name: CELERY_BROKER + value: redis://redis:6379/0 + - name: CELERY_BACKEND + value: redis://redis:6379/0 + - name: POSTGRES_DB + valueFrom: + secretKeyRef: + name: db-secret + key: POSTGRES_DB + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: db-secret + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: db-secret + key: POSTGRES_PASSWORD + - name: POSTGRES_HOST + value: db # Name of the PostgreSQL service + - name: POSTGRES_PORT + value: "5432" + volumeMounts: + - name: github-repos + mountPath: /usr/src/github + - name: wordlist + mountPath: /usr/src/wordlist + - name: scan-results + mountPath: /usr/src/scan_results + - name: gf-patterns + mountPath: /root/.gf + - name: nuclei-templates + mountPath: /root/nuclei-templates + - name: tool-config + mountPath: /root/.config + - name: shared-data + mountPath: /usr/src/app + volumes: + - name: github-repos + persistentVolumeClaim: + claimName: github-repos-pvc + - name: wordlist + persistentVolumeClaim: + claimName: wordlist-pvc + - name: scan-results + persistentVolumeClaim: + claimName: scan-results-pvc + - name: gf-patterns + persistentVolumeClaim: + claimName: gf-patterns-pvc + - name: nuclei-templates + persistentVolumeClaim: + claimName: nuclei-templates-pvc + - name: tool-config + persistentVolumeClaim: + claimName: tool-config-pvc + - name: shared-data + persistentVolumeClaim: + claimName: shared-data-pvc \ No newline at end of file diff --git a/k8s/celery-beat/pvc.yml b/k8s/celery-beat/pvc.yml new file mode 100644 index 000000000..a09a0362f --- /dev/null +++ b/k8s/celery-beat/pvc.yml @@ -0,0 +1,65 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: github-repos-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: wordlist-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: scan-results-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: gf-patterns-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: nuclei-templates-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: tool-config-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi diff --git a/k8s/celery-beat/service.yml b/k8s/celery-beat/service.yml new file mode 100644 index 000000000..5ae0621a6 --- /dev/null +++ b/k8s/celery-beat/service.yml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: celery-beat +spec: + selector: + app: celery-beat + ports: + - protocol: TCP + port: 5672 # Default Celery port (adjust as necessary) + targetPort: 5672 + type: ClusterIP # Change to NodePort or LoadBalancer if needed diff --git a/k8s/celery/celery-config.yml b/k8s/celery/celery-config.yml new file mode 100644 index 000000000..ffba68267 --- /dev/null +++ b/k8s/celery/celery-config.yml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: celery-config +data: + MAX_CONCURRENCY: "10" + MIN_CONCURRENCY: "1" diff --git a/k8s/celery/deployment.yml b/k8s/celery/deployment.yml new file mode 100644 index 000000000..ab9db017b --- /dev/null +++ b/k8s/celery/deployment.yml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: celery +spec: + replicas: 1 + selector: + matchLabels: + app: celery + template: + metadata: + labels: + app: celery + spec: + containers: + - name: celery + image: ghcr.io/0xtejas/rengine/celery:latest + command: ["/bin/bash", "-c", "/usr/src/app/celery-entrypoint.sh"] + env: + - name: DEBUG + value: "0" + - name: CELERY_BROKER + value: redis://redis:6379/0 + - name: CELERY_BACKEND + value: redis://redis:6379/0 + - name: DOMAIN_NAME + valueFrom: + secretKeyRef: + name: db-secret + key: DOMAIN_NAME + - name: POSTGRES_DB + valueFrom: + secretKeyRef: + name: db-secret + key: POSTGRES_DB + - name: POSTGRES_PORT + valueFrom: + secretKeyRef: + name: db-secret + key: POSTGRES_PORT + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: db-secret + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: db-secret + key: POSTGRES_PASSWORD + - name: POSTGRES_HOST + value: db + envFrom: + - configMapRef: + name: celery-config + volumeMounts: + - mountPath: /usr/src/app + name: shared-data + resources: + requests: + memory: "2Gi" + cpu: "600m" + limits: + memory: "4Gi" + cpu: "1.5" + volumes: + - name: shared-data + persistentVolumeClaim: + claimName: shared-data-pvc \ No newline at end of file diff --git a/k8s/cert-manager/certificate.yaml b/k8s/cert-manager/certificate.yaml new file mode 100644 index 000000000..39e46270c --- /dev/null +++ b/k8s/cert-manager/certificate.yaml @@ -0,0 +1,12 @@ +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: rengine-cert + namespace: default +spec: + secretName: rengine-tls + issuerRef: + name: letsencrypt-prod + kind: ClusterIssuer + dnsNames: + - rengine.example.com diff --git a/k8s/cert-manager/cluster-issuer.yml b/k8s/cert-manager/cluster-issuer.yml new file mode 100644 index 000000000..4f0d9d3cf --- /dev/null +++ b/k8s/cert-manager/cluster-issuer.yml @@ -0,0 +1,14 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-prod +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: rengine@example.com + privateKeySecretRef: + name: letsencrypt-prod + solvers: + - http01: + ingress: + class: nginx \ No newline at end of file diff --git a/k8s/nginx/configmap.yml b/k8s/nginx/configmap.yml new file mode 100644 index 000000000..fda770dfc --- /dev/null +++ b/k8s/nginx/configmap.yml @@ -0,0 +1,38 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: nginx-config +data: + rengine.conf: | + server { + listen 80; + listen [::]:80; + server_name rengine.example.com; + + charset utf-8; + keepalive_timeout 70; + + client_max_body_size 800M; + + location / { + proxy_read_timeout 300; + proxy_connect_timeout 300; + proxy_redirect off; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_pass http://rengine:8000/; + } + + location /staticfiles/ { + alias /usr/src/app/staticfiles/; + } + + location /protected_media/ { + internal; + alias /usr/src/scan_results/; + autoindex off; + } + } \ No newline at end of file diff --git a/k8s/nginx/deployment.yml b/k8s/nginx/deployment.yml new file mode 100644 index 000000000..72981d140 --- /dev/null +++ b/k8s/nginx/deployment.yml @@ -0,0 +1,38 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx +spec: + replicas: 1 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:alpine + volumeMounts: + - name: nginx-config-volume + mountPath: /etc/nginx/conf.d/rengine.conf + subPath: rengine.conf + - name: certs + mountPath: /etc/nginx/certs + - name: static-files + mountPath: /usr/src/app/staticfiles + ports: + - containerPort: 80 + - containerPort: 443 + volumes: + - name: nginx-config-volume + configMap: + name: nginx-config + - name: certs + secret: + secretName: nginx-certificates + - name: static-files + persistentVolumeClaim: + claimName: static-pvc \ No newline at end of file diff --git a/k8s/nginx/ingress.yml b/k8s/nginx/ingress.yml new file mode 100644 index 000000000..fad6297d6 --- /dev/null +++ b/k8s/nginx/ingress.yml @@ -0,0 +1,30 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: nginx-ingress + annotations: + nginx.ingress.kubernetes.io/ssl-redirect: "true" + nginx.ingress.kubernetes.io/rewrite-target: / + nginx.ingress.kubernetes.io/proxy-body-size: "800m" + nginx.ingress.kubernetes.io/proxy-read-timeout: "300" + nginx.ingress.kubernetes.io/proxy-connect-timeout: "300" + nginx.ingress.kubernetes.io/whitelist-source-range: "0.0.0.0/0" + acme.cert-manager.io/http01-edit-in-place: "true" + cert-manager.io/cluster-issuer: letsencrypt-prod +spec: + ingressClassName: nginx + tls: + - hosts: + - rengine.example.com + secretName: rengine-tls + rules: + - host: rengine.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: nginx + port: + number: 80 diff --git a/k8s/nginx/service.yml b/k8s/nginx/service.yml new file mode 100644 index 000000000..94e728065 --- /dev/null +++ b/k8s/nginx/service.yml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: nginx +spec: + type: ClusterIP + selector: + app: nginx + ports: + - name: http + port: 80 + targetPort: 80 + - name: https + port: 443 + targetPort: 443 \ No newline at end of file diff --git a/k8s/ollama/deployment.yml b/k8s/ollama/deployment.yml new file mode 100644 index 000000000..8e131f248 --- /dev/null +++ b/k8s/ollama/deployment.yml @@ -0,0 +1,28 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ollama + labels: + app: ollama +spec: + replicas: 1 + selector: + matchLabels: + app: ollama + template: + metadata: + labels: + app: ollama + spec: + containers: + - name: ollama + image: ollama/ollama:latest # Using the image from docker-compose + ports: + - containerPort: 11434 # Port used inside the container + volumeMounts: + - name: ollama-data + mountPath: /root/.ollama # Same mount path as in docker-compose + volumes: + - name: ollama-data + persistentVolumeClaim: + claimName: ollama-pvc diff --git a/k8s/ollama/pvc.yml b/k8s/ollama/pvc.yml new file mode 100644 index 000000000..2bdbbdeaa --- /dev/null +++ b/k8s/ollama/pvc.yml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: ollama-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi # Adjust storage size as needed diff --git a/k8s/ollama/service.yml b/k8s/ollama/service.yml new file mode 100644 index 000000000..cf0d4be19 --- /dev/null +++ b/k8s/ollama/service.yml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: ollama + labels: + app: ollama +spec: + selector: + app: ollama + ports: + - protocol: TCP + port: 11434 # Service port exposed + targetPort: 11434 # Port in the container + type: ClusterIP # Or LoadBalancer if you need external access diff --git a/k8s/postgres/secret.yml b/k8s/postgres/secret.yml new file mode 100644 index 000000000..abe6849d1 --- /dev/null +++ b/k8s/postgres/secret.yml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Secret +metadata: + name: db-secret +type: Opaque +data: + POSTGRES_DB: cmVuZ2luZQ== + POSTGRES_USER: cmVuZ2luZQ== + POSTGRES_PASSWORD: aEUyYTVASyY5bkVZMWZ6Z0E2WA== + POSTGRES_PORT: NTQzMg== + DOMAIN_NAME: cmVuZ2luZS5leGFtcGxlLmNvbQ== \ No newline at end of file diff --git a/k8s/postgres/service.yml b/k8s/postgres/service.yml new file mode 100644 index 000000000..41f82a20c --- /dev/null +++ b/k8s/postgres/service.yml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: db +spec: + ports: + - port: 5432 + targetPort: 5432 + selector: + app: postgres \ No newline at end of file diff --git a/k8s/postgres/statefulset.yml b/k8s/postgres/statefulset.yml new file mode 100644 index 000000000..8e1c7f3c8 --- /dev/null +++ b/k8s/postgres/statefulset.yml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: postgres +spec: + selector: + matchLabels: + app: postgres + serviceName: postgres + replicas: 1 + template: + metadata: + labels: + app: postgres + spec: + containers: + - name: postgres + image: "postgres:12.3-alpine" + env: + - name: POSTGRES_DB + valueFrom: + secretKeyRef: + name: db-secret + key: POSTGRES_DB + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: db-secret + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: db-secret + key: POSTGRES_PASSWORD + - name: PGDATA + value: /var/lib/postgresql/data/pgdata # Specify a subdirectory here + ports: + - containerPort: 5432 + volumeMounts: + - mountPath: /var/lib/postgresql/data # Volume mount path remains the same + name: postgres-storage + volumeClaimTemplates: + - metadata: + name: postgres-storage + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 5Gi diff --git a/k8s/pvc.yml b/k8s/pvc.yml new file mode 100644 index 000000000..a3ab3c254 --- /dev/null +++ b/k8s/pvc.yml @@ -0,0 +1,34 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: web-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: shared-data-pvc +spec: + storageClassName: nfs-rwx-storage + accessModes: + - ReadWriteMany + resources: + requests: + storage: 5Gi +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: static-pvc +spec: + storageClassName: nfs-rwx-storage + accessModes: + - ReadWriteMany + resources: + requests: + storage: 5Gi diff --git a/k8s/readme.md b/k8s/readme.md new file mode 100644 index 000000000..8aada7859 --- /dev/null +++ b/k8s/readme.md @@ -0,0 +1,135 @@ +# K8s Deployment Instructions + +This guide provides step-by-step instructions for deploying the application on a Kubernetes cluster. The deployment files should be applied in the following order: `ollama`, `postgres`, `redis`, `web`, `celery`, and `celery-beat`. + +## Prerequisites + +- A running Kubernetes cluster +- `kubectl` installed and configured to interact with your cluster + +## Configuration + +- To get a LetsEncrypt SSL certificate, you'll require to set up the Nginx Ingres Controller first. Then, configure the DNS record. Following that repace rengine.example.com to the domain name that you wish to receive SSL certificate for. + +- To use openssl or existing SSL certificate you can use `nginx-certificates` secret instead of `rengine-tls` secret and ignore creating cert-manager. + +## Step 1: Install the Ingress Controller + +1. **Add the NGINX Ingress Controller Helm repository:** + ```sh + helm repo add nginx-stable https://helm.nginx.com/stable + helm repo update + ``` + +2. **Install the NGINX Ingress Controller:** + ```sh + helm install nginx-ingress nginx-stable/nginx-ingress --namespace ingress-nginx --create-namespace --set controller.service.type=LoadBalancer + ``` + +## Step 2: Install Cert Manager + +1. **Add the Jetstack Helm repository:** + ```sh + helm repo add jetstack https://charts.jetstack.io + helm repo update + ``` + +2. **Install Cert Manager:** + ```sh + helm install cert-manager jetstack/cert-manager \ + --namespace cert-manager \ + --create-namespace \ + --version v1.11.0 \ + --set installCRDs=true + ``` + +3. **Verify the installation:** + ```sh + kubectl get pods --namespace cert-manager + ``` + +## Step 3: Install OpenEBS NFS Provisioner (Optional) + +Note: Either you can install it manually or use the OpenEBS provisioner from the marketplace in the Cloud Provider. + +1. **Add the OpenEBS Helm repository:** + ```sh + helm repo add openebs https://openebs.github.io/charts + helm repo update + ``` + +2. **Install OpenEBS NFS Provisioner:** + ```sh + helm install openebs-nfs openebs/openebs --namespace openebs --create-namespace + ``` + +3. **Verify the installation:** + ```sh + kubectl get pods --namespace openebs + ``` + +4. **Create the Storage Class nfsrwx** + ```sh + kubectl apply -f - <