Files
homelab-manifests/admin-system/renovate.yaml
T
admin d92d2c31a6 re-pin moving tags so Renovate can track them
Renovate can't propose updates for moving tags (the tag string never
changes; the registry just points it at a different image). These three
were pinned to moving variants:

  felhom-system/webpage.yaml : filebrowser/filebrowser:v2-alpine
  felhom-system/umami.yaml   : ghcr.io/umami-software/umami:postgresql-latest
  tandoor-system/tandoor.yaml: vabene1111/recipes:2.6

Pin each to the current actual version per Viktor's call:
  - filebrowser -> v2.63.13 (matches the other 4 filebrowser pinnings
    in the repo; dropped the `-alpine` variant so Renovate can group
    them via the existing default datasource path)
  - umami       -> postgresql-v1.38.0 (current upstream postgresql
    variant latest; tracked via new customManager below)
  - recipes     -> 2.6.9 (current actual semver of the 2.6 series)

For umami, the `postgresql-vX.Y.Z` tag pattern is rejected by Renovate's
default docker versioning pre-check (same failure class as termix +
linuxserver servarr). Added a customManager regex + packageRule disable
pair so Renovate can track future `postgresql-vX.Y.Z` updates via regex
versioning. filebrowser and recipes use standard semver `X.Y.Z` after
the re-pin and need no special handling.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-06 13:35:12 +02:00

257 lines
12 KiB
YAML

# ============================================
# Renovate Bot - Self-hosted dependency updater
# ============================================
# https://docs.renovatebot.com
# Image: renovate/renovate (plain tag = minimal image, "formerly slim";
# -slim suffix was retired after v37.440.x, so we pin the plain tag)
#
# PILOT SCOPE (intentionally narrow):
# Runs weekly (Sat 02:00 Europe/Budapest) as a CronJob and opens
# dependency-update PRs against admin/homelab-manifests on Gitea.
# Only the `kubernetes` and `helm-values` managers are enabled, and a
# default-deny packageRule limits updates to exactly four pilot images:
# - ghcr.io/thomiceli/opengist
# - louislam/uptime-kuma
# - f0rc3/gokapi
# - docker.io/calcom/cal.com
# minor/patch -> PR with Gitea native auto-merge; major -> waits for
# manual approval via a checkbox on the Dependency Dashboard issue.
#
# Stateless & ephemeral: no Service, Ingress, or PVC. Writable /tmp is an
# emptyDir (root FS is read-only); Renovate uses it for git clones + cache.
#
# Secrets (created manually, NOT in git) come from Secret `renovate-secrets`:
# - RENOVATE_TOKEN (Gitea PAT)
# - RENOVATE_GITHUB_COM_TOKEN (GitHub PAT, for release notes)
# ============================================
---
apiVersion: v1
kind: ConfigMap
metadata:
name: renovate-config
namespace: admin-system
labels:
app.kubernetes.io/instance: renovate
app.kubernetes.io/name: renovate
data:
config.json: |
{
"platform": "gitea",
"endpoint": "https://gitea.dooplex.hu/api/v1",
"gitAuthor": "Renovate Bot <renovate@dooplex.hu>",
"repositories": ["admin/homelab-manifests"],
"onboarding": false,
"requireConfig": "optional",
"dependencyDashboard": true,
"dependencyDashboardTitle": "Renovate Dependency Dashboard",
"prHourlyLimit": 16,
"prConcurrentLimit": 16,
"enabledManagers": ["kubernetes", "helm-values", "custom.regex"],
"kubernetes": {
"managerFilePatterns": ["/.+\\.ya?ml$/"]
},
"customManagers": [
{
"description": "termix: docker image tag is `release-X.Y.Z` but the upstream GitHub release tag_name is `release-X.Y.Z-tag` (different from the release name). regex versioning parses currentValue (no -tag); extractVersion strips the -tag suffix from candidate tag_names so they normalize to the same shape Renovate writes back to the manifest.",
"customType": "regex",
"managerFilePatterns": ["/termix-system/.+\\.ya?ml$/"],
"matchStrings": [
"image:\\s+(?<depName>ghcr\\.io/lukegus/termix):(?<currentValue>release-\\d+\\.\\d+\\.\\d+)"
],
"datasourceTemplate": "github-releases",
"packageNameTemplate": "Termix-SSH/Termix",
"versioningTemplate": "regex:^release-(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)$",
"extractVersionTemplate": "^(?<version>release-\\d+\\.\\d+\\.\\d+)"
},
{
"description": "linuxserver servarr apps (prowlarr, radarr, sonarr) use tag pattern `version-X.Y.Z.B` (4 segments + `version-` prefix). The kubernetes manager's default docker versioning rejects them at the pre-check (same failure class as termix), so no PRs ever open. Use regex versioning to parse the prefixed 4-segment form; depName is captured from the regex so the same customManager handles all three apps.",
"customType": "regex",
"managerFilePatterns": ["/servarr-system/.+\\.ya?ml$/"],
"matchStrings": [
"image:\\s+linuxserver/(?<depName>prowlarr|radarr|sonarr):(?<currentValue>version-\\d+\\.\\d+\\.\\d+\\.\\d+)"
],
"datasourceTemplate": "docker",
"packageNameTemplate": "linuxserver/{{depName}}",
"versioningTemplate": "regex:^version-(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)\\.(?<build>\\d+)$"
},
{
"description": "umami: the docker image tag is `postgresql-vX.Y.Z` (the PostgreSQL-flavored variant). Default docker versioning rejects the prefix. Same fix as termix/servarr: regex versioning parses the prefixed value; ghcr.io tag list is filtered to the postgresql-v* track only.",
"customType": "regex",
"managerFilePatterns": ["/felhom-system/umami\\.ya?ml$/"],
"matchStrings": [
"image:\\s+(?<depName>ghcr\\.io/umami-software/umami):(?<currentValue>postgresql-v\\d+\\.\\d+\\.\\d+)"
],
"datasourceTemplate": "docker",
"versioningTemplate": "regex:^postgresql-v(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)$"
}
],
"packageRules": [
{
"description": "All apps: 3-day stability gate before any PR opens",
"matchPackageNames": ["*"],
"minimumReleaseAge": "3 days"
},
{
"description": "Auto-merge minor/patch after the stability window",
"matchUpdateTypes": ["minor", "patch"],
"automerge": true,
"automergeType": "pr",
"platformAutomerge": true
},
{
"description": "Major bumps wait for dashboard approval (catches breaking/schema migrations)",
"matchUpdateTypes": ["major"],
"automerge": false,
"dependencyDashboardApproval": true
},
{
"description": "k3s-bundled components: never touch, they ride k3s upgrades",
"matchPackageNames": [
"rancher/local-path-provisioner",
"rancher/mirrored-coredns/coredns",
"rancher/mirrored-metrics-server"
],
"enabled": false
},
{
"description": "Critical core: PR opens with changelog but Viktor merges manually (deploy pipeline + SSO + DB operator). Some entries are no-ops if the image isn't pinned in this repo (ArgoCD bootstrap, authentik outpost images inherit chart defaults).",
"matchPackageNames": [
"gitea/gitea",
"quay.io/argoproj/argocd",
"ghcr.io/goauthentik/server",
"ghcr.io/goauthentik/ldap",
"ghcr.io/goauthentik/proxy",
"ghcr.io/cloudnative-pg/cloudnative-pg"
],
"automerge": false
},
{
"description": "wanderer: db + web update together in one PR",
"matchPackageNames": ["flomp/wanderer-db", "flomp/wanderer-web"],
"groupName": "wanderer"
},
{
"description": "meilisearch: every version bump can require an index format migration via dump/restore (see https://www.meilisearch.com/docs/learn/update_and_migration/updating). PR #32 (v1.11.3 -> v1.45.2) on 2026-06-06 broke wanderer with `Your database version (1.11.3) is incompatible with your current engine version (1.45.2)`. Hold ALL meilisearch updates behind dashboard approval so the migration is planned before the PR even opens.",
"matchPackageNames": ["getmeili/meilisearch"],
"dependencyDashboardApproval": true
},
{
"description": "Postgres-family images: a major bump (e.g. 16 -> 17) requires pg_upgrade or dump/restore — the new server binary refuses to open the old data directory (`database files are incompatible with server`). PR #76 (immich-app/postgres 16 -> 17) on 2026-06-06 crashlooped immich-postgres and immich-server. Renovate's docker versioning treats these custom tag formats inconsistently, so don't trust the major/minor classification: hold ALL updates for these images behind explicit dashboard approval. Includes vanilla postgres, postgis/postgis (where the tag prefix IS the pg major), and ghcr.io/immich-app/postgres (custom `N-vectorchordX.Y.Z` form).",
"matchPackageNames": [
"postgres",
"postgis/postgis",
"ghcr.io/immich-app/postgres"
],
"dependencyDashboardApproval": true
},
{
"description": "termix: kubernetes manager would extract the image with versioning=docker and silently skip it (release-1.11.0 fails the docker pre-check). Disable that extraction; customManagers above does the real work via github-releases.",
"matchManagers": ["kubernetes"],
"matchPackageNames": ["ghcr.io/lukegus/termix"],
"enabled": false
},
{
"description": "linuxserver servarr apps: same disable pattern as termix. The customManager above handles extraction with the right versioning; turn off the default kubernetes-manager extraction so it doesn't silently skip + clutter the dashboard.",
"matchManagers": ["kubernetes"],
"matchPackageNames": [
"linuxserver/prowlarr",
"linuxserver/radarr",
"linuxserver/sonarr"
],
"enabled": false
},
{
"description": "umami: same disable pattern. customManager handles extraction; kubernetes-manager would silently skip `postgresql-vX.Y.Z`.",
"matchManagers": ["kubernetes"],
"matchPackageNames": ["ghcr.io/umami-software/umami"],
"enabled": false
}
],
"labels": ["renovate"]
}
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: renovate
namespace: admin-system
labels:
app.kubernetes.io/instance: renovate
app.kubernetes.io/name: renovate
app.kubernetes.io/version: "43.209.3"
spec:
# Sat 02:00 Europe/Budapest — leaves the full weekend for troubleshooting
# if a Renovate-merged update breaks something.
schedule: "0 2 * * 6"
timeZone: "Europe/Budapest"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
startingDeadlineSeconds: 600
jobTemplate:
metadata:
labels:
app.kubernetes.io/instance: renovate
app.kubernetes.io/name: renovate
app.kubernetes.io/version: "43.209.3"
spec:
template:
metadata:
labels:
app.kubernetes.io/instance: renovate
app.kubernetes.io/name: renovate
app.kubernetes.io/version: "43.209.3"
annotations:
# Renovate uses plain X.Y.Z semver tags (no -slim suffix anymore)
match-regex.version-checker.io/renovate: '^\d+\.\d+\.\d+$'
spec:
enableServiceLinks: false
restartPolicy: OnFailure
containers:
- name: renovate
image: renovate/renovate:43.209.3
imagePullPolicy: IfNotPresent
envFrom:
- secretRef:
name: renovate-secrets
env:
- name: TZ
value: Europe/Budapest
- name: LOG_LEVEL
value: info
- name: RENOVATE_CONFIG_FILE
value: /config/config.json
# Renovate needs a writable tmp for git clones + cache;
# root FS is read-only so point it at the emptyDir below.
- name: TMPDIR
value: /tmp
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 2000m
memory: 2Gi
securityContext:
runAsNonRoot: true
runAsUser: 12021
runAsGroup: 0
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
volumeMounts:
- name: config
mountPath: /config
readOnly: true
- name: tmp
mountPath: /tmp
volumes:
- name: config
configMap:
name: renovate-config
- name: tmp
emptyDir:
sizeLimit: 2Gi