Compare commits

..

1 Commits

Author SHA1 Message Date
2a1d7ef396 Update rmcrackan/libation Docker tag to v12.2.0
All checks were successful
lint-and-test-charts / lint-test (pull_request) Successful in 15s
renovate/stability-days Updates have met minimum release age requirement
2025-03-22 21:30:56 +00:00
736 changed files with 14204 additions and 21378 deletions

View File

@@ -1,141 +0,0 @@
name: lint-test-docker
on:
pull_request:
branches:
- main
paths:
- 'hosts/**'
push:
branches:
- main
paths:
- 'hosts/**'
env:
BASE_BRANCH: "origin/${{ gitea.base_ref }}"
jobs:
lint-docker-compose:
runs-on: ubuntu-js
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Check Branch Exists
id: check-branch-exists
if: github.event_name == 'pull_request'
uses: GuillaumeFalourd/branch-exists@v1.1
with:
branch: "${{ github.base_ref }}"
- name: Report Branch Exists
id: branch-exists
if: github.event_name == 'push' || steps.check-branch-exists.outputs.exists == 'true' && github.event_name == 'pull_request'
run: |
if [ ${{ github.event_name == 'push' }} ]; then
echo ">> Action is from a push event, will continue with linting"
else
echo ">> Branch ${{ gitea.base_ref }} exists, will continue with linting"
fi
echo "----"
echo "exists=true" >> $GITEA_OUTPUT
- name: Set up Node.js
if: steps.branch-exists.outputs.exists == 'true'
uses: actions/setup-node@v6
with:
node-version: '24'
- name: Check Directories for Changes
id: check-dir-changes
if: steps.branch-exists.outputs.exists == 'true'
run: |
CHANGED_COMPOSE=()
echo ">> Target branch for diff is: ${BASE_BRANCH}"
if [ "${{ github.event_name }}" == "pull_request" ]; then
echo ""
echo ">> Checking for changes in a pull request ..."
GIT_DIFF=$(git diff --name-only "${BASE_BRANCH}" | xargs -I {} dirname {} | sort -u)
else
echo ""
echo ">> Checking for changes from a push ..."
GIT_DIFF=$(git diff --name-only ${{ gitea.event.before }}..HEAD | xargs -I {} dirname {} | sort -u)
fi
if [ -n "${GIT_DIFF}" ]; then
echo ""
echo ">> Changes detected:"
echo "$GIT_DIFF"
for path in $GIT_DIFF; do
if echo "$path" | grep -q -E "hosts/[^/]+/[^/]+"; then
echo ""
echo ">> Adding path: $path"
CHANGED_COMPOSE+=$(echo "$path")
CHANGED_COMPOSE+=$(echo " ")
fi
done
else
echo ""
echo ">> No changes detected"
fi
if [ -n "${CHANGED_COMPOSE}" ]; then
echo ""
echo ">> Compose to Lint:"
echo "$(echo "${CHANGED_COMPOSE}" | sort -u)"
echo "----"
echo "changes-detected=true" >> $GITEA_OUTPUT
echo "compose-dir<<EOF" >> $GITEA_OUTPUT
echo "$(echo "${CHANGED_COMPOSE}" | sort -u)" >> $GITEA_OUTPUT
echo "EOF" >> $GITEA_OUTPUT
else
echo ""
echo ">> Did not find any docker compose files to lint"
echo "----"
echo "changes-detected=false" >> $GITEA_OUTPUT
fi
- name: Lint Docker Compose
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
CHANGED_COMPOSE: ${{ steps.check-dir-changes.outputs.compose-dir }}
run: |
echo ">> Running dclint on changed compose files:"
echo "$CHANGED_COMPOSE"
for compose in $CHANGED_COMPOSE; do
echo ">> Linting $compose ..."
npx dclint $compose
done
- name: ntfy Failed
uses: niniyas/ntfy-action@master
if: failure()
with:
url: '${{ secrets.NTFY_URL }}'
topic: '${{ secrets.NTFY_TOPIC }}'
title: 'Test Failure - Infrastructure'
priority: 3
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,failed
details: 'Docker linting on Pull Request for Infrastructure has failed!'
icon: 'https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png'
actions: '[{"action": "view", "label": "Open Gitea", "url": "https://gitea.alexlebens.dev/alexlebens/infrastructure/actions?workflow=lint-test-docker-pull.yaml", "clear": true}]'
image: true

View File

@@ -1,188 +0,0 @@
name: lint-test-helm
on:
pull_request:
branches:
- main
paths:
- 'clusters/cl01tl/helm/**'
push:
branches:
- main
paths:
- 'clusters/cl01tl/helm/**'
env:
CLUSTER: cl01tl
BASE_BRANCH: "origin/${{ gitea.base_ref }}"
jobs:
lint-helm:
runs-on: ubuntu-js
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Check Branch Exists
id: check-branch-exists
if: github.event_name == 'pull_request'
uses: GuillaumeFalourd/branch-exists@v1.1
with:
branch: ${{ gitea.base_ref }}
- name: Report Branch Exists
id: branch-exists
if: github.event_name == 'push' || steps.check-branch-exists.outputs.exists == 'true' && github.event_name == 'pull_request'
run: |
if [ ${{ github.event_name == 'push' }} ]; then
echo ">> Action is from a push event, will continue with linting"
else
echo ">> Branch ${{ gitea.base_ref }} exists, will continue with linting"
fi
echo "----"
echo "exists=true" >> $GITEA_OUTPUT
- name: Set up Helm
if: steps.branch-exists.outputs.exists == 'true'
uses: azure/setup-helm@v4
with:
token: ${{ secrets.GITEA_TOKEN }}
version: v3.19.2
cache: true
- name: Check Directories for Changes
id: check-dir-changes
if: steps.branch-exists.outputs.exists == 'true'
run: |
CHANGED_CHARTS=()
echo ">> Target branch for diff is: ${BASE_BRANCH}"
if [ "${{ github.event_name }}" == "pull_request" ]; then
echo ""
echo ">> Checking for changes in a pull request ..."
GIT_DIFF=$(git diff --name-only "${BASE_BRANCH}" | xargs -I {} dirname {} | sort -u)
else
echo ""
echo ">> Checking for changes from a push ..."
GIT_DIFF=$(git diff --name-only ${{ gitea.event.before }}..HEAD | xargs -I {} dirname {} | sort -u)
fi
if [ -n "${GIT_DIFF}" ]; then
echo ""
echo ">> Changes detected:"
echo "$GIT_DIFF"
for path in $GIT_DIFF; do
if echo "$path" | grep -q -E "clusters/[^/]+/helm/[^/]+"; then
echo ""
echo ">> Adding path: $path"
CHANGED_CHARTS+=$(echo "$path" | awk -F '/' '{print $4}')
CHANGED_CHARTS+=$(echo "\n")
fi
done
else
echo ""
echo ">> No changes detected"
fi
if [ -n "${CHANGED_CHARTS}" ]; then
echo ""
echo ">> Chart to Lint:"
echo "$(echo "${CHANGED_CHARTS}" | sort -u)"
echo "----"
echo "changes-detected=true" >> $GITEA_OUTPUT
echo "chart-dir<<EOF" >> $GITEA_OUTPUT
echo "$(echo "${CHANGED_CHARTS}" | sort -u)" >> $GITEA_OUTPUT
echo "EOF" >> $GITEA_OUTPUT
else
echo ""
echo ">> Did not find any helm charts files to lint"
echo "----"
echo "changes-detected=false" >> $GITEA_OUTPUT
fi
- name: Add Repositories
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
CHANGED_CHARTS: ${{ steps.check-dir-changes.outputs.chart-dir }}
run: |
echo ">> Adding repositories for chart dependencies ..."
for dir in ${CHANGED_CHARTS}; do
helm dependency list --max-col-width 120 clusters/${CLUSTER}/helm/$dir 2> /dev/null \
| tail +2 | head -n -1 \
| awk '{ print "helm repo add " $1 " " $3 }' \
| while read cmd; do
if [[ "$cmd" == "*oci://*" ]]; then
echo ">> Ignoring OCI repo"
else
echo ">> Command: $cmd"
echo "$cmd" | sh;
fi
done || true
done
if helm repo list | tail +2 | read -r; then
echo ""
echo ">> Update repository cache ..."
helm repo update
fi
echo "----"
- name: Lint Helm Chart
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
CHANGED_CHARTS: ${{ steps.check-dir-changes.outputs.chart-dir }}
run: |
echo ">> Running linting on changed charts ..."
for dir in ${CHANGED_CHARTS}; do
chart_path=clusters/${CLUSTER}/helm/$dir
chart_name=$(basename "$chart_path")
if [ -f "$chart_path/Chart.yaml" ]; then
cd $chart_path
echo ""
echo ">> Building helm dependency ..."
helm dependency build --skip-refresh
echo ""
echo ">> Linting helm ..."
helm lint --namespace "$chart_name"
else
echo ""
echo ">> Directory $chart_path does not contain a Chart.yaml. Skipping ..."
echo ""
fi
done
- name: ntfy Failed
uses: niniyas/ntfy-action@master
if: failure()
with:
url: '${{ secrets.NTFY_URL }}'
topic: '${{ secrets.NTFY_TOPIC }}'
title: 'Test Failure - Infrastructure'
priority: 3
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,failed
details: 'Helm linting on Pull Request for Infrastructure has failed!'
icon: 'https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png'
actions: '[{"action": "view", "label": "Open Gitea", "url": "https://gitea.alexlebens.dev/alexlebens/infrastructure/actions?workflow=lint-test-helm-pull.yaml", "clear": true}]'
image: true

View File

@@ -0,0 +1,37 @@
name: lint-and-test-charts
on: pull_request
jobs:
lint-test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Helm
uses: azure/setup-helm@v4
with:
version: latest
- uses: actions/setup-python@v5
with:
python-version: "3.13"
check-latest: true
- name: Set up chart-testing
uses: helm/chart-testing-action@v2.7.0
- name: Run chart-testing (list-changed)
id: list-changed
run: |
changed=$(ct list-changed --target-branch ${{ github.event.repository.default_branch }})
if [[ -n "$changed" ]]; then
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
- name: Run chart-testing (lint)
if: steps.list-changed.outputs.changed == 'true'
run: ct lint --target-branch ${{ github.event.repository.default_branch }}

View File

@@ -1,440 +0,0 @@
name: render-manifests-automerge
on:
pull_request:
branches:
- main
paths:
- 'clusters/cl01tl/helm/**'
types:
- closed
env:
CLUSTER: cl01tl
BASE_BRANCH: manifests
BRANCH_NAME_BASE: auto/update-manifests-automerge
MAIN_DIR: /workspace/alexlebens/infrastructure/infrastructure
MANIFEST_DIR: /workspace/alexlebens/infrastructure/infrastructure-manifests
jobs:
render-manifests-automerge:
runs-on: ubuntu-js
if: ${{ (github.event.pull_request.merged == true) && (contains(github.event.pull_request.labels.*.name, 'automerge')) }}
steps:
- name: Checkout Main
uses: actions/checkout@v6
with:
path: infrastructure
fetch-depth: 0
- name: Checkout Manifests
uses: actions/checkout@v6
with:
ref: manifests
path: infrastructure-manifests
- name: Set up Helm
uses: azure/setup-helm@v4
with:
token: ${{ secrets.GITEA_TOKEN }}
version: v3.17.2 # Pending https://github.com/helm/helm/pull/30743
cache: true
- name: Configure Kubeconfig
uses: azure/k8s-set-context@v4
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBECONFIG }}
- name: Prepare Manifest Branch
id: prepare-manifest-branch
run: |
cd ${MANIFEST_DIR}
BRANCH_NAME="${BRANCH_NAME_BASE}-$(date +%Y%m%d%H%M%S)"
echo ">> Configure git to use gitea-bot as user ..."
git config user.name "gitea-bot"
git config user.email "gitea-bot@alexlebens.net"
echo ">> Creating branch ..."
git checkout -b $BRANCH_NAME
echo "----"
echo "BRANCH_NAME=${BRANCH_NAME}" >> $GITEA_OUTPUT
- name: Check which Directories have Changes
id: check-dir-changes
run: |
cd ${MAIN_DIR}
RENDER_DIR=()
echo ">> Checking for changes from HEAD^..HEAD ..."
GIT_DIFF=$(git diff --name-only HEAD^..HEAD | xargs -I {} dirname {} | sort -u | grep -E "clusters/[^/]+/helm/[^/]+")
if [ -n "${GIT_DIFF}" ]; then
echo ">> Changes detected:"
echo "$GIT_DIFF"
for path in $GIT_DIFF; do
RENDER_DIR+=$(echo "$path" | awk -F '/' '{print $4}')
RENDER_DIR+=$(echo " ")
done
else
echo ">> No changes detected"
fi
if [ -n "${RENDER_DIR}" ]; then
echo ">> Directories to Render:"
echo "$(echo "${RENDER_DIR}" | sort -u)"
echo "----"
echo "changes-detected=true" >> $GITEA_OUTPUT
echo "render-dir<<EOF" >> $GITEA_OUTPUT
echo "$(echo "${RENDER_DIR}" | sort -u)" >> $GITEA_OUTPUT
echo "EOF" >> $GITEA_OUTPUT
else
echo "changes-detected=false" >> $GITEA_OUTPUT
fi
- name: Add Repositories
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MAIN_DIR}
echo ">> Adding repositories for chart dependencies ..."
for dir in ${RENDER_DIR}; do
helm dependency list --max-col-width 120 ${MAIN_DIR}/clusters/${CLUSTER}/helm/$dir 2> /dev/null \
| tail +2 | head -n -1 \
| awk '{ print "helm repo add " $1 " " $3 }' \
| while read cmd; do
if [[ "$cmd" == "*oci://*" ]]; then
echo ">> Ignoring OCI repo"
else
echo "$cmd" | sh;
fi
done || true
done
if helm repo list | tail +2 | read -r; then
echo ">> Update repository cache ..."
helm repo update
fi
echo "----"
- name: Remove Changed Manifest Files
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MANIFEST_DIR}
echo ">> Remove manfiest files and rebuild from source ..."
for dir in ${RENDER_DIR}; do
chart_path=${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$dir
echo "$chart_path"
rm -rf $chart_path/*
done
echo "----"
- name: Render Helm Manifests
id: render-manifests
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MAIN_DIR}
echo ">> Rendering Manifests ..."
for dir in ${RENDER_DIR}; do
chart_path=${MAIN_DIR}/clusters/${CLUSTER}/helm/$dir
chart_name=$(basename "$chart_path")
echo ""
echo ""
echo ">> Rendering chart: $chart_name"
echo ">> Chart path $chart_path"
if [ -f "$chart_path/Chart.yaml" ]; then
OUTPUT_FOLDER="${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$chart_name/"
TEMPLATE=""
mkdir -p ${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$chart_name
cd $chart_path
echo ""
echo ">> Updating helm dependency ..."
helm dependency update --skip-refresh
echo ""
echo ">> Building helm dependency ..."
helm dependency build --skip-refresh
echo ""
echo ">> Linting helm ..."
helm lint --namespace "$chart_name"
echo ""
echo ">> Rendering templates ..."
case "$chart_name" in
"stack")
echo ""
echo ">> Special Rendering for stack into argocd namespace ..."
TEMPLATE=$(helm template $chart_name ./ --namespace argocd --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
"cilium" | "coredns" | "metrics-server" |"prometheus-operator-crds")
echo ""
echo ">> Special Rendering for $chart_name into kube-system namespace ..."
TEMPLATE=$(helm template $chart_name ./ --namespace kube-system --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
*)
echo ""
echo ">> Standard Rendering for $chart_name ..."
TEMPLATE=$(helm template "$chart_name" ./ --namespace "$chart_name" --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
esac
echo ""
echo ">> Formating rendered template ..."
echo "$TEMPLATE" | yq '... comments=""' | yq 'select(. != null)' | yq -s '"'"$OUTPUT_FOLDER"'" + .kind + "-" + .metadata.name + ".yaml"'
# Strip comments again to ensure formatting correctness
for file in "$OUTPUT_FOLDER"/*; do
yq -i '... comments=""' $file
done
echo ""
echo ">> Manifests for $chart_name rendered to $OUTPUT_FOLDER"
ls $OUTPUT_FOLDER
echo ""
else
echo ""
echo ">> Directory $chart_path does not contain a Chart.yaml. Skipping ..."
echo ""
fi
done
echo "----"
- name: Check for Changes
id: check-changes
if: steps.check-dir-changes.outputs.changes-detected == 'true'
run: |
cd ${MANIFEST_DIR}
GIT_CHANGES=$(git status --porcelain)
if [ -n "$GIT_CHANGES" ]; then
echo ">> Changes detected"
git status --porcelain
echo "changes-detected=true" >> $GITEA_OUTPUT
else
echo ">> No changes detected, skipping PR creation"
fi
echo "----"
- name: Commit and Push Changes
id: commit-push
if: steps.check-changes.outputs.changes-detected == 'true'
env:
BRANCH_NAME: ${{ steps.prepare-manifest-branch.outputs.BRANCH_NAME }}
run: |
cd ${MANIFEST_DIR}
echo ">> Commiting changes to ${BRANCH_NAME} ..."
git add .
git commit -m "chore: Update manifests after automerge"
REPO_URL="${{ secrets.REPO_URL }}/${{ gitea.repository }}"
echo ">> Pushing changes to $REPO_URL ..."
git push -u "https://oauth2:${{ secrets.BOT_TOKEN }}@$(echo $REPO_URL | sed -e 's|https://||')" ${BRANCH_NAME}
echo "----"
echo "push=true" >> $GITEA_OUTPUT
- name: Create Pull Request
id: create-pull-request
if: steps.commit-push.outputs.push == 'true'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
BRANCH_NAME: ${{ steps.prepare-manifest-branch.outputs.BRANCH_NAME }}
run: |
cd ${MANIFEST_DIR}
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls"
PAYLOAD=$( jq -n \
--arg head "${BRANCH_NAME}" \
--arg base "${BASE_BRANCH}" \
--arg title "Automated Manifest Update - Automerge" \
--arg body "This PR contains newly rendered Kubernetes manifests automatically generated by the CI workflow. This is expected to be automerged." \
'{head: $head, base: $base, title: $title, body: $body}' )
echo ">> Creating PR from branch ${BRANCH_NAME} into ${BASE_BRANCH}"
echo ">> With Endpoint of:"
echo "$API_ENDPOINT"
echo ">> With Payload of:"
echo "$PAYLOAD"
HTTP_STATUS=$(
curl -X POST \
--silent \
--write-out '%{http_code}' \
--output response_body.json \
--dump-header response_headers.txt \
--data "$PAYLOAD" \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"$API_ENDPOINT" 2> response_errors.txt
)
echo ">> HTTP Status Code: $HTTP_STATUS"
echo ">> Response Output ..."
echo "----"
cat response_body.json
echo "----"
cat response_headers.txt
echo "----"
cat response_errors.txt
echo "----"
if [ "$HTTP_STATUS" == "201" ]; then
echo ">> Pull Request created successfully!"
PR_URL=$(cat response_body.json | jq -r .html_url)
echo ">> Pull Request URL: $PR_URL"
echo "pull-request-url=${PR_URL}" >> $GITEA_OUTPUT
PR_NUMBER=$(cat response_body.json | jq -r .number)
echo ">> Pull Request Number: $PR_NUMBER"
echo "pull-request-number=${PR_NUMBER}" >> $GITEA_OUTPUT
echo "pull-request-operation=created" >> $GITEA_OUTPUT
elif [ "$HTTP_STATUS" == "422" ]; then
echo ">> Failed to create PR (HTTP 422: Unprocessable Entity), PR may already exist"
elif [ "$HTTP_STATUS" == "409" ]; then
echo ">> Failed to create PR (HTTP 409: Conflict), PR already exists"
else
echo ">> Failed to create PR, HTTP status code: $HTTP_STATUS"
exit 1
fi
echo "----"
- name: Merge Changes
id: merge-changes
if: steps.commit-push.outputs.push == 'true'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
BRANCH_NAME: ${{ steps.prepare-manifest-branch.outputs.BRANCH_NAME }}
PR_NUMBER: ${{ steps.create-pull-request.outputs.pull-request-number }}
run: |
cd ${MANIFEST_DIR}
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls/${PR_NUMBER}/merge"
PAYLOAD=$( jq -n \
--arg Do "merge" \
'{Do: $Do}' )
echo ">> Merging PR with ID: ${PR_NUMBER}"
echo ">> With Endpoint of:"
echo "$API_ENDPOINT"
echo ">> With Payload of:"
echo "$PAYLOAD"
HTTP_STATUS=$(
curl -X POST \
--silent \
--write-out '%{http_code}' \
--output response_body.json \
--dump-header response_headers.txt \
--data "$PAYLOAD" \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"$API_ENDPOINT" 2> response_errors.txt
)
echo ">> HTTP Status Code: $HTTP_STATUS"
echo ">> Response Output ..."
echo "----"
cat response_body.json
echo "----"
cat response_headers.txt
echo "----"
cat response_errors.txt
echo "----"
if [ "$HTTP_STATUS" == "200" ]; then
echo ">> Pull Request merged successfully!"
echo "pull-request-operation=merged" >> $GITEA_OUTPUT
else
echo ">> Failed to create PR, HTTP status code: $HTTP_STATUS"
echo "pull-request-operation=failed" >> $GITEA_OUTPUT
exit 1
fi
echo "----"
- name: Cleanup Branch
if: failure()
env:
BRANCH_NAME: ${{ steps.prepare-manifest-branch.outputs.BRANCH_NAME }}
run: |
cd ${MANIFEST_DIR}
echo ">> Removing branch: ${BRANCH_NAME}"
git push origin --delete ${BRANCH_NAME}
echo "----"
- name: ntfy Merged
uses: niniyas/ntfy-action@master
if: steps.merge-changes.outputs.pull-request-operation == 'merged'
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render PR Merged - Infrastructure"
priority: 3
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,successfully,completed
details: "Automerge Manifest rendering for Infrastructure!"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "Open Gitea", "url": "${{ steps.create-pull-request.outputs.pull-request-url }}", "clear": true}]'
- name: ntfy Failed
uses: niniyas/ntfy-action@master
if: failure()
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render Failure - Infrastructure"
priority: 4
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,failed
details: "Automerge Manifest rendering for Infrastructure has failed!"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "Open Gitea", "url": "https://gitea.alexlebens.dev/alexlebens/infrastructure/actions?workflow=render-manifests-automerge.yaml", "clear": true}]'
image: true

View File

@@ -1,390 +0,0 @@
name: render-manifests-dispatch
on:
schedule:
- cron: '0 3 * * *'
workflow_dispatch:
env:
CLUSTER: cl01tl
BASE_BRANCH: manifests
BRANCH_NAME: auto/update-manifests
ASSIGNEE: alexlebens
MAIN_DIR: /workspace/alexlebens/infrastructure/infrastructure
MANIFEST_DIR: /workspace/alexlebens/infrastructure/infrastructure-manifests
jobs:
render-manifests-dispatch:
runs-on: ubuntu-js
steps:
- name: Checkout Main
uses: actions/checkout@v6
with:
path: infrastructure
fetch-depth: 0
- name: Checkout Manifests
uses: actions/checkout@v6
with:
ref: manifests
path: infrastructure-manifests
- name: Set up Helm
uses: azure/setup-helm@v4
with:
token: ${{ secrets.GITEA_TOKEN }}
version: v3.17.2 # Pending https://github.com/helm/helm/pull/30743
cache: true
- name: Configure Kubeconfig
uses: azure/k8s-set-context@v4
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBECONFIG }}
- name: Prepare Manifest Branch
run: |
cd ${MANIFEST_DIR}
echo ">> Configure git to use gitea-bot as user ..."
git config user.name "gitea-bot"
git config user.email "gitea-bot@alexlebens.net"
echo ">> Checking if PR branch exists ..."
if [[ $(git ls-remote --heads origin "${BRANCH_NAME}" | wc -l) -gt 0 ]]; then
echo ">> Branch '${BRANCH_NAME}' exists, pulling changes ..."
git fetch origin "${BRANCH_NAME}"
git checkout "${BRANCH_NAME}"
git pull --rebase
else
echo ">> Branch '${BRANCH_NAME}' does not exist, creating ..."
git checkout -b $BRANCH_NAME
fi
echo "----"
- name: Check which Directories have Changes
id: check-dir-changes
run: |
cd ${MAIN_DIR}
RENDER_DIR=()
echo ">> Triggered on dispatch, will check all paths ..."
RENDER_DIR+=$(ls clusters/cl01tl/helm/)
if [ -n "${RENDER_DIR}" ]; then
echo ">> Directories to Render:"
echo "$(echo "${RENDER_DIR}" | sort -u)"
echo "----"
echo "changes-detected=true" >> $GITEA_OUTPUT
echo "render-dir<<EOF" >> $GITEA_OUTPUT
echo "$(echo "${RENDER_DIR}" | sort -u)" >> $GITEA_OUTPUT
echo "EOF" >> $GITEA_OUTPUT
else
echo "changes-detected=false" >> $GITEA_OUTPUT
fi
- name: Add Repositories
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MAIN_DIR}
echo ">> Adding repositories for chart dependencies ..."
for dir in ${RENDER_DIR}; do
helm dependency list --max-col-width 120 ${MAIN_DIR}/clusters/${CLUSTER}/helm/$dir 2> /dev/null \
| tail +2 | head -n -1 \
| awk '{ print "helm repo add " $1 " " $3 }' \
| while read cmd; do
if [[ "$cmd" == "*oci://*" ]]; then
echo ">> Ignoring OCI repo"
else
echo "$cmd" | sh;
fi
done || true
done
if helm repo list | tail +2 | read -r; then
echo ">> Update repository cache ..."
helm repo update
fi
echo "----"
- name: Render Helm Manifests
id: render-manifests
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MAIN_DIR}
echo ">> Rendering Manifests ..."
for dir in ${RENDER_DIR}; do
chart_path=${MAIN_DIR}/clusters/${CLUSTER}/helm/$dir
chart_name=$(basename "$chart_path")
echo ""
echo ""
echo ">> Rendering chart: $chart_name"
echo ">> Chart path $chart_path"
if [ -f "$chart_path/Chart.yaml" ]; then
OUTPUT_FOLDER="${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$chart_name/"
TEMPLATE=""
mkdir -p ${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$chart_name
cd $chart_path
echo ""
echo ">> Updating helm dependency ..."
helm dependency update --skip-refresh
echo ""
echo ">> Building helm dependency ..."
helm dependency build --skip-refresh
echo ""
echo ">> Linting helm ..."
helm lint --namespace "$chart_name"
echo ""
echo ">> Rendering templates ..."
case "$chart_name" in
"stack")
echo ""
echo ">> Special Rendering for stack into argocd namespace ..."
TEMPLATE=$(helm template $chart_name ./ --namespace argocd --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
"cilium" | "coredns" | "metrics-server" |"prometheus-operator-crds")
echo ""
echo ">> Special Rendering for $chart_name into kube-system namespace ..."
TEMPLATE=$(helm template $chart_name ./ --namespace kube-system --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
*)
echo ""
echo ">> Standard Rendering for $chart_name ..."
TEMPLATE=$(helm template "$chart_name" ./ --namespace "$chart_name" --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
esac
echo ""
echo ">> Formating rendered template ..."
echo "$TEMPLATE" | yq '... comments=""' | yq 'select(. != null)' | yq -s '"'"$OUTPUT_FOLDER"'" + .kind + "-" + .metadata.name + ".yaml"'
# Strip comments again to ensure formatting correctness
for file in "$OUTPUT_FOLDER"/*; do
yq -i '... comments=""' $file
done
echo ""
echo ">> Manifests for $chart_name rendered to $OUTPUT_FOLDER"
ls $OUTPUT_FOLDER
echo ""
else
echo ""
echo ">> Directory $chart_path does not contain a Chart.yaml. Skipping ..."
echo ""
fi
done
echo "----"
- name: Check for Changes
id: check-changes
if: steps.check-dir-changes.outputs.changes-detected == 'true'
run: |
cd ${MANIFEST_DIR}
GIT_CHANGES=$(git status --porcelain)
if [ -n "$GIT_CHANGES" ]; then
echo ">> Changes detected"
git status --porcelain
echo "changes-detected=true" >> $GITEA_OUTPUT
else
echo ">> No changes detected, skipping PR creation"
fi
echo "----"
- name: Commit and Push Changes
id: commit-push
if: steps.check-changes.outputs.changes-detected == 'true'
run: |
cd ${MANIFEST_DIR}
echo ">> Commiting changes to ${BRANCH_NAME} ..."
git add .
git commit -m "chore: Update manifests after change"
REPO_URL="${{ secrets.REPO_URL }}/${{ gitea.repository }}"
echo ">> Pushing changes to $REPO_URL ..."
git push -u "https://oauth2:${{ secrets.BOT_TOKEN }}@$(echo $REPO_URL | sed -e 's|https://||')" ${BRANCH_NAME}
echo "----"
echo "HEAD_BRANCH=${BRANCH_NAME}" >> $GITEA_OUTPUT
echo "push=true" >> $GITEA_OUTPUT
- name: Check for Pull Request
id: check-for-pull-requst
if: steps.commit-push.outputs.push == 'true'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
HEAD_BRANCH: ${{ steps.commit-push.outputs.HEAD_BRANCH }}
run: |
cd ${MANIFEST_DIR}
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls?base_branch=${BASE_BRANCH}&state=open&page=1"
echo ">> Checking if PR from branch ${HEAD_BRANCH} into ${BASE_BRANCH}"
echo ">> With Endpoint of:"
echo "$API_ENDPOINT"
HTTP_STATUS=$(
curl -X GET \
--silent \
--write-out '%{http_code}' \
--output response_body.json \
--dump-header response_headers.txt \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"$API_ENDPOINT" 2> response_errors.txt
)
echo ">> HTTP Status Code: $HTTP_STATUS"
echo ">> Response Output ..."
echo "----"
cat response_body.json
echo "----"
cat response_headers.txt
echo "----"
cat response_errors.txt
echo "----"
if [ "$HTTP_STATUS" == "200" ] && [ "$(cat response_body.json | jq -r .[0].state)" == "open" ]; then
echo ">> Pull Request has been found open, will update"
PR_INDEX=$(cat response_body.json | jq -r .[0].number)
echo "pull-request-exists=${PR_INDEX}" >> $GITEA_OUTPUT
echo "pull-request-index=true" >> $GITEA_OUTPUT
elif [ "$HTTP_STATUS" == "200" ] && [ "$(cat response_body.json | jq -r .[0].state)" == "closed" ]; then
echo ">> Pull Request found, but was closed"
echo "pull-request-exists=false" >> $GITEA_OUTPUT
else
echo ">> Pull Request not found"
echo "pull-request-exists=false" >> $GITEA_OUTPUT
fi
echo "----"
- name: Create Pull Request
id: create-pull-request
if: steps.commit-push.outputs.push == 'true' && steps.check-for-pull-requst.outputs.pull-request-exists == 'false'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
HEAD_BRANCH: ${{ steps.commit-push.outputs.HEAD_BRANCH }}
run: |
cd ${MANIFEST_DIR}
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls"
PAYLOAD=$( jq -n \
--arg head "${HEAD_BRANCH}" \
--arg base "${BASE_BRANCH}" \
--arg assignee "${ASSIGNEE}" \
--arg title "Automated Manifest Update" \
--arg body "This PR contains newly rendered Kubernetes manifests automatically generated by the CI workflow." \
'{head: $head, base: $base, assignee: $assignee, title: $title, body: $body}' )
echo ">> Creating PR from branch ${HEAD_BRANCH} into ${BASE_BRANCH}"
echo ">> With Endpoint of:"
echo "$API_ENDPOINT"
echo ">> With Payload of:"
echo "$PAYLOAD"
HTTP_STATUS=$(
curl -X POST \
--silent \
--write-out '%{http_code}' \
--output response_body.json \
--dump-header response_headers.txt \
--data "$PAYLOAD" \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"$API_ENDPOINT" 2> response_errors.txt
)
echo ">> HTTP Status Code: $HTTP_STATUS"
echo ">> Response Output ..."
echo "----"
cat response_body.json
echo "----"
cat response_headers.txt
echo "----"
cat response_errors.txt
echo "----"
if [ "$HTTP_STATUS" == "201" ]; then
echo ">> Pull Request created successfully!"
PR_URL=$(cat response_body.json | jq -r .html_url)
echo "pull-request-url=${PR_URL}" >> $GITEA_OUTPUT
PR_ID=$(cat response_body.json | jq -r .id)
echo "pull-request-id=${PR_ID}" >> $GITEA_OUTPUT
echo "pull-request-operation=created" >> $GITEA_OUTPUT
elif [ "$HTTP_STATUS" == "422" ]; then
echo ">> Failed to create PR (HTTP 422: Unprocessable Entity), PR may already exist"
elif [ "$HTTP_STATUS" == "409" ]; then
echo ">> Failed to create PR (HTTP 409: Conflict), PR already exists"
else
echo ">> Failed to create PR, HTTP status code: $HTTP_STATUS"
exit 1
fi
echo "----"
- name: ntfy Created
uses: niniyas/ntfy-action@master
if: steps.create-pull-request.outputs.pull-request-operation == 'created'
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render PR Created - Infrastructure"
priority: 3
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,successfully,completed
details: "Manifest rendering for Infrastructure has created a new Pull Request with ID: ${{ steps.create-pull-request.outputs.pull-request-id }}!"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "Open Gitea", "url": "${{ steps.create-pull-request.outputs.pull-request-url }}", "clear": true}]'
- name: ntfy Failed
uses: niniyas/ntfy-action@master
if: failure()
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render Failure - Infrastructure"
priority: 4
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,failed
details: "Manifest rendering for Infrastructure has failed!"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "Open Gitea", "url": "https://gitea.alexlebens.dev/alexlebens/infrastructure/actions?workflow=render-manifests.yaml", "clear": true}]'
image: true

View File

@@ -1,425 +0,0 @@
name: render-manifests-merge
on:
pull_request:
branches:
- main
paths:
- 'clusters/cl01tl/helm/**'
types:
- closed
env:
CLUSTER: cl01tl
BASE_BRANCH: manifests
BRANCH_NAME: auto/update-manifests
ASSIGNEE: alexlebens
MAIN_DIR: /workspace/alexlebens/infrastructure/infrastructure
MANIFEST_DIR: /workspace/alexlebens/infrastructure/infrastructure-manifests
jobs:
render-manifests-merge:
runs-on: ubuntu-js
if: ${{ (github.event.pull_request.merged == true) && !(contains(github.event.pull_request.labels.*.name, 'automerge')) }}
steps:
- name: Checkout Main
uses: actions/checkout@v6
with:
path: infrastructure
fetch-depth: 0
- name: Checkout Manifests
uses: actions/checkout@v6
with:
ref: manifests
path: infrastructure-manifests
- name: Set up Helm
uses: azure/setup-helm@v4
with:
token: ${{ secrets.GITEA_TOKEN }}
version: v3.17.2 # Pending https://github.com/helm/helm/pull/30743
cache: true
- name: Configure Kubeconfig
uses: azure/k8s-set-context@v4
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBECONFIG }}
- name: Prepare Manifest Branch
run: |
cd ${MANIFEST_DIR}
echo ">> Configure git to use gitea-bot as user ..."
git config user.name "gitea-bot"
git config user.email "gitea-bot@alexlebens.net"
echo ">> Checking if PR branch exists ..."
if [[ $(git ls-remote --heads origin "${BRANCH_NAME}" | wc -l) -gt 0 ]]; then
echo ">> Branch '${BRANCH_NAME}' exists, pulling changes ..."
git fetch origin "${BRANCH_NAME}"
git checkout "${BRANCH_NAME}"
git pull --rebase
else
echo ">> Branch '${BRANCH_NAME}' does not exist, creating ..."
git checkout -b $BRANCH_NAME
fi
echo "----"
- name: Check which Directories have Changes
id: check-dir-changes
run: |
cd ${MAIN_DIR}
RENDER_DIR=()
echo ">> Checking for changes from HEAD^..HEAD ..."
GIT_DIFF=$(git diff --name-only HEAD^..HEAD | xargs -I {} dirname {} | sort -u | grep -E "clusters/[^/]+/helm/[^/]+")
if [ -n "${GIT_DIFF}" ]; then
echo ">> Changes detected:"
echo "$GIT_DIFF"
for path in $GIT_DIFF; do
RENDER_DIR+=$(echo "$path" | awk -F '/' '{print $4}')
RENDER_DIR+=$(echo " ")
done
else
echo ">> No changes detected"
fi
if [ -n "${RENDER_DIR}" ]; then
echo ">> Directories to Render:"
echo "$(echo "${RENDER_DIR}" | sort -u)"
echo "----"
echo "changes-detected=true" >> $GITEA_OUTPUT
echo "render-dir<<EOF" >> $GITEA_OUTPUT
echo "$(echo "${RENDER_DIR}" | sort -u)" >> $GITEA_OUTPUT
echo "EOF" >> $GITEA_OUTPUT
else
echo "changes-detected=false" >> $GITEA_OUTPUT
fi
- name: Add Repositories
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MAIN_DIR}
echo ">> Adding repositories for chart dependencies ..."
for dir in ${RENDER_DIR}; do
helm dependency list --max-col-width 120 ${MAIN_DIR}/clusters/${CLUSTER}/helm/$dir 2> /dev/null \
| tail +2 | head -n -1 \
| awk '{ print "helm repo add " $1 " " $3 }' \
| while read cmd; do
if [[ "$cmd" == "*oci://*" ]]; then
echo ">> Ignoring OCI repo"
else
echo "$cmd" | sh;
fi
done || true
done
if helm repo list | tail +2 | read -r; then
echo ">> Update repository cache ..."
helm repo update
fi
echo "----"
- name: Remove Changed Manifest Files
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MANIFEST_DIR}
echo ">> Remove manfiest files and rebuild from source ..."
for dir in ${RENDER_DIR}; do
chart_path=${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$dir
echo "$chart_path"
rm -rf $chart_path/*
done
echo "----"
- name: Render Helm Manifests
id: render-manifests
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MAIN_DIR}
echo ">> Rendering Manifests ..."
for dir in ${RENDER_DIR}; do
chart_path=${MAIN_DIR}/clusters/${CLUSTER}/helm/$dir
chart_name=$(basename "$chart_path")
echo ""
echo ""
echo ">> Rendering chart: $chart_name"
echo ">> Chart path $chart_path"
if [ -f "$chart_path/Chart.yaml" ]; then
OUTPUT_FOLDER="${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$chart_name/"
TEMPLATE=""
mkdir -p ${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$chart_name
cd $chart_path
echo ""
echo ">> Updating helm dependency ..."
helm dependency update --skip-refresh
echo ""
echo ">> Building helm dependency ..."
helm dependency build --skip-refresh
echo ""
echo ">> Linting helm ..."
helm lint --namespace "$chart_name"
echo ""
echo ">> Rendering templates ..."
case "$chart_name" in
"stack")
echo ""
echo ">> Special Rendering for stack into argocd namespace ..."
TEMPLATE=$(helm template $chart_name ./ --namespace argocd --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
"cilium" | "coredns" | "metrics-server" |"prometheus-operator-crds")
echo ""
echo ">> Special Rendering for $chart_name into kube-system namespace ..."
TEMPLATE=$(helm template $chart_name ./ --namespace kube-system --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
*)
echo ""
echo ">> Standard Rendering for $chart_name ..."
TEMPLATE=$(helm template "$chart_name" ./ --namespace "$chart_name" --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
esac
echo ""
echo ">> Formating rendered template ..."
echo "$TEMPLATE" | yq '... comments=""' | yq 'select(. != null)' | yq -s '"'"$OUTPUT_FOLDER"'" + .kind + "-" + .metadata.name + ".yaml"'
# Strip comments again to ensure formatting correctness
for file in "$OUTPUT_FOLDER"/*; do
yq -i '... comments=""' $file
done
echo ""
echo ">> Manifests for $chart_name rendered to $OUTPUT_FOLDER"
ls $OUTPUT_FOLDER
echo ""
else
echo ""
echo ">> Directory $chart_path does not contain a Chart.yaml. Skipping ..."
echo ""
fi
done
echo "----"
- name: Check for Changes
id: check-changes
if: steps.check-dir-changes.outputs.changes-detected == 'true'
run: |
cd ${MANIFEST_DIR}
GIT_CHANGES=$(git status --porcelain)
if [ -n "$GIT_CHANGES" ]; then
echo ">> Changes detected"
git status --porcelain
echo "changes-detected=true" >> $GITEA_OUTPUT
else
echo ">> No changes detected, skipping PR creation"
fi
echo "----"
- name: Commit and Push Changes
id: commit-push
if: steps.check-changes.outputs.changes-detected == 'true'
run: |
cd ${MANIFEST_DIR}
echo ">> Commiting changes to ${BRANCH_NAME} ..."
git add .
git commit -m "chore: Update manifests after change"
REPO_URL="${{ secrets.REPO_URL }}/${{ gitea.repository }}"
echo ">> Pushing changes to $REPO_URL ..."
git push -u "https://oauth2:${{ secrets.BOT_TOKEN }}@$(echo $REPO_URL | sed -e 's|https://||')" ${BRANCH_NAME}
echo "----"
echo "HEAD_BRANCH=${BRANCH_NAME}" >> $GITEA_OUTPUT
echo "push=true" >> $GITEA_OUTPUT
- name: Check for Pull Request
id: check-for-pull-requst
if: steps.commit-push.outputs.push == 'true'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
HEAD_BRANCH: ${{ steps.commit-push.outputs.HEAD_BRANCH }}
run: |
cd ${MANIFEST_DIR}
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls?base_branch=${BASE_BRANCH}&state=open&page=1"
echo ">> Checking if PR from branch ${HEAD_BRANCH} into ${BASE_BRANCH}"
echo ">> With Endpoint of:"
echo "$API_ENDPOINT"
HTTP_STATUS=$(
curl -X GET \
--silent \
--write-out '%{http_code}' \
--output response_body.json \
--dump-header response_headers.txt \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"$API_ENDPOINT" 2> response_errors.txt
)
echo ">> HTTP Status Code: $HTTP_STATUS"
echo ">> Response Output ..."
echo "----"
cat response_body.json
echo "----"
cat response_headers.txt
echo "----"
cat response_errors.txt
echo "----"
if [ "$HTTP_STATUS" == "200" ] && [ "$(cat response_body.json | jq -r .[0].state)" == "open" ]; then
echo ">> Pull Request has been found open, will update"
PR_INDEX=$(cat response_body.json | jq -r .[0].number)
echo "pull-request-exists=${PR_INDEX}" >> $GITEA_OUTPUT
echo "pull-request-index=true" >> $GITEA_OUTPUT
elif [ "$HTTP_STATUS" == "200" ] && [ "$(cat response_body.json | jq -r .[0].state)" == "closed" ]; then
echo ">> Pull Request found, but was closed"
echo "pull-request-exists=false" >> $GITEA_OUTPUT
else
echo ">> Pull Request not found"
echo "pull-request-exists=false" >> $GITEA_OUTPUT
fi
echo "----"
- name: Create Pull Request
id: create-pull-request
if: steps.commit-push.outputs.push == 'true' && steps.check-for-pull-requst.outputs.pull-request-exists == 'false'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
HEAD_BRANCH: ${{ steps.commit-push.outputs.HEAD_BRANCH }}
run: |
cd ${MANIFEST_DIR}
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls"
PAYLOAD=$( jq -n \
--arg head "${HEAD_BRANCH}" \
--arg base "${BASE_BRANCH}" \
--arg assignee "${ASSIGNEE}" \
--arg title "Automated Manifest Update" \
--arg body "This PR contains newly rendered Kubernetes manifests automatically generated by the CI workflow." \
'{head: $head, base: $base, assignee: $assignee, title: $title, body: $body}' )
echo ">> Creating PR from branch ${HEAD_BRANCH} into ${BASE_BRANCH}"
echo ">> With Endpoint of:"
echo "$API_ENDPOINT"
echo ">> With Payload of:"
echo "$PAYLOAD"
HTTP_STATUS=$(
curl -X POST \
--silent \
--write-out '%{http_code}' \
--output response_body.json \
--dump-header response_headers.txt \
--data "$PAYLOAD" \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"$API_ENDPOINT" 2> response_errors.txt
)
echo ">> HTTP Status Code: $HTTP_STATUS"
echo ">> Response Output ..."
echo "----"
cat response_body.json
echo "----"
cat response_headers.txt
echo "----"
cat response_errors.txt
echo "----"
if [ "$HTTP_STATUS" == "201" ]; then
echo ">> Pull Request created successfully!"
PR_URL=$(cat response_body.json | jq -r .html_url)
echo "pull-request-url=${PR_URL}" >> $GITEA_OUTPUT
PR_ID=$(cat response_body.json | jq -r .id)
echo "pull-request-id=${PR_ID}" >> $GITEA_OUTPUT
echo "pull-request-operation=created" >> $GITEA_OUTPUT
elif [ "$HTTP_STATUS" == "422" ]; then
echo ">> Failed to create PR (HTTP 422: Unprocessable Entity), PR may already exist"
elif [ "$HTTP_STATUS" == "409" ]; then
echo ">> Failed to create PR (HTTP 409: Conflict), PR already exists"
else
echo ">> Failed to create PR, HTTP status code: $HTTP_STATUS"
exit 1
fi
echo "----"
- name: ntfy Created
uses: niniyas/ntfy-action@master
if: steps.create-pull-request.outputs.pull-request-operation == 'created'
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render PR Created - Infrastructure"
priority: 3
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,successfully,completed
details: "Manifest rendering for Infrastructure has created a new Pull Request with ID: ${{ steps.create-pull-request.outputs.pull-request-id }}!"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "Open Gitea", "url": "${{ steps.create-pull-request.outputs.pull-request-url }}", "clear": true}]'
- name: ntfy Failed
uses: niniyas/ntfy-action@master
if: failure()
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render Failure - Infrastructure"
priority: 4
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,failed
details: "Manifest rendering for Infrastructure has failed!"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "Open Gitea", "url": "https://gitea.alexlebens.dev/alexlebens/infrastructure/actions?workflow=render-manifests.yaml", "clear": true}]'
image: true

View File

@@ -1,423 +0,0 @@
name: render-manifests-push
on:
push:
branches:
- main
paths:
- 'clusters/cl01tl/helm/**'
env:
CLUSTER: cl01tl
BASE_BRANCH: manifests
BRANCH_NAME: auto/update-manifests
ASSIGNEE: alexlebens
MAIN_DIR: /workspace/alexlebens/infrastructure/infrastructure
MANIFEST_DIR: /workspace/alexlebens/infrastructure/infrastructure-manifests
jobs:
render-manifests-push:
runs-on: ubuntu-js
if: gitea.event.commits[0].author.username != 'renovate-bot'
steps:
- name: Checkout Main
uses: actions/checkout@v6
with:
path: infrastructure
fetch-depth: 0
- name: Checkout Manifests
uses: actions/checkout@v6
with:
ref: manifests
path: infrastructure-manifests
- name: Set up Helm
uses: azure/setup-helm@v4
with:
token: ${{ secrets.GITEA_TOKEN }}
version: v3.17.2 # Pending https://github.com/helm/helm/pull/30743
cache: true
- name: Configure Kubeconfig
uses: azure/k8s-set-context@v4
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBECONFIG }}
- name: Prepare Manifest Branch
run: |
cd ${MANIFEST_DIR}
echo ">> Configure git to use gitea-bot as user ..."
git config user.name "gitea-bot"
git config user.email "gitea-bot@alexlebens.net"
echo ">> Checking if PR branch exists ..."
if [[ $(git ls-remote --heads origin "${BRANCH_NAME}" | wc -l) -gt 0 ]]; then
echo ">> Branch '${BRANCH_NAME}' exists, pulling changes ..."
git fetch origin "${BRANCH_NAME}"
git checkout "${BRANCH_NAME}"
git pull --rebase
else
echo ">> Branch '${BRANCH_NAME}' does not exist, creating ..."
git checkout -b $BRANCH_NAME
fi
echo "----"
- name: Check which Directories have Changes
id: check-dir-changes
run: |
cd ${MAIN_DIR}
RENDER_DIR=()
echo ">> Checking for changes ..."
GIT_DIFF=$(git diff --name-only ${{ gitea.event.before }}..HEAD | xargs -I {} dirname {} | sort -u | grep -E "clusters/[^/]+/helm/[^/]+")
if [ -n "${GIT_DIFF}" ]; then
echo ">> Changes detected:"
echo "$GIT_DIFF"
for path in $GIT_DIFF; do
RENDER_DIR+=$(echo "$path" | awk -F '/' '{print $4}')
RENDER_DIR+=$(echo " ")
done
else
echo ">> No changes detected"
fi
if [ -n "${RENDER_DIR}" ]; then
echo ">> Directories to Render:"
echo "$(echo "${RENDER_DIR}" | sort -u)"
echo "----"
echo "changes-detected=true" >> $GITEA_OUTPUT
echo "render-dir<<EOF" >> $GITEA_OUTPUT
echo "$(echo "${RENDER_DIR}" | sort -u)" >> $GITEA_OUTPUT
echo "EOF" >> $GITEA_OUTPUT
else
echo "changes-detected=false" >> $GITEA_OUTPUT
fi
- name: Add Repositories
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MAIN_DIR}
echo ">> Adding repositories for chart dependencies ..."
for dir in ${RENDER_DIR}; do
helm dependency list --max-col-width 120 ${MAIN_DIR}/clusters/${CLUSTER}/helm/$dir 2> /dev/null \
| tail +2 | head -n -1 \
| awk '{ print "helm repo add " $1 " " $3 }' \
| while read cmd; do
if [[ "$cmd" == "*oci://*" ]]; then
echo ">> Ignoring OCI repo"
else
echo "$cmd" | sh;
fi
done || true
done
if helm repo list | tail +2 | read -r; then
echo ">> Update repository cache ..."
helm repo update
fi
echo "----"
- name: Remove Changed Manifest Files
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MANIFEST_DIR}
echo ">> Remove manfiest files and rebuild from source ..."
for dir in ${RENDER_DIR}; do
chart_path=${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$dir
echo "$chart_path"
rm -rf $chart_path/*
done
echo "----"
- name: Render Helm Manifests
id: render-manifests
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MAIN_DIR}
echo ">> Rendering Manifests ..."
for dir in ${RENDER_DIR}; do
chart_path=${MAIN_DIR}/clusters/${CLUSTER}/helm/$dir
chart_name=$(basename "$chart_path")
echo ""
echo ""
echo ">> Rendering chart: $chart_name"
echo ">> Chart path $chart_path"
if [ -f "$chart_path/Chart.yaml" ]; then
OUTPUT_FOLDER="${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$chart_name/"
TEMPLATE=""
mkdir -p ${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$chart_name
cd $chart_path
echo ""
echo ">> Updating helm dependency ..."
helm dependency update --skip-refresh
echo ""
echo ">> Building helm dependency ..."
helm dependency build --skip-refresh
echo ""
echo ">> Linting helm ..."
helm lint --namespace "$chart_name"
echo ""
echo ">> Rendering templates ..."
case "$chart_name" in
"stack")
echo ""
echo ">> Special Rendering for stack into argocd namespace ..."
TEMPLATE=$(helm template $chart_name ./ --namespace argocd --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
"cilium" | "coredns" | "metrics-server" |"prometheus-operator-crds")
echo ""
echo ">> Special Rendering for $chart_name into kube-system namespace ..."
TEMPLATE=$(helm template $chart_name ./ --namespace kube-system --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
*)
echo ""
echo ">> Standard Rendering for $chart_name ..."
TEMPLATE=$(helm template "$chart_name" ./ --namespace "$chart_name" --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
esac
echo ""
echo ">> Formating rendered template ..."
echo "$TEMPLATE" | yq '... comments=""' | yq 'select(. != null)' | yq -s '"'"$OUTPUT_FOLDER"'" + .kind + "-" + .metadata.name + ".yaml"'
# Strip comments again to ensure formatting correctness
for file in "$OUTPUT_FOLDER"/*; do
yq -i '... comments=""' $file
done
echo ""
echo ">> Manifests for $chart_name rendered to $OUTPUT_FOLDER"
ls $OUTPUT_FOLDER
echo ""
else
echo ""
echo ">> Directory $chart_path does not contain a Chart.yaml. Skipping ..."
echo ""
fi
done
echo "----"
- name: Check for Changes
id: check-changes
if: steps.check-dir-changes.outputs.changes-detected == 'true'
run: |
cd ${MANIFEST_DIR}
GIT_CHANGES=$(git status --porcelain)
if [ -n "$GIT_CHANGES" ]; then
echo ">> Changes detected"
git status --porcelain
echo "changes-detected=true" >> $GITEA_OUTPUT
else
echo ">> No changes detected, skipping PR creation"
fi
echo "----"
- name: Commit and Push Changes
id: commit-push
if: steps.check-changes.outputs.changes-detected == 'true'
run: |
cd ${MANIFEST_DIR}
echo ">> Commiting changes to ${BRANCH_NAME} ..."
git add .
git commit -m "chore: Update manifests after change"
REPO_URL="${{ secrets.REPO_URL }}/${{ gitea.repository }}"
echo ">> Pushing changes to $REPO_URL ..."
git push -u "https://oauth2:${{ secrets.BOT_TOKEN }}@$(echo $REPO_URL | sed -e 's|https://||')" ${BRANCH_NAME}
echo "----"
echo "HEAD_BRANCH=${BRANCH_NAME}" >> $GITEA_OUTPUT
echo "push=true" >> $GITEA_OUTPUT
- name: Check for Pull Request
id: check-for-pull-requst
if: steps.commit-push.outputs.push == 'true'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
HEAD_BRANCH: ${{ steps.commit-push.outputs.HEAD_BRANCH }}
run: |
cd ${MANIFEST_DIR}
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls?base_branch=${BASE_BRANCH}&state=open&page=1"
echo ">> Checking if PR from branch ${HEAD_BRANCH} into ${BASE_BRANCH}"
echo ">> With Endpoint of:"
echo "$API_ENDPOINT"
HTTP_STATUS=$(
curl -X GET \
--silent \
--write-out '%{http_code}' \
--output response_body.json \
--dump-header response_headers.txt \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"$API_ENDPOINT" 2> response_errors.txt
)
echo ">> HTTP Status Code: $HTTP_STATUS"
echo ">> Response Output ..."
echo "----"
cat response_body.json
echo "----"
cat response_headers.txt
echo "----"
cat response_errors.txt
echo "----"
if [ "$HTTP_STATUS" == "200" ] && [ "$(cat response_body.json | jq -r .[0].state)" == "open" ]; then
echo ">> Pull Request has been found open, will update"
PR_INDEX=$(cat response_body.json | jq -r .[0].number)
echo "pull-request-exists=${PR_INDEX}" >> $GITEA_OUTPUT
echo "pull-request-index=true" >> $GITEA_OUTPUT
elif [ "$HTTP_STATUS" == "200" ] && [ "$(cat response_body.json | jq -r .[0].state)" == "closed" ]; then
echo ">> Pull Request found, but was closed"
echo "pull-request-exists=false" >> $GITEA_OUTPUT
else
echo ">> Pull Request not found"
echo "pull-request-exists=false" >> $GITEA_OUTPUT
fi
echo "----"
- name: Create Pull Request
id: create-pull-request
if: steps.commit-push.outputs.push == 'true' && steps.check-for-pull-requst.outputs.pull-request-exists == 'false'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
HEAD_BRANCH: ${{ steps.commit-push.outputs.HEAD_BRANCH }}
run: |
cd ${MANIFEST_DIR}
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls"
PAYLOAD=$( jq -n \
--arg head "${HEAD_BRANCH}" \
--arg base "${BASE_BRANCH}" \
--arg assignee "${ASSIGNEE}" \
--arg title "Automated Manifest Update" \
--arg body "This PR contains newly rendered Kubernetes manifests automatically generated by the CI workflow." \
'{head: $head, base: $base, assignee: $assignee, title: $title, body: $body}' )
echo ">> Creating PR from branch ${HEAD_BRANCH} into ${BASE_BRANCH}"
echo ">> With Endpoint of:"
echo "$API_ENDPOINT"
echo ">> With Payload of:"
echo "$PAYLOAD"
HTTP_STATUS=$(
curl -X POST \
--silent \
--write-out '%{http_code}' \
--output response_body.json \
--dump-header response_headers.txt \
--data "$PAYLOAD" \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"$API_ENDPOINT" 2> response_errors.txt
)
echo ">> HTTP Status Code: $HTTP_STATUS"
echo ">> Response Output ..."
echo "----"
cat response_body.json
echo "----"
cat response_headers.txt
echo "----"
cat response_errors.txt
echo "----"
if [ "$HTTP_STATUS" == "201" ]; then
echo ">> Pull Request created successfully!"
PR_URL=$(cat response_body.json | jq -r .html_url)
echo "pull-request-url=${PR_URL}" >> $GITEA_OUTPUT
PR_ID=$(cat response_body.json | jq -r .id)
echo "pull-request-id=${PR_ID}" >> $GITEA_OUTPUT
echo "pull-request-operation=created" >> $GITEA_OUTPUT
elif [ "$HTTP_STATUS" == "422" ]; then
echo ">> Failed to create PR (HTTP 422: Unprocessable Entity), PR may already exist"
elif [ "$HTTP_STATUS" == "409" ]; then
echo ">> Failed to create PR (HTTP 409: Conflict), PR already exists"
else
echo ">> Failed to create PR, HTTP status code: $HTTP_STATUS"
exit 1
fi
echo "----"
- name: ntfy Created
uses: niniyas/ntfy-action@master
if: steps.create-pull-request.outputs.pull-request-operation == 'created'
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render PR Created - Infrastructure"
priority: 3
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,successfully,completed
details: "Manifest rendering for Infrastructure has created a new Pull Request with ID: ${{ steps.create-pull-request.outputs.pull-request-id }}!"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "Open Gitea", "url": "${{ steps.create-pull-request.outputs.pull-request-url }}", "clear": true}]'
- name: ntfy Failed
uses: niniyas/ntfy-action@master
if: failure()
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render Failure - Infrastructure"
priority: 4
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,failed
details: "Manifest rendering for Infrastructure has failed!"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "Open Gitea", "url": "https://gitea.alexlebens.dev/alexlebens/infrastructure/actions?workflow=render-manifests.yaml", "clear": true}]'
image: true

View File

@@ -1,32 +0,0 @@
name: renovate
on:
schedule:
- cron: "@hourly"
push:
branches:
- main
workflow_dispatch:
jobs:
renovate:
runs-on: ubuntu-latest
container: ghcr.io/renovatebot/renovate:42
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Renovate
run: renovate
env:
RENOVATE_PLATFORM: gitea
RENOVATE_ENDPOINT: ${{ vars.INSTANCE_URL }}
RENOVATE_REPOSITORIES: alexlebens/infrastructure
RENOVATE_GIT_AUTHOR: Renovate Bot <renovate-bot@alexlebens.net>
LOG_LEVEL: info
RENOVATE_TOKEN: ${{ secrets.RENOVATE_TOKEN }}
RENOVATE_GIT_PRIVATE_KEY: ${{ secrets.RENOVATE_GIT_PRIVATE_KEY }}
RENOVATE_GITHUB_COM_TOKEN: ${{ secrets.RENOVATE_GITHUB_COM_TOKEN }}
RENOVATE_REDIS_URL: ${{ vars.RENOVATE_REDIS_URL }}

4
.gitignore vendored
View File

@@ -1,4 +0,0 @@
/**/archive/
/**/charts/
/**/manifests/
/**/tmpcharts*/

View File

@@ -2,12 +2,6 @@
GitOps definied infrastrucutre for the alexlebens.net domain. GitOps definied infrastrucutre for the alexlebens.net domain.
## Stack-cl01tl
https://argocd.alexlebens.net/api/badge?name=stack-cl01tl&revision=true&showAppName=true
App-of-Apps Application for cl01tl
## License ## License
This project is licensed under the terms of the Apache 2.0 License license. This project is licensed under the terms of the Apache 2.0 License license.

View File

@@ -0,0 +1,23 @@
apiVersion: v2
name: audiobookshelf
version: 1.0.0
description: Audiobookshelf
keywords:
- audiobookshelf
- books
- podcasts
- audiobooks
home: https://wiki.alexlebens.dev/doc/audiobookshelf-uNciuFjzDw
sources:
- https://github.com/advplyr/audiobookshelf
- https://github.com/advplyr/audiobookshelf/pkgs/container/audiobookshelf
- https://github.com/bjw-s/helm-charts/tree/main/charts/other/app-template
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: audiobookshelf
repository: https://bjw-s.github.io/helm-charts/
version: 3.7.3
icon: https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/audiobookshelf.png
appVersion: 2.17.5

View File

@@ -0,0 +1,116 @@
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: audiobookshelf-config-backup-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: audiobookshelf-config-backup-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: backup
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
target:
template:
mergePolicy: Merge
engineVersion: v2
data:
RESTIC_REPOSITORY: "{{ `{{ .BUCKET_ENDPOINT }}` }}/audiobookshelf/audiobookshelf-config"
data:
- secretKey: BUCKET_ENDPOINT
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: S3_BUCKET_ENDPOINT
- secretKey: RESTIC_PASSWORD
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: RESTIC_PASSWORD
- secretKey: AWS_DEFAULT_REGION
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: AWS_DEFAULT_REGION
- secretKey: AWS_ACCESS_KEY_ID
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/volsync-backups
metadataPolicy: None
property: access_key
- secretKey: AWS_SECRET_ACCESS_KEY
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/volsync-backups
metadataPolicy: None
property: secret_key
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: audiobookshelf-metadata-backup-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: audiobookshelf-metadata-backup-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: backup
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
target:
template:
mergePolicy: Merge
engineVersion: v2
data:
RESTIC_REPOSITORY: "{{ `{{ .BUCKET_ENDPOINT }}` }}/audiobookshelf/audiobookshelf-metadata"
data:
- secretKey: BUCKET_ENDPOINT
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: S3_BUCKET_ENDPOINT
- secretKey: RESTIC_PASSWORD
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: RESTIC_PASSWORD
- secretKey: AWS_DEFAULT_REGION
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: AWS_DEFAULT_REGION
- secretKey: AWS_ACCESS_KEY_ID
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/volsync-backups
metadataPolicy: None
property: access_key
- secretKey: AWS_SECRET_ACCESS_KEY
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/volsync-backups
metadataPolicy: None
property: secret_key

View File

@@ -0,0 +1,30 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-route-audiobookshelf
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: http-route-audiobookshelf
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- audiobookshelf.alexlebens.net
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ''
kind: Service
name: audiobookshelf
port: 80
weight: 100

View File

@@ -0,0 +1,40 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: audiobookshelf-nfs-storage-backup
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: audiobookshelf-nfs-storage-backup
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
volumeMode: Filesystem
storageClassName: nfs-client
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: audiobookshelf-nfs-storage
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: audiobookshelf-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
volumeName: audiobookshelf-nfs-storage
storageClassName: nfs-client
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi

View File

@@ -6,6 +6,8 @@ metadata:
labels: labels:
app.kubernetes.io/name: audiobookshelf-nfs-storage app.kubernetes.io/name: audiobookshelf-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
persistentVolumeReclaimPolicy: Retain persistentVolumeReclaimPolicy: Retain

View File

@@ -0,0 +1,56 @@
apiVersion: volsync.backube/v1alpha1
kind: ReplicationSource
metadata:
name: audiobookshelf-config-backup-source
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: audiobookshelf-config-backup-source
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: backup
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
sourcePVC: audiobookshelf-config
trigger:
schedule: 0 4 * * *
restic:
pruneIntervalDays: 7
repository: audiobookshelf-config-backup-secret
retain:
hourly: 1
daily: 3
weekly: 2
monthly: 2
yearly: 4
copyMethod: Snapshot
storageClassName: ceph-block
volumeSnapshotClassName: ceph-blockpool-snapshot
---
apiVersion: volsync.backube/v1alpha1
kind: ReplicationSource
metadata:
name: audiobookshelf-metadata-backup-source
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: audiobookshelf-metadata-backup-source
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: backup
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
sourcePVC: audiobookshelf-metadata
trigger:
schedule: 0 4 * * *
restic:
pruneIntervalDays: 7
repository: audiobookshelf-metadata-backup-secret
retain:
hourly: 1
daily: 3
weekly: 2
monthly: 2
yearly: 4
copyMethod: Snapshot
storageClassName: ceph-block
volumeSnapshotClassName: ceph-blockpool-snapshot

View File

@@ -0,0 +1,65 @@
audiobookshelf:
controllers:
main:
type: deployment
replicas: 1
strategy: Recreate
revisionHistoryLimit: 3
containers:
main:
image:
repository: ghcr.io/advplyr/audiobookshelf
tag: 2.20.0
pullPolicy: IfNotPresent
env:
- name: TZ
value: US/Central
resources:
requests:
cpu: 10m
memory: 128Mi
serviceAccount:
create: true
service:
main:
controller: main
ports:
http:
port: 80
targetPort: 80
protocol: HTTP
persistence:
config:
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 2Gi
retain: true
advancedMounts:
main:
main:
- path: /config
readOnly: false
metadata:
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 10Gi
retain: true
advancedMounts:
main:
main:
- path: /metadata
readOnly: false
backup:
existingClaim: audiobookshelf-nfs-storage-backup
advancedMounts:
main:
main:
- path: /metadata/backups
readOnly: false
audiobooks:
existingClaim: audiobookshelf-nfs-storage
advancedMounts:
main:
main:
- path: /mnt/store/
readOnly: false

View File

@@ -0,0 +1,21 @@
apiVersion: v2
name: calibre-web-automated
version: 1.0.0
description: Calibre Web Automated
keywords:
- calibre-web-automated
- books
home: https://wiki.alexlebens.dev/doc/calibre-web-automated-1SMf1jPFsb
sources:
- https://github.com/crocodilestick/Calibre-Web-Automator
- https://hub.docker.com/r/crocodilestick/calibre-web-automated
- https://github.com/bjw-s/helm-charts/tree/main/charts/other/app-template
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: calibre-web-automated
repository: https://bjw-s.github.io/helm-charts/
version: 3.7.3
icon: https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/calibre-web.png
appVersion: V2.1.2

View File

@@ -0,0 +1,82 @@
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: calibre-web-automated-gmail-config
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: calibre-web-automated-gmail-config
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: gmail.json
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/calibre-web/gmail
metadataPolicy: None
property: gmail.json
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: calibre-web-automated-config-backup-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: calibre-web-automated-config-backup-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: backup
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
target:
template:
mergePolicy: Merge
engineVersion: v2
data:
RESTIC_REPOSITORY: "{{ `{{ .BUCKET_ENDPOINT }}` }}/calibre-web-automated/calibre-web-automated-config"
data:
- secretKey: BUCKET_ENDPOINT
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: S3_BUCKET_ENDPOINT
- secretKey: RESTIC_PASSWORD
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: RESTIC_PASSWORD
- secretKey: AWS_DEFAULT_REGION
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: AWS_DEFAULT_REGION
- secretKey: AWS_ACCESS_KEY_ID
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/volsync-backups
metadataPolicy: None
property: access_key
- secretKey: AWS_SECRET_ACCESS_KEY
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/volsync-backups
metadataPolicy: None
property: secret_key

View File

@@ -0,0 +1,62 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-route-calibre
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: http-route-calibre
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- calibre.alexlebens.net
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ''
kind: Service
name: calibre-web-automated-main
port: 8083
weight: 100
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-route-calibre-downloader
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: http-route-calibre-downloader
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- calibre-downloader.alexlebens.net
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ''
kind: Service
name: calibre-web-automated-downloader
port: 8084
weight: 100

View File

@@ -0,0 +1,40 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: calibre-web-automated-nfs-storage
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: calibre-web-automated-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
volumeName: calibre-web-automated-nfs-storage
storageClassName: nfs-client
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: calibre-web-automated-ingest-nfs-storage
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: calibre-web-automated-ingest-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
volumeName: calibre-web-automated-ingest-nfs-storage
storageClassName: nfs-client
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi

View File

@@ -1,11 +1,13 @@
apiVersion: v1 apiVersion: v1
kind: PersistentVolume kind: PersistentVolume
metadata: metadata:
name: booklore-books-nfs-storage name: calibre-web-automated-nfs-storage
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
app.kubernetes.io/name: booklore-books-nfs-storage app.kubernetes.io/name: calibre-web-automated-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
persistentVolumeReclaimPolicy: Retain persistentVolumeReclaimPolicy: Retain
@@ -15,7 +17,7 @@ spec:
accessModes: accessModes:
- ReadWriteMany - ReadWriteMany
nfs: nfs:
path: /volume2/Storage/Books path: /volume2/Storage/Calibre
server: synologybond.alexlebens.net server: synologybond.alexlebens.net
mountOptions: mountOptions:
- vers=4 - vers=4
@@ -26,11 +28,13 @@ spec:
apiVersion: v1 apiVersion: v1
kind: PersistentVolume kind: PersistentVolume
metadata: metadata:
name: booklore-books-import-nfs-storage name: calibre-web-automated-ingest-nfs-storage
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
app.kubernetes.io/name: booklore-books-import-nfs-storage app.kubernetes.io/name: calibre-web-automated-ingest-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
persistentVolumeReclaimPolicy: Retain persistentVolumeReclaimPolicy: Retain
@@ -40,7 +44,7 @@ spec:
accessModes: accessModes:
- ReadWriteMany - ReadWriteMany
nfs: nfs:
path: /volume2/Storage/Books Import path: /volume2/Storage/Calibre Import
server: synologybond.alexlebens.net server: synologybond.alexlebens.net
mountOptions: mountOptions:
- vers=4 - vers=4

View File

@@ -0,0 +1,30 @@
apiVersion: volsync.backube/v1alpha1
kind: ReplicationSource
metadata:
name: calibre-web-automated-config-backup-source
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: calibre-web-automated-config-backup-source
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: backup
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
sourcePVC: calibre-web-automated-config
trigger:
schedule: 0 4 * * *
restic:
pruneIntervalDays: 7
repository: calibre-web-automated-config-backup-secret
retain:
hourly: 1
daily: 3
weekly: 2
monthly: 2
yearly: 4
moverSecurityContext:
runAsUser: 1000
runAsGroup: 100
copyMethod: Snapshot
storageClassName: ceph-block
volumeSnapshotClassName: ceph-blockpool-snapshot

View File

@@ -0,0 +1,120 @@
calibre-web-automated:
controllers:
main:
type: deployment
replicas: 1
strategy: Recreate
revisionHistoryLimit: 3
containers:
main:
image:
repository: crocodilestick/calibre-web-automated
tag: V3.0.4
pullPolicy: IfNotPresent
env:
- name: TZ
value: US/Central
- name: PUID
value: 1000
- name: PGID
value: 100
resources:
requests:
cpu: 100m
memory: 256Mi
downloader:
type: deployment
replicas: 1
strategy: Recreate
revisionHistoryLimit: 3
containers:
main:
image:
repository: ghcr.io/calibrain/calibre-web-automated-book-downloader
tag: latest@sha256:e4c205932b0ece06d76de09ba8569d5aa30768cc46d04beb3a24ddc0106043d6
pullPolicy: IfNotPresent
env:
- name: FLASK_PORT
value: 8084
- name: UID
value: 1000
- name: GID
value: 100
- name: USE_CF_BYPASS
value: true
- name: CLOUDFLARE_PROXY_URL
value: http://localhost:8000
- name: INGEST_DIR
value: /cwa-book-ingest
- name: BOOK_LANGUAGE
value: end
resources:
requests:
cpu: 10m
memory: 256Mi
bypass:
image:
repository: ghcr.io/sarperavci/cloudflarebypassforscraping
tag: latest@sha256:8e99847ae05bce24fe8a400bb9b30990a4cec32853f3975905eab95e05febefa
pullPolicy: IfNotPresent
resources:
requests:
cpu: 10m
memory: 128Mi
serviceAccount:
create: true
service:
main:
controller: main
ports:
http:
port: 8083
targetPort: 8083
protocol: HTTP
downloader:
controller: downloader
ports:
http:
port: 8084
targetPort: 8084
protocol: HTTP
persistence:
config:
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 5Gi
retain: true
advancedMounts:
main:
main:
- path: /config
readOnly: false
gmail:
enabled: true
type: secret
name: calibre-web-automated-gmail-config
advancedMounts:
main:
main:
- path: /app/calibre-web/gmail.json
readOnly: true
mountPropagation: None
subPath: gmail.json
books:
existingClaim: calibre-web-automated-nfs-storage
advancedMounts:
main:
main:
- path: /calibre-library
readOnly: false
ingest:
existingClaim: calibre-web-automated-ingest-nfs-storage
advancedMounts:
main:
main:
- path: /cwa-book-ingest
readOnly: false
downloader:
main:
- path: /cwa-book-ingest
readOnly: false

View File

@@ -0,0 +1,28 @@
apiVersion: v2
name: code-server
version: 1.0.0
description: Code Server
keywords:
- code-server
- code
- ide
home: https://wiki.alexlebens.dev/doc/code-server-1WziinqCFS
sources:
- https://github.com/coder/code-server
- https://github.com/cloudflare/cloudflared
- https://hub.docker.com/r/linuxserver/code-server
- https://github.com/bjw-s/helm-charts/tree/main/charts/other/app-template
- https://github.com/alexlebens/helm-charts/tree/main/charts/cloudflared
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: code-server
repository: https://bjw-s.github.io/helm-charts/
version: 3.7.3
- name: cloudflared
alias: cloudflared
repository: https://gitea.alexlebens.dev/api/packages/alexlebens/helm
version: 1.14.3
icon: https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/code-server.png
appVersion: 4.96.1

View File

@@ -1,11 +1,13 @@
apiVersion: external-secrets.io/v1 apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret kind: ExternalSecret
metadata: metadata:
name: home-assistant-code-server-password-secret name: codeserver-password-secret
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
app.kubernetes.io/name: home-assistant-code-server-password-secret app.kubernetes.io/name: codeserver-password-secret
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
secretStoreRef: secretStoreRef:
@@ -16,36 +18,38 @@ spec:
remoteRef: remoteRef:
conversionStrategy: Default conversionStrategy: Default
decodingStrategy: None decodingStrategy: None
key: /cl01tl/home-assistant/code-server/auth key: /cl01tl/code-server/auth
metadataPolicy: None metadataPolicy: None
property: PASSWORD property: PASSWORD
- secretKey: SUDO_PASSWORD - secretKey: SUDO_PASSWORD
remoteRef: remoteRef:
conversionStrategy: Default conversionStrategy: Default
decodingStrategy: None decodingStrategy: None
key: /cl01tl/home-assistant/code-server/auth key: /cl01tl/code-server/auth
metadataPolicy: None metadataPolicy: None
property: SUDO_PASSWORD property: SUDO_PASSWORD
--- ---
apiVersion: external-secrets.io/v1 apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret kind: ExternalSecret
metadata: metadata:
name: home-assistant-token-secret name: code-server-cloudflared-secret
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
app.kubernetes.io/name: home-assistant-token-secret app.kubernetes.io/name: code-server-cloudflared-secret
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
secretStoreRef: secretStoreRef:
kind: ClusterSecretStore kind: ClusterSecretStore
name: vault name: vault
data: data:
- secretKey: bearer-token - secretKey: cf-tunnel-token
remoteRef: remoteRef:
conversionStrategy: Default conversionStrategy: Default
decodingStrategy: None decodingStrategy: None
key: /cl01tl/home-assistant/auth key: /cloudflare/tunnels/codeserver
metadataPolicy: None metadataPolicy: None
property: bearer-token property: token

View File

@@ -0,0 +1,30 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-route-code-server
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: http-route-code-server
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- code-server.alexlebens.net
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ''
kind: Service
name: code-server
port: 8443
weight: 100

View File

@@ -1,17 +1,19 @@
apiVersion: v1 apiVersion: v1
kind: PersistentVolumeClaim kind: PersistentVolumeClaim
metadata: metadata:
name: audiobookshelf-nfs-storage name: code-server-nfs-storage
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
app.kubernetes.io/name: audiobookshelf-nfs-storage app.kubernetes.io/name: code-server-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
volumeName: audiobookshelf-nfs-storage volumeMode: Filesystem
storageClassName: nfs-client storageClassName: nfs-client
accessModes: accessModes:
- ReadWriteMany - ReadWriteOnce
resources: resources:
requests: requests:
storage: 1Gi storage: 1Gi

View File

@@ -0,0 +1,49 @@
code-server:
controllers:
main:
type: deployment
replicas: 1
strategy: Recreate
revisionHistoryLimit: 3
containers:
main:
image:
repository: ghcr.io/linuxserver/code-server
tag: 4.98.2@sha256:87fbf594ae4a6494d0623967fc4c7a42774945c9cf032b55c57128ca675f2221
pullPolicy: IfNotPresent
env:
- name: TZ
value: US/Central
- name: PUID
value: 1000
- name: PGID
value: 1000
- name: DEFAULT_WORKSPACE
value: /config
envFrom:
- secretRef:
name: codeserver-password-secret
resources:
requests:
cpu: 10m
memory: 128Mi
serviceAccount:
create: true
service:
main:
controller: main
ports:
http:
port: 8443
targetPort: 8443
protocol: HTTP
persistence:
config:
existingClaim: code-server-nfs-storage
advancedMounts:
main:
main:
- path: /config
readOnly: false
cloudflared:
existingSecretName: code-server-cloudflared-secret

View File

@@ -0,0 +1,44 @@
apiVersion: v2
name: directus
version: 1.0.0
description: Directus
keywords:
- directus
- cms
home: https://wiki.alexlebens.dev/doc/directus-EvV9wese9H
sources:
- https://github.com/directus/directus
- https://github.com/minio/operator
- https://github.com/valkey-io/valkey
- https://github.com/cloudflare/cloudflared
- https://github.com/cloudnative-pg/cloudnative-pg
- https://hub.docker.com/r/directus/directus
- https://github.com/bjw-s/helm-charts/tree/main/charts/other/app-template
- https://github.com/minio/operator/tree/master/helm/tenant
- https://github.com/bitnami/charts/tree/main/bitnami/valkey
- https://github.com/alexlebens/helm-charts/charts/cloudflared
- https://github.com/alexlebens/helm-charts/charts/postgres-cluster
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: directus
repository: https://bjw-s.github.io/helm-charts/
version: 3.7.3
- name: tenant
alias: minio
version: 7.0.1
repository: https://operator.min.io/
- name: valkey
version: 2.4.6
repository: oci://harbor.alexlebens.net/proxy-registry-1.docker.io/bitnamicharts
- name: cloudflared
alias: cloudflared-directus
repository: https://gitea.alexlebens.dev/api/packages/alexlebens/helm
version: 1.14.3
- name: postgres-cluster
alias: postgres-17-cluster
version: 4.2.1
repository: https://gitea.alexlebens.dev/api/packages/alexlebens/helm
icon: https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/directus.png
appVersion: 11.3.2

View File

@@ -0,0 +1,247 @@
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: directus-config
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: directus-config
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: admin-email
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/directus/config
metadataPolicy: None
property: admin-email
- secretKey: admin-password
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/directus/config
metadataPolicy: None
property: admin-password
- secretKey: secret
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/directus/config
metadataPolicy: None
property: secret
- secretKey: key
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/directus/config
metadataPolicy: None
property: key
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: directus-valkey-config
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: directus-valkey-config
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: user
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/directus/valkey
metadataPolicy: None
property: user
- secretKey: password
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/directus/valkey
metadataPolicy: None
property: password
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: directus-oidc-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: directus-oidc-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: OIDC_CLIENT_ID
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /authentik/oidc/directus
metadataPolicy: None
property: client
- secretKey: OIDC_CLIENT_SECRET
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /authentik/oidc/directus
metadataPolicy: None
property: secret
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: directus-minio-user-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: directus-minio-user-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: database
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: AWS_ACCESS_KEY_ID
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/directus/minio/auth
metadataPolicy: None
property: AWS_ACCESS_KEY_ID
- secretKey: AWS_SECRET_ACCESS_KEY
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/directus/minio/auth
metadataPolicy: None
property: AWS_SECRET_ACCESS_KEY
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: directus-minio-root-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: directus-minio-root-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: database
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: config.env
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/directus/minio/config
metadataPolicy: None
property: root-config.env
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: directus-minio-config-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: directus-minio-config-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: database
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: config.env
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/directus/minio/config
metadataPolicy: None
property: config.env
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: directus-cloudflared-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: directus-cloudflared-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: cf-tunnel-token
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cloudflare/tunnels/directus
metadataPolicy: None
property: token
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: directus-postgresql-17-cluster-backup-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: directus-postgresql-17-cluster-backup-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: database
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: ACCESS_KEY_ID
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/postgres-backups
metadataPolicy: None
property: access
- secretKey: ACCESS_SECRET_KEY
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/postgres-backups
metadataPolicy: None
property: secret

View File

@@ -0,0 +1,30 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-route-directus-minio
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: http-route-directus-minio
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- minio-directus.alexlebens.net
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ''
kind: Service
name: minio-directus-console
port: 9090
weight: 100

View File

@@ -9,7 +9,7 @@ directus:
main: main:
image: image:
repository: directus/directus repository: directus/directus
tag: 11.14.1 tag: 11.5.1
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
env: env:
- name: PUBLIC_URL - name: PUBLIC_URL
@@ -41,47 +41,43 @@ directus:
- name: DB_HOST - name: DB_HOST
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: directus-postgresql-18-cluster-app name: directus-postgresql-17-cluster-app
key: host key: host
- name: DB_DATABASE - name: DB_DATABASE
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: directus-postgresql-18-cluster-app name: directus-postgresql-17-cluster-app
key: dbname key: dbname
- name: DB_PORT - name: DB_PORT
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: directus-postgresql-18-cluster-app name: directus-postgresql-17-cluster-app
key: port key: port
- name: DB_USER - name: DB_USER
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: directus-postgresql-18-cluster-app name: directus-postgresql-17-cluster-app
key: user key: user
- name: DB_PASSWORD - name: DB_PASSWORD
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: directus-postgresql-18-cluster-app name: directus-postgresql-17-cluster-app
key: password key: password
- name: SYNCHRONIZATION_STORE
value: redis
- name: CACHE_ENABLED
value: true
- name: CACHE_STORE
value: redis
- name: REDIS_ENABLED - name: REDIS_ENABLED
value: true value: true
- name: REDIS_HOST - name: REDIS_HOST
value: redis-replication-directus-master value: directus-valkey-primary
- name: REDIS_PORT
value: 6379
- name: REDIS_USERNAME - name: REDIS_USERNAME
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: directus-redis-config name: directus-valkey-config
key: user key: user
- name: REDIS_PASSWORD - name: REDIS_PASSWORD
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: directus-redis-config name: directus-valkey-config
key: password key: password
- name: STORAGE_LOCATIONS - name: STORAGE_LOCATIONS
value: s3 value: s3
@@ -90,24 +86,21 @@ directus:
- name: STORAGE_S3_KEY - name: STORAGE_S3_KEY
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: ceph-bucket-directus name: directus-minio-user-secret
key: AWS_ACCESS_KEY_ID key: AWS_ACCESS_KEY_ID
- name: STORAGE_S3_SECRET - name: STORAGE_S3_SECRET
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: ceph-bucket-directus name: directus-minio-user-secret
key: AWS_SECRET_ACCESS_KEY key: AWS_SECRET_ACCESS_KEY
- name: STORAGE_S3_BUCKET - name: STORAGE_S3_BUCKET
valueFrom: value: directus
configMapKeyRef:
name: ceph-bucket-directus
key: BUCKET_NAME
- name: STORAGE_S3_REGION - name: STORAGE_S3_REGION
value: us-east-1 value: us-east-1
- name: STORAGE_S3_ENDPOINT - name: STORAGE_S3_ENDPOINT
value: http://rook-ceph-rgw-ceph-objectstore.rook-ceph.svc:80 value: http://minio.directus:80
- name: STORAGE_S3_FORCE_PATH_STYLE - name: STORAGE_S3_FORCE_PATH_STYLE
value: true value: "true"
- name: AUTH_PROVIDERS - name: AUTH_PROVIDERS
value: AUTHENTIK value: AUTHENTIK
- name: AUTH_AUTHENTIK_DRIVER - name: AUTH_AUTHENTIK_DRIVER
@@ -134,17 +127,12 @@ directus:
value: Authentik value: Authentik
- name: TELEMETRY - name: TELEMETRY
value: false value: false
- name: METRICS_ENABLED
value: true
- name: METRICS_TOKENS
valueFrom:
secretKeyRef:
name: directus-metric-token
key: metric-token
resources: resources:
requests: requests:
cpu: 10m cpu: 10m
memory: 256Mi memory: 256Mi
serviceAccount:
create: true
service: service:
main: main:
controller: main controller: main
@@ -153,69 +141,58 @@ directus:
port: 80 port: 80
targetPort: 8055 targetPort: 8055
protocol: TCP protocol: TCP
serviceMonitor: minio:
main:
selector:
matchLabels:
app.kubernetes.io/name: directus
app.kubernetes.io/instance: directus
serviceName: '{{ include "bjw-s.common.lib.chart.names.fullname" $ }}'
endpoints:
- port: http
interval: 30s
scrapeTimeout: 15s
path: /metrics
bearerTokenSecret:
name: directus-metric-token
key: metric-token
postgres-18-cluster:
mode: recovery
recovery:
method: objectStore
objectStore:
index: 1
backup:
objectStore:
- name: garage-local
index: 1
destinationBucket: postgres-backups
externalSecretCredentialPath: /garage/home-infra/postgres-backups
isWALArchiver: true
# - name: garage-remote
# index: 1
# destinationBucket: postgres-backups
# externalSecretCredentialPath: /garage/home-infra/postgres-backups
# retentionPolicy: "90d"
# data:
# compression: bzip2
# - name: external
# index: 1
# endpointURL: https://nyc3.digitaloceanspaces.com
# destinationBucket: postgres-backups-ce540ddf106d186bbddca68a
# externalSecretCredentialPath: /garage/home-infra/postgres-backups
# isWALArchiver: false
scheduledBackups:
- name: live-backup
suspend: false
immediate: true
schedule: "0 0 0 * * *"
backupName: garage-local
# - name: weekly-backup
# suspend: true
# immediate: true
# schedule: "0 0 4 * * SAT"
# backupName: garage-remote
# - name: daily-backup
# suspend: true
# immediate: true
# schedule: "0 0 0 * * *"
# backupName: external
redis-replication:
existingSecret: existingSecret:
enabled: true name: directus-minio-root-secret
name: directus-redis-config tenant:
key: password name: minio-directus
redisReplication: configuration:
clusterSize: 3 name: directus-minio-config-secret
sentinel: pools:
- servers: 3
name: pool
volumesPerServer: 2
size: 10Gi
storageClassName: ceph-block
mountPath: /export
subPath: /data
metrics:
enabled: true enabled: true
port: 9000
protocol: http
certificate:
requestAutoCert: false
ingress:
console:
enabled: false
valkey:
architecture: standalone
auth:
enabled: true
existingSecret: directus-valkey-config
existingSecretPasswordKey: password
usePasswordFiles: false
primary:
persistence:
enabled: false
replica:
persistence:
enabled: false
cloudflared-directus:
name: cloudflared-directus
existingSecretName: directus-cloudflared-secret
postgres-17-cluster:
mode: standalone
cluster:
walStorage:
storageClass: local-path
storage:
storageClass: local-path
monitoring:
enabled: true
backup:
enabled: true
endpointURL: https://nyc3.digitaloceanspaces.com
destinationPath: s3://postgres-backups-ce540ddf106d186bbddca68a/cl01tl/directus/directus-postgresql-17-cluster
endpointCredentials: directus-postgresql-17-cluster-backup-secret
backupIndex: 2

View File

@@ -6,22 +6,22 @@ keywords:
- element-web - element-web
- chat - chat
- matrix - matrix
home: https://wiki.alexlebens.dev/s/e3b03481-1a1d-4b56-8cd9-e75a8dcc0f6c home: https://wiki.alexlebens.dev/doc/element-web-R4dzXXspgr
sources: sources:
- https://github.com/element-hq/element-web - https://github.com/element-hq/element-web
- https://github.com/cloudflare/cloudflared - https://github.com/cloudflare/cloudflared
- https://hub.docker.com/r/vectorim/element-web - https://hub.docker.com/r/vectorim/element-web
- https://gitlab.com/ananace/charts/-/tree/master/charts/element-web - https://gitlab.com/ananace/charts/-/tree/master/charts/element-web
- https://gitea.alexlebens.dev/alexlebens/helm-charts/src/branch/main/charts/cloudflared - https://github.com/alexlebens/helm-charts/tree/main/charts/cloudflared
maintainers: maintainers:
- name: alexlebens - name: alexlebens
dependencies: dependencies:
- name: element-web - name: element-web
version: 1.4.28 version: 1.4.5
repository: https://ananace.gitlab.io/charts repository: https://ananace.gitlab.io/charts
- name: cloudflared - name: cloudflared
repository: oci://harbor.alexlebens.net/helm-charts alias: cloudflared
version: 2.1.9 repository: https://gitea.alexlebens.dev/api/packages/alexlebens/helm
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/png/element.png version: 1.14.3
# renovate: datasource=github-releases depName=element-hq/element-web icon: https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/element.png
appVersion: v1.12.8 appVersion: v1.11.88

View File

@@ -0,0 +1,23 @@
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: element-web-cloudflared-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: element-web-cloudflared-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: cf-tunnel-token
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cloudflare/tunnels/element
metadataPolicy: None
property: token

View File

@@ -2,7 +2,7 @@ element-web:
replicaCount: 1 replicaCount: 1
image: image:
repository: vectorim/element-web repository: vectorim/element-web
tag: v1.12.8 tag: v1.11.95
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
defaultServer: defaultServer:
url: https://matrix.alexlebens.dev url: https://matrix.alexlebens.dev
@@ -12,8 +12,8 @@ element-web:
disable_3pid_login: true disable_3pid_login: true
brand: "Alex Lebens" brand: "Alex Lebens"
branding: branding:
welcome_background_url: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/background.jpg welcome_background_url: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/background-4.jpg
auth_header_logo_url: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/logo-new-round.png auth_header_logo_url: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/icon_white.png
sso_redirect_options: sso_redirect_options:
immediate: true immediate: true
default_theme: dark default_theme: dark
@@ -24,3 +24,5 @@ element-web:
requests: requests:
cpu: 10m cpu: 10m
memory: 128Mi memory: 128Mi
cloudflared:
existingSecretName: element-web-cloudflared-secret

View File

@@ -0,0 +1,33 @@
apiVersion: v2
name: freshrss
version: 1.0.0
description: FreshRSS
keywords:
- freshrss
- rss
home: https://wiki.alexlebens.dev/doc/freshrss-W6nFVTmKJw
sources:
- https://github.com/FreshRSS/FreshRSS
- https://github.com/cloudflare/cloudflared
- https://github.com/cloudnative-pg/cloudnative-pg
- https://hub.docker.com/r/freshrss/freshrss
- https://github.com/bjw-s/helm-charts/tree/main/charts/other/app-template
- https://github.com/alexlebens/helm-charts/tree/main/charts/cloudflared
- https://github.com/alexlebens/helm-charts/tree/main/charts/postgres-cluster
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: freshrss
repository: https://bjw-s.github.io/helm-charts/
version: 3.7.3
- name: cloudflared
alias: cloudflared
repository: https://gitea.alexlebens.dev/api/packages/alexlebens/helm
version: 1.14.3
- name: postgres-cluster
alias: postgres-17-cluster
version: 4.2.1
repository: https://gitea.alexlebens.dev/api/packages/alexlebens/helm
icon: https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/freshrss.png
appVersion: 1.24.3

View File

@@ -0,0 +1,192 @@
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: freshrss-install-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: freshrss-install-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: ADMIN_EMAIL
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/freshrss/config
metadataPolicy: None
property: ADMIN_EMAIL
- secretKey: ADMIN_PASSWORD
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/freshrss/config
metadataPolicy: None
property: ADMIN_PASSWORD
- secretKey: ADMIN_API_PASSWORD
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/freshrss/config
metadataPolicy: None
property: ADMIN_API_PASSWORD
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: freshrss-oidc-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: {{ .Release.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: OIDC_CLIENT_ID
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /authentik/oidc/freshrss
metadataPolicy: None
property: client
- secretKey: OIDC_CLIENT_SECRET
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /authentik/oidc/freshrss
metadataPolicy: None
property: secret
- secretKey: OIDC_CLIENT_CRYPTO_KEY
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /authentik/oidc/freshrss
metadataPolicy: None
property: crypto-key
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: freshrss-cloudflared-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: freshrss-cloudflared-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: cf-tunnel-token
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cloudflare/tunnels/freshrss
metadataPolicy: None
property: token
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: freshrss-data-backup-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: freshrss-data-backup-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: backup
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
target:
template:
mergePolicy: Merge
engineVersion: v2
data:
RESTIC_REPOSITORY: "{{ `{{ .BUCKET_ENDPOINT }}` }}/freshrss/freshrss-data"
data:
- secretKey: BUCKET_ENDPOINT
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: S3_BUCKET_ENDPOINT
- secretKey: RESTIC_PASSWORD
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: RESTIC_PASSWORD
- secretKey: AWS_DEFAULT_REGION
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: AWS_DEFAULT_REGION
- secretKey: AWS_ACCESS_KEY_ID
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/volsync-backups
metadataPolicy: None
property: access_key
- secretKey: AWS_SECRET_ACCESS_KEY
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/volsync-backups
metadataPolicy: None
property: secret_key
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: freshrss-postgresql-17-cluster-backup-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: freshrss-postgresql-17-cluster-backup-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: database
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: ACCESS_KEY_ID
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/postgres-backups
metadataPolicy: None
property: access
- secretKey: ACCESS_SECRET_KEY
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/postgres-backups
metadataPolicy: None
property: secret

View File

@@ -0,0 +1,37 @@
apiVersion: volsync.backube/v1alpha1
kind: ReplicationSource
metadata:
name: freshrss-data-backup-source
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: freshrss-data-backup-source
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: backup
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
sourcePVC: freshrss-data
trigger:
schedule: 0 4 * * *
restic:
pruneIntervalDays: 7
repository: freshrss-data-backup-secret
retain:
hourly: 1
daily: 3
weekly: 2
monthly: 2
yearly: 4
moverSecurityContext:
runAsUser: 568
runAsGroup: 568
fsGroup: 568
fsGroupChangePolicy: OnRootMismatch
supplementalGroups:
- 44
- 100
- 109
- 65539
copyMethod: Snapshot
storageClassName: ceph-block
volumeSnapshotClassName: ceph-blockpool-snapshot

View File

@@ -11,7 +11,7 @@ freshrss:
runAsUser: 0 runAsUser: 0
image: image:
repository: alpine repository: alpine
tag: 3.23.2 tag: 3.21.3
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
command: command:
- /bin/sh - /bin/sh
@@ -28,14 +28,14 @@ freshrss:
chown -R 568:568 /var/www/FreshRSS/extensions/xExtension-YouTubeChannel2RssFeed chown -R 568:568 /var/www/FreshRSS/extensions/xExtension-YouTubeChannel2RssFeed
resources: resources:
requests: requests:
cpu: 10m cpu: 100m
memory: 128Mi memory: 128Mi
init-download-extension-2: init-download-extension-2:
securityContext: securityContext:
runAsUser: 0 runAsUser: 0
image: image:
repository: alpine repository: alpine
tag: 3.23.2 tag: 3.21.3
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
command: command:
- /bin/sh - /bin/sh
@@ -49,38 +49,16 @@ freshrss:
git checkout; git checkout;
rm -rf /var/www/FreshRSS/extensions/xExtension-ImageProxy rm -rf /var/www/FreshRSS/extensions/xExtension-ImageProxy
cp -r xExtension-ImageProxy /var/www/FreshRSS/extensions cp -r xExtension-ImageProxy /var/www/FreshRSS/extensions
chown -R 568:568 /var/www/FreshRSS/extensions/xExtension-ImageProxy chown -R 568:568 /var/www/FreshRSS/extensions/xExtension-YouTubeChannel2RssFeed
resources: resources:
requests: requests:
cpu: 10m cpu: 100m
memory: 128Mi
init-download-extension-3:
securityContext:
runAsUser: 0
image:
repository: alpine
tag: 3.23.2
pullPolicy: IfNotPresent
command:
- /bin/sh
- -ec
- |
cd /tmp;
wget https://github.com/zimmra/xExtension-karakeep-button/archive/refs/tags/v1.1.tar.gz;
tar -xvzf *.tar.gz;
rm -rf /var/www/FreshRSS/extensions/xExtension-karakeep-button
mkdir /var/www/FreshRSS/extensions/xExtension-karakeep-button
cp -r /tmp/xExtension-karakeep-button-*/* /var/www/FreshRSS/extensions/xExtension-karakeep-button
chown -R 568:568 /var/www/FreshRSS/extensions/xExtension-karakeep-button
resources:
requests:
cpu: 10m
memory: 128Mi memory: 128Mi
containers: containers:
main: main:
image: image:
repository: freshrss/freshrss repository: freshrss/freshrss
tag: 1.28.0 tag: 1.26.1
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
env: env:
- name: PGID - name: PGID
@@ -98,22 +76,22 @@ freshrss:
- name: DB_HOST - name: DB_HOST
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: freshrss-postgresql-18-cluster-app name: freshrss-postgresql-17-cluster-app
key: host key: host
- name: DB_BASE - name: DB_BASE
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: freshrss-postgresql-18-cluster-app name: freshrss-postgresql-17-cluster-app
key: dbname key: dbname
- name: DB_USER - name: DB_USER
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: freshrss-postgresql-18-cluster-app name: freshrss-postgresql-17-cluster-app
key: user key: user
- name: DB_PASSWORD - name: DB_PASSWORD
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: freshrss-postgresql-18-cluster-app name: freshrss-postgresql-17-cluster-app
key: password key: password
- name: FRESHRSS_INSTALL - name: FRESHRSS_INSTALL
value: | value: |
@@ -153,6 +131,8 @@ freshrss:
requests: requests:
cpu: 10m cpu: 10m
memory: 128Mi memory: 128Mi
serviceAccount:
create: true
service: service:
main: main:
controller: main controller: main
@@ -163,7 +143,6 @@ freshrss:
protocol: HTTP protocol: HTTP
persistence: persistence:
data: data:
forceRename: freshrss-data
storageClass: ceph-block storageClass: ceph-block
accessMode: ReadWriteOnce accessMode: ReadWriteOnce
size: 5Gi size: 5Gi
@@ -186,71 +165,23 @@ freshrss:
init-download-extension-2: init-download-extension-2:
- path: /var/www/FreshRSS/extensions - path: /var/www/FreshRSS/extensions
readOnly: false readOnly: false
init-download-extension-3:
- path: /var/www/FreshRSS/extensions
readOnly: false
main: main:
- path: /var/www/FreshRSS/extensions - path: /var/www/FreshRSS/extensions
readOnly: false readOnly: false
postgres-18-cluster: cloudflared:
mode: recovery existingSecretName: freshrss-cloudflared-secret
recovery: postgres-17-cluster:
method: objectStore mode: standalone
objectStore: cluster:
index: 1 walStorage:
storageClass: local-path
storage:
storageClass: local-path
monitoring:
enabled: true
backup: backup:
objectStore:
- name: garage-local
index: 1
destinationBucket: postgres-backups
externalSecretCredentialPath: /garage/home-infra/postgres-backups
isWALArchiver: true
# - name: garage-remote
# index: 1
# destinationBucket: postgres-backups
# externalSecretCredentialPath: /garage/home-infra/postgres-backups
# retentionPolicy: "90d"
# data:
# compression: bzip2
# - name: external
# index: 1
# endpointURL: https://nyc3.digitaloceanspaces.com
# destinationBucket: postgres-backups-ce540ddf106d186bbddca68a
# externalSecretCredentialPath: /garage/home-infra/postgres-backups
# isWALArchiver: false
scheduledBackups:
- name: live-backup
suspend: false
immediate: true
schedule: "0 0 0 * * *"
backupName: garage-local
# - name: weekly-backup
# suspend: true
# immediate: true
# schedule: "0 0 4 * * SAT"
# backupName: garage-remote
# - name: daily-backup
# suspend: true
# immediate: true
# schedule: "0 0 0 * * *"
# backupName: external
volsync-target-data:
pvcTarget: freshrss-data
moverSecurityContext:
runAsUser: 568
runAsGroup: 568
fsGroup: 568
fsGroupChangePolicy: OnRootMismatch
supplementalGroups:
- 44
- 100
- 109
- 65539
local:
enabled: true enabled: true
schedule: 18 8 * * * endpointURL: https://nyc3.digitaloceanspaces.com
remote: destinationPath: s3://postgres-backups-ce540ddf106d186bbddca68a/cl01tl/freshrss/freshrss-postgresql-17-cluster
enabled: false endpointCredentials: freshrss-postgresql-17-cluster-backup-secret
external: backupIndex: 3
enabled: true
schedule: 18 9 * * *

View File

@@ -0,0 +1,32 @@
apiVersion: v2
name: hoarder
version: 1.0.0
description: Hoarder
keywords:
- hoarder
- bookmarks
home: https://wiki.alexlebens.dev/doc/hoarder-
sources:
- https://github.com/hoarder-app/hoarder
- https://github.com/cloudflare/cloudflared
- https://github.com/meilisearch/meilisearch
- https://github.com/hoarder-app/hoarder/pkgs/container/hoarder
- https://github.com/bjw-s/helm-charts/tree/main/charts/other/app-template
- https://github.com/alexlebens/helm-charts/tree/main/charts/cloudflared
- https://github.com/meilisearch/meilisearch-kubernetes/tree/main/charts/meilisearch
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: hoarder
repository: https://bjw-s.github.io/helm-charts/
version: 3.7.3
- name: meilisearch
version: 0.12.0
repository: https://meilisearch.github.io/meilisearch-kubernetes
- name: cloudflared
alias: cloudflared
repository: https://gitea.alexlebens.dev/api/packages/alexlebens/helm
version: 1.14.3
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/svg/hoarder.svg
appVersion: 0.19.0

View File

@@ -0,0 +1,164 @@
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: hoarder-key-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: hoarder-key-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: key
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/hoarder/key
metadataPolicy: None
property: key
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: hoarder-oidc-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: hoarder-oidc-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: AUTHENTIK_CLIENT_ID
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /authentik/oidc/hoarder
metadataPolicy: None
property: client
- secretKey: AUTHENTIK_CLIENT_SECRET
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /authentik/oidc/hoarder
metadataPolicy: None
property: secret
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: hoarder-meilisearch-master-key-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: hoarder-meilisearch-master-key-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: meilisearch
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: MEILI_MASTER_KEY
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/hoarder/meilisearch
metadataPolicy: None
property: MEILI_MASTER_KEY
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: hoarder-cloudflared-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: hoarder-cloudflared-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: cf-tunnel-token
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cloudflare/tunnels/hoarder
metadataPolicy: None
property: token
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: hoarder-data-backup-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: hoarder-data-backup-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: backup
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
target:
template:
mergePolicy: Merge
engineVersion: v2
data:
RESTIC_REPOSITORY: "{{ `{{ .BUCKET_ENDPOINT }}` }}/hoarder/hoarder-data"
data:
- secretKey: BUCKET_ENDPOINT
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: S3_BUCKET_ENDPOINT
- secretKey: RESTIC_PASSWORD
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: RESTIC_PASSWORD
- secretKey: AWS_DEFAULT_REGION
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: AWS_DEFAULT_REGION
- secretKey: AWS_ACCESS_KEY_ID
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/volsync-backups
metadataPolicy: None
property: access_key
- secretKey: AWS_SECRET_ACCESS_KEY
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/volsync-backups
metadataPolicy: None
property: secret_key

View File

@@ -0,0 +1,27 @@
apiVersion: volsync.backube/v1alpha1
kind: ReplicationSource
metadata:
name: hoarder-data-backup-source
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: hoarder-data-backup-source
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: backup
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
sourcePVC: hoarder-data
trigger:
schedule: 0 4 * * *
restic:
pruneIntervalDays: 7
repository: hoarder-data-backup-secret
retain:
hourly: 1
daily: 3
weekly: 2
monthly: 2
yearly: 4
copyMethod: Snapshot
storageClassName: ceph-block
volumeSnapshotClassName: ceph-blockpool-snapshot

View File

@@ -1,4 +1,4 @@
karakeep: hoarder:
controllers: controllers:
main: main:
type: deployment type: deployment
@@ -8,82 +8,54 @@ karakeep:
containers: containers:
main: main:
image: image:
repository: ghcr.io/karakeep-app/karakeep repository: ghcr.io/hoarder-app/hoarder
tag: 0.30.0 tag: 0.23.0
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
env: env:
- name: DATA_DIR - name: DATA_DIR
value: /data value: /data
- name: DB_WAL_MODE
value: true
- name: NEXTAUTH_URL - name: NEXTAUTH_URL
value: https://karakeep.alexlebens.dev/ value: https://hoarder.alexlebens.dev/
- name: NEXTAUTH_SECRET - name: NEXTAUTH_SECRET
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: karakeep-key-secret name: hoarder-key-secret
key: key key: key
- name: PROMETHEUS_AUTH_TOKEN
valueFrom:
secretKeyRef:
name: karakeep-key-secret
key: prometheus-token
- name: ASSET_STORE_S3_ENDPOINT
value: http://rook-ceph-rgw-ceph-objectstore.rook-ceph.svc:80
- name: ASSET_STORE_S3_REGION
value: us-east-1
- name: ASSET_STORE_S3_BUCKET
valueFrom:
configMapKeyRef:
name: ceph-bucket-karakeep
key: BUCKET_NAME
- name: ASSET_STORE_S3_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: ceph-bucket-karakeep
key: AWS_ACCESS_KEY_ID
- name: ASSET_STORE_S3_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: ceph-bucket-karakeep
key: AWS_SECRET_ACCESS_KEY
- name: ASSET_STORE_S3_FORCE_PATH_STYLE
value: true
- name: MEILI_ADDR - name: MEILI_ADDR
value: http://karakeep-meilisearch.karakeep:7700 value: http://hoarder-meilisearch.hoarder:7700
- name: MEILI_MASTER_KEY - name: MEILI_MASTER_KEY
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: karakeep-meilisearch-master-key-secret name: hoarder-meilisearch-master-key-secret
key: MEILI_MASTER_KEY key: MEILI_MASTER_KEY
- name: BROWSER_WEB_URL - name: BROWSER_WEB_URL
value: http://karakeep.karakeep:9222 value: http://hoarder.hoarder:9222
- name: DISABLE_SIGNUPS - name: DISABLE_SIGNUPS
value: false value: false
- name: OAUTH_PROVIDER_NAME - name: OAUTH_PROVIDER_NAME
value: "Authentik" value: "Authentik"
- name: OAUTH_WELLKNOWN_URL - name: OAUTH_WELLKNOWN_URL
value: https://auth.alexlebens.dev/application/o/karakeep/.well-known/openid-configuration value: https://auth.alexlebens.dev/application/o/hoarder/.well-known/openid-configuration
- name: OAUTH_SCOPE - name: OAUTH_SCOPE
value: "openid email profile" value: "openid email profile"
- name: OAUTH_CLIENT_ID - name: OAUTH_CLIENT_ID
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: karakeep-oidc-secret name: hoarder-oidc-secret
key: AUTHENTIK_CLIENT_ID key: AUTHENTIK_CLIENT_ID
- name: OAUTH_CLIENT_SECRET - name: OAUTH_CLIENT_SECRET
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: karakeep-oidc-secret name: hoarder-oidc-secret
key: AUTHENTIK_CLIENT_SECRET key: AUTHENTIK_CLIENT_SECRET
- name: OLLAMA_BASE_URL - name: OLLAMA_BASE_URL
value: http://ollama-server-3.ollama:11434 value: http://ollama-server-1.ollama:11434
- name: OLLAMA_KEEP_ALIVE - name: OLLAMA_KEEP_ALIVE
value: 5m value: 5m
- name: INFERENCE_TEXT_MODEL - name: INFERENCE_TEXT_MODEL
value: gemma3:4b value: llama3.1:8b
- name: INFERENCE_IMAGE_MODEL - name: INFERENCE_IMAGE_MODEL
value: granite3.2-vision:2b value: llama3.2-vision:11b
- name: EMBEDDING_TEXT_MODEL - name: EMBEDDING_TEXT_MODEL
value: mxbai-embed-large value: mxbai-embed-large
- name: INFERENCE_JOB_TIMEOUT_SEC - name: INFERENCE_JOB_TIMEOUT_SEC
@@ -108,6 +80,8 @@ karakeep:
requests: requests:
cpu: 10m cpu: 10m
memory: 128Mi memory: 128Mi
serviceAccount:
create: true
service: service:
main: main:
controller: main controller: main
@@ -120,25 +94,8 @@ karakeep:
port: 9222 port: 9222
targetPort: 9222 targetPort: 9222
protocol: HTTP protocol: HTTP
serviceMonitor:
main:
selector:
matchLabels:
app.kubernetes.io/name: karakeep
app.kubernetes.io/instance: karakeep
serviceName: '{{ include "bjw-s.common.lib.chart.names.fullname" $ }}'
endpoints:
- port: http
interval: 30s
scrapeTimeout: 15s
path: /api/metrics
authorization:
credentials:
key: prometheus-token
name: karakeep-key-secret
persistence: persistence:
data: data:
forceRename: karakeep
storageClass: ceph-block storageClass: ceph-block
accessMode: ReadWriteOnce accessMode: ReadWriteOnce
size: 10Gi size: 10Gi
@@ -152,9 +109,8 @@ meilisearch:
environment: environment:
MEILI_NO_ANALYTICS: true MEILI_NO_ANALYTICS: true
MEILI_ENV: production MEILI_ENV: production
MEILI_EXPERIMENTAL_DUMPLESS_UPGRADE: true
auth: auth:
existingMasterKeySecret: karakeep-meilisearch-master-key-secret existingMasterKeySecret: hoarder-meilisearch-master-key-secret
service: service:
type: ClusterIP type: ClusterIP
port: 7700 port: 7700
@@ -168,13 +124,5 @@ meilisearch:
memory: 128Mi memory: 128Mi
serviceMonitor: serviceMonitor:
enabled: true enabled: true
volsync-target-data: cloudflared:
pvcTarget: karakeep existingSecretName: hoarder-cloudflared-secret
local:
enabled: true
schedule: 34 8 * * *
remote:
enabled: false
external:
enabled: true
schedule: 34 9 * * *

View File

@@ -0,0 +1,23 @@
apiVersion: v2
name: home-assistant
version: 1.0.0
description: Home Assistant
keywords:
- home-assistant
- home
- automation
home: https://wiki.alexlebens.dev/doc/home-assistant-
sources:
- https://www.home-assistant.io/
- https://github.com/home-assistant/core
- https://github.com/home-assistant/core/pkgs/container/home-assistant
- https://github.com/bjw-s/helm-charts/tree/main/charts/other/app-template
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: home-assistant
repository: https://bjw-s.github.io/helm-charts/
version: 3.7.3
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/home-assistant.webp
appVersion: 2025.3.1

View File

@@ -1,11 +1,13 @@
apiVersion: external-secrets.io/v1 apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret kind: ExternalSecret
metadata: metadata:
name: codeserver-password-secret name: home-assistant-code-server-password-secret
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
app.kubernetes.io/name: codeserver-password-secret app.kubernetes.io/name: home-assistant-code-server-password-secret
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
secretStoreRef: secretStoreRef:
@@ -16,13 +18,13 @@ spec:
remoteRef: remoteRef:
conversionStrategy: Default conversionStrategy: Default
decodingStrategy: None decodingStrategy: None
key: /cl01tl/code-server/auth key: /cl01tl/home-assistant/code-server/auth
metadataPolicy: None metadataPolicy: None
property: PASSWORD property: PASSWORD
- secretKey: SUDO_PASSWORD - secretKey: SUDO_PASSWORD
remoteRef: remoteRef:
conversionStrategy: Default conversionStrategy: Default
decodingStrategy: None decodingStrategy: None
key: /cl01tl/code-server/auth key: /cl01tl/home-assistant/code-server/auth
metadataPolicy: None metadataPolicy: None
property: SUDO_PASSWORD property: SUDO_PASSWORD

View File

@@ -0,0 +1,62 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-route-home-assistant
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: http-route-home-assistant
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- home-assistant.alexlebens.net
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ''
kind: Service
name: home-assistant-main
port: 80
weight: 100
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-route-home-assistant-code-server
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: http-route-home-assistant-code-server
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- home-assistant-code-server.alexlebens.net
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ''
kind: Service
name: home-assistant-code-server
port: 8443
weight: 100

View File

@@ -0,0 +1,24 @@
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: home-assistant
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: home-assistant
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: metrics
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
selector:
matchLabels:
app.kubernetes.io/name: home-assistant
app.kubernetes.io/instance: {{ .Release.Name }}
endpoints:
- port: http
interval: 3m
scrapeTimeout: 1m
path: /api/prometheus
bearerTokenSecret:
name: secretName
key: secretKey

View File

@@ -0,0 +1,71 @@
home-assistant:
controllers:
main:
type: deployment
replicas: 1
strategy: Recreate
revisionHistoryLimit: 3
containers:
main:
image:
repository: ghcr.io/home-assistant/home-assistant
tag: 2025.3.3
pullPolicy: IfNotPresent
env:
- name: TZ
value: US/Central
resources:
requests:
cpu: 1
memory: 2Gi
code-server:
image:
repository: ghcr.io/linuxserver/code-server
tag: 4.98.2@sha256:87fbf594ae4a6494d0623967fc4c7a42774945c9cf032b55c57128ca675f2221
pullPolicy: IfNotPresent
env:
- name: TZ
value: US/Central
- name: PUID
value: 1000
- name: PGID
value: 1000
- name: DEFAULT_WORKSPACE
value: /config
envFrom:
- secretRef:
name: home-assistant-code-server-password-secret
resources:
requests:
cpu: 10m
memory: 128Mi
serviceAccount:
create: true
service:
main:
controller: main
ports:
http:
port: 80
targetPort: 8123
protocol: TCP
code-server:
controller: main
ports:
http:
port: 8443
targetPort: 8443
protocol: HTTP
persistence:
config:
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 5Gi
advancedMounts:
main:
main:
- path: /config
readOnly: false
code-server:
- path: /config/home-assistant
readOnly: false

View File

@@ -0,0 +1,27 @@
apiVersion: v2
name: homepage
version: 1.0.0
description: Homepage
keywords:
- homepage
- dashboard
home: https://wiki.alexlebens.dev/doc/homepage-dev-crZPAd8FEj
sources:
- https://github.com/gethomepage/homepage
- https://github.com/cloudflare/cloudflared
- https://github.com/gethomepage/homepage/pkgs/container/homepage
- https://github.com/bjw-s/helm-charts/tree/main/charts/other/app-template
- https://github.com/alexlebens/helm-charts/tree/main/charts/cloudflared
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: homepage
repository: https://bjw-s.github.io/helm-charts/
version: 3.7.3
- name: cloudflared
alias: cloudflared
repository: https://gitea.alexlebens.dev/api/packages/alexlebens/helm
version: 1.14.3
icon: https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/homepage.png
appVersion: v0.10.0

View File

@@ -0,0 +1,23 @@
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: homepage-dev-cloudflared-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: homepage-dev-cloudflared-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: cf-tunnel-token
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cloudflare/tunnels/homepage-dev
metadataPolicy: None
property: token

View File

@@ -11,7 +11,7 @@ homepage:
main: main:
image: image:
repository: ghcr.io/gethomepage/homepage repository: ghcr.io/gethomepage/homepage
tag: v1.9.0 tag: v1.0.4
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
env: env:
- name: HOMEPAGE_ALLOWED_HOSTS - name: HOMEPAGE_ALLOWED_HOSTS
@@ -20,6 +20,8 @@ homepage:
requests: requests:
cpu: 10m cpu: 10m
memory: 128Mi memory: 128Mi
serviceAccount:
create: true
configMaps: configMaps:
config: config:
enabled: true enabled: true
@@ -27,18 +29,18 @@ homepage:
docker.yaml: "" docker.yaml: ""
kubernetes.yaml: "" kubernetes.yaml: ""
settings.yaml: | settings.yaml: |
favicon: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/logo-new-round.svg favicon: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/icon_white.png
headerStyle: clean headerStyle: clean
hideVersion: true hideVersion: true
color: zinc color: zinc
background: background:
image: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/background.jpg image: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/background-4.jpg
brightness: 50 brightness: 50
theme: dark theme: dark
disableCollapse: true disableCollapse: true
widgets.yaml: | widgets.yaml: |
- logo: - logo:
icon: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/logo-new-round.png icon: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/icon_white.png
- datetime: - datetime:
text_size: xl text_size: xl
format: format:
@@ -57,25 +59,19 @@ homepage:
services.yaml: | services.yaml: |
- Applications: - Applications:
- Auth: - Auth:
icon: sh-authentik.webp icon: sh-authentik.svg
description: Authentik description: Authentik
href: https://auth.alexlebens.dev href: https://auth.alexlebens.dev
siteMonitor: https://auth.alexlebens.dev siteMonitor: https://auth.alexlebens.dev
statusStyle: dot statusStyle: dot
- Gitea: - Gitea:
icon: sh-gitea.webp icon: sh-gitea.svg
description: Gitea description: Gitea
href: https://gitea.alexlebens.dev href: https://gitea.alexlebens.dev
siteMonitor: https://gitea.alexlebens.dev siteMonitor: https://gitea.alexlebens.dev
statusStyle: dot statusStyle: dot
- Code:
icon: sh-visual-studio-code.webp
description: VS Code
href: https://codeserver.alexlebens.dev
siteMonitor: https://codeserver.alexlebens.dev
statusStyle: dot
- Site: - Site:
icon: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/logo-new-round.png icon: https://d21zlbwtcn424f.cloudfront.net/icon_white.png
description: Profile Website description: Profile Website
href: https://www.alexlebens.dev href: https://www.alexlebens.dev
siteMonitor: https://www.alexlebens.dev siteMonitor: https://www.alexlebens.dev
@@ -86,38 +82,32 @@ homepage:
href: https://directus.alexlebens.dev href: https://directus.alexlebens.dev
siteMonitor: https://directus.alexlebens.dev siteMonitor: https://directus.alexlebens.dev
statusStyle: dot statusStyle: dot
- Social Media Management:
icon: sh-postiz.webp
description: Postiz
href: https://postiz.alexlebens.dev
siteMonitor: https://postiz.alexlebens.dev
statusStyle: dot
- Chat: - Chat:
icon: sh-element.webp icon: sh-element.svg
description: Matrix description: Matrix
href: https://chat.alexlebens.dev href: https://chat.alexlebens.dev
siteMonitor: https://chat.alexlebens.dev siteMonitor: https://chat.alexlebens.dev
statusStyle: dot statusStyle: dot
- Wiki: - Wiki:
icon: sh-outline.webp icon: sh-outline.svg
description: Outline description: Outline
href: https://wiki.alexlebens.dev href: https://wiki.alexlebens.dev
siteMonitor: https://wiki.alexlebens.dev siteMonitor: https://wiki.alexlebens.dev
statusStyle: dot statusStyle: dot
- Passwords: - Passwords:
icon: sh-vaultwarden-light.webp icon: sh-vaultwarden-light.svg
description: Vaultwarden description: Vaultwarden
href: https://passwords.alexlebens.dev href: https://passwords.alexlebens.dev
siteMonitor: https://passwords.alexlebens.dev siteMonitor: https://passwords.alexlebens.dev
statusStyle: dot statusStyle: dot
- Bookmarks: - Bookmarks:
icon: sh-karakeep-light.webp icon: sh-hoarder-light.svg
description: Karakeep description: Hoader
href: https://karakeep.alexlebens.dev href: https://hoarder.alexlebens.dev
siteMonitor: https://karakeep.alexlebens.dev siteMonitor: https://hoarder.alexlebens.dev
statusStyle: dot statusStyle: dot
- RSS: - RSS:
icon: sh-freshrss.webp icon: sh-freshrss.svg
description: FreshRSS description: FreshRSS
href: https://rss.alexlebens.dev href: https://rss.alexlebens.dev
siteMonitor: https://rss.alexlebens.dev siteMonitor: https://rss.alexlebens.dev
@@ -135,7 +125,7 @@ homepage:
config: config:
enabled: true enabled: true
type: configMap type: configMap
name: homepage-dev name: homepage-dev-config
advancedMounts: advancedMounts:
main: main:
main: main:
@@ -163,3 +153,5 @@ homepage:
readOnly: true readOnly: true
mountPropagation: None mountPropagation: None
subPath: widgets.yaml subPath: widgets.yaml
cloudflared:
existingSecretName: homepage-dev-cloudflared-secret

View File

@@ -0,0 +1,21 @@
apiVersion: v2
name: homepage
version: 1.0.0
description: Homepage
keywords:
- homepage
- dashboard
home: https://wiki.alexlebens.dev/doc/homepage-s2clWoI5EC
sources:
- https://github.com/gethomepage/homepage
- https://github.com/gethomepage/homepage/pkgs/container/homepage
- https://github.com/bjw-s/helm-charts/tree/main/charts/other/app-template
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: homepage
repository: https://bjw-s.github.io/helm-charts/
version: 3.7.3
icon: https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/homepage.png
appVersion: v0.10.0

View File

@@ -6,6 +6,8 @@ metadata:
labels: labels:
app.kubernetes.io/name: homepage app.kubernetes.io/name: homepage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
roleRef: roleRef:
apiGroup: rbac.authorization.k8s.io apiGroup: rbac.authorization.k8s.io

View File

@@ -6,6 +6,8 @@ metadata:
labels: labels:
app.kubernetes.io/name: homepage app.kubernetes.io/name: homepage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
rules: rules:
- apiGroups: - apiGroups:
@@ -26,20 +28,13 @@ rules:
- get - get
- list - list
- apiGroups: - apiGroups:
- traefik.containo.us
- traefik.io - traefik.io
resources: resources:
- ingressroutes - ingressroutes
verbs: verbs:
- get - get
- list - list
- apiGroups:
- gateway.networking.k8s.io
resources:
- httproutes
- gateways
verbs:
- get
- list
- apiGroups: - apiGroups:
- metrics.k8s.io - metrics.k8s.io
resources: resources:
@@ -48,3 +43,9 @@ rules:
verbs: verbs:
- get - get
- list - list
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions/status
verbs:
- get

View File

@@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1 apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret kind: ExternalSecret
metadata: metadata:
name: homepage-keys-secret name: homepage-keys-secret
@@ -6,6 +6,8 @@ metadata:
labels: labels:
app.kubernetes.io/name: homepage-keys-secret app.kubernetes.io/name: homepage-keys-secret
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
secretStoreRef: secretStoreRef:

View File

@@ -0,0 +1,30 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-route-homepage
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: http-route-homepage
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- home.alexlebens.net
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ''
kind: Service
name: homepage
port: 80
weight: 100

View File

@@ -0,0 +1,34 @@
apiVersion: v1
kind: Service
metadata:
name: gitea-ps10rp
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: gitea-ps10rp
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: tailscale
app.kubernetes.io/part-of: {{ .Release.Name }}
annotations:
tailscale.com/tailnet-fqdn: gitea-ps10rp.boreal-beaufort.ts.net
spec:
externalName: placeholder
type: ExternalName
---
apiVersion: v1
kind: Service
metadata:
name: home-ps10rp
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: home-ps10rp
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: tailscale
app.kubernetes.io/part-of: {{ .Release.Name }}
annotations:
tailscale.com/tailnet-fqdn: home-ps10rp.boreal-beaufort.ts.net
spec:
externalName: placeholder
type: ExternalName

View File

@@ -7,15 +7,11 @@ homepage:
annotations: annotations:
reloader.stakater.com/auto: "true" reloader.stakater.com/auto: "true"
strategy: Recreate strategy: Recreate
serviceAccount:
name: homepage
pod:
automountServiceAccountToken: true
containers: containers:
main: main:
image: image:
repository: ghcr.io/gethomepage/homepage repository: ghcr.io/gethomepage/homepage
tag: v1.9.0 tag: v1.0.4
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
env: env:
- name: HOMEPAGE_ALLOWED_HOSTS - name: HOMEPAGE_ALLOWED_HOSTS
@@ -28,9 +24,8 @@ homepage:
cpu: 10m cpu: 10m
memory: 256Mi memory: 256Mi
serviceAccount: serviceAccount:
homepage: create: true
enabled: true name: homepage
staticToken: true
configMaps: configMaps:
config: config:
enabled: true enabled: true
@@ -39,12 +34,12 @@ homepage:
kubernetes.yaml: | kubernetes.yaml: |
mode: cluster mode: cluster
settings.yaml: | settings.yaml: |
favicon: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/logo-new-round.svg favicon: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/icon_white.png
headerStyle: clean headerStyle: clean
hideVersion: true hideVersion: true
color: zinc color: zinc
background: background:
image: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/background.jpg image: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/background-4.jpg
brightness: 50 brightness: 50
theme: dark theme: dark
disableCollapse: true disableCollapse: true
@@ -61,9 +56,6 @@ homepage:
- Code: - Code:
tab: Tools tab: Tools
icon: mdi-code-block-braces-#ffffff icon: mdi-code-block-braces-#ffffff
- Automation:
tab: Tools
icon: mdi-wrench-#ffffff
- Monitoring: - Monitoring:
tab: Tools tab: Tools
icon: mdi-chart-line-#ffffff icon: mdi-chart-line-#ffffff
@@ -76,21 +68,18 @@ homepage:
- Storage: - Storage:
tab: Services tab: Services
icon: mdi-database-#ffffff icon: mdi-database-#ffffff
- Content:
tab: Services
icon: mdi-multimedia-#ffffff
- TV Shows: - TV Shows:
tab: Content tab: Servarr
icon: mdi-television-#ffffff icon: mdi-television-#ffffff
- Movies: - Movies:
tab: Content tab: Servarr
icon: mdi-filmstrip-#ffffff icon: mdi-filmstrip-#ffffff
- Music: - Music:
tab: Content tab: Servarr
icon: mdi-music-box-multiple-#ffffff icon: mdi-music-box-multiple-#ffffff
- Books: - Services (Servarr):
tab: Content tab: Servarr
icon: mdi-book-open-variant-#ffffff icon: mdi-radar-#ffffff
- External Services: - External Services:
tab: Bookmarks tab: Bookmarks
icon: mdi-cloud-#ffffff icon: mdi-cloud-#ffffff
@@ -102,7 +91,7 @@ homepage:
icon: mdi-cloud-#ffffff icon: mdi-cloud-#ffffff
widgets.yaml: | widgets.yaml: |
- logo: - logo:
icon: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/logo-new-round.png icon: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/icon_white.png
- kubernetes: - kubernetes:
cluster: cluster:
show: true show: true
@@ -129,69 +118,51 @@ homepage:
maximumFractionDigits: 0 maximumFractionDigits: 0
services.yaml: | services.yaml: |
- Media: - Media:
- Plex:
icon: sh-plex.svg
description: Media server
href: https://plex.alexlebens.net
siteMonitor: http://plex.plex:32400
statusStyle: dot
- Media Requests: - Media Requests:
icon: sh-overseerr.webp icon: sh-overseerr.svg
description: Overseerr description: Overseer
href: https://overseerr.alexlebens.net href: https://overseerr.alexlebens.net
siteMonitor: http://overseerr.overseerr:80 siteMonitor: http://overseerr.overseerr:80
statusStyle: dot statusStyle: dot
- Media Requests (New): - Jellyfin:
icon: sh-overseerr.webp icon: sh-jellyfin.svg
description: Seerr description: Media server
href: https://seerr.alexlebens.net
siteMonitor: http://seerr-seerr-chart.seerr:80
statusStyle: dot
- Media Tracking:
icon: sh-yamtrack.webp
description: Yamtrack
href: https://yamtrack.alexlebens.net
siteMonitor: http://yamtrack.yamtrack:80
statusStyle: dot
- Movies and TV:
icon: sh-jellyfin.webp
description: Jellyfin
href: https://jellyfin.alexlebens.net href: https://jellyfin.alexlebens.net
siteMonitor: http://jellyfin.jellyfin:80 siteMonitor: http://jellyfin.jellyfin:80
statusStyle: dot statusStyle: dot
- Youtube Archive: - Youtube Archive:
icon: sh-tube-archivist-light.webp icon: sh-tube-archivist-light.png
description: TubeArchivist description: TubeAchivist
href: https://tubearchivist.alexlebens.net/login href: https://tubearchivist.alexlebens.net/login
siteMonitor: http://tubearchivist.tubearchivist:80 siteMonitor: http://tubearchivist.tubearchivist:80
statusStyle: dot statusStyle: dot
- Music: - Photos:
icon: sh-feishin.webp icon: sh-immich.svg
description: Feishin description: Immich
href: https://feishin.alexlebens.net href: https://immich.alexlebens.net
siteMonitor: http://navidrome-feishin.navidrome:80 siteMonitor: http://immich-main.immich:2283
statusStyle: dot statusStyle: dot
- Podcasts and Audiobooks: - Podcasts and Audiobooks:
icon: sh-audiobookshelf.webp icon: sh-audiobookshelf.svg
description: Audiobookshelf description: Audiobookshelf
href: https://audiobookshelf.alexlebens.net href: https://audiobookshelf.alexlebens.net
siteMonitor: http://audiobookshelf.audiobookshelf:80 siteMonitor: http://audiobookshelf.audiobookshelf:80
statusStyle: dot statusStyle: dot
- Photos:
icon: sh-immich.webp
description: Immich
href: https://immich.alexlebens.net
siteMonitor: http://immich.immich:2283
statusStyle: dot
- Pictures:
icon: sh-photoview.webp
description: Photoview
href: https://photoview.alexlebens.net
siteMonitor: http://photoview.photoview:80
statusStyle: dot
- Books: - Books:
icon: sh-booklore.webp icon: sh-calibre-web-light.svg
description: Booklore description: Calibre Web Automated
href: https://booklore.alexlebens.net href: https://calibre.alexlebens.net
siteMonitor: http://booklore.booklore:80 siteMonitor: http://calibre-web-automated-main.calibre-web-automated:8083
statusStyle: dot statusStyle: dot
- Public: - Public:
- Site: - Site:
icon: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/logo-new-round.png icon: https://web-assets-3bfcb5585cbd63dc365d32a3.nyc3.cdn.digitaloceanspaces.com/alexlebens-net/icon_white.png
description: Profile Website description: Profile Website
href: https://www.alexlebens.dev href: https://www.alexlebens.dev
siteMonitor: https://www.alexlebens.dev siteMonitor: https://www.alexlebens.dev
@@ -202,57 +173,45 @@ homepage:
href: https://directus.alexlebens.dev href: https://directus.alexlebens.dev
siteMonitor: https://directus.alexlebens.dev siteMonitor: https://directus.alexlebens.dev
statusStyle: dot statusStyle: dot
- Social Media Management:
icon: sh-postiz.webp
description: Postiz
href: https://postiz.alexlebens.dev
siteMonitor: https://postiz.alexlebens.dev
statusStyle: dot
- Chat: - Chat:
icon: sh-element.webp icon: sh-element.svg
description: Matrix description: Matrix
href: https://chat.alexlebens.dev href: https://chat.alexlebens.dev
siteMonitor: https://chat.alexlebens.dev siteMonitor: https://chat.alexlebens.dev
statusStyle: dot statusStyle: dot
- Wiki: - Wiki:
icon: sh-outline.webp icon: sh-outline.svg
description: Outline description: Outline
href: https://wiki.alexlebens.dev href: https://wiki.alexlebens.dev
siteMonitor: https://wiki.alexlebens.dev siteMonitor: https://wiki.alexlebens.dev
statusStyle: dot statusStyle: dot
- Passwords: - Passwords:
icon: sh-vaultwarden-light.webp icon: sh-vaultwarden-light.svg
description: Vaultwarden description: Vaultwarden
href: https://passwords.alexlebens.dev href: https://passwords.alexlebens.dev
siteMonitor: https://passwords.alexlebens.dev siteMonitor: https://passwords.alexlebens.dev
statusStyle: dot statusStyle: dot
- Bookmarks: - Bookmarks:
icon: sh-karakeep-light.webp icon: sh-hoarder-light.svg
description: Karakeep description: Hoader
href: https://karakeep.alexlebens.dev href: https://hoarder.alexlebens.dev
siteMonitor: https://karakeep.alexlebens.dev siteMonitor: https://hoarder.alexlebens.dev
statusStyle: dot statusStyle: dot
- RSS: - RSS:
icon: sh-freshrss.webp icon: sh-freshrss.svg
description: FreshRSS description: FreshRSS
href: https://rss.alexlebens.dev href: https://rss.alexlebens.dev
siteMonitor: https://rss.alexlebens.dev siteMonitor: https://rss.alexlebens.dev
statusStyle: dot statusStyle: dot
- Internal: - Internal:
- Home Automation: - Home Automation:
icon: sh-home-assistant.webp icon: sh-home-assistant.svg
description: Home Assistant description: Home Assistant
href: https://home-assistant.alexlebens.net href: https://home-assistant.alexlebens.net
siteMonitor: http://home-assistant-main.home-assistant:80 siteMonitor: http://home-assistant-main.home-assistant:80
statusStyle: dot statusStyle: dot
- Budgeting:
icon: sh-actual-budget.webp
description: Actual
href: https://actual.alexlebens.net
siteMonitor: http://actual.actual:80
statusStyle: dot
- AI: - AI:
icon: sh-ollama.webp icon: sh-ollama-light.svg
description: Ollama description: Ollama
href: https://ollama.alexlebens.net href: https://ollama.alexlebens.net
siteMonitor: http://ollama-web.ollama:80 siteMonitor: http://ollama-web.ollama:80
@@ -264,112 +223,102 @@ homepage:
siteMonitor: https://stable-diffusion-pd05wd.boreal-beaufort.ts.net siteMonitor: https://stable-diffusion-pd05wd.boreal-beaufort.ts.net
statusStyle: dot statusStyle: dot
- Search: - Search:
icon: sh-searxng.webp icon: sh-searxng.svg
description: Searxng description: Searxng
href: https://searxng.alexlebens.net/ href: https://searxng.alexlebens.net/
siteMonitor: http://searxng-browser.searxng:80 siteMonitor: http://searxng-browser.searxng:80
statusStyle: dot statusStyle: dot
- Email: - Email:
icon: sh-roundcube.webp icon: sh-roundcube.svg
description: Roundcube description: Roundcube
href: https://mail.alexlebens.net href: https://mail.alexlebens.net
siteMonitor: http://roundcube.roundcube:80 siteMonitor: http://roundcube.roundcube:80
statusStyle: dot statusStyle: dot
- Wiki: - Wiki:
icon: sh-kiwix-light.webp icon: sh-kiwix-light.svg
description: Kiwix description: Kiwix
href: https://kiwix.alexlebens.net href: https://kiwix.alexlebens.net
siteMonitor: http://kiwix.kiwix:80 siteMonitor: http://kiwix.kiwix:80
statusStyle: dot statusStyle: dot
- Draw: - Pictures:
icon: sh-excalidraw.webp icon: sh-photoview.svg
description: Excalidraw description: Photoview
href: https://excalidraw.alexlebens.net href: https://photoview.alexlebens.net
siteMonitor: http://excalidraw.excalidraw:80 siteMonitor: http://photoview.photoview:80
statusStyle: dot statusStyle: dot
- Code: - Code:
- Code (Public): - Code (Public):
icon: sh-gitea.webp icon: sh-gitea.svg
description: Gitea description: Gitea
href: https://gitea.alexlebens.dev href: https://gitea.alexlebens.dev
siteMonitor: https://gitea.alexlebens.dev siteMonitor: https://gitea.alexlebens.dev
statusStyle: dot statusStyle: dot
- Code (Local): - Code (Local):
icon: sh-gitea.webp icon: sh-gitea.svg
description: Gitea description: Gitea
href: https://gitea.alexlebens.net href: https://gitea.alexlebens.net
siteMonitor: https://gitea.alexlebens.net siteMonitor: https://gitea.alexlebens.net
statusStyle: dot statusStyle: dot
- Code (ps10rp): - Code (ps10rp):
icon: sh-gitea.webp icon: sh-gitea.svg
description: Gitea description: Gitea
href: https://gitea-ps10rp.boreal-beaufort.ts.net href: https://gitea.lebens-home.net
siteMonitor: https://gitea-ps10rp.boreal-beaufort.ts.net siteMonitor: https://gitea.lebens-home.net
statusStyle: dot statusStyle: dot
- IDE (Public): - IDE (Public):
icon: sh-visual-studio-code.webp icon: sh-visual-studio-code.svg
description: VS Code description: VS Code
href: https://codeserver.alexlebens.dev href: https://codeserver.alexlebens.dev
siteMonitor: https://codeserver.alexlebens.dev siteMonitor: https://codeserver.alexlebens.dev
statusStyle: dot statusStyle: dot
- IDE (Home Assistant): - IDE (Home Assistant):
icon: sh-visual-studio-code.webp icon: sh-visual-studio-code.svg
description: Edit config for Home Assistant description: Edit config for Home Assistant
href: https://home-assistant-code-server.alexlebens.net href: https://home-assistant-code-server.alexlebens.net
siteMonitor: http://home-assistant-code-server.home-assistant:8443 siteMonitor: http://home-assistant-code-server.home-assistant:8443
statusStyle: dot statusStyle: dot
- Continuous Deployment: - Continuous Deployment:
icon: sh-argo-cd.webp icon: sh-argo-cd.svg
description: ArgoCD description: ArgoCD
href: https://argocd.alexlebens.net href: https://argocd.alexlebens.net
siteMonitor: http://argocd-server.argocd:80 siteMonitor: http://argocd-server.argocd:80
statusStyle: dot statusStyle: dot
- Docker Deployment: namespace: argocd
icon: sh-komodo-light.webp - Workflows:
description: Komodo icon: sh-argo-cd.svg
href: https://komodo.alexlebens.net
siteMonitor: http://komodo-main.komodo:80
statusStyle: dot
- Automation:
- Deployment Workflows:
icon: sh-argo-cd.webp
description: Argo Workflows description: Argo Workflows
href: https://argo-workflows.alexlebens.net href: https://argo-workflows.alexlebens.net
siteMonitor: http://argo-workflows-server.argo-workflows:2746 siteMonitor: http://argo-workflows-server.argo-workflows:2746
statusStyle: dot statusStyle: dot
- Uptime: namespace: argocd
icon: sh-gatus.webp - Deployment:
description: Gatus icon: sh-komodo-light.svg
href: https://gatus.alexlebens.net description: Komodo
siteMonitor: http://gatus.gatus:80 href: https://komodo.alexlebens.net
statusStyle: dot siteMonitor: http://komodo.komodo:80
- Tools:
icon: sh-omnitools.webp
description: OmniTools
href: https://omni-tools.alexlebens.net
siteMonitor: http://omni-tools.omni-tools:80
statusStyle: dot statusStyle: dot
namespace: komodo
- Monitoring: - Monitoring:
- Kubernetes: - Kubernetes:
icon: sh-headlamp.webp icon: kubernetes.png
description: Headlamp description: Headlamp
href: https://headlamp.alexlebens.net href: https://headlamp.alexlebens.net
siteMonitor: http://headlamp.headlamp:80 siteMonitor: http://headlamp.headlamp:80
statusStyle: dot statusStyle: dot
- Network Monitoring: - Network Monitoring:
icon: sh-cilium.webp icon: cilium.png
description: Hubble for Cilium description: Hubble for Cilium
href: https://hubble.alexlebens.net href: https://hubble.alexlebens.net
siteMonitor: http://hubble-ui.kube-system:80 siteMonitor: http://hubble-ui.kube-system:80
statusStyle: dot statusStyle: dot
- Dashboard: - Dashboard:
icon: sh-grafana.webp icon: sh-grafana.svg
description: Grafana description: Grafana
href: https://grafana.alexlebens.net href: https://grafana.alexlebens.net
siteMonitor: http://grafana-main-service.grafana-operator:3000/api/health siteMonitor: http://grafana.grafana:80/api/health
statusStyle: dot statusStyle: dot
- Metrics: - Metrics:
icon: sh-prometheus.webp icon: sh-prometheus.svg
description: Prometheus description: Prometheus
href: https://prometheus.alexlebens.net href: https://prometheus.alexlebens.net
siteMonitor: http://kube-prometheus-stack-prometheus.kube-prometheus-stack:9090 siteMonitor: http://kube-prometheus-stack-prometheus.kube-prometheus-stack:9090
@@ -377,56 +326,39 @@ homepage:
widget: widget:
type: prometheus type: prometheus
url: http://kube-prometheus-stack-prometheus.kube-prometheus-stack:9090 url: http://kube-prometheus-stack-prometheus.kube-prometheus-stack:9090
- Alerting: - Tautulli:
icon: sh-prometheus-light.webp icon: sh-tautulli.svg
description: Alertmanager description: Plex Monitoring
href: https://alertmanager.alexlebens.net href: https://tautulli.alexlebens.net
siteMonitor: http://kube-prometheus-stack-alertmanager.kube-prometheus-stack:9093 siteMonitor: http://tautulli.tautulli:80
statusStyle: dot statusStyle: dot
widget:
type: prometheusmetric
url: http://kube-prometheus-stack-prometheus.kube-prometheus-stack:9090
refreshInterval: 120s
metrics:
- label: Alerts Active
query: alertmanager_alerts{state="active"}
- label: Metric Database Size
query: prometheus_tsdb_storage_blocks_bytes
format:
type: bytes
- Jellystat: - Jellystat:
icon: sh-jellystat.webp icon: sh-jellystat.png
description: Jellyfin Monitoring description: Jellyfin Monitoring
href: https://jellystat.alexlebens.net href: https://jellystat.alexlebens.net
siteMonitor: http://jellystat.jellystat:80 siteMonitor: http://jellystat.jellystat:80
statusStyle: dot statusStyle: dot
- Services: - Services:
- Auth (Public): - Auth (Public):
icon: sh-authentik.webp icon: sh-authentik.svg
description: Authentik description: Authentik
href: https://auth.alexlebens.dev href: https://auth.alexlebens.dev
siteMonitor: https://auth.alexlebens.dev siteMonitor: https://auth.alexlebens.dev
statusStyle: dot statusStyle: dot
- Auth (Local): - Auth (Local):
icon: sh-authentik.webp icon: sh-authentik.svg
description: Authentik description: Authentik
href: https://authentik.alexlebens.net href: https://authentik.alexlebens.net
siteMonitor: http://authentik-server.authentik:80 siteMonitor: http://authentik-server.authentik:80
statusStyle: dot statusStyle: dot
- Email: - Email:
icon: sh-stalwart.webp icon: sh-stalwart-mail-server.svg
description: Stalwart description: Stalwart
href: https://stalwart.alexlebens.net href: https://stalwart.alexlebens.net
siteMonitor: http://stalwart.stalwart:80 siteMonitor: http://stalwart.stalwart:80
statusStyle: dot statusStyle: dot
- Notifications:
icon: sh-ntfy.webp
description: ntfy
href: https://ntfy.alexlebens.net
siteMonitor: http://ntfy.ntfy:80
statusStyle: dot
- Reverse Proxy: - Reverse Proxy:
icon: sh-traefik.webp icon: sh-traefik.svg
description: Traefik description: Traefik
href: https://traefik-cl01tl.alexlebens.net/dashboard/#/ href: https://traefik-cl01tl.alexlebens.net/dashboard/#/
siteMonitor: https://traefik-cl01tl.alexlebens.net/dashboard/#/ siteMonitor: https://traefik-cl01tl.alexlebens.net/dashboard/#/
@@ -435,20 +367,20 @@ homepage:
type: traefik type: traefik
url: https://traefik-cl01tl.alexlebens.net url: https://traefik-cl01tl.alexlebens.net
- Image Cache: - Image Cache:
icon: sh-harbor.webp icon: sh-harbor.svg
description: Harbor description: Harbor
href: https://harbor.alexlebens.net href: https://harbor.alexlebens.net
siteMonitor: http://harbor-portal.harbor:80 siteMonitor: http://harbor-portal.harbor:80
statusStyle: dot statusStyle: dot
- Hardware: - Hardware:
- Network Management (alexlebens.net): - Network Management (alexlebens.net):
icon: sh-ubiquiti-unifi.webp icon: sh-ubiquiti-unifi.svg
description: Unifi description: Unifi
href: https://unifi.alexlebens.net href: https://unifi.alexlebens.net
siteMonitor: https://unifi.alexlebens.net siteMonitor: https://unifi.alexlebens.net
statusStyle: dot statusStyle: dot
- Network Attached Storage: - Network Attached Storage:
icon: sh-synology-light.webp icon: sh-synology-light.svg
description: Synology description: Synology
href: https://synology.alexlebens.net href: https://synology.alexlebens.net
siteMonitor: https://synology.alexlebens.net siteMonitor: https://synology.alexlebens.net
@@ -460,7 +392,7 @@ homepage:
password: {{ "{{HOMEPAGE_VAR_SYNOLOGY_PASSWORD}}" }} password: {{ "{{HOMEPAGE_VAR_SYNOLOGY_PASSWORD}}" }}
volume: volume_2 volume: volume_2
- TV Tuner: - TV Tuner:
icon: sh-hdhomerun.webp icon: sh-hdhomerun.svg
description: HD Homerun description: HD Homerun
href: http://hdhr.alexlebens.net href: http://hdhr.alexlebens.net
siteMonitor: http://hdhr.alexlebens.net siteMonitor: http://hdhr.alexlebens.net
@@ -471,95 +403,45 @@ homepage:
tuner: 0 tuner: 0
fields: ["channels", "hd"] fields: ["channels", "hd"]
- KVM: - KVM:
icon: sh-pikvm-light.webp icon: sh-pikvm-light.svg
description: Pi KVM description: Pi KVM
href: https://pikvm.alexlebens.net href: https://pikvm.alexlebens.net
siteMonitor: https://pikvm.alexlebens.net siteMonitor: https://pikvm.alexlebens.net
statusStyle: dot statusStyle: dot
- Server Plug:
icon: sh-shelly.webp
description: Shelly
href: http://it05sp.alexlebens.net
siteMonitor: http://it05sp.alexlebens.net
statusStyle: dot
- Storage: - Storage:
- Cluster Storage: - Cluster Storage:
icon: sh-ceph.webp icon: ceph.png
description: Ceph description: Ceph
href: https://ceph.alexlebens.net href: https://ceph.alexlebens.net
siteMonitor: http://rook-ceph-mgr-dashboard.rook-ceph:7000 siteMonitor: http://rook-ceph-mgr-dashboard.rook-ceph:7000
statusStyle: dot statusStyle: dot
- Object Storage (NAS):
icon: sh-garage.webp
description: Garage
href: https://garage-webui.alexlebens.net
siteMonitor: http://garage-webui.garage:3909
statusStyle: dot
- Object Storage (ps10rp):
icon: sh-garage.webp
description: Garage
href: https://garage-ui-ps10rp.boreal-beaufort.ts.net
siteMonitor: https://garage-ui-ps10rp.boreal-beaufort.ts.net
statusStyle: dot
- Database: - Database:
icon: sh-whodb.webp icon: sh-pgadmin-light.svg
description: WhoDB description: PGAdmin
href: https://whodb.alexlebens.net href: https://pgadmin.alexlebens.net
siteMonitor: http://whodb.whodb:80 siteMonitor: http://pgadmin.pgadmin:80
statusStyle: dot statusStyle: dot
- Secrets: - Secrets:
icon: sh-hashicorp-vault.webp icon: sh-hashicorp-vault.svg
description: Vault description: Vault
href: https://vault.alexlebens.net href: https://vault.alexlebens.net
siteMonitor: http://vault.vault:8200 siteMonitor: http://vault.vault:8200
statusStyle: dot statusStyle: dot
- Backups: - Object Storage (Outline):
icon: sh-backrest-light.webp icon: sh-minio.svg
description: Backrest description: Minio Tenant
href: https://backrest.alexlebens.net href: https://minio-outline.alexlebens.net
siteMonitor: http://backrest.backrest:80 siteMonitor: http://minio-outline-console.outline:9090
statusStyle: dot statusStyle: dot
- Content: - Object Storage (Directus):
- qUI: icon: sh-minio.svg
icon: https://raw.githubusercontent.com/autobrr/qui/8487c818886df9abb2b1456f43b54e0ba180a2bd/web/public/icons.svg description: Minio Tenant
description: qbitorrent href: https://minio-directus.alexlebens.net
href: https://qui.alexlebens.net siteMonitor: http://minio-directus-console.directus:9090
siteMonitor: http://qbittorrent-qui.qbittorrent:80
statusStyle: dot statusStyle: dot
widget:
type: qbittorrent
url: http://qbittorrent.qbittorrent:8080
enableLeechProgress: true
- Prowlarr:
icon: sh-prowlarr.webp
description: Indexers
href: https://prowlarr.alexlebens.net
siteMonitor: http://prowlarr.prowlarr:80
statusStyle: dot
- Huntarr:
icon: https://raw.githubusercontent.com/plexguide/Huntarr.io/main/frontend/static/logo/128.png
description: Content upgrader
href: https://huntarr.alexlebens.net
siteMonitor: http://huntarr.huntarr:80
statusStyle: dot
- Bazarr:
icon: sh-bazarr.webp
description: Subtitles
href: https://bazarr.alexlebens.net
siteMonitor: http://bazarr.bazarr:80
statusStyle: dot
- Tdarr:
icon: sh-tdarr.webp
description: Media transcoding and health checks
href: https://tdarr.alexlebens.net
siteMonitor: http://tdarr-web.tdarr:8265
statusStyle: dot
widget:
type: tdarr
url: http://tdarr-web.tdarr:8265
- TV Shows: - TV Shows:
- Sonarr: - Sonarr:
icon: sh-sonarr.webp icon: sh-sonarr.svg
description: TV Shows description: TV Shows
href: https://sonarr.alexlebens.net href: https://sonarr.alexlebens.net
siteMonitor: http://sonarr.sonarr:80 siteMonitor: http://sonarr.sonarr:80
@@ -571,7 +453,7 @@ homepage:
fields: ["wanted", "queued", "series"] fields: ["wanted", "queued", "series"]
enableQueue: false enableQueue: false
- Sonarr 4K: - Sonarr 4K:
icon: sh-sonarr.webp icon: sh-sonarr.svg
description: TV Shows 4K description: TV Shows 4K
href: https://sonarr-4k.alexlebens.net href: https://sonarr-4k.alexlebens.net
siteMonitor: http://sonarr-4k.sonarr-4k:80 siteMonitor: http://sonarr-4k.sonarr-4k:80
@@ -583,7 +465,7 @@ homepage:
fields: ["wanted", "queued", "series"] fields: ["wanted", "queued", "series"]
enableQueue: false enableQueue: false
- Sonarr Anime: - Sonarr Anime:
icon: sh-sonarr.webp icon: sh-sonarr.svg
description: Anime Shows description: Anime Shows
href: https://sonarr-anime.alexlebens.net href: https://sonarr-anime.alexlebens.net
siteMonitor: http://sonarr-anime.sonarr-anime:80 siteMonitor: http://sonarr-anime.sonarr-anime:80
@@ -596,7 +478,7 @@ homepage:
enableQueue: false enableQueue: false
- Movies: - Movies:
- Radarr: - Radarr:
icon: sh-radarr.webp icon: sh-radarr.svg
description: Movies description: Movies
href: https://radarr.alexlebens.net href: https://radarr.alexlebens.net
siteMonitor: http://radarr.radarr:80 siteMonitor: http://radarr.radarr:80
@@ -608,7 +490,7 @@ homepage:
fields: ["wanted", "queued", "movies"] fields: ["wanted", "queued", "movies"]
enableQueue: false enableQueue: false
- Radarr 4K: - Radarr 4K:
icon: sh-radarr-4k.webp icon: sh-radarr.svg
description: Movies 4K description: Movies 4K
href: https://radarr-4k.alexlebens.net href: https://radarr-4k.alexlebens.net
siteMonitor: http://radarr-4k.radarr-4k:80 siteMonitor: http://radarr-4k.radarr-4k:80
@@ -620,7 +502,7 @@ homepage:
fields: ["wanted", "queued", "movies"] fields: ["wanted", "queued", "movies"]
enableQueue: false enableQueue: false
- Radarr Anime: - Radarr Anime:
icon: sh-radarr-anime.webp icon: sh-radarr.svg
description: Anime Movies description: Anime Movies
href: https://radarr-anime.alexlebens.net href: https://radarr-anime.alexlebens.net
siteMonitor: http://radarr-anime.radarr-anime:80 siteMonitor: http://radarr-anime.radarr-anime:80
@@ -632,7 +514,7 @@ homepage:
fields: ["wanted", "queued", "movies"] fields: ["wanted", "queued", "movies"]
enableQueue: false enableQueue: false
- Radarr Stand Up: - Radarr Stand Up:
icon: sh-radarr-light-hybrid.webp icon: sh-radarr.svg
description: Stand Up description: Stand Up
href: https://radarr-standup.alexlebens.net href: https://radarr-standup.alexlebens.net
siteMonitor: http://radarr-standup.radarr-standup:80 siteMonitor: http://radarr-standup.radarr-standup:80
@@ -645,7 +527,7 @@ homepage:
enableQueue: false enableQueue: false
- Music: - Music:
- Lidarr: - Lidarr:
icon: sh-lidarr.webp icon: sh-lidarr.svg
description: Music description: Music
href: https://lidarr.alexlebens.net href: https://lidarr.alexlebens.net
siteMonitor: http://lidarr.lidarr:80 siteMonitor: http://lidarr.lidarr:80
@@ -655,34 +537,59 @@ homepage:
url: http://lidarr.lidarr:80 url: http://lidarr.lidarr:80
key: {{ "{{HOMEPAGE_VAR_LIDARR_KEY}}" }} key: {{ "{{HOMEPAGE_VAR_LIDARR_KEY}}" }}
fields: ["wanted", "queued", "artists"] fields: ["wanted", "queued", "artists"]
- Yubal Playlist: - LidaTube:
icon: sh-yubal.webp icon: sh-lidatube.png
description: Replicate Youtube playlist description: Searches for Music
href: https://yubal-playlist.alexlebens.net href: https://lidatube.alexlebens.net
siteMonitor: http://yubal-playlist.yubal-playlist:80 siteMonitor: http://lidatube.lidatube:80
statusStyle: dot statusStyle: dot
- slskd: - Services (Servarr):
icon: sh-slskd.webp - qBittorrent:
icon: sh-qbittorrent.svg
description: P2P Downloads
href: https://qbittorrent.alexlebens.net
siteMonitor: http://qbittorrent.qbittorrent:8080
statusStyle: dot
widget:
type: qbittorrent
url: http://qbittorrent.qbittorrent:8080
enableLeechProgress: true
- Prowlarr:
icon: sh-prowlarr.svg
description: Indexers
href: https://prowlarr.alexlebens.net
siteMonitor: http://prowlarr.prowlarr:80
statusStyle: dot
- Soulseek:
icon: sh-slskd.png
description: slskd description: slskd
href: https://slskd.alexlebens.net href: https://slskd.alexlebens.net
siteMonitor: http://slskd.slskd:5030 siteMonitor: http://slskd.slskd:5030
statusStyle: dot statusStyle: dot
- Books: - CWA Downloader:
- Shelfmark: icon: sh-calibre.png
icon: sh-shelfmark.webp description: Calibre Web Automated Book Downloader
description: Books href: https://calibre-downloader.alexlebens.net
href: https://shelfmark.alexlebens.net siteMonitor: http://calibre-web-automated-downloader.calibre-web-automated:8084
siteMonitor: http://shelfmark.shelfmark:80
statusStyle: dot statusStyle: dot
- Tdarr:
icon: sh-tdarr.png
description: Media transcoding and health checks
href: https://tdarr.alexlebens.net
siteMonitor: http://tdarr-web.tdarr:8265
statusStyle: dot
widget:
type: tdarr
url: http://tdarr-web.tdarr:8265
- Other Homes: - Other Homes:
- Dev: - Dev:
icon: sh-homepage.webp icon: sh-homepage.png
description: Public Homepage description: Public Homepage
href: https://home.alexlebens.dev href: https://home.alexlebens.dev
siteMonitor: https://home.alexlebens.dev siteMonitor: https://home.alexlebens.dev
statusStyle: dot statusStyle: dot
- Lebens Home: - Lebens Home:
icon: sh-homepage.webp icon: sh-homepage.png
description: Lebens Homepage description: Lebens Homepage
href: https://home-ps10rp.boreal-beaufort.ts.net href: https://home-ps10rp.boreal-beaufort.ts.net
siteMonitor: https://home-ps10rp.boreal-beaufort.ts.net siteMonitor: https://home-ps10rp.boreal-beaufort.ts.net
@@ -692,6 +599,9 @@ homepage:
- Github: - Github:
- abbr: GH - abbr: GH
href: https://github.com/alexlebens href: https://github.com/alexlebens
- Renovate:
- abbr: RN
href: https://developer.mend.io/[platform]/alexlebens/infrastructure
- Digital Ocean: - Digital Ocean:
- abbr: DO - abbr: DO
href: https://www.digitalocean.com/ href: https://www.digitalocean.com/
@@ -743,32 +653,11 @@ homepage:
port: 80 port: 80
targetPort: 3000 targetPort: 3000
protocol: HTTP protocol: HTTP
route:
main:
kind: HTTPRoute
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- home.alexlebens.net
rules:
- backendRefs:
- group: ''
kind: Service
name: homepage
port: 80
weight: 100
matches:
- path:
type: PathPrefix
value: /
persistence: persistence:
config: config:
enabled: true enabled: true
type: configMap type: configMap
name: homepage name: homepage-config
advancedMounts: advancedMounts:
main: main:
main: main:

View File

@@ -0,0 +1,31 @@
apiVersion: v2
name: immich
version: 1.0.0
description: Immich
keywords:
- immich
- photos
home: https://wiki.alexlebens.dev/doc/immich-AVxvAWeWQ5
sources:
- https://github.com/immich-app/immich
- https://github.com/valkey-io/valkey
- https://github.com/cloudnative-pg/cloudnative-pg
- https://github.com/bjw-s/helm-charts/tree/main/charts/other/app-template
- https://github.com/bitnami/charts/tree/main/bitnami/valkey
- https://github.com/alexlebens/helm-charts/charts/postgres-cluster
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: immich
repository: https://bjw-s.github.io/helm-charts/
version: 3.7.3
- name: valkey
version: 2.4.6
repository: oci://harbor.alexlebens.net/proxy-registry-1.docker.io/bitnamicharts
- name: postgres-cluster
alias: postgres-16-cluster
version: 4.2.1
repository: https://gitea.alexlebens.dev/api/packages/alexlebens/helm
icon: https://raw.githubusercontent.com/immich-app/immich/main/design/immich-logo.svg
appVersion: v1.123.0

View File

@@ -1,52 +1,55 @@
apiVersion: external-secrets.io/v1beta1
apiVersion: external-secrets.io/v1
kind: ExternalSecret kind: ExternalSecret
metadata: metadata:
name: ollama-key-secret name: immich-config-secret
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
app.kubernetes.io/name: ollama-key-secret app.kubernetes.io/name: immich-config-secret
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: config
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
secretStoreRef: secretStoreRef:
kind: ClusterSecretStore kind: ClusterSecretStore
name: vault name: vault
data: data:
- secretKey: key - secretKey: immich.json
remoteRef: remoteRef:
conversionStrategy: Default conversionStrategy: Default
decodingStrategy: None decodingStrategy: None
key: /cl01tl/ollama/key key: /cl01tl/immich/config
metadataPolicy: None metadataPolicy: None
property: key property: immich.json
--- ---
apiVersion: external-secrets.io/v1 apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret kind: ExternalSecret
metadata: metadata:
name: ollama-oidc-secret name: immich-postgresql-16-cluster-backup-secret
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
app.kubernetes.io/name: ollama-oidc-secret app.kubernetes.io/name: immich-postgresql-16-cluster-backup-secret
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: database
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
secretStoreRef: secretStoreRef:
kind: ClusterSecretStore kind: ClusterSecretStore
name: vault name: vault
data: data:
- secretKey: client - secretKey: ACCESS_KEY_ID
remoteRef: remoteRef:
conversionStrategy: Default conversionStrategy: Default
decodingStrategy: None decodingStrategy: None
key: /authentik/oidc/ollama key: /digital-ocean/home-infra/postgres-backups
metadataPolicy: None metadataPolicy: None
property: client property: access
- secretKey: secret - secretKey: ACCESS_SECRET_KEY
remoteRef: remoteRef:
conversionStrategy: Default conversionStrategy: Default
decodingStrategy: None decodingStrategy: None
key: /authentik/oidc/ollama key: /digital-ocean/home-infra/postgres-backups
metadataPolicy: None metadataPolicy: None
property: secret property: secret

View File

@@ -0,0 +1,30 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-route-immich
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: http-route-immich
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- immich.alexlebens.net
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ''
kind: Service
name: immich-main
port: 2283
weight: 100

View File

@@ -1,14 +1,16 @@
apiVersion: v1 apiVersion: v1
kind: PersistentVolumeClaim kind: PersistentVolumeClaim
metadata: metadata:
name: libation-nfs-storage name: immich-nfs-storage
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
app.kubernetes.io/name: libation-nfs-storage app.kubernetes.io/name: immich-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
volumeName: libation-nfs-storage volumeName: immich-nfs-storage
storageClassName: nfs-client storageClassName: nfs-client
accessModes: accessModes:
- ReadWriteMany - ReadWriteMany

View File

@@ -1,11 +1,13 @@
apiVersion: v1 apiVersion: v1
kind: PersistentVolume kind: PersistentVolume
metadata: metadata:
name: bazarr-nfs-storage name: immich-nfs-storage
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
app.kubernetes.io/name: bazarr-nfs-storage app.kubernetes.io/name: immich-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
persistentVolumeReclaimPolicy: Retain persistentVolumeReclaimPolicy: Retain
@@ -15,7 +17,7 @@ spec:
accessModes: accessModes:
- ReadWriteMany - ReadWriteMany
nfs: nfs:
path: /volume2/Storage path: /volume2/Storage/Immich
server: synologybond.alexlebens.net server: synologybond.alexlebens.net
mountOptions: mountOptions:
- vers=4 - vers=4

View File

@@ -0,0 +1,25 @@
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: immich
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: immich
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: metrics
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
selector:
matchLabels:
app.kubernetes.io/name: immich
app.kubernetes.io/instance: {{ .Release.Name }}
endpoints:
- port: metrics-api
interval: 3m
scrapeTimeout: 1m
path: /metrics
- port: metrics-ms
interval: 3m
scrapeTimeout: 1m
path: /metrics

View File

@@ -0,0 +1,236 @@
immich:
controllers:
main:
type: deployment
replicas: 1
strategy: Recreate
revisionHistoryLimit: 3
containers:
main:
image:
repository: ghcr.io/immich-app/immich-server
tag: v1.129.0
pullPolicy: IfNotPresent
env:
- name: TZ
value: US/Central
- name: IMMICH_TELEMETRY_INCLUDE
value: all
- name: IMMICH_CONFIG_FILE
value: /config/immich.json
- name: IMMICH_MACHINE_LEARNING_URL
value: http://immich-machine-learning.immich:3003
- name: REDIS_HOSTNAME
value: immich-valkey-primary
- name: DB_VECTOR_EXTENSION
value: pgvecto.rs
- name: DB_HOSTNAME
valueFrom:
secretKeyRef:
name: immich-postgresql-16-cluster-app
key: host
- name: DB_DATABASE_NAME
valueFrom:
secretKeyRef:
name: immich-postgresql-16-cluster-app
key: dbname
- name: DB_PORT
valueFrom:
secretKeyRef:
name: immich-postgresql-16-cluster-app
key: port
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: immich-postgresql-16-cluster-app
key: user
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: immich-postgresql-16-cluster-app
key: password
probes:
liveness:
enabled: true
custom: true
spec:
httpGet:
path: /api/server/ping
port: 2283
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 1
failureThreshold: 3
readiness:
enabled: true
custom: true
spec:
httpGet:
path: /api/server/ping
port: 2283
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 1
failureThreshold: 3
startup:
enabled: true
custom: true
spec:
httpGet:
path: /api/server/ping
port: 2283
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 1
failureThreshold: 30
resources:
requests:
gpu.intel.com/i915: 1
cpu: 10m
memory: 512Mi
limits:
gpu.intel.com/i915: 1
cpu: 2
machine-learning:
type: deployment
replicas: 1
strategy: Recreate
revisionHistoryLimit: 3
containers:
main:
image:
repository: ghcr.io/immich-app/immich-machine-learning
tag: v1.129.0
pullPolicy: IfNotPresent
env:
- name: TRANSFORMERS_CACHE
value: /cache
probes:
liveness:
enabled: true
custom: true
spec:
httpGet:
path: /ping
port: 3003
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 1
failureThreshold: 3
readiness:
enabled: true
custom: true
spec:
httpGet:
path: /ping
port: 3003
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 1
failureThreshold: 3
startup:
enabled: false
resources:
requests:
gpu.intel.com/i915: 1
cpu: 10m
memory: 256Mi
limits:
gpu.intel.com/i915: 1
cpu: 8
memory: 10Gi
serviceAccount:
create: true
service:
main:
controller: main
ports:
http:
port: 2283
targetPort: 2283
protocol: TCP
metrics-api:
port: 8081
targetPort: 8081
protocol: TCP
metrics-ms:
port: 8082
targetPort: 8082
protocol: TCP
machine-learning:
controller: machine-learning
ports:
http:
port: 3003
targetPort: 3003
protocol: TCP
persistence:
config:
enabled: true
type: secret
name: immich-config-secret
advancedMounts:
main:
main:
- path: /config/immich.json
readOnly: true
mountPropagation: None
subPath: immich.json
media:
existingClaim: immich-nfs-storage
advancedMounts:
main:
main:
- path: /usr/src/app/upload
readOnly: false
cache:
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 10Gi
retain: true
advancedMounts:
machine-learning:
main:
- path: /cache
readOnly: false
valkey:
architecture: standalone
auth:
enabled: false
usePasswordFiles: false
primary:
persistence:
enabled: false
replica:
persistence:
enabled: false
postgres-16-cluster:
# Tensorchord
#--- https://github.com/immich-app/immich/discussions/9060
#--- https://docs.pgvecto.rs/admin/kubernetes.html
#--- https://github.com/tensorchord/cloudnative-pgvecto.rs
type: tensorchord
mode: standalone
cluster:
image:
repository: ghcr.io/tensorchord/cloudnative-pgvecto.rs
tag: 16.3-v0.2.1
walStorage:
storageClass: local-path
storage:
storageClass: local-path
resources:
requests:
memory: 384Mi
cpu: 200m
monitoring:
enabled: true
postgresql:
parameters:
shared_buffers: 256MB
backup:
enabled: true
endpointURL: https://nyc3.digitaloceanspaces.com
destinationPath: s3://postgres-backups-ce540ddf106d186bbddca68a/cl01tl/immich/immich-postgresql-16-cluster
endpointCredentials: immich-postgresql-16-cluster-backup-secret
backupIndex: 2

View File

@@ -0,0 +1,27 @@
apiVersion: v2
name: jellyfin
version: 1.0.0
description: Jellyfin
keywords:
- jellyfin
- media
- movies
- tv shows
- books
- music
home: https://wiki.alexlebens.dev/doc/jellyfin-li98lrEiuA
sources:
- https://github.com/jellyfin/jellyfin
- https://github.com/jellyfin/jellyfin-vue
- https://hub.docker.com/r/jellyfin/jellyfin
- https://github.com/jellyfin/jellyfin-vue/pkgs/container/jellyfin-vue
- https://github.com/bjw-s/helm-charts/tree/main/charts/other/app-template
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: jellyfin
repository: https://bjw-s.github.io/helm-charts/
version: 3.7.3
icon: https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/jellyfin.png
appVersion: 10.10.3

View File

@@ -0,0 +1,57 @@
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: jellyfin-config-backup-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: jellyfin-config-backup-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: backup
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
target:
template:
mergePolicy: Merge
engineVersion: v2
data:
RESTIC_REPOSITORY: "{{ `{{ .BUCKET_ENDPOINT }}` }}/jellyfin/jellyfin-config"
data:
- secretKey: BUCKET_ENDPOINT
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: S3_BUCKET_ENDPOINT
- secretKey: RESTIC_PASSWORD
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: RESTIC_PASSWORD
- secretKey: AWS_DEFAULT_REGION
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: AWS_DEFAULT_REGION
- secretKey: AWS_ACCESS_KEY_ID
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/volsync-backups
metadataPolicy: None
property: access_key
- secretKey: AWS_SECRET_ACCESS_KEY
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/volsync-backups
metadataPolicy: None
property: secret_key

View File

@@ -0,0 +1,30 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-route-jellyfin
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: http-route-jellyfin
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- jellyfin.alexlebens.net
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ''
kind: Service
name: jellyfin
port: 80
weight: 100

View File

@@ -6,6 +6,8 @@ metadata:
labels: labels:
app.kubernetes.io/name: jellyfin-nfs-storage app.kubernetes.io/name: jellyfin-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
volumeName: jellyfin-nfs-storage volumeName: jellyfin-nfs-storage
@@ -25,6 +27,8 @@ metadata:
labels: labels:
app.kubernetes.io/name: jellyfin-youtube-nfs-storage app.kubernetes.io/name: jellyfin-youtube-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
volumeName: jellyfin-youtube-nfs-storage volumeName: jellyfin-youtube-nfs-storage

View File

@@ -6,6 +6,8 @@ metadata:
labels: labels:
app.kubernetes.io/name: jellyfin-nfs-storage app.kubernetes.io/name: jellyfin-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
persistentVolumeReclaimPolicy: Retain persistentVolumeReclaimPolicy: Retain
@@ -31,6 +33,8 @@ metadata:
labels: labels:
app.kubernetes.io/name: jellyfin-youtube-nfs-storage app.kubernetes.io/name: jellyfin-youtube-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
persistentVolumeReclaimPolicy: Retain persistentVolumeReclaimPolicy: Retain

View File

@@ -0,0 +1,27 @@
apiVersion: volsync.backube/v1alpha1
kind: ReplicationSource
metadata:
name: jellyfin-config-backup-source
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: jellyfin-config-backup-source
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: backup
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
sourcePVC: jellyfin-config
trigger:
schedule: 0 4 * * *
restic:
pruneIntervalDays: 7
repository: jellyfin-config-backup-secret
retain:
hourly: 1
daily: 3
weekly: 2
monthly: 2
yearly: 4
copyMethod: Snapshot
storageClassName: ceph-block
volumeSnapshotClassName: ceph-blockpool-snapshot

View File

@@ -0,0 +1,70 @@
jellyfin:
controllers:
main:
type: deployment
replicas: 1
strategy: Recreate
revisionHistoryLimit: 3
containers:
main:
image:
repository: ghcr.io/jellyfin/jellyfin
tag: 10.10.6
pullPolicy: IfNotPresent
env:
- name: TZ
value: US/Central
- name: JELLYFIN_hostwebclient
value: true
- name: JELLYFIN_PublishedServerUrl
value: https://jellyfin.alexlebens.net/
resources:
requests:
gpu.intel.com/i915: 1
cpu: 1
memory: 2Gi
limits:
gpu.intel.com/i915: 1
cpu: 4
serviceAccount:
create: true
service:
main:
controller: main
ports:
http:
port: 80
targetPort: 8096
protocol: HTTP
persistence:
config:
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 60Gi
retain: true
advancedMounts:
main:
main:
- path: /config
readOnly: false
cache:
type: emptyDir
advancedMounts:
main:
main:
- path: /cache
readOnly: false
media:
existingClaim: jellyfin-nfs-storage
advancedMounts:
main:
main:
- path: /mnt/store
readOnly: false
youtube:
existingClaim: jellyfin-youtube-nfs-storage
advancedMounts:
main:
main:
- path: /mnt/youtube
readOnly: true

View File

@@ -0,0 +1,27 @@
apiVersion: v2
name: jellystat
version: 1.0.0
description: Jellystat
keywords:
- jellystat
- jellyfin
home: https://wiki.alexlebens.dev/doc/jellystat-0FixP7GqGZ
sources:
- https://github.com/CyferShepard/Jellystat
- https://github.com/cloudnative-pg/cloudnative-pg
- https://hub.docker.com/r/cyfershepard/jellystat
- https://github.com/bjw-s/helm-charts/tree/main/charts/other/app-template
- https://github.com/alexlebens/helm-charts/charts/postgres-cluster
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: jellystat
repository: https://bjw-s.github.io/helm-charts/
version: 3.7.3
- name: postgres-cluster
alias: postgres-17-cluster
version: 4.2.1
repository: https://gitea.alexlebens.dev/api/packages/alexlebens/helm
icon: https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/jellystat.png
appVersion: 1.1.1

View File

@@ -0,0 +1,128 @@
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: jellystat-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: jellystat-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: secret-key
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/jellystat/auth
metadataPolicy: None
property: secret-key
- secretKey: user
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/jellystat/auth
metadataPolicy: None
property: user
- secretKey: password
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/jellystat/auth
metadataPolicy: None
property: password
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: jellystat-data-backup-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: jellystat-data-backup-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: backup
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
target:
template:
mergePolicy: Merge
engineVersion: v2
data:
RESTIC_REPOSITORY: "{{ `{{ .BUCKET_ENDPOINT }}` }}/jellystat/jellystat-data"
data:
- secretKey: BUCKET_ENDPOINT
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: S3_BUCKET_ENDPOINT
- secretKey: RESTIC_PASSWORD
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: RESTIC_PASSWORD
- secretKey: AWS_DEFAULT_REGION
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: AWS_DEFAULT_REGION
- secretKey: AWS_ACCESS_KEY_ID
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/volsync-backups
metadataPolicy: None
property: access_key
- secretKey: AWS_SECRET_ACCESS_KEY
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/volsync-backups
metadataPolicy: None
property: secret_key
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: jellystat-postgresql-17-cluster-backup-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: jellystat-postgresql-17-cluster-backup-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: database
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: ACCESS_KEY_ID
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/postgres-backups
metadataPolicy: None
property: access
- secretKey: ACCESS_SECRET_KEY
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/postgres-backups
metadataPolicy: None
property: secret

View File

@@ -0,0 +1,30 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-route-jellystat
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: http-route-jellystat
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- jellystat.alexlebens.net
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ''
kind: Service
name: jellystat
port: 80
weight: 100

View File

@@ -0,0 +1,27 @@
apiVersion: volsync.backube/v1alpha1
kind: ReplicationSource
metadata:
name: jellystat-data-backup-source
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: jellystat-data-backup-source
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: backup
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
sourcePVC: jellystat-data
trigger:
schedule: 0 4 * * *
restic:
pruneIntervalDays: 7
repository: jellystat-data-backup-secret
retain:
hourly: 1
daily: 3
weekly: 2
monthly: 2
yearly: 4
copyMethod: Snapshot
storageClassName: ceph-block
volumeSnapshotClassName: ceph-blockpool-snapshot

View File

@@ -0,0 +1,97 @@
jellystat:
controllers:
main:
type: deployment
replicas: 1
strategy: Recreate
revisionHistoryLimit: 3
containers:
main:
image:
repository: cyfershepard/jellystat
tag: 1.1.3
pullPolicy: IfNotPresent
env:
- name: TZ
value: US/Central
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: jellystat-secret
key: secret-key
- name: JS_USER
valueFrom:
secretKeyRef:
name: jellystat-secret
key: user
- name: JS_PASSWORD
valueFrom:
secretKeyRef:
name: jellystat-secret
key: password
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: jellystat-postgresql-17-cluster-app
key: username
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: jellystat-postgresql-17-cluster-app
key: password
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
name: jellystat-postgresql-17-cluster-app
key: dbname
- name: POSTGRES_IP
valueFrom:
secretKeyRef:
name: jellystat-postgresql-17-cluster-app
key: host
- name: POSTGRES_PORT
valueFrom:
secretKeyRef:
name: jellystat-postgresql-17-cluster-app
key: port
resources:
requests:
cpu: 10m
memory: 256Mi
serviceAccount:
create: true
service:
main:
controller: main
ports:
http:
port: 80
targetPort: 3000
protocol: HTTP
persistence:
data:
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 5Gi
retain: true
advancedMounts:
main:
main:
- path: /app/backend/backup-data
readOnly: false
postgres-17-cluster:
mode: standalone
cluster:
walStorage:
storageClass: local-path
storage:
storageClass: local-path
monitoring:
enabled: true
backup:
enabled: true
endpointURL: https://nyc3.digitaloceanspaces.com
destinationPath: s3://postgres-backups-ce540ddf106d186bbddca68a/cl01tl/jellystat/jellystat-postgresql-17-cluster
endpointCredentials: jellystat-postgresql-17-cluster-backup-secret
backupIndex: 2
retentionPolicy: "7d"

View File

@@ -0,0 +1,21 @@
apiVersion: v2
name: kiwix
version: 1.0.0
description: Kiwix
keywords:
- kiwix
- wikipedia
home: https://wiki.alexlebens.dev/doc/kiwix-
sources:
- https://github.com/kiwix
- https://github.com/kiwix/kiwix-tools/pkgs/container/kiwix-serve
- https://github.com/bjw-s/helm-charts/tree/main/charts/other/app-template
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: kiwix
repository: https://bjw-s.github.io/helm-charts/
version: 3.7.3
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/svg/kiwix-light.svg
appVersion: 3.7.0

View File

@@ -1,11 +1,13 @@
apiVersion: gateway.networking.k8s.io/v1 apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute kind: HTTPRoute
metadata: metadata:
name: http-route-postiz name: http-route-kiwix
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
app.kubernetes.io/name: http-route-postiz app.kubernetes.io/name: http-route-kiwix
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
parentRefs: parentRefs:
@@ -14,7 +16,7 @@ spec:
name: traefik-gateway name: traefik-gateway
namespace: traefik namespace: traefik
hostnames: hostnames:
- postiz.alexlebens.net - kiwix.alexlebens.net
rules: rules:
- matches: - matches:
- path: - path:
@@ -23,6 +25,6 @@ spec:
backendRefs: backendRefs:
- group: '' - group: ''
kind: Service kind: Service
name: postiz name: kiwix
port: 80 port: 80
weight: 100 weight: 100

View File

@@ -6,6 +6,8 @@ metadata:
labels: labels:
app.kubernetes.io/name: kiwix-nfs-storage app.kubernetes.io/name: kiwix-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
volumeName: kiwix-nfs-storage volumeName: kiwix-nfs-storage

View File

@@ -6,6 +6,8 @@ metadata:
labels: labels:
app.kubernetes.io/name: kiwix-nfs-storage app.kubernetes.io/name: kiwix-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
persistentVolumeReclaimPolicy: Retain persistentVolumeReclaimPolicy: Retain

View File

@@ -9,7 +9,7 @@ kiwix:
main: main:
image: image:
repository: ghcr.io/kiwix/kiwix-serve repository: ghcr.io/kiwix/kiwix-serve
tag: 3.8.1 tag: 3.7.0
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
args: args:
- '*.zim' - '*.zim'
@@ -20,6 +20,8 @@ kiwix:
requests: requests:
cpu: 50m cpu: 50m
memory: 512Mi memory: 512Mi
serviceAccount:
create: true
service: service:
main: main:
controller: main controller: main
@@ -28,27 +30,6 @@ kiwix:
port: 80 port: 80
targetPort: 8080 targetPort: 8080
protocol: HTTP protocol: HTTP
route:
main:
kind: HTTPRoute
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- kiwix.alexlebens.net
rules:
- backendRefs:
- group: ''
kind: Service
name: kiwix
port: 80
weight: 100
matches:
- path:
type: PathPrefix
value: /
persistence: persistence:
media: media:
existingClaim: kiwix-nfs-storage existingClaim: kiwix-nfs-storage

View File

@@ -0,0 +1,22 @@
apiVersion: v2
name: libation
version: 1.0.0
description: Libation
keywords:
- libation
- audiobooks
- audible
home: https://wiki.alexlebens.dev/doc/libation-bbiuA1SKtu
sources:
- https://github.com/rmcrackan/Libation
- https://hub.docker.com/r/rmcrackan/libation
- https://github.com/bjw-s/helm-charts/tree/main/charts/other/app-template
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: libation
repository: https://bjw-s.github.io/helm-charts/
version: 3.7.3
icon: https://getlibation.com/images/libation-logo.png
appVersion: 11.6.3

View File

@@ -1,33 +1,37 @@
apiVersion: v1 apiVersion: v1
kind: PersistentVolumeClaim kind: PersistentVolumeClaim
metadata: metadata:
name: booklore-books-nfs-storage name: libation-config
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
app.kubernetes.io/name: booklore-books-nfs-storage app.kubernetes.io/name: libation-config
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
volumeName: booklore-books-nfs-storage
storageClassName: nfs-client storageClassName: nfs-client
accessModes: accessModes:
- ReadWriteMany - ReadWriteOnce
resources: resources:
requests: requests:
storage: 1Gi storage: 1Gi
volumeMode: Filesystem
--- ---
apiVersion: v1 apiVersion: v1
kind: PersistentVolumeClaim kind: PersistentVolumeClaim
metadata: metadata:
name: booklore-books-import-nfs-storage name: libation-nfs-storage
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
app.kubernetes.io/name: booklore-books-import-nfs-storage app.kubernetes.io/name: libation-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
volumeName: booklore-books-import-nfs-storage volumeName: libation-nfs-storage
storageClassName: nfs-client storageClassName: nfs-client
accessModes: accessModes:
- ReadWriteMany - ReadWriteMany

View File

@@ -6,6 +6,8 @@ metadata:
labels: labels:
app.kubernetes.io/name: libation-nfs-storage app.kubernetes.io/name: libation-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
persistentVolumeReclaimPolicy: Retain persistentVolumeReclaimPolicy: Retain

View File

@@ -0,0 +1,44 @@
libation:
controllers:
main:
type: cronjob
cronjob:
suspend: false
concurrencyPolicy: Forbid
timeZone: US/Central
schedule: "0 * * * *"
startingDeadlineSeconds: 90
successfulJobsHistory: 3
failedJobsHistory: 3
backoffLimit: 3
parallelism: 1
containers:
main:
image:
repository: rmcrackan/libation
tag: 12.2.0
pullPolicy: IfNotPresent
env:
- name: SLEEP_TIME
value: "-1"
resources:
requests:
cpu: 10m
memory: 128Mi
serviceAccount:
create: true
persistence:
config:
existingClaim: libation-config
advancedMounts:
main:
main:
- path: /config
readOnly: false
data:
existingClaim: libation-nfs-storage
advancedMounts:
main:
main:
- path: /data
readOnly: false

View File

@@ -0,0 +1,30 @@
apiVersion: v2
name: lidarr
version: 1.0.0
description: Lidarr V2
keywords:
- lidarr
- servarr
- music
- metrics
home: https://wiki.alexlebens.dev/doc/lidarr-BIqpxux60p
sources:
- https://github.com/Lidarr/Lidarr
- https://github.com/linuxserver/docker-lidarr
- https://github.com/cloudnative-pg/cloudnative-pg
- https://github.com/onedr0p/exportarr/pkgs/container/exportarr
- https://github.com/bjw-s/helm-charts/tree/main/charts/other/app-template
- https://github.com/alexlebens/helm-charts/charts/postgres-cluster
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: lidarr
repository: https://bjw-s.github.io/helm-charts/
version: 3.7.3
- name: postgres-cluster
alias: postgres-17-cluster
version: 4.2.1
repository: https://gitea.alexlebens.dev/api/packages/alexlebens/helm
icon: https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/lidarr.png
appVersion: 2.8.2

View File

@@ -0,0 +1,89 @@
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: lidarr-config-backup-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: lidarr-config-backup-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: backup
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
target:
template:
mergePolicy: Merge
engineVersion: v2
data:
RESTIC_REPOSITORY: "{{ `{{ .BUCKET_ENDPOINT }}` }}/lidarr2/lidarr2-config"
data:
- secretKey: BUCKET_ENDPOINT
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: S3_BUCKET_ENDPOINT
- secretKey: RESTIC_PASSWORD
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: RESTIC_PASSWORD
- secretKey: AWS_DEFAULT_REGION
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/volsync/restic/config
metadataPolicy: None
property: AWS_DEFAULT_REGION
- secretKey: AWS_ACCESS_KEY_ID
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/volsync-backups
metadataPolicy: None
property: access_key
- secretKey: AWS_SECRET_ACCESS_KEY
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/volsync-backups
metadataPolicy: None
property: secret_key
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: lidarr-postgresql-17-cluster-backup-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: lidarr-postgresql-17-cluster-backup-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: database
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: ACCESS_KEY_ID
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/postgres-backups
metadataPolicy: None
property: access
- secretKey: ACCESS_SECRET_KEY
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /digital-ocean/home-infra/postgres-backups
metadataPolicy: None
property: secret

View File

@@ -0,0 +1,30 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-route-lidarr
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: http-route-lidarr
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- lidarr.alexlebens.net
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ''
kind: Service
name: lidarr
port: 80
weight: 100

View File

@@ -6,6 +6,8 @@ metadata:
labels: labels:
app.kubernetes.io/name: lidarr-nfs-storage app.kubernetes.io/name: lidarr-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
volumeName: lidarr-nfs-storage volumeName: lidarr-nfs-storage

View File

@@ -6,6 +6,8 @@ metadata:
labels: labels:
app.kubernetes.io/name: lidarr-nfs-storage app.kubernetes.io/name: lidarr-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
persistentVolumeReclaimPolicy: Retain persistentVolumeReclaimPolicy: Retain

View File

@@ -6,6 +6,8 @@ metadata:
labels: labels:
app.kubernetes.io/name: lidarr app.kubernetes.io/name: lidarr
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: metrics
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
groups: groups:

View File

@@ -0,0 +1,30 @@
apiVersion: volsync.backube/v1alpha1
kind: ReplicationSource
metadata:
name: lidarr-config-backup-source
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: lidarr-config-backup-source
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: backup
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
sourcePVC: lidarr-config
trigger:
schedule: 0 4 * * *
restic:
pruneIntervalDays: 7
repository: lidarr-config-backup-secret
retain:
hourly: 1
daily: 3
weekly: 2
monthly: 2
yearly: 4
moverSecurityContext:
runAsUser: 1000
runAsGroup: 1000
copyMethod: Snapshot
storageClassName: ceph-block
volumeSnapshotClassName: ceph-blockpool-snapshot

View File

@@ -1,16 +1,21 @@
apiVersion: monitoring.coreos.com/v1 apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor kind: ServiceMonitor
metadata: metadata:
name: gitea name: lidarr
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
app.kubernetes.io/name: gitea app.kubernetes.io/name: lidarr
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: metrics
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: gitea app.kubernetes.io/name: lidarr
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
endpoints: endpoints:
- port: http - port: metrics
interval: 3m
scrapeTimeout: 1m
path: /metrics

View File

@@ -0,0 +1,129 @@
lidarr:
controllers:
main:
type: deployment
replicas: 1
strategy: Recreate
revisionHistoryLimit: 3
pod:
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
fsGroupChangePolicy: OnRootMismatch
containers:
main:
image:
repository: ghcr.io/linuxserver/lidarr
tag: version-2.8.2.4493@sha256:108ecf0fcbd8f77b6e8a513be6f3446feb47666dd1b45ea360569e9aac0960e4
pullPolicy: IfNotPresent
env:
- name: TZ
value: US/Central
- name: PUID
value: 1000
- name: PGID
value: 1000
probes:
liveness:
enabled: true
custom: true
spec:
exec:
command:
- /usr/bin/env
- bash
- -c
- curl --fail localhost:8686/api/v1/system/status?apiKey=`IFS=\> && while
read -d \< E C; do if [[ $E = "ApiKey" ]]; then echo $C; fi; done < /config/config.xml`
failureThreshold: 5
initialDelaySeconds: 60
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 10
resources:
requests:
cpu: 100m
memory: 256Mi
metrics:
image:
repository: ghcr.io/onedr0p/exportarr
tag: v2.0.1
pullPolicy: IfNotPresent
args: ["lidarr"]
env:
- name: URL
value: http://localhost
- name: CONFIG
value: /config/config.xml
- name: PORT
value: 9792
- name: ENABLE_ADDITIONAL_METRICS
value: false
- name: ENABLE_UNKNOWN_QUEUE_ITEMS
value: false
resources:
requests:
cpu: 100m
memory: 256Mi
serviceAccount:
create: true
service:
main:
controller: main
ports:
http:
port: 80
targetPort: 8686
protocol: HTTP
metrics:
port: 9792
targetPort: 9792
protocol: TCP
persistence:
config:
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 10Gi
retain: true
advancedMounts:
main:
main:
- path: /config
readOnly: false
metrics:
- path: /config
readOnly: true
media:
existingClaim: lidarr-nfs-storage
advancedMounts:
main:
main:
- path: /mnt/store
readOnly: false
postgres-17-cluster:
nameOverride: lidarr2-postgresql-17
mode: standalone
cluster:
walStorage:
storageClass: local-path
storage:
storageClass: local-path
resources:
requests:
memory: 1Gi
cpu: 200m
monitoring:
enabled: true
bootstrap:
initdb:
postInitSQL:
- CREATE DATABASE "lidarr-main" OWNER "app";
- CREATE DATABASE "lidarr-log" OWNER "app";
backup:
enabled: true
endpointURL: https://nyc3.digitaloceanspaces.com
destinationPath: s3://postgres-backups-ce540ddf106d186bbddca68a/cl01tl/lidarr2/lidarr2-postgresql-17-cluster
endpointCredentials: lidarr-postgresql-17-cluster-backup-secret
backupIndex: 3
retentionPolicy: "7d"

View File

@@ -0,0 +1,22 @@
apiVersion: v2
name: lidatube
version: 1.0.0
description: LidaTube
keywords:
- lidatube
- music
- yt-dlp
home: https://wiki.alexlebens.dev/doc/lidatube-Rm5ioxwcaS
sources:
- https://github.com/TheWicklowWolf/LidaTube
- https://registry.hub.docker.com/r/thewicklowwolf/lidatube
- https://github.com/bjw-s/helm-charts/tree/main/charts/other/app-template
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: lidatube
repository: https://bjw-s.github.io/helm-charts/
version: 3.7.3
icon: https://raw.githubusercontent.com/TheWicklowWolf/LidaTube/main/src/static/lidatube.png
appVersion: 0.2.9

View File

@@ -1,21 +1,23 @@
apiVersion: external-secrets.io/v1 apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret kind: ExternalSecret
metadata: metadata:
name: authentik-key-secret name: lidatube-secret
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
app.kubernetes.io/name: authentik-key-secret app.kubernetes.io/name: lidatube-secret
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
secretStoreRef: secretStoreRef:
kind: ClusterSecretStore kind: ClusterSecretStore
name: vault name: vault
data: data:
- secretKey: key - secretKey: lidarr_api_key
remoteRef: remoteRef:
conversionStrategy: Default conversionStrategy: Default
decodingStrategy: None decodingStrategy: None
key: /cl01tl/authentik/key key: /cl01tl/lidarr2/key
metadataPolicy: None metadataPolicy: None
property: key property: key

View File

@@ -0,0 +1,30 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-route-lidatube
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: http-route-lidatube
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: web
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- lidatube.alexlebens.net
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ''
kind: Service
name: lidatube
port: 80
weight: 100

View File

@@ -1,14 +1,16 @@
apiVersion: v1 apiVersion: v1
kind: PersistentVolumeClaim kind: PersistentVolumeClaim
metadata: metadata:
name: bazarr-nfs-storage name: lidatube-nfs-storage
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
app.kubernetes.io/name: bazarr-nfs-storage app.kubernetes.io/name: lidatube-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/component: storage
app.kubernetes.io/part-of: {{ .Release.Name }} app.kubernetes.io/part-of: {{ .Release.Name }}
spec: spec:
volumeName: bazarr-nfs-storage volumeName: lidatube-nfs-storage
storageClassName: nfs-client storageClassName: nfs-client
accessModes: accessModes:
- ReadWriteMany - ReadWriteMany

Some files were not shown because too many files have changed in this diff Show More