move everything top level so it can be used by the k3s built-in helm-controller. add woodpecker ci config.

This commit is contained in:
Madison Grubb
2025-07-10 10:21:39 -04:00
parent 85ff210135
commit bc2debdea0
58 changed files with 188 additions and 704 deletions

View File

@@ -1,22 +0,0 @@
name: Deploy
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
container: bitnami/kubectl
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up kubeconfig
run: echo "$KUBE_CONFIG" > ~/.kube/config
env:
KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
- name: Deploy
run: ./deploy.sh

View File

@@ -1,20 +0,0 @@
name: Dry Run
on:
pull_request:
jobs:
dry-run:
runs-on: ubuntu-latest
container: bitnami/kubectl
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up kubeconfig
run: echo "$KUBE_CONFIG" > ~/.kube/config
env:
KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
- name: Dry-run deployment
run: DRU_RUN=true ./deploy.sh

9
.woodpecker/ci.yaml Normal file
View File

@@ -0,0 +1,9 @@
when:
- event: push
branch: main
steps:
- name: test
image: debian
commands:
- echo "This is the test step"

View File

@@ -8,7 +8,7 @@ spec:
targetNamespace: authentik targetNamespace: authentik
repo: https://charts.goauthentik.io repo: https://charts.goauthentik.io
# https://artifacthub.io/packages/helm/goauthentik/authentik # https://artifacthub.io/packages/helm/goauthentik/authentik
version: 2025.4.0 version: 2025.6.3
valuesContent: |- valuesContent: |-
authentik: authentik:
secret_key: "0hETw0LhioALQ6vhNTiN5MuW1349KjPlol3Q3D6sC8BV+IlzyhIfZYth/7WapdmOM8ib3qyyGLC5/8Xk" secret_key: "0hETw0LhioALQ6vhNTiN5MuW1349KjPlol3Q3D6sC8BV+IlzyhIfZYth/7WapdmOM8ib3qyyGLC5/8Xk"
@@ -26,12 +26,12 @@ spec:
- secretName: authentik-tls - secretName: authentik-tls
hosts: hosts:
- login.keligrubb.com - login.keligrubb.com
metrics: # metrics:
enabled: true # enabled: true
serviceMonitor: # serviceMonitor:
enabled: true # enabled: true
labels: # labels:
release: prometheus # release: prometheus
postgresql: postgresql:
enabled: true enabled: true
auth: auth:

View File

@@ -0,0 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: authentik-oauth-client-secret
namespace: monitoring
type: Opaque
stringData:
client-secret: "xfUwLZZuKmAwILcYqMhNOi6LsF5IaflS7zMU9hj7pTauOC5uXbzY2vzGuHuHsFMMdlhRUtzE7UPus85Gk1ABqcjj5fJv1fiOJ1Nkhe8H9Wot4hCsrr2CqDC5huZkWRQI"

View File

@@ -1,15 +0,0 @@
#!/bin/sh
for namespace in namespaces/*; do
if [ "$DRY_RUN" = true ]; then
printf "\033[1;33m*******************************************************\n"
printf "Dry running changes to %s\n" "$(basename "$namespace")"
printf "*******************************************************\033[0m\n"
kubectl apply -f "$namespace" --dry-run=server
else
printf "\033[1;33m*******************************************************\n"
printf "Deploying changes to %s\n" "$(basename "$namespace")"
printf "*******************************************************\033[0m\n"
kubectl apply -f "$namespace"
fi
done

View File

@@ -10,7 +10,7 @@ spec:
targetNamespace: git targetNamespace: git
repo: https://dl.gitea.io/charts/ repo: https://dl.gitea.io/charts/
# https://gitea.com/gitea/helm-chart/releases # https://gitea.com/gitea/helm-chart/releases
version: 11.0.1 version: 12.1.1
valuesContent: |- valuesContent: |-
resources: resources:
limits: limits:
@@ -33,21 +33,9 @@ spec:
config: config:
ui: ui:
DEFAULT_THEME: gitea-dark DEFAULT_THEME: gitea-dark
picture:
ENABLE_FEDERATED_AVATAR: false
DISABLE_GRAVATAR: true
database: database:
DB_TYPE: sqlite3 DB_TYPE: sqlite3
NAME: /data/gitea/gitea.db NAME: /data/gitea/gitea.db
actions:
ENABLED: true
actions:
enabled: true
provisioning:
enabled: true
service:
ssh:
port: 22
ingress: ingress:
enabled: true enabled: true
className: nginx className: nginx

34
jellyfin-chart.yml Normal file
View File

@@ -0,0 +1,34 @@
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: jellyfin
namespace: jellyfin
spec:
repo: https://jellyfin.github.io/jellyfin-helm
chart: jellyfin
targetNamespace: jellyfin
# https://github.com/jellyfin/jellyfin-helm/releases
version: 2.3.0
valuesContent: |-
timezone: "America/New_York"
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-cluster-issuer"
hosts:
- host: media.keligrubb.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: jellyfin-tls
hosts:
- media.keligrubb.com
persistence:
config:
enabled: true
size: 5Gi
media:
enabled: true
existingClaim: "jellyfin-nfs-media-pvc"

4
jellyfin-namespace.yml Normal file
View File

@@ -0,0 +1,4 @@
kind: Namespace
apiVersion: v1
metadata:
name: jellyfin

33
jellyfin-nfs.yml Normal file
View File

@@ -0,0 +1,33 @@
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: jellyfin-nfs-media-pv
spec:
capacity:
storage: 5Ti
volumeMode: Filesystem
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
mountOptions:
- hard
- nfsvers=4.1
nfs:
server: 192.168.1.153
path: "/mnt/homestead/jellyfin"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jellyfin-nfs-media-pvc
namespace: jellyfin
spec:
accessModes:
- ReadWriteMany
storageClassName: ""
resources:
requests:
storage: 5Ti
volumeName: jellyfin-nfs-media-pv

View File

@@ -8,7 +8,7 @@ spec:
targetNamespace: monitoring targetNamespace: monitoring
repo: https://prometheus-community.github.io/helm-charts repo: https://prometheus-community.github.io/helm-charts
# https://artifacthub.io/packages/helm/prometheus-community/kube-prometheus-stack # https://artifacthub.io/packages/helm/prometheus-community/kube-prometheus-stack
version: 70.7.0 version: 75.9.0
valuesContent: |- valuesContent: |-
grafana: grafana:
envValueFrom: envValueFrom:
@@ -40,18 +40,18 @@ spec:
auth.generic_oauth: auth.generic_oauth:
name: authentik name: authentik
enabled: true enabled: true
client_id: "exAcNQX8GILZdQHGUQfa9Dpj0XGSjTVBpfagQ8VL" client_id: "8hpxfQs7B1BNwlHx6PrAOYc2K5PMzU9Xig1ImXU9"
scopes: "openid profile email" scopes: "openid profile email"
auth_url: "https://login.keligrubb.com/application/o/authorize/" auth_url: "https://login.keligrubb.com/application/o/authorize/"
token_url: "https://login.keligrubb.com/application/o/token/" token_url: "https://login.keligrubb.com/application/o/token/"
api_url: "https://login.keligrubb.com/application/o/userinfo/" api_url: "https://login.keligrubb.com/application/o/userinfo/"
role_attribute_path: contains(groups, 'Grafana Admins') && 'Admin' || contains(groups, 'Grafana Editors') && 'Editor' || 'Viewer' role_attribute_path: contains(groups, 'Grafana Admins') && 'Admin' || contains(groups, 'Grafana Editors') && 'Editor' || 'Viewer'
additionalDataSources: # additionalDataSources:
- name: Loki # - name: Loki
type: loki # type: loki
access: proxy # access: proxy
basicAuth: false # basicAuth: false
url: http://loki-gateway.monitoring.svc.cluster.local # url: http://loki-gateway.monitoring.svc.cluster.local
config: config:
auth: auth:
signout_redirect_url: "https://login.keligrubb.com/application/o/grafana/end-session/" signout_redirect_url: "https://login.keligrubb.com/application/o/grafana/end-session/"
@@ -116,4 +116,4 @@ spec:
- ReadWriteOnce - ReadWriteOnce
resources: resources:
requests: requests:
storage: 64Gi storage: 16Gi

View File

@@ -1,381 +0,0 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: helmcharts.helm.cattle.io
spec:
group: helm.cattle.io
names:
kind: HelmChart
plural: helmcharts
singular: helmchart
preserveUnknownFields: false
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .status.jobName
name: Job
type: string
- jsonPath: .spec.chart
name: Chart
type: string
- jsonPath: .spec.targetNamespace
name: TargetNamespace
type: string
- jsonPath: .spec.version
name: Version
type: string
- jsonPath: .spec.repo
name: Repo
type: string
- jsonPath: .spec.helmVersion
name: HelmVersion
type: string
- jsonPath: .spec.bootstrap
name: Bootstrap
type: string
name: v1
schema:
openAPIV3Schema:
properties:
spec:
properties:
authPassCredentials:
type: boolean
authSecret:
nullable: true
properties:
name:
nullable: true
type: string
type: object
backOffLimit:
nullable: true
type: integer
bootstrap:
type: boolean
chart:
nullable: true
type: string
chartContent:
nullable: true
type: string
createNamespace:
type: boolean
dockerRegistrySecret:
nullable: true
properties:
name:
nullable: true
type: string
type: object
failurePolicy:
nullable: true
type: string
helmVersion:
nullable: true
type: string
insecureSkipTLSVerify:
type: boolean
jobImage:
nullable: true
type: string
plainHTTP:
type: boolean
podSecurityContext:
nullable: true
properties:
appArmorProfile:
nullable: true
properties:
localhostProfile:
nullable: true
type: string
type:
nullable: true
type: string
type: object
fsGroup:
nullable: true
type: integer
fsGroupChangePolicy:
nullable: true
type: string
runAsGroup:
nullable: true
type: integer
runAsNonRoot:
nullable: true
type: boolean
runAsUser:
nullable: true
type: integer
seLinuxOptions:
nullable: true
properties:
level:
nullable: true
type: string
role:
nullable: true
type: string
type:
nullable: true
type: string
user:
nullable: true
type: string
type: object
seccompProfile:
nullable: true
properties:
localhostProfile:
nullable: true
type: string
type:
nullable: true
type: string
type: object
supplementalGroups:
items:
type: integer
nullable: true
type: array
supplementalGroupsPolicy:
nullable: true
type: string
sysctls:
items:
properties:
name:
nullable: true
type: string
value:
nullable: true
type: string
type: object
nullable: true
type: array
windowsOptions:
nullable: true
properties:
gmsaCredentialSpec:
nullable: true
type: string
gmsaCredentialSpecName:
nullable: true
type: string
hostProcess:
nullable: true
type: boolean
runAsUserName:
nullable: true
type: string
type: object
type: object
repo:
nullable: true
type: string
repoCA:
nullable: true
type: string
repoCAConfigMap:
nullable: true
properties:
name:
nullable: true
type: string
type: object
securityContext:
nullable: true
properties:
allowPrivilegeEscalation:
nullable: true
type: boolean
appArmorProfile:
nullable: true
properties:
localhostProfile:
nullable: true
type: string
type:
nullable: true
type: string
type: object
capabilities:
nullable: true
properties:
add:
items:
nullable: true
type: string
nullable: true
type: array
drop:
items:
nullable: true
type: string
nullable: true
type: array
type: object
privileged:
nullable: true
type: boolean
procMount:
nullable: true
type: string
readOnlyRootFilesystem:
nullable: true
type: boolean
runAsGroup:
nullable: true
type: integer
runAsNonRoot:
nullable: true
type: boolean
runAsUser:
nullable: true
type: integer
seLinuxOptions:
nullable: true
properties:
level:
nullable: true
type: string
role:
nullable: true
type: string
type:
nullable: true
type: string
user:
nullable: true
type: string
type: object
seccompProfile:
nullable: true
properties:
localhostProfile:
nullable: true
type: string
type:
nullable: true
type: string
type: object
windowsOptions:
nullable: true
properties:
gmsaCredentialSpec:
nullable: true
type: string
gmsaCredentialSpecName:
nullable: true
type: string
hostProcess:
nullable: true
type: boolean
runAsUserName:
nullable: true
type: string
type: object
type: object
set:
additionalProperties:
x-kubernetes-int-or-string: true
nullable: true
type: object
targetNamespace:
nullable: true
type: string
timeout:
nullable: true
type: string
valuesContent:
nullable: true
type: string
version:
nullable: true
type: string
type: object
status:
properties:
conditions:
items:
properties:
message:
nullable: true
type: string
reason:
nullable: true
type: string
status:
nullable: true
type: string
type:
nullable: true
type: string
type: object
nullable: true
type: array
jobName:
nullable: true
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: helmchartconfigs.helm.cattle.io
spec:
group: helm.cattle.io
names:
kind: HelmChartConfig
plural: helmchartconfigs
singular: helmchartconfig
preserveUnknownFields: false
scope: Namespaced
versions:
- name: v1
schema:
openAPIV3Schema:
properties:
spec:
properties:
failurePolicy:
nullable: true
type: string
valuesContent:
nullable: true
type: string
type: object
type: object
served: true
storage: true
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: helm-controller
name: helm-controller
spec:
replicas: 1
selector:
matchLabels:
app: helm-controller
template:
metadata:
labels:
app: helm-controller
spec:
containers:
- command:
- helm-controller
image: rancher/helm-controller:v0.16.6
name: helm-controller
---

View File

@@ -1,205 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
k8s-app: metrics-server
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rbac.authorization.k8s.io/aggregate-to-view: "true"
name: system:aggregated-metrics-reader
rules:
- apiGroups:
- metrics.k8s.io
resources:
- pods
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
k8s-app: metrics-server
name: system:metrics-server
rules:
- apiGroups:
- ""
resources:
- nodes/metrics
verbs:
- get
- apiGroups:
- ""
resources:
- pods
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
k8s-app: metrics-server
name: metrics-server-auth-reader
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: metrics-server
name: metrics-server:system:auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: metrics-server
name: system:metrics-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:metrics-server
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
ports:
- name: https
port: 443
protocol: TCP
targetPort: https
selector:
k8s-app: metrics-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
selector:
matchLabels:
k8s-app: metrics-server
strategy:
rollingUpdate:
maxUnavailable: 0
template:
metadata:
labels:
k8s-app: metrics-server
spec:
containers:
- args:
- --cert-dir=/tmp
- --secure-port=4443
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
- --kubelet-insecure-tls
- --metric-resolution=15s
image: registry.k8s.io/metrics-server/metrics-server:v0.7.2
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /livez
port: https
scheme: HTTPS
periodSeconds: 10
name: metrics-server
ports:
- containerPort: 4443
name: https
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /readyz
port: https
scheme: HTTPS
initialDelaySeconds: 20
periodSeconds: 10
resources:
requests:
cpu: 100m
memory: 200Mi
limits:
cpu: 200m
memory: 400Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
seccompProfile:
type: RuntimeDefault
volumeMounts:
- mountPath: /tmp
name: tmp-dir
nodeSelector:
kubernetes.io/os: linux
priorityClassName: system-cluster-critical
serviceAccountName: metrics-server
volumes:
- emptyDir: {}
name: tmp-dir
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
labels:
k8s-app: metrics-server
name: v1beta1.metrics.k8s.io
spec:
group: metrics.k8s.io
groupPriorityMinimum: 100
insecureSkipTLSVerify: true
service:
name: metrics-server
namespace: kube-system
version: v1beta1
versionPriority: 100

View File

@@ -1,8 +0,0 @@
apiVersion: v1
kind: Secret
metadata:
name: authentik-oauth-client-secret
namespace: monitoring
type: Opaque
stringData:
client-secret: "P6VVD9VSOpewht6kYMqRpsPNp3BUcwcJ4DUzIYIwnQ6XWtfZU3sGF3y229dqpA52e9aQVS3Bcn7SZso7ANyb6z3kcsCS7V173nH7tZtrpmHE5e7mNnLfD4LdxPWn1iWO"

View File

@@ -1,21 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-config
namespace: monitoring # Change if using a different namespace
data:
grafana.ini: |
[auth]
signout_redirect_url = https://authentik.company/application/o/<Slug of the application>/end-session/
oauth_auto_login = true
[auth.generic_oauth]
name = authentik
enabled = true
client_id = "<Client ID from above>"
client_secret = "<Client Secret from above>"
scopes = openid profile email
auth_url = https://authentik.company/application/o/authorize/
token_url = https://authentik.company/application/o/token/
api_url = https://authentik.company/application/o/userinfo/
role_attribute_path = contains(groups, 'Grafana Admins') && 'Admin' || contains(groups, 'Grafana Editors') && 'Editor' || 'Viewer'

View File

@@ -18,7 +18,7 @@ spec:
# cpu: 200m # cpu: 200m
# memory: 200Mi # memory: 200Mi
lifecycle: lifecycle:
postStartCommand: ["/bin/bash", "-c", "apt update -y && apt install ffmpeg -y"] postStartCommand: ["/bin/bash", "-c", "apt update -y && apt install ffmpeg fuse libfuse2 libc6 iproute2 -y"]
metrics: metrics:
enabled: true enabled: true
serviceMonitor: serviceMonitor:
@@ -101,7 +101,7 @@ spec:
persistence: persistence:
enabled: true enabled: true
storageClass: longhorn storageClass: longhorn
size: 512Gi size: 256Gi
nextcloudData.size: 512Gi nextcloudData.size: 256Gi
cronjob: cronjob:
enabled: true enabled: true

35
openwebui-chart.yml Normal file
View File

@@ -0,0 +1,35 @@
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: open-webui
namespace: open-webui
spec:
repo: https://helm.openwebui.com/
chart: open-webui
targetNamespace: open-webui
valuesContent: |-
logging:
level: "debug"
ingress:
enabled: true
class: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-cluster-issuer"
host: "ai.keligrubb.com"
tls: true
existingSecret: "open-webui-tls"
persistence:
enabled: true
size: 64Gi
sso:
enabled: true
enableRoleManagement: true
roleManagement:
rolesClaim: "groups"
adminRoles: "authentik Admins"
oidc:
enabled: true
providerName: "authentik"
clientId: "xCwvgZsb5376ZWjvGpjNfagYKseLcnGjBYaqnJwl"
clientSecret: "WN0CyvBG6tXkUmiXIm3UH7EtOml0UkcHV35jYbuuQ4nDN52jLDwSDg9XEAuEz4hs69FcbNPn8hYl21z2091P6AWOb186kcMr4an2dNIa3D82O092pPadQewQFZXijuNh"
providerUrl: "https://login.keligrubb.com/application/o/luma/.well-known/openid-configuration"

4
openwebui-namespace.yml Normal file
View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: open-webui

41
woodpecker-ci-chart.yml Normal file
View File

@@ -0,0 +1,41 @@
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: woodpecker-ci
namespace: git
spec:
chart: oci://ghcr.io/woodpecker-ci/helm/woodpecker
targetNamespace: git
valuesContent: |-
server:
host: "ci.keligrubb.com"
agent:
enabled: true
env:
WOODPECKER_HOST: "https://ci.keligrubb.com"
WOODPECKER_OPEN: "true"
WOODPECKER_GITEA: "true"
WOODPECKER_GITEA_URL: "https://git.keligrubb.com"
WOODPECKER_GITEA_CLIENT: "15006ffa-071e-4edb-80f3-8dae4ebf450c"
WOODPECKER_GITEA_SECRET: "gto_qo4svebb6jmjmty3scezsswxqygquf45osrmd5dfigktvemqlh7a"
ingress:
enabled: true
ingressClassName: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-cluster-issuer"
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
hosts:
- host: "ci.keligrubb.com"
paths:
- path: /
pathType: Prefix
tls:
- secretName: woodpecker-ci-tls
hosts:
- "ci.keligrubb.com"
agent:
replicas: 1
env:
WOODPECKER_BACKEND_K8S_NAMESPACE: git
WOODPECKER_MAX_WORKFLOWS: "2"
WOODPECKER_SERVER: "woodpecker-ci-server.git.svc.cluster.local:9000"