commit 643024b01cf633535120590fd41016c19a0d90f6 Author: Super User Date: Fri Aug 14 13:49:47 2026 -0400 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3752678 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +#K3s Secrets +bootstrap/token +bootstrap/get_helm.sh +charts/ +*.kubeconfig +kubeconfig +k3s.yaml + +#Cloudflare variables +*.json +!**/kustomization.json +.cloudflared/ + + +#TLS Certs +*.crt +*.key +*.pem + +#Secret Manifests +**/secret.yaml +**/secrets.yaml +*-secret.yaml + diff --git a/apps/argocd/apps/gitea.yaml b/apps/argocd/apps/gitea.yaml new file mode 100644 index 0000000..9749ed6 --- /dev/null +++ b/apps/argocd/apps/gitea.yaml @@ -0,0 +1,9 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: gitea + namespace: argocd +spec: + project: default + source: + diff --git a/apps/argocd/ingress.yaml b/apps/argocd/ingress.yaml new file mode 100644 index 0000000..92e64ea --- /dev/null +++ b/apps/argocd/ingress.yaml @@ -0,0 +1,20 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: argocd + namespace: argocd + annotations: + traefik.ingress.kubernetes.io/router.entrypoints: websecure +spec: + ingressClassName: traefik + rules: + - host: argo.panopticons.org + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: argocd-server + port: + number: 80 diff --git a/apps/cloudflared/configmap.yaml b/apps/cloudflared/configmap.yaml new file mode 100644 index 0000000..0b049da --- /dev/null +++ b/apps/cloudflared/configmap.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: cloudflared-config + namespace: cloudflared +data: + config.yaml: | + tunnel: 63418c8c-38c2-45db-968b-7f3fab3c75a6 + credentials-file: /etc/cloudflared/creds/credentials.json + + + ingress: + - hostname: jellyfin.panopticons.org + service: http://10.0.20.52:8096 + - hostname: plex.panopticons.org + service: http://10.0.20.53:32400 + - hostname: "*.panopticons.org" + service: https://traefik.kube-system.svc.cluster.local:443 + originRequest: + noTLSVerify: true + - service: http_status:404 diff --git a/apps/cloudflared/deployment.yaml b/apps/cloudflared/deployment.yaml new file mode 100644 index 0000000..95b5510 --- /dev/null +++ b/apps/cloudflared/deployment.yaml @@ -0,0 +1,67 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cloudflared + namespace: cloudflared +spec: + replicas: 2 + selector: + matchLabels: + app: cloudflared + template: + metadata: + labels: + app: cloudflared + spec: + securityContext: + runAsNonRoot: true + runAsUser: 65532 + runAsGroup: 65532 + fsGroup: 65532 + seccompProfile: + type: RuntimeDefault + containers: + - name: cloudflared + image: cloudflare/cloudflared:2025.4.0 + args: + - tunnel + - --config + - /etc/cloudflared/config.yaml + - --metrics + - 0.0.0.0:2000 + - --protocol + - http2 + - --no-autoupdate + - run + volumeMounts: + - name: config + mountPath: /etc/cloudflared/config.yaml + subPath: config.yaml + - name: creds + mountPath: /etc/cloudflared/creds + readOnly: true + resources: + requests: + memory: "256Mi" + cpu: "100m" + limits: + memory: "512Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: /ready + port: 2000 + initialDelaySeconds: 10 + periodSeconds: 10 + securityContext: + allowPrivilegeEscalation: False + capabilities: + drop: + - ALL + volumes: + - name: config + configMap: + name: cloudflared-config + - name: creds + secret: + secretName: tunnel-credentials diff --git a/apps/gitea/deployment.yaml b/apps/gitea/deployment.yaml new file mode 100644 index 0000000..ff73593 --- /dev/null +++ b/apps/gitea/deployment.yaml @@ -0,0 +1,38 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gitea + namespace: gitea +spec: + replicas: 1 + selector: + matchLabels: + app: gitea + template: + metadata: + labels: + app: gitea + spec: + securityContext: + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + containers: + - name: gitea + image: gitea/gitea:latest-rootless + ports: + - containerPort: 3000 + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + volumeMounts: + - mountPath: /data + name: gitea-data + volumes: + - name: gitea-data + persistentVolumeClaim: + claimName: gitea-pvc + diff --git a/apps/gitea/ingress.yaml b/apps/gitea/ingress.yaml new file mode 100644 index 0000000..4fdba01 --- /dev/null +++ b/apps/gitea/ingress.yaml @@ -0,0 +1,24 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: gitea + namespace: gitea + annotations: + cert-manager.io/cluster-issuer: letsencrypt-cloudflare + traefik.ingress.kubernetes.io/router.entrypoints: websecure +spec: + tls: + - hosts: + - git.panopticons.org + secretName: wildcard-panopticon-org-tls + rules: + - host: git.panopticons.org + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: gitea + port: + number: 3000 diff --git a/apps/gitea/pvc.yaml b/apps/gitea/pvc.yaml new file mode 100644 index 0000000..bca10bd --- /dev/null +++ b/apps/gitea/pvc.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: gitea-pvc + namespace: gitea +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + diff --git a/apps/gitea/service.yaml b/apps/gitea/service.yaml new file mode 100644 index 0000000..5a480d1 --- /dev/null +++ b/apps/gitea/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: gitea + namespace: gitea +spec: + ports: + - port: 3000 + targetPort: 3000 + selector: + app: gitea + diff --git a/apps/homepage/deployment.yaml b/apps/homepage/deployment.yaml new file mode 100644 index 0000000..32b4ac6 --- /dev/null +++ b/apps/homepage/deployment.yaml @@ -0,0 +1,42 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: homepage + namespace: homepage +spec: + replicas: 1 + selector: + matchLabels: + app: homepage + template: + metadata: + labels: + app: homepage + spec: + securityContext: + seccompProfile: + type: RuntimeDefault + containers: + - name: homepage + image: linuxserver/heimdall:latest + + env: + - name: PUID + value: "1000" + - name: PGID + value: "1000" + - name: TZ + value: "America/Los_Angeles" + + ports: + - containerPort: 80 + + volumeMounts: + - mountPath: /config + name: homepage-data + + volumes: + - name: homepage-data + persistentVolumeClaim: + claimName: homepage-pvc + diff --git a/apps/homepage/ingress.yaml b/apps/homepage/ingress.yaml new file mode 100644 index 0000000..0c301f1 --- /dev/null +++ b/apps/homepage/ingress.yaml @@ -0,0 +1,24 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: homepage + namespace: homepage + annotations: + cert-manager.io/cluster-issuer: letsencrypt-cloudflare + traefik.ingress.kubernetes.io/router.entrypoints: websecure +spec: + tls: + - hosts: + - home.panopticons.org + secretName: wildcard-panopticon-org-tls + rules: + - host: home.panopticons.org + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: homepage + port: + number: 80 diff --git a/apps/homepage/pvc.yaml b/apps/homepage/pvc.yaml new file mode 100644 index 0000000..2a5f0f6 --- /dev/null +++ b/apps/homepage/pvc.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: homepage-pvc + namespace: homepage +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi + diff --git a/apps/homepage/service.yaml b/apps/homepage/service.yaml new file mode 100644 index 0000000..197528f --- /dev/null +++ b/apps/homepage/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: homepage + namespace: homepage +spec: + ports: + - port: 80 + targetPort: 80 + selector: + app: homepage + diff --git a/apps/jellyseerr/deployment.yaml b/apps/jellyseerr/deployment.yaml new file mode 100644 index 0000000..b6f5f8b --- /dev/null +++ b/apps/jellyseerr/deployment.yaml @@ -0,0 +1,28 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: jellyseerr + namespace: jellyseerr +spec: + replicas: 1 + selector: + matchLabels: + app: jellyseerr + template: + metadata: + labels: + app: jellyseerr + spec: + containers: + - name: jellyseerr + image: fallenbagel/jellyseerr:latest + ports: + - containerPort: 5055 + volumeMounts: + - mountPath: /app/config + name: jellyseerr-data + volumes: + - name: jellyseerr-data + persistentVolumeClaim: + claimName: jellyseerr-pvc + diff --git a/apps/jellyseerr/ingress.yaml b/apps/jellyseerr/ingress.yaml new file mode 100644 index 0000000..adceb51 --- /dev/null +++ b/apps/jellyseerr/ingress.yaml @@ -0,0 +1,24 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: jellyseerr + namespace: jellyseerr + annotations: + cert-manager.io/cluster-issuer: letsencrypt-cloudflare + traefik.ingress.kubernetes.io/router.entrypoints: websecure +spec: + tls: + - hosts: + - requests.panopticons.org + secretName: wildcard-panopticon-org-tls + rules: + - host: requests.panopticons.org + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: jellyseerr + port: + number: 80 diff --git a/apps/jellyseerr/pvc.yaml b/apps/jellyseerr/pvc.yaml new file mode 100644 index 0000000..3bfc585 --- /dev/null +++ b/apps/jellyseerr/pvc.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: jellyseerr-pvc + namespace: jellyseerr +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + diff --git a/apps/jellyseerr/service.yaml b/apps/jellyseerr/service.yaml new file mode 100644 index 0000000..363c8e2 --- /dev/null +++ b/apps/jellyseerr/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: jellyseerr + namespace: jellyseerr +spec: + ports: + - port: 80 + targetPort: 5055 + selector: + app: jellyseerr + diff --git a/apps/uptime-kuma/deployment.yaml b/apps/uptime-kuma/deployment.yaml new file mode 100644 index 0000000..d892dfe --- /dev/null +++ b/apps/uptime-kuma/deployment.yaml @@ -0,0 +1,38 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: uptime-kuma + namespace: uptime-kuma +spec: + replicas: 1 + selector: + matchLabels: + app: uptime-kuma + template: + metadata: + labels: + app: uptime-kuma + spec: + securityContext: + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + containers: + - name: uptime-kuma + image: louislam/uptime-kuma:2-slim-rootless + ports: + - containerPort: 3001 + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + volumeMounts: + - mountPath: /data + name: uptime-kuma-data + volumes: + - name: uptime-kuma-data + persistentVolumeClaim: + claimName: uptime-kuma-pvc + diff --git a/apps/uptime-kuma/ingress.yaml b/apps/uptime-kuma/ingress.yaml new file mode 100644 index 0000000..8561b00 --- /dev/null +++ b/apps/uptime-kuma/ingress.yaml @@ -0,0 +1,24 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: uptime-kuma + namespace: uptime-kuma + annotations: + cert-manager.io/cluster-issuer: letsencrypt-cloudflare + traefik.ingress.kubernetes.io/router.entrypoints: websecure +spec: + tls: + - hosts: + - status.panopticons.org + secretName: wildcard-panopticon-org-tls + rules: + - host: status.panopticons.org + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: uptime-kuma + port: + number: 3001 diff --git a/apps/uptime-kuma/pvc.yaml b/apps/uptime-kuma/pvc.yaml new file mode 100644 index 0000000..5640040 --- /dev/null +++ b/apps/uptime-kuma/pvc.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: uptime-kuma-pvc + namespace: uptime-kuma +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + diff --git a/apps/uptime-kuma/service.yaml b/apps/uptime-kuma/service.yaml new file mode 100644 index 0000000..5ac08a7 --- /dev/null +++ b/apps/uptime-kuma/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: uptime-kuma + namespace: uptime-kuma +spec: + ports: + - port: 3001 + targetPort: 3001 + selector: + app: uptime-kuma + diff --git a/cluster/cert-manager/letsencrypt.yaml b/cluster/cert-manager/letsencrypt.yaml new file mode 100644 index 0000000..a0c175a --- /dev/null +++ b/cluster/cert-manager/letsencrypt.yaml @@ -0,0 +1,16 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-cloudflare +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: jakebutler@jakebutler.me + privateKeySecretRef: + name: letsencrypt-cloudflare-key + solvers: + - dns01: + cloudflare: + apiTokenSecretRef: + name: cloudflare-api-token + key: api-token diff --git a/cluster/ingress/ingress.yaml b/cluster/ingress/ingress.yaml new file mode 100644 index 0000000..e363c80 --- /dev/null +++ b/cluster/ingress/ingress.yaml @@ -0,0 +1,8 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +ingress: + - hostname: "*.panopticons.org" + service: https://ingress-nginx-controller.ingress-nginx.svc.cluster.local:443 + originRequest: + noTLSVerify: true + - service: http_status:404 diff --git a/cluster/metallb/metallb-pool.yaml b/cluster/metallb/metallb-pool.yaml new file mode 100644 index 0000000..ca7c1ee --- /dev/null +++ b/cluster/metallb/metallb-pool.yaml @@ -0,0 +1,14 @@ +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: lan-pool + namespace: metallb-system +spec: + addresses: + - 192.168.0.200-192.168.0.220 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: l2 + namespace: metallb-system diff --git a/cluster/namespaces/cloudflared.yaml b/cluster/namespaces/cloudflared.yaml new file mode 100644 index 0000000..c304c25 --- /dev/null +++ b/cluster/namespaces/cloudflared.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: cloudflared + labels: + name: cloudflared diff --git a/cluster/namespaces/gitea.yaml b/cluster/namespaces/gitea.yaml new file mode 100644 index 0000000..4e9dabc --- /dev/null +++ b/cluster/namespaces/gitea.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: gitea + labels: + name: gitea + pod-security.kubernetes.io/enforce: restricted + pod-security.kubernetes.io/audit: restricted + pod-security.kubernetes.io/warn: restricted + diff --git a/cluster/namespaces/homepage.yaml b/cluster/namespaces/homepage.yaml new file mode 100644 index 0000000..7992bd5 --- /dev/null +++ b/cluster/namespaces/homepage.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: homepage + labels: + name: homepage + pod-security.kubernetes.io/enforce: baseline + pod-security.kubernetes.io/audit: restricted + pod-security.kubernetes.io/warn: restricted + diff --git a/cluster/namespaces/jellyseerr.yaml b/cluster/namespaces/jellyseerr.yaml new file mode 100644 index 0000000..bf5d354 --- /dev/null +++ b/cluster/namespaces/jellyseerr.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: jellyseerr + labels: + name: jellyseerr + pod-security.kubernetes.io/enforce: baseline + pod-security.kubernetes.io/audit: restricted + pod-security.kubernetes.io/warn: restricted + diff --git a/cluster/namespaces/portainer.yaml b/cluster/namespaces/portainer.yaml new file mode 100644 index 0000000..f357aa0 --- /dev/null +++ b/cluster/namespaces/portainer.yaml @@ -0,0 +1,8 @@ +--- +# Source: portainer/templates/namespace.yaml +apiVersion: v1 +kind: Namespace +metadata: + name: portainer + labels: + pod-security.kubernetes.io/enforce: privileged diff --git a/cluster/namespaces/uptime-kuma.yaml b/cluster/namespaces/uptime-kuma.yaml new file mode 100644 index 0000000..e9cbcc2 --- /dev/null +++ b/cluster/namespaces/uptime-kuma.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: uptime-kuma + labels: + name: uptime-kuma + pod-security.kubernetes.io/enforce: restricted + pod-security.kubernetes.io/audit: restricted + pod-security.kubernetes.io/warn: restricted +