mirror of
https://github.com/auricom/home-cluster.git
synced 2025-09-09 21:30:39 +02:00
Compare commits
177 Commits
auricom-pa
...
renovate/g
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5af2e1a31e | ||
![]() |
ec731bc9fa | ||
![]() |
fdd48638fc | ||
![]() |
c32ab7fa93 | ||
![]() |
7fcf748471 | ||
![]() |
5710a51e91 | ||
![]() |
ae74f4d45c | ||
![]() |
13d1f33a29 | ||
![]() |
1e36280e7b | ||
![]() |
a7ced309bc | ||
![]() |
4f4e2f2112 | ||
![]() |
75c232fe7d | ||
![]() |
f2d3945dba | ||
![]() |
5407bd13c5 | ||
![]() |
bba7830719 | ||
![]() |
b883542381 | ||
![]() |
2bdb26c096 | ||
![]() |
90f5289388 | ||
![]() |
f5ac2a8608 | ||
![]() |
1b8fea4885 | ||
![]() |
064b698661 | ||
![]() |
b095335122 | ||
![]() |
a1d74b381a | ||
![]() |
6e80968c16 | ||
![]() |
74dc1a5cec | ||
![]() |
c51192b10c | ||
![]() |
6659c0b0e5 | ||
![]() |
2b367ce0fb | ||
![]() |
669e25bde2 | ||
![]() |
a290a59b9a | ||
![]() |
f0f1712035 | ||
![]() |
044c93aec7 | ||
![]() |
b8c7fc168e | ||
![]() |
34c4f62d75 | ||
![]() |
fec15049cc | ||
![]() |
860140e819 | ||
![]() |
edd7878dd9 | ||
![]() |
57106870da | ||
![]() |
7ef092f8be | ||
![]() |
10862205af | ||
![]() |
47ffdb5776 | ||
![]() |
9ec3d31b91 | ||
![]() |
1a6371daf6 | ||
![]() |
be24812688 | ||
![]() |
8ba629951d | ||
![]() |
b8608e6b8b | ||
![]() |
aed016836e | ||
![]() |
5846b98c52 | ||
![]() |
3fff89cc6d | ||
![]() |
503bda433a | ||
![]() |
a09042a93d | ||
![]() |
c1b788f8e2 | ||
![]() |
3e81917e8c | ||
![]() |
dd3ea7e34e | ||
![]() |
7a01cffc19 | ||
![]() |
aefb965c59 | ||
![]() |
53333aa685 | ||
![]() |
a2164db200 | ||
![]() |
787703d81a | ||
![]() |
e138dd810c | ||
![]() |
b4b0023b3e | ||
![]() |
4a0a1e699b | ||
![]() |
07c5882052 | ||
![]() |
b9ba0124aa | ||
![]() |
72341e3fb3 | ||
![]() |
de18ed75b3 | ||
![]() |
f5eb49330d | ||
![]() |
a90a874348 | ||
![]() |
d1711142b2 | ||
![]() |
363b2f06cd | ||
![]() |
5e5a92d2f1 | ||
![]() |
17dd9b01e3 | ||
![]() |
c0a6af05c6 | ||
![]() |
58739a4f0b | ||
![]() |
e5048ae5b8 | ||
![]() |
0496bb6c44 | ||
![]() |
0ba9421fc8 | ||
![]() |
645f96d836 | ||
![]() |
cfa88d449b | ||
![]() |
e631810d26 | ||
![]() |
eea258ea29 | ||
![]() |
d54a8a24a0 | ||
![]() |
d0241f9e4a | ||
![]() |
a0093f1791 | ||
![]() |
14a5bad916 | ||
![]() |
942b7a02ac | ||
![]() |
447132e698 | ||
![]() |
aae2958a86 | ||
![]() |
8e73e20277 | ||
![]() |
e4e1f39d6c | ||
![]() |
d754b9a605 | ||
![]() |
eda65010b8 | ||
![]() |
b3fd1adc0b | ||
![]() |
f612da4dea | ||
![]() |
f65476bc67 | ||
![]() |
a237836252 | ||
![]() |
3513908fe0 | ||
![]() |
c8e6569b4f | ||
![]() |
a32e1ea9ac | ||
![]() |
4a96a72ad4 | ||
![]() |
163267c01f | ||
![]() |
ae84b5c90f | ||
![]() |
1e58822ff9 | ||
![]() |
64090f6726 | ||
![]() |
3370e109b7 | ||
![]() |
e39da2cf6e | ||
![]() |
c749f48222 | ||
![]() |
8e925ed6ab | ||
![]() |
e85d87f797 | ||
![]() |
210747d035 | ||
![]() |
015261496e | ||
![]() |
566dcb1077 | ||
![]() |
27f6a041dd | ||
![]() |
1f4da645ec | ||
![]() |
a9121abaa4 | ||
![]() |
32fb57090f | ||
![]() |
9b44942c14 | ||
![]() |
5df0524700 | ||
![]() |
19eed68ce2 | ||
![]() |
82a5be323e | ||
![]() |
e41aca7321 | ||
![]() |
7780cdf24d | ||
![]() |
b2f74e5882 | ||
![]() |
062d475f7e | ||
![]() |
217c8a6d43 | ||
![]() |
1456811fd7 | ||
![]() |
83a750c0f8 | ||
![]() |
5eeae9bf00 | ||
![]() |
2f13468c4a | ||
![]() |
cf8106734e | ||
![]() |
37f12b4973 | ||
![]() |
7c3838555e | ||
![]() |
944cae7db3 | ||
![]() |
de34643721 | ||
![]() |
42a98c5d16 | ||
![]() |
9fc23d7e2c | ||
![]() |
f6b721c93d | ||
![]() |
abc58c39b0 | ||
![]() |
3a5f3ba38b | ||
![]() |
7d5c6092d1 | ||
![]() |
bb45d35433 | ||
![]() |
f28d3fc10c | ||
![]() |
4ffe8355ff | ||
![]() |
23ce5d323a | ||
![]() |
5d06406f1b | ||
![]() |
91e0761b47 | ||
![]() |
038768729f | ||
![]() |
af536e55e3 | ||
![]() |
c591d151c5 | ||
![]() |
c579fcecd2 | ||
![]() |
4b51603a59 | ||
![]() |
5e863fd53b | ||
![]() |
0267b868df | ||
![]() |
0d394ba118 | ||
![]() |
b8494c73ed | ||
![]() |
d8839f3d6d | ||
![]() |
2b35cb9b42 | ||
![]() |
6888b51140 | ||
![]() |
cc06bc3af1 | ||
![]() |
668d7884ab | ||
![]() |
7e1b7593e2 | ||
![]() |
0cfe09244c | ||
![]() |
4ec3b11218 | ||
![]() |
611ed9107d | ||
![]() |
288481f3bf | ||
![]() |
acabc00810 | ||
![]() |
fa9e278136 | ||
![]() |
6ec045bc5a | ||
![]() |
9cd520d74a | ||
![]() |
6db214c211 | ||
![]() |
539ec1b7db | ||
![]() |
94f56b30e1 | ||
![]() |
c0dde8be0a | ||
![]() |
5b82fd7742 | ||
![]() |
e04439b50e | ||
![]() |
5876dc61cd | ||
![]() |
1bd155ae8b |
16
.archive/.taskfiles/bootstrap/Taskfile.yaml
Normal file
16
.archive/.taskfiles/bootstrap/Taskfile.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
# yaml-language-server: $schema=https://taskfile.dev/schema.json
|
||||
version: '3'
|
||||
|
||||
vars:
|
||||
BOOTSTRAP_SCRIPT: '{{.SCRIPTS_DIR}}/bootstrap-talos.sh'
|
||||
|
||||
tasks:
|
||||
|
||||
default:
|
||||
desc: Bootstrap Talos and Kubernetes cluster
|
||||
cmd: bash {{.BOOTSTRAP_SCRIPT}}
|
||||
preconditions:
|
||||
- find --version | grep -q GNU
|
||||
- test -f {{.BOOTSTRAP_SCRIPT}}
|
||||
- which gum helm helmfile kubectl op talosctl yq
|
@@ -1,19 +1,19 @@
|
||||
---
|
||||
# yaml-language-server: $schema=https://schemas.budimanjojo.com/gateway.networking.k8s.io/gateway_v1.json
|
||||
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/gateway_v1.json
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: Gateway
|
||||
metadata:
|
||||
name: external
|
||||
# annotations:
|
||||
# external-dns.alpha.kubernetes.io/target: external.${SECRET_EXTERNAL_DOMAIN}
|
||||
annotations:
|
||||
external-dns.alpha.kubernetes.io/target: &hostname external.${SECRET_EXTERNAL_DOMAIN}
|
||||
spec:
|
||||
gatewayClassName: envoy-gateway
|
||||
gatewayClassName: cilium
|
||||
addresses:
|
||||
- type: IPAddress
|
||||
value: 192.168.169.122
|
||||
# infrastructure:
|
||||
# annotations:
|
||||
# external-dns.alpha.kubernetes.io/hostname: external.${SECRET_EXTERNAL_DOMAIN}
|
||||
infrastructure:
|
||||
annotations:
|
||||
external-dns.alpha.kubernetes.io/hostname: *hostname
|
||||
listeners:
|
||||
- name: http
|
||||
protocol: HTTP
|
7
.archive/kubernetes/cilium/gateway/gatewayclass.yaml
Normal file
7
.archive/kubernetes/cilium/gateway/gatewayclass.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/gatewayclass_v1.json
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: GatewayClass
|
||||
metadata:
|
||||
name: cilium
|
||||
spec:
|
||||
controllerName: io.cilium/gateway-controller
|
@@ -1,19 +1,19 @@
|
||||
---
|
||||
# yaml-language-server: $schema=https://schemas.budimanjojo.com/gateway.networking.k8s.io/gateway_v1.json
|
||||
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/gateway_v1.json
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: Gateway
|
||||
metadata:
|
||||
name: internal
|
||||
# annotations:
|
||||
# external-dns.alpha.kubernetes.io/target: internal.${SECRET_EXTERNAL_DOMAIN}
|
||||
annotations:
|
||||
external-dns.alpha.kubernetes.io/target: &hostname internal.${SECRET_EXTERNAL_DOMAIN}
|
||||
spec:
|
||||
gatewayClassName: envoy-gateway
|
||||
gatewayClassName: cilium
|
||||
addresses:
|
||||
- type: IPAddress
|
||||
value: 192.168.169.121
|
||||
# infrastructure:
|
||||
# annotations:
|
||||
# external-dns.alpha.kubernetes.io/hostname: internal.${SECRET_EXTERNAL_DOMAIN}
|
||||
infrastructure:
|
||||
annotations:
|
||||
external-dns.alpha.kubernetes.io/hostname: *hostname
|
||||
listeners:
|
||||
- name: http
|
||||
protocol: HTTP
|
9
.archive/kubernetes/cilium/gateway/kustomization.yaml
Normal file
9
.archive/kubernetes/cilium/gateway/kustomization.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
# yaml-language-server: $schema=https://json.schemastore.org/kustomization
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ./external.yaml
|
||||
- ./internal.yaml
|
||||
- ./gatewayclass.yaml
|
||||
- ./redirect.yaml
|
22
.archive/kubernetes/cilium/gateway/redirect.yaml
Normal file
22
.archive/kubernetes/cilium/gateway/redirect.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: httpsredirect
|
||||
annotations:
|
||||
external-dns.alpha.kubernetes.io/controller: none
|
||||
spec:
|
||||
parentRefs:
|
||||
- name: internal
|
||||
namespace: kube-system
|
||||
sectionName: http
|
||||
- name: external
|
||||
namespace: kube-system
|
||||
sectionName: http
|
||||
rules:
|
||||
- filters:
|
||||
- requestRedirect:
|
||||
scheme: https
|
||||
statusCode: 301
|
||||
type: RequestRedirect
|
@@ -54,20 +54,17 @@ spec:
|
||||
serviceAccount:
|
||||
create: true
|
||||
name: *app
|
||||
ingress:
|
||||
route:
|
||||
app:
|
||||
enabled: true
|
||||
className: internal
|
||||
hosts:
|
||||
- host: &host "{{ .Release.Name }}.${SECRET_EXTERNAL_DOMAIN}"
|
||||
paths:
|
||||
- path: /
|
||||
service:
|
||||
identifier: app
|
||||
port: http
|
||||
tls:
|
||||
- hosts:
|
||||
- *host
|
||||
hostnames: ["{{ .Release.Name }}.${SECRET_EXTERNAL_DOMAIN}"]
|
||||
parentRefs:
|
||||
- name: internal
|
||||
namespace: network
|
||||
sectionName: https
|
||||
rules:
|
||||
- backendRefs:
|
||||
- name: *app
|
||||
port: *port
|
||||
persistence:
|
||||
config:
|
||||
type: configMap
|
@@ -2,34 +2,6 @@
|
||||
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: &app nginx-certificates
|
||||
namespace: &namespace network
|
||||
spec:
|
||||
commonMetadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: *app
|
||||
dependsOn:
|
||||
- name: cert-manager
|
||||
namespace: cert-manager
|
||||
interval: 1h
|
||||
path: ./kubernetes/apps/network/nginx/certificates
|
||||
postBuild:
|
||||
substitute:
|
||||
APP: *app
|
||||
prune: true
|
||||
retryInterval: 2m
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
namespace: flux-system
|
||||
targetNamespace: *namespace
|
||||
timeout: 5m
|
||||
wait: false
|
||||
---
|
||||
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: &app nginx-external
|
||||
namespace: &namespace network
|
@@ -3,22 +3,18 @@
|
||||
apiVersion: external-secrets.io/v1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: freshrss
|
||||
name: opnsense-dns
|
||||
spec:
|
||||
secretStoreRef:
|
||||
kind: ClusterSecretStore
|
||||
name: onepassword-connect
|
||||
target:
|
||||
name: freshrss-secret
|
||||
name: opnsense-dns-secret
|
||||
template:
|
||||
engineVersion: v2
|
||||
data:
|
||||
OIDC_CLIENT_SECRET: "{{ .FRESHRSS_OAUTH_CLIENT_SECRET }}"
|
||||
FRESHRSS_OIDC_CLIENT_CRYPTO_KEY: "{{ .FRESHRSS_OIDC_CLIENT_CRYPTO_KEY}}"
|
||||
OPNSENSE_API_KEY: "{{ .EXTERNAL_DNS_OPNSENSE_API_KEY }}"
|
||||
OPNSENSE_API_SECRET: "{{ .EXTERNAL_DNS_OPNSENSE_API_SECRET }}"
|
||||
OPNSENSE_HOST: "{{ .OPNSENSE_HOST }}"
|
||||
dataFrom:
|
||||
- extract:
|
||||
key: authelia
|
||||
- extract:
|
||||
key: cloudnative-pg
|
||||
- extract:
|
||||
key: freshrss
|
||||
key: opnsense
|
90
.archive/kubernetes/opnsense-dns/app/helmrelease.yaml
Normal file
90
.archive/kubernetes/opnsense-dns/app/helmrelease.yaml
Normal file
@@ -0,0 +1,90 @@
|
||||
---
|
||||
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: OCIRepository
|
||||
metadata:
|
||||
name: opnsense-dns
|
||||
spec:
|
||||
interval: 5m
|
||||
layerSelector:
|
||||
mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip
|
||||
operation: copy
|
||||
ref:
|
||||
tag: 1.18.0
|
||||
url: oci://ghcr.io/home-operations/charts-mirror/external-dns
|
||||
---
|
||||
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: &app opnsense-dns
|
||||
spec:
|
||||
interval: 1h
|
||||
chartRef:
|
||||
kind: OCIRepository
|
||||
name: opnsense-dns
|
||||
install:
|
||||
remediation:
|
||||
retries: 3
|
||||
upgrade:
|
||||
cleanupOnFail: true
|
||||
remediation:
|
||||
strategy: rollback
|
||||
retries: 3
|
||||
values:
|
||||
fullnameOverride: *app
|
||||
logLevel: debug
|
||||
deploymentAnnotations:
|
||||
reloader.stakater.com/auto: "true"
|
||||
provider:
|
||||
name: webhook
|
||||
webhook:
|
||||
image:
|
||||
repository: ghcr.io/crutonjohn/external-dns-opnsense-webhook
|
||||
tag: v0.1.0@sha256:72d4f5c79e515b8a70bb2e48f6472c746671a3ae3d8ad224aa686dd7192e1609
|
||||
env:
|
||||
- name: LOG_LEVEL
|
||||
value: debug
|
||||
- name: OPNSENSE_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: &secret opnsense-dns-secret
|
||||
key: OPNSENSE_API_KEY
|
||||
- name: OPNSENSE_API_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: *secret
|
||||
key: OPNSENSE_API_SECRET
|
||||
- name: OPNSENSE_HOST
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: *secret
|
||||
key: OPNSENSE_HOST
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
timeoutSeconds: 5
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /readyz
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
timeoutSeconds: 5
|
||||
resources:
|
||||
requests:
|
||||
memory: 20Mi
|
||||
cpu: 10m
|
||||
limits:
|
||||
memory: 100Mi
|
||||
extraArgs:
|
||||
- --managed-record-types=A,AAAA
|
||||
policy: upsert-only
|
||||
registry: noop
|
||||
sources: ["gateway-httproute", "service"]
|
||||
domainFilters: ["${SECRET_EXTERNAL_DOMAIN}"]
|
||||
serviceMonitor:
|
||||
enabled: true
|
||||
podAnnotations:
|
||||
secret.reloader.stakater.com/reload: *secret
|
@@ -3,4 +3,5 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ./externalsecret.yaml
|
||||
- ./helmrelease.yaml
|
24
.archive/kubernetes/opnsense-dns/ks.yaml
Normal file
24
.archive/kubernetes/opnsense-dns/ks.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: &app opnsense-dns
|
||||
namespace: &namespace network
|
||||
spec:
|
||||
commonMetadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: *app
|
||||
dependsOn:
|
||||
- name: external-secrets-stores
|
||||
namespace: external-secrets
|
||||
interval: 1h
|
||||
path: ./kubernetes/apps/network/opnsense-dns/app
|
||||
prune: true
|
||||
retryInterval: 2m
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
namespace: flux-system
|
||||
targetNamespace: *namespace
|
||||
timeout: 5m
|
96
.github/workflows/flux-diff.yaml
vendored
96
.github/workflows/flux-diff.yaml
vendored
@@ -1,96 +0,0 @@
|
||||
---
|
||||
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
||||
name: Flux Diff
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths: [kubernetes/**]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
flux-diff:
|
||||
name: Flux Diff
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
strategy:
|
||||
matrix:
|
||||
resources: [helmrelease, kustomization]
|
||||
max-parallel: 4
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Generate Token
|
||||
uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2
|
||||
id: app-token
|
||||
with:
|
||||
app-id: "${{ secrets.BOT_APP_ID }}"
|
||||
private-key: "${{ secrets.BOT_APP_PRIVATE_KEY }}"
|
||||
|
||||
- name: Setup System Tools
|
||||
shell: bash
|
||||
run: sudo apt-get -qq update && sudo apt-get -qq install --no-install-recommends -y curl git
|
||||
|
||||
- name: Checkout Default Branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: "${{ steps.app-token.outputs.token }}"
|
||||
ref: "${{ github.event.repository.default_branch }}"
|
||||
path: default
|
||||
|
||||
- name: Checkout Pull Request Branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: "${{ steps.app-token.outputs.token }}"
|
||||
path: pull
|
||||
|
||||
- name: Diff Resources
|
||||
uses: docker://ghcr.io/allenporter/flux-local:v7.8.0@sha256:e8cd431e824eddd169763e02ef73ebb76c40740f1e1e67f6234a29b28304ce9c
|
||||
with:
|
||||
args: >-
|
||||
diff ${{ matrix.resources }}
|
||||
--unified 6
|
||||
--path /github/workspace/pull/kubernetes/flux
|
||||
--path-orig /github/workspace/default/kubernetes/flux
|
||||
--strip-attrs "helm.sh/chart,checksum/config,app.kubernetes.io/version,chart"
|
||||
--limit-bytes 10000
|
||||
--all-namespaces
|
||||
--sources "flux-system"
|
||||
--output-file diff.patch
|
||||
|
||||
- name: Generate Diff
|
||||
id: diff
|
||||
run: |
|
||||
echo "diff<<EOF" >> $GITHUB_OUTPUT
|
||||
cat diff.patch >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
echo "### Diff" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```diff' >> $GITHUB_STEP_SUMMARY
|
||||
cat diff.patch >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- if: ${{ steps.diff.outputs.diff != '' }}
|
||||
name: Add comment
|
||||
uses: mshick/add-pr-comment@v2
|
||||
with:
|
||||
repo-token: "${{ steps.app-token.outputs.token }}"
|
||||
message-id: "${{ github.event.pull_request.number }}/${{ matrix.paths }}/${{ matrix.resources }}"
|
||||
message-failure: Diff was not successful
|
||||
message: |
|
||||
```diff
|
||||
${{ steps.diff.outputs.diff }}
|
||||
```
|
||||
|
||||
# Summarize matrix https://github.community/t/status-check-for-a-matrix-jobs/127354/7
|
||||
flux-diff-success:
|
||||
if: ${{ always() }}
|
||||
needs: ["flux-diff"]
|
||||
name: Flux Diff Successful
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
|
||||
name: Check matrix status
|
||||
run: exit 1
|
115
.github/workflows/flux-image-test.yaml
vendored
115
.github/workflows/flux-image-test.yaml
vendored
@@ -1,115 +0,0 @@
|
||||
---
|
||||
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
||||
name: Flux Image Test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths: [kubernetes/**]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
extract-images:
|
||||
name: Extract Images
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
outputs:
|
||||
matrix: ${{ steps.extract-images.outputs.images }}
|
||||
steps:
|
||||
- name: Generate Token
|
||||
uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2
|
||||
id: app-token
|
||||
with:
|
||||
app-id: "${{ secrets.BOT_APP_ID }}"
|
||||
private-key: "${{ secrets.BOT_APP_PRIVATE_KEY }}"
|
||||
|
||||
- name: Setup Homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
|
||||
- name: Setup Workflow Tools
|
||||
shell: bash
|
||||
run: brew install jo yq
|
||||
|
||||
- name: Checkout Default Branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: "${{ steps.app-token.outputs.token }}"
|
||||
ref: "${{ github.event.repository.default_branch }}"
|
||||
path: default
|
||||
|
||||
- name: Checkout Pull Request Branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: "${{ steps.app-token.outputs.token }}"
|
||||
path: pull
|
||||
|
||||
- name: Gather Images in Default Branch
|
||||
uses: docker://ghcr.io/allenporter/flux-local:v7.8.0@sha256:e8cd431e824eddd169763e02ef73ebb76c40740f1e1e67f6234a29b28304ce9c
|
||||
with:
|
||||
args: >-
|
||||
get cluster
|
||||
--path /github/workspace/default/kubernetes/flux
|
||||
--enable-images
|
||||
--output yaml
|
||||
--output-file default.yaml
|
||||
|
||||
- name: Gather Images in Pull Request Branch
|
||||
uses: docker://ghcr.io/allenporter/flux-local:v7.8.0@sha256:e8cd431e824eddd169763e02ef73ebb76c40740f1e1e67f6234a29b28304ce9c
|
||||
with:
|
||||
args: >-
|
||||
get cluster
|
||||
--path /github/workspace/pull/kubernetes/flux
|
||||
--enable-images
|
||||
--output yaml
|
||||
--output-file pull.yaml
|
||||
|
||||
- name: Filter Default Branch Results
|
||||
shell: bash
|
||||
run: |
|
||||
yq -r '[.. | .images? | select(. != null)] | flatten | sort | unique | .[]' \
|
||||
default.yaml > default.txt
|
||||
|
||||
- name: Filter Pull Request Branch Results
|
||||
shell: bash
|
||||
run: |
|
||||
yq -r '[.. | .images? | select(. != null)] | flatten | sort | unique | .[]' \
|
||||
pull.yaml > pull.txt
|
||||
|
||||
- name: Compare Default and Pull Request Images
|
||||
id: extract-images
|
||||
shell: bash
|
||||
run: |
|
||||
images=$(jo -a $(grep -vf default.txt pull.txt))
|
||||
echo "images=${images}" >> $GITHUB_OUTPUT
|
||||
echo "${images}"
|
||||
echo "### Images" >> $GITHUB_STEP_SUMMARY
|
||||
echo "${images}" | jq -r 'to_entries[] | "* \(.value)"' >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
test-images:
|
||||
if: ${{ needs.extract-images.outputs.matrix != '[]' }}
|
||||
name: Test images
|
||||
runs-on: ubuntu-latest
|
||||
needs: [extract-images]
|
||||
strategy:
|
||||
matrix:
|
||||
images: ${{ fromJSON(needs.extract-images.outputs.matrix) }}
|
||||
max-parallel: 4
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Test Images
|
||||
run: docker buildx imagetools inspect ${{ matrix.images }}
|
||||
|
||||
# Summarize matrix https://github.community/t/status-check-for-a-matrix-jobs/127354/7
|
||||
test-images-success:
|
||||
if: ${{ always() }}
|
||||
needs: [test-images]
|
||||
name: Test Images Successful
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
|
||||
name: Check matrix status
|
||||
run: exit 1
|
127
.github/workflows/flux-local.yaml
vendored
Normal file
127
.github/workflows/flux-local.yaml
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
---
|
||||
name: Flux Local
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: ["main"]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
filter:
|
||||
name: Flux Local - Filter
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
changed-files: ${{ steps.changed-files.outputs.changed_files }}
|
||||
steps:
|
||||
- name: Get Changed Files
|
||||
id: changed-files
|
||||
uses: bjw-s-labs/action-changed-files@930cef8463348e168cab7235c47fe95a7a235f65 # v0.3.3
|
||||
with:
|
||||
patterns: kubernetes/**/*
|
||||
|
||||
test:
|
||||
if: ${{ needs.filter.outputs.changed-files != '[]' }}
|
||||
needs: filter
|
||||
name: Flux Local - Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Run flux-local test
|
||||
uses: docker://ghcr.io/allenporter/flux-local:v7.9.0
|
||||
with:
|
||||
args: >-
|
||||
test
|
||||
--all-namespaces
|
||||
--enable-helm
|
||||
--path /github/workspace/kubernetes/flux
|
||||
--verbose
|
||||
|
||||
diff:
|
||||
if: ${{ needs.filter.outputs.changed-files != '[]' }}
|
||||
needs: filter
|
||||
name: Flux Local - Diff
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
strategy:
|
||||
matrix:
|
||||
resource: ["helmrelease", "kustomization"]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout Pull Request Branch
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
path: pull
|
||||
persist-credentials: false
|
||||
|
||||
- name: Checkout Default Branch
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
path: default
|
||||
persist-credentials: false
|
||||
ref: "${{ github.event.repository.default_branch }}"
|
||||
|
||||
- name: Run flux-local diff
|
||||
uses: docker://ghcr.io/allenporter/flux-local:v7.9.0
|
||||
with:
|
||||
args: >-
|
||||
diff ${{ matrix.resource }}
|
||||
--unified 6
|
||||
--path /github/workspace/pull/kubernetes/flux
|
||||
--path-orig /github/workspace/default/kubernetes/flux
|
||||
--strip-attrs "helm.sh/chart,checksum/config,app.kubernetes.io/version,chart"
|
||||
--limit-bytes 10000
|
||||
--all-namespaces
|
||||
--sources "flux-system"
|
||||
--output-file diff.patch
|
||||
|
||||
- name: Generate Diff
|
||||
id: diff
|
||||
run: |
|
||||
echo 'diff<<EOF' >> $GITHUB_OUTPUT
|
||||
cat diff.patch >> $GITHUB_OUTPUT
|
||||
echo 'EOF' >> $GITHUB_OUTPUT
|
||||
|
||||
- if: ${{ steps.diff.outputs.diff != '' }}
|
||||
name: Generate Token
|
||||
uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.BOT_APP_ID }}
|
||||
private-key: ${{ secrets.BOT_APP_PRIVATE_KEY }}
|
||||
|
||||
- if: ${{ steps.diff.outputs.diff != '' }}
|
||||
name: Add Comment
|
||||
uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # v2.9.4
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
header: ${{ github.event.pull_request.number }}/kubernetes/${{ matrix.resource }}
|
||||
message: |
|
||||
```diff
|
||||
${{ steps.diff.outputs.diff }}
|
||||
```
|
||||
|
||||
success:
|
||||
if: ${{ !cancelled() }}
|
||||
needs: ["test", "diff"]
|
||||
name: Flux Local - Success
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Any jobs failed?
|
||||
if: ${{ contains(needs.*.result, 'failure') }}
|
||||
run: exit 1
|
||||
|
||||
- name: All jobs passed or skipped?
|
||||
if: ${{ !(contains(needs.*.result, 'failure')) }}
|
||||
run: echo "All jobs passed or skipped" && echo "${{ toJSON(needs.*.result) }}"
|
2
.github/workflows/labeler.yml
vendored
2
.github/workflows/labeler.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
private-key: "${{ secrets.BOT_APP_PRIVATE_KEY }}"
|
||||
|
||||
- name: Labeler
|
||||
uses: actions/labeler@v5
|
||||
uses: actions/labeler@v6
|
||||
with:
|
||||
repo-token: "${{ steps.app-token.outputs.token }}"
|
||||
configuration-path: .github/labeler.yaml
|
||||
|
2
.github/workflows/labels-sync.yaml
vendored
2
.github/workflows/labels-sync.yaml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
private-key: "${{ secrets.BOT_APP_PRIVATE_KEY }}"
|
||||
|
||||
- name: Checkout Default Branch
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
token: "${{ steps.app-token.outputs.token }}"
|
||||
|
||||
|
63
.github/workflows/lychee.yaml
vendored
63
.github/workflows/lychee.yaml
vendored
@@ -1,63 +0,0 @@
|
||||
---
|
||||
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
||||
name: "Lychee"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: ["main"]
|
||||
paths: [".github/workflows/lychee.yaml"]
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
env:
|
||||
WORKFLOW_ISSUE_TITLE: "Link Checker Dashboard 🔗"
|
||||
|
||||
jobs:
|
||||
lychee:
|
||||
name: Lychee
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Generate Token
|
||||
uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2
|
||||
id: app-token
|
||||
with:
|
||||
app-id: "${{ secrets.BOT_APP_ID }}"
|
||||
private-key: "${{ secrets.BOT_APP_PRIVATE_KEY }}"
|
||||
|
||||
- name: Checkout Default Branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: "${{ steps.app-token.outputs.token }}"
|
||||
|
||||
- name: Scan For Broken Links
|
||||
uses: lycheeverse/lychee-action@5c4ee84814c983aa7164eaee476f014e53ff3963 # v2
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ steps.app-token.outputs.token }}"
|
||||
with:
|
||||
args: --verbose --no-progress --exclude-mail './**/*.md'
|
||||
output: /tmp/results.md
|
||||
|
||||
- name: Find Link Checker Issue
|
||||
id: find-issue
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: "${{ steps.app-token.outputs.token }}"
|
||||
run: |
|
||||
issue_number=$( \
|
||||
gh issue list \
|
||||
--search "in:title ${{ env.WORKFLOW_ISSUE_TITLE }}" \
|
||||
--state open \
|
||||
--json number \
|
||||
| jq --raw-output '.[0].number' \
|
||||
)
|
||||
echo "issue-number=${issue_number}" >> $GITHUB_OUTPUT
|
||||
echo "${issue_number}"
|
||||
|
||||
- name: Create or Update Issue
|
||||
uses: peter-evans/create-issue-from-file@e8ef132d6df98ed982188e460ebb3b5d4ef3a9cd # v5
|
||||
with:
|
||||
token: "${{ steps.app-token.outputs.token }}"
|
||||
title: "${{ env.WORKFLOW_ISSUE_TITLE }}"
|
||||
issue-number: "${{ steps.find-issue.outputs.issue-number || '' }}"
|
||||
content-filepath: /tmp/results.md
|
4
.github/workflows/renovate.yaml
vendored
4
.github/workflows/renovate.yaml
vendored
@@ -48,7 +48,7 @@ jobs:
|
||||
private-key: "${{ secrets.BOT_APP_PRIVATE_KEY }}"
|
||||
|
||||
- name: Checkout Default Branch
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
token: "${{ steps.app-token.outputs.token }}"
|
||||
|
||||
@@ -59,7 +59,7 @@ jobs:
|
||||
echo "LOG_LEVEL=${{ github.event.inputs.logLevel || env.WORKFLOW_RENOVATE_LOG_LEVEL }}" >> "${GITHUB_ENV}"
|
||||
|
||||
- name: Renovate
|
||||
uses: renovatebot/github-action@85b17ebd5abf43d1c34c01bd4c8dbb8d45bbc2c7 # v43.0.7
|
||||
uses: renovatebot/github-action@7876d7a812254599d262d62b6b2c2706018258a2 # v43.0.10
|
||||
with:
|
||||
configurationFile: "${{ env.RENOVATE_ONBOARDING_CONFIG_FILE_NAME }}"
|
||||
token: "${{ steps.app-token.outputs.token }}"
|
||||
|
89
.just/bootstrap.just
Normal file
89
.just/bootstrap.just
Normal file
@@ -0,0 +1,89 @@
|
||||
set quiet
|
||||
set shell := ['bash', '-eu', '-o', 'pipefail', '-c']
|
||||
|
||||
bootstrap_dir := justfile_dir() + '/bootstrap'
|
||||
kubernetes_dir := justfile_dir() + '/kubernetes'
|
||||
|
||||
controller := `talosctl config info -o yaml | yq -e '.endpoints[0]'`
|
||||
nodes := `talosctl config info -o yaml | yq -e '.nodes | join (" ")'`
|
||||
|
||||
[doc('Bootstrap Cluster')]
|
||||
default: talos kubernetes kubeconfig wait namespaces resources crds apps
|
||||
|
||||
[doc('Install Talos')]
|
||||
talos: (with-banner "Installing Talos")
|
||||
for node in {{nodes}}; do \
|
||||
if ! output=$(just talos apply-node "${node}" --insecure 2>&1); then \
|
||||
if [[ "${output}" == *"certificate required"* ]]; then \
|
||||
just log info "Talos node is already configured, skipping apply of config" "node" "${node}"; \
|
||||
continue; \
|
||||
fi; \
|
||||
just log fatal "Failed to apply Talos node configuration" "node" "${node}" "output" "${output}"; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
[doc('Install Kubernetes')]
|
||||
kubernetes: (with-banner "Installing Kubernetes")
|
||||
until output=$(talosctl -n "{{controller}}" bootstrap 2>&1 || true) && [[ "${output}" == *"AlreadyExists"* ]]; do \
|
||||
just log info "Talos bootstrap in progress, waiting 5 seconds..."; \
|
||||
sleep 5; \
|
||||
done
|
||||
|
||||
[doc('Fetch Kubeconfig')]
|
||||
kubeconfig: (with-banner "Fetching kubeconfig")
|
||||
if ! talosctl -n "{{controller}}" kubeconfig -f --force-context-name main "{{justfile_dir()}}" &>/dev/null; then \
|
||||
just log fatal "Failed to fetch kubeconfig"; \
|
||||
fi
|
||||
|
||||
[doc('Wait for nodes to be not-ready')]
|
||||
wait: (with-banner "Waiting for nodes to be not-ready")
|
||||
if ! kubectl wait nodes --for=condition=Ready=True --all --timeout=10s &>/dev/null; then \
|
||||
until kubectl wait nodes --for=condition=Ready=False --all --timeout=10s &>/dev/null; do \
|
||||
just log info "Nodes are not available, waiting for nodes to be available. Retrying in 5 seconds..."; \
|
||||
sleep 5; \
|
||||
done \
|
||||
fi
|
||||
|
||||
[doc('Apply Namespaces')]
|
||||
namespaces: (with-banner "Applying Namespaces")
|
||||
find "{{kubernetes_dir}}/apps" -mindepth 1 -maxdepth 1 -type d -printf "%f\n" | while IFS= read -r namespace; do \
|
||||
if kubectl get namespace "${namespace}" &>/dev/null; then \
|
||||
continue; \
|
||||
fi; \
|
||||
if ! kubectl create namespace "${namespace}" --dry-run=client -o yaml | kubectl apply --server-side -f - &>/dev/null; then \
|
||||
just log error "Failed to apply namespace" "namespace" "${namespace}"; \
|
||||
fi; \
|
||||
just log info "Namespace applied successfully" "namespace" "${namespace}"; \
|
||||
done
|
||||
|
||||
[doc('Apply Resources')]
|
||||
resources: (with-banner "Applying Resources")
|
||||
if ! resources=$(op inject -i "{{bootstrap_dir}}/resources.yaml") || [[ -z "${resources}" ]]; then \
|
||||
just log fatal "Failed to render resources"; \
|
||||
fi; \
|
||||
if ! echo "${resources}" | kubectl diff -f - &>/dev/null; then \
|
||||
if ! echo "${resources}" | kubectl apply --server-side -f - &>/dev/null; then \
|
||||
just log fatal "Failed to apply resources"; \
|
||||
fi \
|
||||
fi
|
||||
|
||||
[doc('Apply CRDs')]
|
||||
crds: (with-banner "Applying CRDs")
|
||||
if ! crds=$(helmfile --file "{{bootstrap_dir}}/helmfile.d/00-crds.yaml" template -q | yq ea -e 'select(.kind == "CustomResourceDefinition")') || [[ -z "${crds}" ]]; then \
|
||||
just log fatal "Failed to render CRDs from Helmfile"; \
|
||||
fi; \
|
||||
if ! echo "${crds}" | kubectl diff --filename - &>/dev/null; then \
|
||||
if ! echo "${crds}" | kubectl apply --server-side --filename - &>/dev/null; then \
|
||||
just log fatal "Failed to apply crds from Helmfile"; \
|
||||
fi; \
|
||||
fi
|
||||
|
||||
[doc('Apply Apps')]
|
||||
apps: (with-banner "Applying Apps")
|
||||
if ! helmfile --file "{{bootstrap_dir}}/helmfile.d/01-apps.yaml" sync --hide-notes; then \
|
||||
just log fatal "Failed to apply apps from Helmfile"; \
|
||||
fi
|
||||
|
||||
[private]
|
||||
with-banner msg:
|
||||
just log info "{{msg}}"
|
16
.just/kube.just
Normal file
16
.just/kube.just
Normal file
@@ -0,0 +1,16 @@
|
||||
set quiet
|
||||
set shell := ['bash', '-eu', '-o', 'pipefail', '-c']
|
||||
|
||||
[private]
|
||||
default:
|
||||
just --list kube
|
||||
|
||||
[doc('Spawn a shell on a node')]
|
||||
node-shell node:
|
||||
kubectl node-shell -n kube-system -x {{node}}
|
||||
|
||||
[doc('Prune all unused Pods')]
|
||||
prune-pods:
|
||||
for phase in Failed Pending Succeeded; do \
|
||||
kubectl delete pods -A --field-selector status.phase="${phase}" --ignore-not-found=true; \
|
||||
done
|
36
.just/sync.just
Normal file
36
.just/sync.just
Normal file
@@ -0,0 +1,36 @@
|
||||
set quiet
|
||||
set shell := ['bash', '-eu', '-o', 'pipefail', '-c']
|
||||
|
||||
[private]
|
||||
default:
|
||||
just --list sync
|
||||
|
||||
[doc('Sync ExternalSecrets')]
|
||||
es:
|
||||
kubectl get es -A --no-headers | while read -r ns name _; do \
|
||||
kubectl -n "${ns}" annotate --field-manager flux-client-side-apply --overwrite es "${name}" force-sync="$(date +%s)"; \
|
||||
done
|
||||
|
||||
[doc('Sync GitRepositories')]
|
||||
git:
|
||||
kubectl get gitrepo -A --no-headers | while read -r ns name _; do \
|
||||
kubectl -n "${ns}" annotate --field-manager flux-client-side-apply --overwrite gitrepo "${name}" reconcile.fluxcd.io/requestedAt="$(date +%s)"; \
|
||||
done
|
||||
|
||||
[doc('Sync HelmReleases')]
|
||||
hr:
|
||||
kubectl get hr -A --no-headers | while read -r ns name _; do \
|
||||
kubectl -n "${ns}" annotate --field-manager flux-client-side-apply --overwrite hr "${name}" reconcile.fluxcd.io/requestedAt="$(date +%s)" reconcile.fluxcd.io/forceAt="$(date +%s)"; \
|
||||
done
|
||||
|
||||
[doc('Sync Kustomizations')]
|
||||
ks:
|
||||
kubectl get ks -A --no-headers | while read -r ns name _; do \
|
||||
kubectl -n "${ns}" annotate --field-manager flux-client-side-apply --overwrite ks "${name}" reconcile.fluxcd.io/requestedAt="$(date +%s)"; \
|
||||
done
|
||||
|
||||
[doc('Sync OCIRepositories')]
|
||||
oci:
|
||||
kubectl get ocirepo -A --no-headers | while read -r ns name _; do \
|
||||
kubectl -n "${ns}" annotate --field-manager flux-client-side-apply --overwrite ocirepo "${name}" reconcile.fluxcd.io/requestedAt="$(date +%s)"; \
|
||||
done
|
70
.just/talos.just
Normal file
70
.just/talos.just
Normal file
@@ -0,0 +1,70 @@
|
||||
set quiet
|
||||
set shell := ['bash', '-eu', '-o', 'pipefail', '-c']
|
||||
|
||||
scripts_dir := justfile_dir() + '/scripts'
|
||||
talos_dir := justfile_dir() + '/talos'
|
||||
temp_dir := `mktemp -d`
|
||||
|
||||
controller := `talosctl config info -o yaml | yq -e '.endpoints[0]'`
|
||||
|
||||
[private]
|
||||
default:
|
||||
just --list talos
|
||||
|
||||
[doc('Apply Node')]
|
||||
apply-node node *args:
|
||||
just talos render-config "{{node}}" | talosctl -n "{{node}}" apply-config -f /dev/stdin {{args}}
|
||||
|
||||
[doc('Download Image')]
|
||||
download-image version schematic:
|
||||
gum spin -s line --title "Downloading Talos {{version}} ..." -- \
|
||||
curl -sfL --remove-on-error --retry 5 --retry-delay 5 --retry-all-errors \
|
||||
-o "{{talos_dir}}/talos-{{version}}-{{replace_regex(schematic, '^(.{8}).*', '$1')}}.iso" \
|
||||
"https://factory.talos.dev/image/{{schematic}}/{{version}}/metal-amd64.iso"
|
||||
just log info "Downloaded Talos" version "{{version}}" schematic "{{schematic}}"
|
||||
|
||||
[doc('Generate Kubeconfig')]
|
||||
generate-kubeconfig:
|
||||
talosctl kubeconfig -n "{{controller}}" -f --force-context-name main {{justfile_dir()}}
|
||||
|
||||
[doc('Generate Schematic Id')]
|
||||
generate-schematic-id:
|
||||
curl -sX POST --data-binary "@{{talos_dir}}/schematic.yaml" \
|
||||
"https://factory.talos.dev/schematics" | jq -r '.id'
|
||||
|
||||
[doc('Reboot Node')]
|
||||
reboot-node node:
|
||||
talosctl -n {{node}} reboot -m powercycle
|
||||
|
||||
[doc('Render Config')]
|
||||
render-config node:
|
||||
minijinja-cli -D "machinetype=$(just talos machine-type {{node}})" \
|
||||
"{{talos_dir}}/machineconfig.yaml.j2" | op inject >"{{temp_dir}}/base.yaml"
|
||||
minijinja-cli -D "machinetype=$(just talos machine-type {{node}})" \
|
||||
"{{talos_dir}}/nodes/{{node}}.yaml.j2" | op inject >"{{temp_dir}}/patch.yaml"
|
||||
talosctl machineconfig patch "{{temp_dir}}/base.yaml" -p "{{temp_dir}}/patch.yaml"
|
||||
|
||||
[doc('Reset Node')]
|
||||
[confirm]
|
||||
reset-node node:
|
||||
talosctl -n "{{node}}" reset --graceful=false
|
||||
|
||||
[doc('Shutdown Node')]
|
||||
shutdown-node node:
|
||||
talosctl -n "{{node}}" shutdown --force
|
||||
|
||||
[doc('Upgrade Kubernetes')]
|
||||
upgrade-k8s version:
|
||||
talosctl -n "{{controller}}" upgrade-k8s --to {{version}}
|
||||
|
||||
[doc('Upgrade Node')]
|
||||
upgrade-node node:
|
||||
talosctl -n "{{node}}" upgrade -i "$(just talos machine-image)" -m powercycle --timeout=10m
|
||||
|
||||
[private]
|
||||
machine-type node:
|
||||
minijinja-cli "{{talos_dir}}/nodes/{{node}}.yaml.j2" | yq -e '.machine.type // ""'
|
||||
|
||||
[private]
|
||||
machine-image:
|
||||
minijinja-cli "{{talos_dir}}/machineconfig.yaml.j2" | yq -e '.machine.install.image // ""'
|
231
.just/volsync.just
Normal file
231
.just/volsync.just
Normal file
@@ -0,0 +1,231 @@
|
||||
set quiet
|
||||
set shell := ['bash', '-eu', '-o', 'pipefail', '-c']
|
||||
|
||||
# This justfile is used to manage certain VolSync tasks for a given application, limitations are described below.
|
||||
# 1. Fluxtomization, HelmRelease, PVC, ReplicationSource all have the same name (e.g. plex)
|
||||
# 2. ReplicationSource and ReplicationDestination are a Restic repository
|
||||
# 3. Applications are deployed as either a Kubernetes Deployment or StatefulSet
|
||||
# 4. Each application only has one PVC that is being replicated
|
||||
|
||||
scripts_dir := justfile_directory() + '/.just/volsync/scripts'
|
||||
templates_dir := justfile_directory() + '/.just/volsync/templates'
|
||||
|
||||
[private]
|
||||
default:
|
||||
just --list volsync
|
||||
|
||||
[doc('List snapshots for an application')]
|
||||
list app ns="default":
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Check preconditions
|
||||
if [[ ! -f "{{scripts_dir}}/wait.sh" ]]; then
|
||||
echo "Wait script not found"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "{{templates_dir}}/list.tmpl.yaml" ]]; then
|
||||
echo "List template not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ts=$(date +%H%M%S)
|
||||
export app="{{app}}"
|
||||
export controller=""
|
||||
export claim=""
|
||||
export puid=""
|
||||
export pgid=""
|
||||
export ns="{{ns}}"
|
||||
export previous=""
|
||||
export ts="${ts}"
|
||||
|
||||
envsubst < <(cat {{templates_dir}}/list.tmpl.yaml) | kubectl apply -f -
|
||||
bash {{scripts_dir}}/wait.sh list-{{app}}-${ts} {{ns}}
|
||||
kubectl -n {{ns}} wait job/list-{{app}}-${ts} --for condition=complete --timeout=1m
|
||||
kubectl -n {{ns}} logs job/list-{{app}}-${ts} --container list
|
||||
kubectl -n {{ns}} delete job list-{{app}}-${ts}
|
||||
|
||||
[doc('Unlock a Restic repository for an application')]
|
||||
unlock app ns="default":
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Check preconditions
|
||||
if [[ ! -f "{{scripts_dir}}/wait.sh" ]]; then
|
||||
echo "Wait script not found"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "{{templates_dir}}/unlock.tmpl.yaml" ]]; then
|
||||
echo "Unlock template not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ts=$(date +%H%M%S)
|
||||
export app="{{app}}"
|
||||
export controller=""
|
||||
export claim=""
|
||||
export puid=""
|
||||
export pgid=""
|
||||
export ns="{{ns}}"
|
||||
export previous=""
|
||||
export ts="${ts}"
|
||||
|
||||
envsubst < <(cat {{templates_dir}}/unlock.tmpl.yaml) | kubectl apply -f -
|
||||
bash {{scripts_dir}}/wait.sh unlock-{{app}}-${ts} {{ns}}
|
||||
kubectl -n {{ns}} wait job/unlock-{{app}}-${ts} --for condition=complete --timeout=1m
|
||||
kubectl -n {{ns}} logs job/{{app}}-unlock-snapshots-${ts} --container unlock-minio
|
||||
kubectl -n {{ns}} logs job/{{app}}-unlock-snapshots-${ts} --container unlock-r2
|
||||
kubectl -n {{ns}} delete job unlock-{{app}}-${ts}
|
||||
|
||||
[doc('Snapshot a PVC for an application')]
|
||||
snapshot app ns="default":
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Check preconditions
|
||||
if [[ ! -f "{{scripts_dir}}/controller.sh" ]]; then
|
||||
echo "Controller script not found"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "{{scripts_dir}}/wait.sh" ]]; then
|
||||
echo "Wait script not found"
|
||||
exit 1
|
||||
fi
|
||||
if ! kubectl -n {{ns}} get replicationsources {{app}} &>/dev/null; then
|
||||
echo "RepositorySource not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ts=$(date +%H%M%S)
|
||||
controller=$({{scripts_dir}}/controller.sh {{app}} {{ns}})
|
||||
export app="{{app}}"
|
||||
export controller="${controller}"
|
||||
export claim=""
|
||||
export puid=""
|
||||
export pgid=""
|
||||
export ns="{{ns}}"
|
||||
export previous=""
|
||||
export ts="${ts}"
|
||||
|
||||
kubectl -n {{ns}} patch replicationsources {{app}} --type merge -p '{"spec":{"trigger":{"manual":"'${ts}'"}}}'
|
||||
bash {{scripts_dir}}/wait.sh volsync-src-{{app}} {{ns}}
|
||||
kubectl -n {{ns}} wait job/volsync-src-{{app}} --for condition=complete --timeout=120m
|
||||
|
||||
[doc('Restore a PVC for an application')]
|
||||
restore app ns="default" previous="2":
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Check preconditions
|
||||
if [[ ! -f "{{scripts_dir}}/controller.sh" ]]; then
|
||||
echo "Controller script not found"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "{{scripts_dir}}/wait.sh" ]]; then
|
||||
echo "Wait script not found"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "{{templates_dir}}/replicationdestination.tmpl.yaml" ]]; then
|
||||
echo "ReplicationDestination script not found"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "{{templates_dir}}/wipe.tmpl.yaml" ]]; then
|
||||
echo "Wipe template not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ts=$(date +%H%M%S)
|
||||
controller=$({{scripts_dir}}/controller.sh {{app}} {{ns}})
|
||||
claim=$(kubectl -n {{ns}} get replicationsources/{{app}} -o jsonpath="{.spec.sourcePVC}")
|
||||
puid=$(kubectl -n {{ns}} get replicationsources/{{app}} -o jsonpath="{.spec.restic.moverSecurityContext.runAsUser}")
|
||||
pgid=$(kubectl -n {{ns}} get replicationsources/{{app}} -o jsonpath="{.spec.restic.moverSecurityContext.runAsGroup}")
|
||||
|
||||
export app="{{app}}"
|
||||
export controller="${controller}"
|
||||
export claim="${claim}"
|
||||
export puid="${puid}"
|
||||
export pgid="${pgid}"
|
||||
export ns="{{ns}}"
|
||||
export previous="{{previous}}"
|
||||
export ts="${ts}"
|
||||
|
||||
just volsync suspend {{app}} {{ns}} "${controller}"
|
||||
just volsync wipe {{app}} {{ns}} "${claim}" "${puid}" "${pgid}" "${ts}"
|
||||
just volsync restore-internal {{app}} {{ns}} "${claim}" "${puid}" "${pgid}" "${ts}"
|
||||
just volsync resume {{app}} {{ns}}
|
||||
|
||||
[doc('Delete volume populator PVCs in all namespaces')]
|
||||
cleanup:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Delete destination PVCs
|
||||
kubectl get pvc --all-namespaces --no-headers | grep "dst-dest" | awk '{print $1 "/" $2}' | while IFS='/' read -r namespace pvc; do
|
||||
kubectl delete pvc -n "${namespace}" "${pvc}"
|
||||
done
|
||||
|
||||
# Delete cache PVCs
|
||||
kubectl get pvc --all-namespaces --no-headers | grep "dst-cache" | awk '{print $1 "/" $2}' | while IFS='/' read -r namespace pvc; do
|
||||
kubectl delete pvc -n "${namespace}" "${pvc}"
|
||||
done
|
||||
|
||||
[private]
|
||||
[doc('Suspend the Flux ks and hr')]
|
||||
suspend app ns controller:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
flux -n {{ns}} suspend kustomization {{app}}
|
||||
flux -n {{ns}} suspend helmrelease {{app}}
|
||||
kubectl -n {{ns}} scale {{controller}} --replicas 0
|
||||
kubectl -n {{ns}} wait pod --for delete --selector="app.kubernetes.io/name={{app}}" --timeout=2m
|
||||
|
||||
[private]
|
||||
[doc('Wipe the PVC of all data')]
|
||||
wipe app ns claim puid pgid ts:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
export app="{{app}}"
|
||||
export controller=""
|
||||
export claim="{{claim}}"
|
||||
export puid="{{puid}}"
|
||||
export pgid="{{pgid}}"
|
||||
export ns="{{ns}}"
|
||||
export previous=""
|
||||
export ts="{{ts}}"
|
||||
|
||||
envsubst < <(cat {{templates_dir}}/wipe.tmpl.yaml) | kubectl apply -f -
|
||||
bash {{scripts_dir}}/wait.sh wipe-{{app}}-{{ts}} {{ns}}
|
||||
kubectl -n {{ns}} wait job/wipe-{{app}}-{{ts}} --for condition=complete --timeout=120m
|
||||
kubectl -n {{ns}} logs job/wipe-{{app}}-{{ts}} --container wipe
|
||||
kubectl -n {{ns}} delete job wipe-{{app}}-{{ts}}
|
||||
|
||||
[private]
|
||||
[doc('Create VolSync replicationdestination CR to restore data')]
|
||||
restore-internal app ns claim puid pgid ts:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
export app="{{app}}"
|
||||
export controller=""
|
||||
export claim="{{claim}}"
|
||||
export puid="{{puid}}"
|
||||
export pgid="{{pgid}}"
|
||||
export ns="{{ns}}"
|
||||
export previous=""
|
||||
export ts="{{ts}}"
|
||||
|
||||
envsubst < <(cat {{templates_dir}}/replicationdestination.tmpl.yaml) | kubectl apply -f -
|
||||
bash {{scripts_dir}}/wait.sh volsync-dst-{{app}}-{{ts}} {{ns}}
|
||||
kubectl -n {{ns}} wait job/volsync-dst-{{app}}-{{ts}} --for condition=complete --timeout=120m
|
||||
kubectl -n {{ns}} delete replicationdestination {{app}}-{{ts}}
|
||||
|
||||
[private]
|
||||
[doc('Resume Flux ks and hr')]
|
||||
resume app ns:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
flux -n {{ns}} resume helmrelease {{app}}
|
||||
flux -n {{ns}} resume kustomization {{app}}
|
21
.just/volsync/scripts/controller.sh
Executable file
21
.just/volsync/scripts/controller.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
APP=$1
|
||||
NAMESPACE="${2:-default}"
|
||||
|
||||
is_deployment() {
|
||||
kubectl -n "${NAMESPACE}" get deployment "${APP}" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
is_statefulset() {
|
||||
kubectl -n "${NAMESPACE}" get statefulset "${APP}" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
if is_deployment; then
|
||||
echo "deployment.apps/${APP}"
|
||||
elif is_statefulset; then
|
||||
echo "statefulset.apps/${APP}"
|
||||
else
|
||||
echo "No deployment or statefulset found for ${APP}"
|
||||
exit 1
|
||||
fi
|
14
.just/volsync/scripts/wait.sh
Executable file
14
.just/volsync/scripts/wait.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
JOB=$1
|
||||
NAMESPACE="${2:-default}"
|
||||
CLUSTER="${3:-main}"
|
||||
|
||||
[[ -z "${JOB}" ]] && echo "Job name not specified" && exit 1
|
||||
while true; do
|
||||
STATUS="$(kubectl -n "${NAMESPACE}" get pod -l job-name="${JOB}" -o jsonpath='{.items[*].status.phase}')"
|
||||
if [ "${STATUS}" == "Pending" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
19
.just/volsync/templates/list.tmpl.yaml
Normal file
19
.just/volsync/templates/list.tmpl.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: "list-${app}-${ts}"
|
||||
namespace: "${ns}"
|
||||
spec:
|
||||
ttlSecondsAfterFinished: 3600
|
||||
template:
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: list
|
||||
image: docker.io/restic/restic:0.18.0@sha256:4cf4a61ef9786f4de53e9de8c8f5c040f33830eb0a10bf3d614410ee2fcb6120
|
||||
args: ["snapshots"]
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: "${app}-volsync-secret"
|
31
.just/volsync/templates/replicationdestination.tmpl.yaml
Normal file
31
.just/volsync/templates/replicationdestination.tmpl.yaml
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
apiVersion: volsync.backube/v1alpha1
|
||||
kind: ReplicationDestination
|
||||
metadata:
|
||||
name: "${app}-${ts}"
|
||||
namespace: "${ns}"
|
||||
spec:
|
||||
trigger:
|
||||
manual: restore-once
|
||||
restic:
|
||||
repository: "${app}-volsync-secret"
|
||||
destinationPVC: "${claim}"
|
||||
copyMethod: Direct
|
||||
storageClassName: rook-ceph-block
|
||||
# storageClassName: ceph-filesystem
|
||||
# accessModes: ["ReadWriteMany"]
|
||||
# IMPORTANT NOTE:
|
||||
# Set to the last X number of snapshots to restore from
|
||||
previous: ${previous}
|
||||
# OR;
|
||||
# IMPORTANT NOTE:
|
||||
# On bootstrap set `restoreAsOf` to the time the old cluster was destroyed.
|
||||
# This will essentially prevent volsync from trying to restore a backup
|
||||
# from a application that started with default data in the PVC.
|
||||
# Do not restore snapshots made after the following RFC3339 Timestamp.
|
||||
# date --rfc-3339=seconds (--utc)
|
||||
# restoreAsOf: "2022-12-10T16:00:00-05:00"
|
||||
moverSecurityContext:
|
||||
runAsUser: ${puid}
|
||||
runAsGroup: ${pgid}
|
||||
fsGroup: ${pgid}
|
25
.just/volsync/templates/unlock.tmpl.yaml
Normal file
25
.just/volsync/templates/unlock.tmpl.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: "unlock-${app}-${ts}"
|
||||
namespace: "${ns}"
|
||||
spec:
|
||||
ttlSecondsAfterFinished: 3600
|
||||
template:
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: unlock-minio
|
||||
image: docker.io/restic/restic:0.18.0@sha256:4cf4a61ef9786f4de53e9de8c8f5c040f33830eb0a10bf3d614410ee2fcb6120
|
||||
args: ["unlock", "--remove-all"]
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: "${app}-volsync-secret"
|
||||
- name: unlock-r2
|
||||
image: docker.io/restic/restic:0.18.0@sha256:4cf4a61ef9786f4de53e9de8c8f5c040f33830eb0a10bf3d614410ee2fcb6120
|
||||
args: ["unlock", "--remove-all"]
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: "${app}-volsync-r2-secret"
|
25
.just/volsync/templates/wipe.tmpl.yaml
Normal file
25
.just/volsync/templates/wipe.tmpl.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: "wipe-${app}-${ts}"
|
||||
namespace: "${ns}"
|
||||
spec:
|
||||
ttlSecondsAfterFinished: 3600
|
||||
template:
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: wipe
|
||||
image: docker.io/library/busybox:latest
|
||||
command: ["/bin/sh", "-c", "cd /config; find . -delete"]
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /config
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumes:
|
||||
- name: config
|
||||
persistentVolumeClaim:
|
||||
claimName: "${claim}"
|
27
.justfile
Normal file
27
.justfile
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env -S just --justfile
|
||||
|
||||
set quiet
|
||||
set shell := ['bash', '-eu', '-o', 'pipefail', '-c']
|
||||
|
||||
[doc('Bootstrap Recipes')]
|
||||
mod bootstrap '.just/bootstrap.just'
|
||||
|
||||
[doc('Kubernetes Recipes')]
|
||||
mod kube '.just/kube.just'
|
||||
|
||||
[doc('Sync Recipes')]
|
||||
mod sync '.just/sync.just'
|
||||
|
||||
[doc('Talos Recipes')]
|
||||
mod talos '.just/talos.just'
|
||||
|
||||
[doc('Volsync')]
|
||||
mod volsync '.just/volsync.just'
|
||||
|
||||
[private]
|
||||
default:
|
||||
just --list
|
||||
|
||||
[positional-arguments, private]
|
||||
log lvl msg *args:
|
||||
gum log -t rfc3339 -s -l "{{lvl}}" "{{msg}}" {{args}}
|
@@ -1,51 +0,0 @@
|
||||
---
|
||||
# yaml-language-server: $schema=https://taskfile.dev/schema.json
|
||||
version: '3'
|
||||
|
||||
vars:
|
||||
BOOTSTRAP_RESOURCES_DIR: '{{.ROOT_DIR}}/.taskfiles/bootstrap/resources'
|
||||
CLUSTER_DIR: '{{.ROOT_DIR}}/kubernetes'
|
||||
|
||||
tasks:
|
||||
|
||||
base:
|
||||
desc: Bootstrap Base Apps
|
||||
cmds:
|
||||
- until kubectl wait nodes --for=condition=Ready=False --all --timeout=10m; do sleep 5; done
|
||||
- helmfile --quiet --file {{.CLUSTER_DIR}}/bootstrap/apps/helmfile.yaml apply --skip-diff-on-install --suppress-diff
|
||||
- until kubectl wait nodes --for=condition=Ready --all --timeout=10m; do sleep 5; done
|
||||
preconditions:
|
||||
- talosctl config info
|
||||
# - test -f {{.CLUSTER_DIR}}/talos/cluster-0/talosconfig
|
||||
- test -f {{.CLUSTER_DIR}}/bootstrap/apps/helmfile.yaml
|
||||
- which helmfile kubectl
|
||||
|
||||
# NOTE: Nodes must all be part of the Ceph cluster and Ceph disks must share the same disk model
|
||||
rook:
|
||||
desc: Bootstrap Rook-Ceph
|
||||
cmds:
|
||||
- minijinja-cli {{.BOOTSTRAP_RESOURCES_DIR}}/wipe-rook.yaml.j2 | kubectl apply --server-side --filename -
|
||||
- until kubectl --namespace default get job/wipe-rook &>/dev/null; do sleep 5; done
|
||||
- kubectl --namespace default wait job/wipe-rook --for=condition=complete --timeout=5m
|
||||
- stern --namespace default job/wipe-rook --no-follow
|
||||
- kubectl --namespace default delete job wipe-rook
|
||||
env:
|
||||
NODE_COUNT:
|
||||
sh: talosctl config info --output json | jq --raw-output '.nodes | length'
|
||||
preconditions:
|
||||
- test -f {{.BOOTSTRAP_RESOURCES_DIR}}/wipe-rook.yaml.j2
|
||||
- which jq kubectl minijinja-cli stern talosctl
|
||||
|
||||
flux:
|
||||
desc: Bootstrap Flux
|
||||
cmds:
|
||||
- kubectl create namespace flux-system --dry-run=client -o yaml | kubectl apply --filename -
|
||||
- cat {{.SOPS_AGE_KEY}} | kubectl --namespace flux-system create secret generic sops-age --from-file=age.agekey=/dev/stdin
|
||||
- kubectl apply --server-side --kustomize {{.CLUSTER_DIR}}/bootstrap/flux
|
||||
- SOPS_AGE_KEY_FILE={{.SOPS_AGE_KEY}} sops exec-file {{.CLUSTER_DIR}}/bootstrap/flux/github-deploy-key.sops.yaml "kubectl apply --server-side --filename {}"
|
||||
- SOPS_AGE_KEY_FILE={{.SOPS_AGE_KEY}} sops exec-file {{.CLUSTER_DIR}}/flux/vars/cluster-secrets.sops.yaml "kubectl apply --server-side --filename {}"
|
||||
- kubectl apply --server-side --filename ./flux/vars/cluster-settings.yaml
|
||||
|
||||
apps:
|
||||
desc: Bootstrap Flux
|
||||
- kubectl apply --server-side --kustomize {{.CLUSTER_DIR}}/flux/config
|
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.12.0/.schema/devbox.schema.json",
|
||||
"packages": ["ansible@2.18.6", "sshpass@latest"]
|
||||
"packages": ["ansible@2.18.7", "sshpass@latest"]
|
||||
}
|
||||
|
@@ -1,67 +1,67 @@
|
||||
{
|
||||
"lockfile_version": "1",
|
||||
"packages": {
|
||||
"ansible@2.18.6": {
|
||||
"last_modified": "2025-05-24T21:46:02Z",
|
||||
"resolved": "github:NixOS/nixpkgs/edb3633f9100d9277d1c9af245a4e9337a980c07#ansible",
|
||||
"ansible@2.18.7": {
|
||||
"last_modified": "2025-07-24T15:00:16Z",
|
||||
"resolved": "github:NixOS/nixpkgs/b74a30dbc0a72e20df07d43109339f780b439291#ansible",
|
||||
"source": "devbox-search",
|
||||
"version": "2.18.6",
|
||||
"version": "2.18.7",
|
||||
"systems": {
|
||||
"aarch64-darwin": {
|
||||
"outputs": [
|
||||
{
|
||||
"name": "out",
|
||||
"path": "/nix/store/gnls4kcmy9fr5a3x7kqrsqwq2m96rrsg-python3.12-ansible-core-2.18.6",
|
||||
"path": "/nix/store/qmar5zgs9lxar7b7mriazvrka20hcslx-python3.13-ansible-core-2.18.7",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"name": "dist",
|
||||
"path": "/nix/store/8k2zgmsdlpxk759rxlgfzsqss0gqxhvp-python3.12-ansible-core-2.18.6-dist"
|
||||
"path": "/nix/store/1vwgkixmh7bm5qj8v03db8b5dnmp65q3-python3.13-ansible-core-2.18.7-dist"
|
||||
}
|
||||
],
|
||||
"store_path": "/nix/store/gnls4kcmy9fr5a3x7kqrsqwq2m96rrsg-python3.12-ansible-core-2.18.6"
|
||||
"store_path": "/nix/store/qmar5zgs9lxar7b7mriazvrka20hcslx-python3.13-ansible-core-2.18.7"
|
||||
},
|
||||
"aarch64-linux": {
|
||||
"outputs": [
|
||||
{
|
||||
"name": "out",
|
||||
"path": "/nix/store/nj97yd3bivyxs5a2j3q9gyg8304av07q-python3.12-ansible-core-2.18.6",
|
||||
"path": "/nix/store/zi2xpjjb9d6l2blr95pxdvwcjw9jjaxd-python3.13-ansible-core-2.18.7",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"name": "dist",
|
||||
"path": "/nix/store/m89q34vq01hrd0immb0ibqgln30pg0zs-python3.12-ansible-core-2.18.6-dist"
|
||||
"path": "/nix/store/6car8i7dyqcmr0x2n7z4p3d12rim2k0j-python3.13-ansible-core-2.18.7-dist"
|
||||
}
|
||||
],
|
||||
"store_path": "/nix/store/nj97yd3bivyxs5a2j3q9gyg8304av07q-python3.12-ansible-core-2.18.6"
|
||||
"store_path": "/nix/store/zi2xpjjb9d6l2blr95pxdvwcjw9jjaxd-python3.13-ansible-core-2.18.7"
|
||||
},
|
||||
"x86_64-darwin": {
|
||||
"outputs": [
|
||||
{
|
||||
"name": "out",
|
||||
"path": "/nix/store/17x48nrxx7lc60c201bv5kjxw7zvgbzf-python3.12-ansible-core-2.18.6",
|
||||
"path": "/nix/store/w8kipz2an728f5cjys6bpmkk42p6mmhf-python3.13-ansible-core-2.18.7",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"name": "dist",
|
||||
"path": "/nix/store/c9dzvapldzam22w76fxdjqjqmv2vizw8-python3.12-ansible-core-2.18.6-dist"
|
||||
"path": "/nix/store/cq7k1xwcl1z6g76qf0cdyw46dsi4c9s5-python3.13-ansible-core-2.18.7-dist"
|
||||
}
|
||||
],
|
||||
"store_path": "/nix/store/17x48nrxx7lc60c201bv5kjxw7zvgbzf-python3.12-ansible-core-2.18.6"
|
||||
"store_path": "/nix/store/w8kipz2an728f5cjys6bpmkk42p6mmhf-python3.13-ansible-core-2.18.7"
|
||||
},
|
||||
"x86_64-linux": {
|
||||
"outputs": [
|
||||
{
|
||||
"name": "out",
|
||||
"path": "/nix/store/xpzn3bbrzvqbqnm5bgkwg87v2wcbmyfg-python3.12-ansible-core-2.18.6",
|
||||
"path": "/nix/store/2q4k547d89dnvxpyw7qql77bwpc34dby-python3.13-ansible-core-2.18.7",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"name": "dist",
|
||||
"path": "/nix/store/04m7w60ygl176rrw3lyj87vsk1zbf0m6-python3.12-ansible-core-2.18.6-dist"
|
||||
"path": "/nix/store/sp5myxai1h56n8q4d6hjpz0n7raxp7yx-python3.13-ansible-core-2.18.7-dist"
|
||||
}
|
||||
],
|
||||
"store_path": "/nix/store/xpzn3bbrzvqbqnm5bgkwg87v2wcbmyfg-python3.12-ansible-core-2.18.6"
|
||||
"store_path": "/nix/store/2q4k547d89dnvxpyw7qql77bwpc34dby-python3.13-ansible-core-2.18.7"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@@ -92,6 +92,10 @@ spec:
|
||||
databases:
|
||||
- paperless
|
||||
password: *password
|
||||
- name: playnite
|
||||
databases:
|
||||
- playnite
|
||||
password: *password
|
||||
- name: prowlarr
|
||||
databases:
|
||||
- prowlarr_main
|
||||
@@ -106,6 +110,11 @@ spec:
|
||||
- radarr_main
|
||||
- radarr_log
|
||||
password: *password
|
||||
- name: radarr-archive
|
||||
databases:
|
||||
- radarr_archive_main
|
||||
- radarr_archive_log
|
||||
password: *password
|
||||
- name: sonarr
|
||||
databases:
|
||||
- sonarr_main
|
||||
@@ -186,7 +195,7 @@ spec:
|
||||
service:
|
||||
metadata:
|
||||
annotations:
|
||||
lbipam.cilium.io/ips: ${CLUSTER_LB_POSTGRES}
|
||||
io.cilium/lb-ipam-ips: ${CLUSTER_LB_POSTGRES}
|
||||
type: LoadBalancer
|
||||
replicas: *replica
|
||||
metadata:
|
||||
|
@@ -10,7 +10,7 @@ spec:
|
||||
mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip
|
||||
operation: copy
|
||||
ref:
|
||||
tag: 5.8.2
|
||||
tag: 5.8.3
|
||||
url: oci://registry.developers.crunchydata.com/crunchydata/pgo
|
||||
---
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/helmrelease-helm-v2.json
|
||||
|
@@ -0,0 +1,27 @@
|
||||
---
|
||||
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: pgadmin
|
||||
spec:
|
||||
hostnames:
|
||||
- pgadmin.${SECRET_EXTERNAL_DOMAIN}
|
||||
parentRefs:
|
||||
- group: pgadmin.networking.k8s.io
|
||||
kind: Gateway
|
||||
name: internal
|
||||
namespace: network
|
||||
sectionName: https
|
||||
rules:
|
||||
- backendRefs:
|
||||
- group: ''
|
||||
kind: Service
|
||||
name: pgadmin
|
||||
namespace: database
|
||||
port: 5050
|
||||
weight: 1
|
||||
matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
@@ -1,32 +0,0 @@
|
||||
---
|
||||
# trunk-ignore(checkov/CKV_K8S_21)
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: pgadmin
|
||||
annotations:
|
||||
gethomepage.dev/enabled: "true"
|
||||
gethomepage.dev/name: pgAdmin
|
||||
gethomepage.dev/description: PostgreSQL management tool.
|
||||
gethomepage.dev/group: Infrrastructure
|
||||
gethomepage.dev/icon: pgadmin.png
|
||||
gethomepage.dev/pod-selector: >-
|
||||
app in (
|
||||
pgadmin
|
||||
)
|
||||
spec:
|
||||
ingressClassName: internal
|
||||
tls:
|
||||
- hosts:
|
||||
- &host pgadmin.${SECRET_EXTERNAL_DOMAIN}
|
||||
rules:
|
||||
- host: *host
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: pgadmin
|
||||
port:
|
||||
number: 5050
|
@@ -4,6 +4,6 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ./externalsecret.yaml
|
||||
- ./ingress.yaml
|
||||
- ./httproute.yaml
|
||||
- ./pgadmin.yaml
|
||||
- ./service.yaml
|
||||
|
@@ -26,7 +26,7 @@ spec:
|
||||
app:
|
||||
image:
|
||||
repository: ghcr.io/dragonflydb/operator
|
||||
tag: v1.1.11@sha256:11cef45ec1079b9d97930fc99ecd08ba29d4eca55cdb45887cb0ac40ee4e4d24
|
||||
tag: v1.2.1@sha256:6aa4f9e21d7b5d1f17856e25e110d1c6762bdda27640ddfb33684b269fa826f7
|
||||
command: [/manager]
|
||||
args:
|
||||
- --health-probe-bind-address=:8081
|
||||
@@ -93,5 +93,4 @@ spec:
|
||||
interval: 1m
|
||||
scrapeTimeout: 10s
|
||||
serviceAccount:
|
||||
create: true
|
||||
name: *app
|
||||
dragonfly-operator: {}
|
||||
|
@@ -4,6 +4,6 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
# renovate: datasource=github-releases depName=dragonflydb/dragonfly-operator
|
||||
- https://raw.githubusercontent.com/dragonflydb/dragonfly-operator/v1.1.11/manifests/crd.yaml
|
||||
- https://raw.githubusercontent.com/dragonflydb/dragonfly-operator/v1.2.1/manifests/crd.yaml
|
||||
- ./helmrelease.yaml
|
||||
- ./rbac.yaml
|
||||
|
@@ -5,7 +5,7 @@ kind: Dragonfly
|
||||
metadata:
|
||||
name: dragonfly
|
||||
spec:
|
||||
image: ghcr.io/dragonflydb/dragonfly:v1.32.0@sha256:868bb35e6c8a039e8207c8bbf3688530fb7413f494b8fa5e15fc1bca6bfb6655
|
||||
image: ghcr.io/dragonflydb/dragonfly:v1.33.1@sha256:de1a932e51bf50d96bb8bee1b5bde96b429de38e3cab369238aeec3a93f5fdba
|
||||
replicas: 4 # set to the number of nodes in the cluster
|
||||
env:
|
||||
- name: MAX_MEMORY
|
||||
|
@@ -4,9 +4,9 @@ apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: &app dragonfly
|
||||
namespace: flux-system
|
||||
namespace: &namespace database
|
||||
spec:
|
||||
targetNamespace: database
|
||||
targetNamespace: *namespace
|
||||
commonMetadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: *app
|
||||
@@ -29,9 +29,9 @@ apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: &app dragonfly-cluster
|
||||
namespace: flux-system
|
||||
namespace: &namespace database
|
||||
spec:
|
||||
targetNamespace: database
|
||||
targetNamespace: *namespace
|
||||
commonMetadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: *app
|
||||
|
@@ -4,9 +4,9 @@ apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: &app influx
|
||||
namespace: flux-system
|
||||
namespace: &namespace database
|
||||
spec:
|
||||
targetNamespace: database
|
||||
targetNamespace: *namespace
|
||||
commonMetadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: *app
|
||||
|
@@ -94,8 +94,6 @@ spec:
|
||||
controller: *app
|
||||
type: LoadBalancer
|
||||
externalTrafficPolicy: Local
|
||||
annotations:
|
||||
external-dns.alpha.kubernetes.io/hostname: "mqtt.${SECRET_EXTERNAL_DOMAIN}"
|
||||
ports:
|
||||
mqtt:
|
||||
port: 1883
|
||||
|
@@ -9,8 +9,6 @@ spec:
|
||||
commonMetadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: *app
|
||||
components:
|
||||
- ../../../../components/gatus/guarded
|
||||
interval: 1h
|
||||
path: ./kubernetes/apps/database/mosquitto/app
|
||||
postBuild:
|
||||
|
@@ -68,31 +68,17 @@ spec:
|
||||
ports:
|
||||
http:
|
||||
port: *port
|
||||
# route:
|
||||
# app:
|
||||
# hostnames: ["sh.${SECRET_EXTERNAL_DOMAIN}"]
|
||||
# parentRefs:
|
||||
# - name: internal
|
||||
# namespace: network
|
||||
# sectionName: https
|
||||
# rules:
|
||||
# - backendRefs:
|
||||
# - name: app
|
||||
# port: *port
|
||||
ingress:
|
||||
route:
|
||||
app:
|
||||
enabled: true
|
||||
className: internal
|
||||
hosts:
|
||||
- host: &host "sh.${SECRET_EXTERNAL_DOMAIN}"
|
||||
paths:
|
||||
- path: /
|
||||
service:
|
||||
identifier: app
|
||||
port: http
|
||||
tls:
|
||||
- hosts:
|
||||
- *host
|
||||
hostnames: ["sh.${SECRET_EXTERNAL_DOMAIN}"]
|
||||
parentRefs:
|
||||
- name: internal
|
||||
namespace: network
|
||||
sectionName: https
|
||||
rules:
|
||||
- backendRefs:
|
||||
- name: *app
|
||||
port: *port
|
||||
persistence:
|
||||
config:
|
||||
existingClaim: atuin
|
||||
|
@@ -83,15 +83,6 @@ identity_providers:
|
||||
clients:
|
||||
# Genereate client_secret
|
||||
# https://www.authelia.com/integration/openid-connect/frequently-asked-questions/#how-do-i-generate-a-client-identifier-or-client-secret
|
||||
- client_id: freshrss
|
||||
client_name: freshrss
|
||||
client_secret: '{{ secret "/config/secret/FRESHRSS_OAUTH_DIGEST" }}'
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
redirect_uris: ["https://freshrss.${SECRET_EXTERNAL_DOMAIN}:443/i/oidc/"]
|
||||
scopes: [openid, profile, groups, email]
|
||||
userinfo_signed_response_alg: none
|
||||
token_endpoint_auth_method: client_secret_basic
|
||||
- client_name: grafana
|
||||
client_id: grafana
|
||||
client_secret: '{{ secret "/config/secret/GRAFANA_OAUTH_DIGEST" }}'
|
||||
@@ -142,20 +133,3 @@ identity_providers:
|
||||
scopes: [openid, profile, groups, email]
|
||||
redirect_uris: ['https://paperless.${SECRET_EXTERNAL_DOMAIN}/accounts/oidc/authelia/login/callback']
|
||||
userinfo_signed_response_alg: none
|
||||
- client_id: pgadmin
|
||||
client_name: pgAdmin
|
||||
client_secret: '{{ secret "/config/secret/PGADMIN_OAUTH_DIGEST" }}'
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
pre_configured_consent_duration: 1y
|
||||
scopes: [openid, profile, email]
|
||||
redirect_uris: ['https://pgadmin.${SECRET_EXTERNAL_DOMAIN}/oauth2/authorize']
|
||||
userinfo_signed_response_alg: none
|
||||
token_endpoint_auth_method: client_secret_basic
|
||||
- client_id: windmill
|
||||
client_name: Windmill
|
||||
client_secret: '{{ secret "/config/secret/WINDMILL_OAUTH_DIGEST" }}'
|
||||
authorization_policy: two_factor
|
||||
redirect_uris: ['https://windmill.${SECRET_EXTERNAL_DOMAIN}/user/login_callback/authelia']
|
||||
scopes: [openid, profile, groups, email]
|
||||
userinfo_signed_response_alg: none
|
||||
|
@@ -22,23 +22,17 @@ spec:
|
||||
# AUTHELIA_STORAGE_POSTGRES_TLS_SERVER_NAME: *dbHost
|
||||
# AUTHELIA_STORAGE_POSTGRES_TLS_SKIP_VERIFY: "false"
|
||||
OIDC_JWKS_KEY: "{{ .OIDC_JWKS_KEY }}"
|
||||
FRESHRSS_OAUTH_CLIENT_SECRET: "{{ .FRESHRSS_OAUTH_CLIENT_SECRET }}"
|
||||
FRESHRSS_OAUTH_DIGEST: "{{ .FRESHRSS_OAUTH_DIGEST }}"
|
||||
GRAFANA_OAUTH_CLIENT_SECRET: "{{ .GRAFANA_OAUTH_CLIENT_SECRET }}"
|
||||
GRAFANA_OAUTH_DIGEST: "{{ .GRAFANA_OAUTH_DIGEST }}"
|
||||
OUTLINE_OAUTH_CLIENT_SECRET: "{{ .OUTLINE_OAUTH_CLIENT_SECRET }}"
|
||||
OUTLINE_OAUTH_DIGEST: "{{ .OUTLINE_OAUTH_DIGEST }}"
|
||||
JELLYFIN_OAUTH_CLIENT_SECRET: "{{ .JELLYFIN_OAUTH_CLIENT_SECRET }}"
|
||||
JELLYFIN_OAUTH_DIGEST: "{{ .JELLYFIN_OAUTH_DIGEST }}"
|
||||
PGADMIN_OAUTH_CLIENT_SECRET: "{{ .PGADMIN_OAUTH_CLIENT_SECRET }}"
|
||||
PGADMIN_OAUTH_DIGEST: "{{ .PGADMIN_OAUTH_DIGEST }}"
|
||||
PAPERLESS_OAUTH_CLIENT_SECRET: "{{ .OUTLINE_OAUTH_CLIENT_SECRET }}"
|
||||
PAPERLESS_OAUTH_DIGEST: "{{ .OUTLINE_OAUTH_DIGEST }}"
|
||||
KOMGA_OAUTH_CLIENT_SECRET: "{{ .OUTLINE_OAUTH_CLIENT_SECRET }}"
|
||||
KOMGA_OAUTH_DIGEST: "{{ .OUTLINE_OAUTH_DIGEST }}"
|
||||
WINDMILL_OAUTH_CLIENT_SECRET: "{{ .WINDMILL_OAUTH_CLIENT_SECRET }}"
|
||||
WINDMILL_OAUTH_DIGEST: "{{ .WINDMILL_OAUTH_DIGEST }}"
|
||||
SECRET_PUBLIC_DOMAIN: "{{ .SECRET_PUBLIC_DOMAIN }}"
|
||||
SECRET_EXTERNAL_DOMAIN: "{{ .SECRET_EXTERNAL_DOMAIN }}"
|
||||
dataFrom:
|
||||
- extract:
|
||||
key: authelia
|
||||
|
@@ -37,7 +37,7 @@ spec:
|
||||
app:
|
||||
image:
|
||||
repository: ghcr.io/authelia/authelia
|
||||
tag: 4.39.5@sha256:023e02e5203dfa0ebaee7a48b5bae34f393d1f9cada4a9df7fbf87eb1759c671
|
||||
tag: 4.39.9@sha256:a0a6b5560cc0a3717c790dc665859d4f031e6319ffcb32009722185adb8ca89b
|
||||
env:
|
||||
AUTHELIA_LOG_LEVEL: info
|
||||
AUTHELIA_NOTIFIER_SMTP_SENDER: "Authelia <authelia@${SECRET_DOMAIN}>"
|
||||
@@ -94,34 +94,17 @@ spec:
|
||||
path: /metrics
|
||||
interval: 1m
|
||||
scrapeTimeout: 10s
|
||||
ingress:
|
||||
app:
|
||||
enabled: true
|
||||
className: external
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/configuration-snippet: |
|
||||
add_header Cache-Control "no-store";
|
||||
add_header Pragma "no-cache";
|
||||
add_header X-Frame-Options "SAMEORIGIN";
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
gethomepage.dev/enabled: "true"
|
||||
gethomepage.dev/group: Infrastructure
|
||||
gethomepage.dev/name: Authelia
|
||||
gethomepage.dev/icon: authelia.png
|
||||
gethomepage.dev/pod-selector: >-
|
||||
app in (
|
||||
authelia
|
||||
)
|
||||
hosts:
|
||||
- host: &host auth.${SECRET_EXTERNAL_DOMAIN}
|
||||
paths:
|
||||
- path: /
|
||||
service:
|
||||
identifier: app
|
||||
port: http
|
||||
tls:
|
||||
- hosts:
|
||||
- *host
|
||||
route:
|
||||
main:
|
||||
hostnames: ["auth.${SECRET_EXTERNAL_DOMAIN}"]
|
||||
parentRefs:
|
||||
- name: external
|
||||
namespace: network
|
||||
sectionName: https
|
||||
rules:
|
||||
- backendRefs:
|
||||
- name: *app
|
||||
port: *port
|
||||
persistence:
|
||||
config:
|
||||
enabled: true
|
||||
|
@@ -5,6 +5,7 @@ kind: Kustomization
|
||||
resources:
|
||||
- ./externalsecret.yaml
|
||||
- ./helmrelease.yaml
|
||||
- ./referencegrant.yaml
|
||||
configMapGenerator:
|
||||
- name: authelia-configmap
|
||||
files:
|
||||
|
30
kubernetes/apps/default/authelia/app/referencegrant.yaml
Normal file
30
kubernetes/apps/default/authelia/app/referencegrant.yaml
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/referencegrant_v1beta1.json
|
||||
apiVersion: gateway.networking.k8s.io/v1beta1
|
||||
kind: ReferenceGrant
|
||||
metadata:
|
||||
name: authelia-to-default
|
||||
spec:
|
||||
from:
|
||||
- group: gateway.envoyproxy.io
|
||||
kind: SecurityPolicy
|
||||
namespace: default
|
||||
to:
|
||||
- group: ""
|
||||
kind: Service
|
||||
name: authelia
|
||||
---
|
||||
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/referencegrant_v1beta1.json
|
||||
apiVersion: gateway.networking.k8s.io/v1beta1
|
||||
kind: ReferenceGrant
|
||||
metadata:
|
||||
name: authelia-to-observability
|
||||
spec:
|
||||
from:
|
||||
- group: gateway.envoyproxy.io
|
||||
kind: SecurityPolicy
|
||||
namespace: observability
|
||||
to:
|
||||
- group: ""
|
||||
kind: Service
|
||||
name: authelia
|
@@ -16,6 +16,8 @@ spec:
|
||||
namespace: database
|
||||
- name: external-secrets-stores
|
||||
namespace: external-secrets
|
||||
- name: gateway-api-crds
|
||||
namespace: network
|
||||
components:
|
||||
- ../../../../components/gatus/external
|
||||
interval: 1h
|
||||
|
@@ -73,7 +73,7 @@ spec:
|
||||
subcleaner:
|
||||
image:
|
||||
repository: registry.k8s.io/git-sync/git-sync
|
||||
tag: v4.4.2@sha256:3089d9787b89bdc5af01d9f6e8d515aefb9672e8aea3972d7ff67478112bacb3
|
||||
tag: v4.4.3@sha256:ee0dda4203f56848f09b41650447353edf69ab0e4319254cd854adab3074dd2e
|
||||
pullPolicy: IfNotPresent
|
||||
args:
|
||||
- --repo=https://github.com/KBlixt/subcleaner
|
||||
@@ -86,31 +86,17 @@ spec:
|
||||
ports:
|
||||
http:
|
||||
port: *port
|
||||
ingress:
|
||||
route:
|
||||
app:
|
||||
enabled: true
|
||||
className: internal
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/auth-method: GET
|
||||
nginx.ingress.kubernetes.io/auth-url: http://authelia.default.svc.cluster.local.:8888/api/verify
|
||||
nginx.ingress.kubernetes.io/auth-signin: https://auth.${SECRET_EXTERNAL_DOMAIN}?rm=$request_method
|
||||
nginx.ingress.kubernetes.io/auth-response-headers: Remote-User,Remote-Name,Remote-Groups,Remote-Email
|
||||
nginx.ingress.kubernetes.io/auth-snippet: proxy_set_header X-Forwarded-Method $request_method;
|
||||
gethomepage.dev/enabled: "true"
|
||||
gethomepage.dev/group: Media
|
||||
gethomepage.dev/name: Bazarr
|
||||
gethomepage.dev/icon: bazarr.png
|
||||
|
||||
hosts:
|
||||
- host: &host "{{ .Release.Name }}.${SECRET_EXTERNAL_DOMAIN}"
|
||||
paths:
|
||||
- path: /
|
||||
service:
|
||||
identifier: app
|
||||
port: http
|
||||
tls:
|
||||
- hosts:
|
||||
- *host
|
||||
hostnames: ["{{ .Release.Name }}.${SECRET_EXTERNAL_DOMAIN}"]
|
||||
parentRefs:
|
||||
- name: internal
|
||||
namespace: network
|
||||
sectionName: https
|
||||
rules:
|
||||
- backendRefs:
|
||||
- name: *app
|
||||
port: *port
|
||||
persistence:
|
||||
config:
|
||||
enabled: true
|
||||
|
@@ -42,35 +42,17 @@ spec:
|
||||
ports:
|
||||
http:
|
||||
port: *port
|
||||
ingress:
|
||||
route:
|
||||
app:
|
||||
enabled: true
|
||||
className: internal
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/auth-method: GET
|
||||
nginx.ingress.kubernetes.io/auth-url: http://authelia.default.svc.cluster.local.:8888/api/verify
|
||||
nginx.ingress.kubernetes.io/auth-signin: https://auth.${SECRET_EXTERNAL_DOMAIN}?rm=$request_method
|
||||
nginx.ingress.kubernetes.io/auth-response-headers: Remote-User,Remote-Name,Remote-Groups,Remote-Email
|
||||
nginx.ingress.kubernetes.io/auth-snippet: proxy_set_header X-Forwarded-Method $request_method;
|
||||
gethomepage.dev/enabled: "true"
|
||||
gethomepage.dev/name: exercisediary
|
||||
gethomepage.dev/description: Workout diary with GitHub-style year visualization.
|
||||
gethomepage.dev/group: Applications
|
||||
gethomepage.dev/icon: exercisediary.png
|
||||
gethomepage.dev/pod-selector: >-
|
||||
app in (
|
||||
exercisediary
|
||||
)
|
||||
hosts:
|
||||
- host: &host "{{ .Release.Name }}.${SECRET_EXTERNAL_DOMAIN}"
|
||||
paths:
|
||||
- path: /
|
||||
service:
|
||||
identifier: app
|
||||
port: *port
|
||||
tls:
|
||||
- hosts:
|
||||
- *host
|
||||
hostnames: ["{{ .Release.Name }}.${SECRET_EXTERNAL_DOMAIN}"]
|
||||
parentRefs:
|
||||
- name: internal
|
||||
namespace: network
|
||||
sectionName: https
|
||||
rules:
|
||||
- backendRefs:
|
||||
- name: *app
|
||||
port: *port
|
||||
persistence:
|
||||
config:
|
||||
enabled: true
|
||||
|
@@ -10,6 +10,7 @@ spec:
|
||||
labels:
|
||||
app.kubernetes.io/name: *app
|
||||
components:
|
||||
- ../../../../components/ext-auth
|
||||
- ../../../../components/gatus/external
|
||||
- ../../../../components/volsync
|
||||
dependsOn:
|
||||
@@ -22,6 +23,7 @@ spec:
|
||||
postBuild:
|
||||
substitute:
|
||||
APP: *app
|
||||
GATUS_STATUS: "401"
|
||||
VOLSYNC_CAPACITY: 2Gi
|
||||
prune: true
|
||||
retryInterval: 2m
|
||||
|
@@ -24,7 +24,7 @@ spec:
|
||||
app:
|
||||
image:
|
||||
repository: ghcr.io/flaresolverr/flaresolverr
|
||||
tag: v3.3.25@sha256:68160ec125e5cde23bc45549a443da0da0223cf4f0de7571ed2c6851cf6e1561
|
||||
tag: v3.4.0@sha256:ab535d1fef5d7f1654c2756949798442ae4bbecee99d4338128aa137fd8eca0e
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
|
@@ -32,7 +32,7 @@ spec:
|
||||
app:
|
||||
image:
|
||||
repository: jesec/flood
|
||||
tag: master@sha256:e949ba083d9d2be05852f2380863a6e02ff750ba02a31b5f0e1186b6dbee3c7d
|
||||
tag: master@sha256:0a44a4a0cc0d63e81860bd71de168de11fe207585e29828c66b7e55f42f5d366
|
||||
env:
|
||||
FLOOD_OPTION_RUNDIR: /data
|
||||
FLOOD_OPTION_AUTH: none
|
||||
@@ -51,31 +51,18 @@ spec:
|
||||
controller: *app
|
||||
ports:
|
||||
http:
|
||||
port: 3000
|
||||
ingress:
|
||||
port: &port 3000
|
||||
route:
|
||||
app:
|
||||
enabled: true
|
||||
className: internal
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/auth-method: GET
|
||||
nginx.ingress.kubernetes.io/auth-url: http://authelia.default.svc.cluster.local.:8888/api/verify
|
||||
nginx.ingress.kubernetes.io/auth-signin: https://auth.${SECRET_EXTERNAL_DOMAIN}?rm=$request_method
|
||||
nginx.ingress.kubernetes.io/auth-response-headers: Remote-User,Remote-Name,Remote-Groups,Remote-Email
|
||||
nginx.ingress.kubernetes.io/auth-snippet: proxy_set_header X-Forwarded-Method $request_method;
|
||||
gethomepage.dev/enabled: "true"
|
||||
gethomepage.dev/group: Media
|
||||
gethomepage.dev/name: qBittorrent
|
||||
gethomepage.dev/icon: qbittorrent.png
|
||||
hosts:
|
||||
- host: &host "{{ .Release.Name }}.${SECRET_EXTERNAL_DOMAIN}"
|
||||
paths:
|
||||
- path: /
|
||||
service:
|
||||
identifier: app
|
||||
port: http
|
||||
tls:
|
||||
- hosts:
|
||||
- *host
|
||||
hostnames: ["{{ .Release.Name }}.${SECRET_EXTERNAL_DOMAIN}"]
|
||||
parentRefs:
|
||||
- name: internal
|
||||
namespace: network
|
||||
sectionName: https
|
||||
rules:
|
||||
- backendRefs:
|
||||
- name: *app
|
||||
port: *port
|
||||
persistence:
|
||||
config:
|
||||
enabled: true
|
||||
|
@@ -16,6 +16,7 @@ spec:
|
||||
- name: volsync
|
||||
namespace: volsync
|
||||
components:
|
||||
- ../../../../components/ext-auth
|
||||
- ../../../../components/gatus/guarded
|
||||
- ../../../../components/volsync
|
||||
interval: 1h
|
||||
@@ -23,6 +24,7 @@ spec:
|
||||
postBuild:
|
||||
substitute:
|
||||
APP: *app
|
||||
GATUS_STATUS: "401"
|
||||
VOLSYNC_CAPACITY: 2Gi
|
||||
prune: true
|
||||
retryInterval: 2m
|
||||
|
@@ -20,65 +20,53 @@ spec:
|
||||
values:
|
||||
controllers:
|
||||
freshrss:
|
||||
annotations:
|
||||
reloader.stakater.com/auto: "true"
|
||||
secret.reloader.stakater.com/reload: authelia-secret
|
||||
containers:
|
||||
app:
|
||||
image:
|
||||
repository: freshrss/freshrss
|
||||
tag: 1.26.3@sha256:f9733e2cdf754d82e25826324fb4cbf3d736d82e2d36bf8e379dd4f0eeee0932
|
||||
tag: 1.27.0@sha256:2b53d2708fc755aab499a96e865be5ae6deeafb99e855e235e8870b4013c56cd
|
||||
env:
|
||||
TZ: ${TIMEZONE}
|
||||
CRON_MIN: 18,48
|
||||
DOMAIN: "https://freshrss.${SECRET_EXTERNAL_DOMAIN}/"
|
||||
OIDC_ENABLED: 1
|
||||
OIDC_PROVIDER_METADATA_URL: https://auth.${SECRET_EXTERNAL_DOMAIN}/.well-known/openid-configuration
|
||||
OIDC_CLIENT_ID: freshrss
|
||||
OIDC_REMOTE_USER_CLAIM: preferred_username
|
||||
OIDC_SCOPES: openid groups email profile
|
||||
OIDC_X_FORWARDED_HEADERS: X-Forwarded-Host X-Forwarded-Port X-Forwarded-Proto
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: freshrss-secret
|
||||
DOMAIN: "freshrss.${SECRET_EXTERNAL_DOMAIN}"
|
||||
LISTEN: &port 8080
|
||||
probes:
|
||||
liveness:
|
||||
enabled: true
|
||||
readiness:
|
||||
enabled: true
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 256Mi
|
||||
cpu: 12m
|
||||
memory: 128M
|
||||
limits:
|
||||
memory: 512M
|
||||
service:
|
||||
app:
|
||||
controller: *app
|
||||
ports:
|
||||
http:
|
||||
port: 80
|
||||
ingress:
|
||||
port: *port
|
||||
route:
|
||||
app:
|
||||
enabled: true
|
||||
className: internal
|
||||
annotations:
|
||||
gethomepage.dev/enabled: "true"
|
||||
gethomepage.dev/name: FreshRSS
|
||||
gethomepage.dev/description: Developer platform to turn scripts into workflows and UIs
|
||||
gethomepage.dev/group: Applications
|
||||
gethomepage.dev/icon: freshrss.png
|
||||
gethomepage.dev/href: https://windmill.${SECRET_EXTERNAL_DOMAIN}
|
||||
gethomepage.dev/pod-selector: >-
|
||||
app in (
|
||||
freshrss
|
||||
)
|
||||
hosts:
|
||||
- host: &host "{{ .Release.Name }}.${SECRET_EXTERNAL_DOMAIN}"
|
||||
paths:
|
||||
- path: /
|
||||
service:
|
||||
identifier: app
|
||||
port: http
|
||||
tls:
|
||||
- hosts:
|
||||
- *host
|
||||
hostnames: ["{{ .Release.Name }}.${SECRET_EXTERNAL_DOMAIN}"]
|
||||
parentRefs:
|
||||
- name: internal
|
||||
namespace: network
|
||||
sectionName: https
|
||||
rules:
|
||||
- backendRefs:
|
||||
- name: *app
|
||||
port: *port
|
||||
persistence:
|
||||
config:
|
||||
enabled: true
|
||||
existingClaim: *app
|
||||
globalMounts:
|
||||
- path: /var/www/FreshRSS/data
|
||||
advancedMounts:
|
||||
freshrss:
|
||||
app:
|
||||
- path: /var/www/FreshRSS/data
|
||||
subPath: data
|
||||
readOnly: false
|
||||
- path: /var/www/FreshRSS/extensions
|
||||
subPath: extensions
|
||||
readOnly: false
|
||||
|
@@ -3,5 +3,4 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ./externalsecret.yaml
|
||||
- ./helmrelease.yaml
|
||||
|
@@ -18,7 +18,6 @@ spec:
|
||||
substitute:
|
||||
APP: *app
|
||||
GATUS_PATH: /i/
|
||||
GATUS_STATUS: "401"
|
||||
VOLSYNC_CAPACITY: 2Gi
|
||||
prune: true
|
||||
retryInterval: 2m
|
||||
|
@@ -82,37 +82,18 @@ spec:
|
||||
port: *port
|
||||
rtsp:
|
||||
enabled: true
|
||||
port: 8554
|
||||
ingress:
|
||||
port: &port 8554
|
||||
route:
|
||||
app:
|
||||
enabled: true
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/auth-method: GET
|
||||
nginx.ingress.kubernetes.io/auth-url: http://authelia.default.svc.cluster.local.:8888/api/verify
|
||||
nginx.ingress.kubernetes.io/auth-signin: https://auth.${SECRET_EXTERNAL_DOMAIN}?rm=$request_method
|
||||
nginx.ingress.kubernetes.io/auth-response-headers: Remote-User,Remote-Name,Remote-Groups,Remote-Email
|
||||
nginx.ingress.kubernetes.io/auth-snippet: proxy_set_header X-Forwarded-Method $request_method;
|
||||
gethomepage.dev/enabled: "true"
|
||||
gethomepage.dev/name: Frigate
|
||||
gethomepage.dev/description: NVR with realtime local object detection for IP cameras
|
||||
gethomepage.dev/group: Applications
|
||||
gethomepage.dev/icon: frigate.png
|
||||
gethomepage.dev/href: https://frigate.${SECRET_EXTERNAL_DOMAIN}
|
||||
gethomepage.dev/pod-selector: >-
|
||||
app in (
|
||||
frigate
|
||||
)
|
||||
className: internal
|
||||
hosts:
|
||||
- host: &host "{{ .Release.Name }}.${SECRET_EXTERNAL_DOMAIN}"
|
||||
paths:
|
||||
- path: /
|
||||
service:
|
||||
identifier: app
|
||||
port: http
|
||||
tls:
|
||||
- hosts:
|
||||
- *host
|
||||
hostnames: ["{{ .Release.Name }}.${SECRET_EXTERNAL_DOMAIN}"]
|
||||
parentRefs:
|
||||
- name: internal
|
||||
namespace: network
|
||||
sectionName: https
|
||||
rules:
|
||||
- backendRefs:
|
||||
- name: *app
|
||||
port: *port
|
||||
persistence:
|
||||
config:
|
||||
enabled: true
|
||||
|
@@ -15,6 +15,7 @@ spec:
|
||||
- name: node-feature-discovery-rules
|
||||
namespace: kube-system
|
||||
components:
|
||||
- ../../../../components/ext-auth
|
||||
- ../../../../components/gatus/guarded
|
||||
- ../../../../components/volsync
|
||||
interval: 1h
|
||||
@@ -22,6 +23,7 @@ spec:
|
||||
postBuild:
|
||||
substitute:
|
||||
APP: *app
|
||||
GATUS_STATUS: "401"
|
||||
VOLSYNC_CAPACITY: 5Gi
|
||||
prune: true
|
||||
retryInterval: 2m
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user