diff --git a/cluster/flux-system/gotk-components.yaml b/cluster/apps/flux-system/gotk-components.yaml similarity index 100% rename from cluster/flux-system/gotk-components.yaml rename to cluster/apps/flux-system/gotk-components.yaml diff --git a/cluster/flux-system/gotk-sync.yaml b/cluster/apps/flux-system/gotk-sync.yaml similarity index 100% rename from cluster/flux-system/gotk-sync.yaml rename to cluster/apps/flux-system/gotk-sync.yaml diff --git a/cluster/flux-system/kustomization.yaml b/cluster/apps/flux-system/kustomization.yaml similarity index 100% rename from cluster/flux-system/kustomization.yaml rename to cluster/apps/flux-system/kustomization.yaml diff --git a/cluster/apps/production/cert-manager/certificates/production/local-mafyuh-com.yaml b/cluster/apps/production/cert-manager/certificates/production/local-mafyuh-com.yaml new file mode 100644 index 0000000..1d9f421 --- /dev/null +++ b/cluster/apps/production/cert-manager/certificates/production/local-mafyuh-com.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: local-mafyuh-com + namespace: default +spec: + secretName: local-mafyuh-com-production-tls + issuerRef: + name: letsencrypt-production + kind: ClusterIssuer + commonName: "*.local.mafyuh.com" + dnsNames: + - "local.mafyuh.com" + - "*.local.mafyuh.com" \ No newline at end of file diff --git a/cluster/apps/production/cert-manager/certificates/staging/local-mafyuh-com.yaml b/cluster/apps/production/cert-manager/certificates/staging/local-mafyuh-com.yaml new file mode 100644 index 0000000..bbf13c8 --- /dev/null +++ b/cluster/apps/production/cert-manager/certificates/staging/local-mafyuh-com.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: local-mafyuh-com + namespace: default +spec: + secretName: local-mafyuh-com-staging-tls + issuerRef: + name: letsencrypt-staging + kind: ClusterIssuer + commonName: "*.local.mafyuh.com" + dnsNames: + - "local.mafyuh.com" + - "*.local.mafyuh.com" \ No newline at end of file diff --git a/cluster/apps/production/cert-manager/issuers/letsencrypt-prod.yaml b/cluster/apps/production/cert-manager/issuers/letsencrypt-prod.yaml new file mode 100644 index 0000000..c94d51e --- /dev/null +++ b/cluster/apps/production/cert-manager/issuers/letsencrypt-prod.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-production +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: matt@mafyuh.dev + privateKeySecretRef: + name: letsencrypt-production + solvers: + - dns01: + cloudflare: + email: matt@mafyuh.dev + apiTokenSecretRef: + name: cloudflare-token-secret + key: cloudflare-token + selector: + dnsZones: + - "mafyuh.com" \ No newline at end of file diff --git a/cluster/apps/production/cert-manager/issuers/letsencrypt-staging.yaml b/cluster/apps/production/cert-manager/issuers/letsencrypt-staging.yaml new file mode 100644 index 0000000..ebf82e0 --- /dev/null +++ b/cluster/apps/production/cert-manager/issuers/letsencrypt-staging.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-staging +spec: + acme: + server: https://acme-staging-v02.api.letsencrypt.org/directory + email: matt@mafyuh.dev + privateKeySecretRef: + name: letsencrypt-staging + solvers: + - dns01: + cloudflare: + email: matt@mafyuh.dev + apiTokenSecretRef: + name: cloudflare-token-secret + key: cloudflare-token + selector: + dnsZones: + - "mafyuh.com" \ No newline at end of file diff --git a/cluster/apps/production/cert-manager/issuers/secret-cf-token.yaml b/cluster/apps/production/cert-manager/issuers/secret-cf-token.yaml new file mode 100644 index 0000000..f4be248 --- /dev/null +++ b/cluster/apps/production/cert-manager/issuers/secret-cf-token.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: cloudflare-token-secret + namespace: cert-manager +type: Opaque +stringData: + cloudflare-token: cER3bFYzcjk4UVpSeklBeGc0WXNWMkVCU011U0tKdUtPRmZsMGNJMw== \ No newline at end of file diff --git a/cluster/apps/production/cert-manager/values.yaml b/cluster/apps/production/cert-manager/values.yaml new file mode 100644 index 0000000..3453355 --- /dev/null +++ b/cluster/apps/production/cert-manager/values.yaml @@ -0,0 +1,10 @@ +installCRDs: false +replicaCount: 3 +extraArgs: + - --dns01-recursive-nameservers=1.1.1.1:53,9.9.9.9:53 + - --dns01-recursive-nameservers-only +podDnsPolicy: None +podDnsConfig: + nameservers: + - 1.1.1.1 + - 9.9.9.9 \ No newline at end of file diff --git a/cluster/apps/production/radarr/radarr.yaml b/cluster/apps/production/radarr/radarr.yaml index 9781e25..7dddef7 100644 --- a/cluster/apps/production/radarr/radarr.yaml +++ b/cluster/apps/production/radarr/radarr.yaml @@ -31,8 +31,8 @@ spec: memory: "512Mi" cpu: "1" limits: - memory: "4Gi" - cpu: "4" + memory: "1Gi" + cpu: "1" volumeMounts: - mountPath: /config name: radarr-config @@ -68,8 +68,29 @@ metadata: spec: selector: app: radarr - type: LoadBalancer ports: - port: 7878 targetPort: 7878 protocol: TCP + type: ClusterIP +--- +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: radarr + namespace: default + annotations: + kubernetes.io/ingress.class: traefik-external +spec: + entryPoints: + - websecure + routes: + - match: Host(`radarr.local.mafyuh.com`) + kind: Rule + services: + - name: headless-radarr + port: 7878 + middlewares: + - name: default-headers + tls: + secretName: local-mafyuh-com-production-tls diff --git a/cluster/apps/production/sab/sabnzbd.yaml b/cluster/apps/production/sab/sabnzbd.yaml index 871d5e6..b1aa987 100644 --- a/cluster/apps/production/sab/sabnzbd.yaml +++ b/cluster/apps/production/sab/sabnzbd.yaml @@ -70,8 +70,29 @@ metadata: spec: selector: app: sabnzbd - type: LoadBalancer ports: - port: 8080 targetPort: 8080 protocol: TCP + type: ClusterIP +--- +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: sabnzbd + namespace: default + annotations: + kubernetes.io/ingress.class: traefik-external +spec: + entryPoints: + - websecure + routes: + - match: Host(`sabnzbd.local.mafyuh.com`) + kind: Rule + services: + - name: headless-sabnzbd + port: 8080 + middlewares: + - name: default-headers + tls: + secretName: local-mafyuh-com-production-tls diff --git a/cluster/apps/production/sonarr/sonarr.yaml b/cluster/apps/production/sonarr/sonarr.yaml new file mode 100644 index 0000000..94097a6 --- /dev/null +++ b/cluster/apps/production/sonarr/sonarr.yaml @@ -0,0 +1,95 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: sonarr + namespace: default + labels: + app: sonarr +spec: + replicas: 1 + selector: + matchLabels: + app: sonarr + template: + metadata: + labels: + app: sonarr + spec: + containers: + - name: sonarr + image: ghcr.io/linuxserver/sonarr@sha256:3f193d343c1225676c1ea0547c5022fd83c4459a493870179dff9e87c54dbbc9 + imagePullPolicy: IfNotPresent + env: + - name: PUID + value: "1000" + - name: PGID + value: "1000" + - name: TZ + value: America/New_York + resources: + requests: + memory: "512Mi" + cpu: "1" + limits: + memory: "1Gi" + cpu: "4" + volumeMounts: + - mountPath: /config + name: sonarr-config + - mountPath: /data + name: nas + volumes: + - name: nas + nfs: + path: /mnt/thePool/thePoolShare + server: 10.0.0.10 + - name: sonarr-config + persistentVolumeClaim: + claimName: sonarr-config +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: sonarr-config + namespace: default +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi + storageClassName: longhorn +--- +apiVersion: v1 +kind: Service +metadata: + name: headless-sonarr + namespace: default +spec: + selector: + app: sonarr + ports: + - port: 8989 + targetPort: 8989 + protocol: TCP +--- +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: sonarr + namespace: default + annotations: + kubernetes.io/ingress.class: traefik-external +spec: + entryPoints: + - websecure + routes: + - match: Host(`sonarr${SECRET_INTERNAL_DOMAIN_NAME}`) + kind: Rule + services: + - name: headless-sonarr + port: 8989 + middlewares: + - name: default-headers + tls: + secretName: local-mafyuh-com-production-tls \ No newline at end of file diff --git a/cluster/apps/production/traefik/dashboard/ingress.yaml b/cluster/apps/production/traefik/dashboard/ingress.yaml new file mode 100644 index 0000000..38274de --- /dev/null +++ b/cluster/apps/production/traefik/dashboard/ingress.yaml @@ -0,0 +1,21 @@ +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: traefik-dashboard + namespace: traefik + annotations: + kubernetes.io/ingress.class: traefik-external +spec: + entryPoints: + - websecure + routes: + - match: Host(`traefik.local.mafyuh.com`) + kind: Rule + middlewares: + - name: traefik-dashboard-basicauth + namespace: traefik + services: + - name: api@internal + kind: TraefikService + tls: + secretName: local-mafyuh-com-production-tls \ No newline at end of file diff --git a/cluster/apps/production/traefik/dashboard/middleware.yaml b/cluster/apps/production/traefik/dashboard/middleware.yaml new file mode 100644 index 0000000..04b94b7 --- /dev/null +++ b/cluster/apps/production/traefik/dashboard/middleware.yaml @@ -0,0 +1,8 @@ +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: traefik-dashboard-basicauth + namespace: traefik +spec: + basicAuth: + secret: traefik-dashboard-auth \ No newline at end of file diff --git a/cluster/apps/production/traefik/dashboard/secret-dashboard.yaml b/cluster/apps/production/traefik/dashboard/secret-dashboard.yaml new file mode 100644 index 0000000..15774fc --- /dev/null +++ b/cluster/apps/production/traefik/dashboard/secret-dashboard.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: traefik-dashboard-auth + namespace: traefik +type: Opaque +data: + users: bWFmeXVoOiRhcHIxJEpacXJBZ0RPJEpwOEFra1RXVk8zT0R0WjlQRWNUcjEKCg== \ No newline at end of file diff --git a/cluster/apps/production/traefik/headers.yaml b/cluster/apps/production/traefik/headers.yaml new file mode 100644 index 0000000..8811d9a --- /dev/null +++ b/cluster/apps/production/traefik/headers.yaml @@ -0,0 +1,18 @@ +apiVersion: traefik.io/v1alpha1 # traefik.containo.us/v1alpha1 depreciated in Traefik v3 +kind: Middleware +metadata: + name: default-headers + namespace: default +spec: + headers: + browserXssFilter: true + contentTypeNosniff: true + forceSTSHeader: true + stsIncludeSubdomains: true + stsPreload: true + stsSeconds: 15552000 + referrerPolicy: no-referrer + contentSecurityPolicy: "default-src 'none'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; font-src 'self' https: data:; connect-src 'self' https:; frame-src 'self' https:; media-src 'self' https:; object-src 'none'; frame-ancestors 'self'; base-uri 'self'; form-action 'self';" + customFrameOptionsValue: SAMEORIGIN + customRequestHeaders: + X-Forwarded-Proto: https \ No newline at end of file diff --git a/cluster/apps/production/traefik/values.yaml b/cluster/apps/production/traefik/values.yaml new file mode 100644 index 0000000..630b17c --- /dev/null +++ b/cluster/apps/production/traefik/values.yaml @@ -0,0 +1,55 @@ +globalArguments: + - "--global.sendanonymoususage=false" + - "--global.checknewversion=false" + +additionalArguments: + - "--serversTransport.insecureSkipVerify=true" + - "--log.level=INFO" + +deployment: + enabled: true + replicas: 3 + annotations: {} + podAnnotations: {} + additionalContainers: [] + initContainers: [] + +ports: + web: + redirectTo: + port: websecure + priority: 10 + websecure: + http3: + enabled: true + advertisedPort: 4443 + tls: + enabled: true + +ingressRoute: + dashboard: + enabled: false + +providers: + kubernetesCRD: + enabled: true + ingressClass: traefik-external + allowExternalNameServices: true + kubernetesIngress: + enabled: true + allowExternalNameServices: true + publishedService: + enabled: false + +rbac: + enabled: true + +service: + enabled: true + type: LoadBalancer + annotations: {} + labels: {} + spec: + loadBalancerIP: 10.69.69.225 + loadBalancerSourceRanges: [] + externalIPs: [] \ No newline at end of file