Files
homelab-manifests/admin-system/renovate.yaml
T
admin 454cce9691 renovate: expand to Tier 1 allowlist + 3-day stability delay
Grows the Renovate pilot from 4 apps to a 16-app Tier 1 allowlist of
low-risk leaf apps (no DBs / schema migrations). packageRules keeps the
same 4-rule shape (default-deny, enable, automerge-minor/patch,
major-dashboard-approval) with the expanded package list in all three
Tier 1 rules.

Behavior changes:
- minimumReleaseAge "3 days" on the automerge rule: Renovate won't open
  a minor/patch PR until the tag has been published upstream for 3 days
  (stability gate; chosen over branch protection, which would disable
  automerge entirely).

Image-string corrections vs. the planned list (Renovate matches the
exact image as written in the manifest; verified against the YAML):
- homepage  -> ghcr.io/gethomepage/homepage   (had no registry)
- reloader  -> ghcr.io/stakater/reloader      (had no registry)
- termix    -> ghcr.io/lukegus/termix         (had no registry)

Notes:
- registry.k8s.io/kube-state-metrics/kube-state-metrics is kept in the
  list but currently matches nothing: ksm has no image in this repo
  (only a Prometheus scrape target), so it's a harmless no-op until ksm
  is ever deployed via a manifest here.
- ghcr.io/lukegus/termix uses a non-semver tag (release-1.11.0); watch
  whether Renovate categorizes its updates as minor/patch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 22:00:49 +02:00

220 lines
7.5 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 (Sun 04: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": 0,
"prConcurrentLimit": 0,
"enabledManagers": ["kubernetes", "helm-values"],
"kubernetes": {
"managerFilePatterns": ["/.+\\.ya?ml$/"]
},
"packageRules": [
{
"description": "Default-deny everything",
"matchPackageNames": ["*"],
"enabled": false
},
{
"description": "Tier 1: enable updates for low-risk leaf apps",
"matchPackageNames": [
"ghcr.io/thomiceli/opengist",
"louislam/uptime-kuma",
"f0rc3/gokapi",
"docker.io/calcom/cal.com",
"advplyr/audiobookshelf",
"arcadiatechnology/crafty-4",
"codercom/code-server",
"ghcr.io/gethomepage/homepage",
"ghcr.io/headlamp-k8s/headlamp",
"prom/node-exporter",
"rommapp/romm",
"ghcr.io/stakater/reloader",
"privatebin/nginx-fpm-alpine",
"flomp/wanderer-db",
"flomp/wanderer-web",
"registry.k8s.io/kube-state-metrics/kube-state-metrics",
"ghcr.io/lukegus/termix"
],
"enabled": true
},
{
"description": "Tier 1: automerge minor/patch after 3-day stability window",
"matchPackageNames": [
"ghcr.io/thomiceli/opengist",
"louislam/uptime-kuma",
"f0rc3/gokapi",
"docker.io/calcom/cal.com",
"advplyr/audiobookshelf",
"arcadiatechnology/crafty-4",
"codercom/code-server",
"ghcr.io/gethomepage/homepage",
"ghcr.io/headlamp-k8s/headlamp",
"prom/node-exporter",
"rommapp/romm",
"ghcr.io/stakater/reloader",
"privatebin/nginx-fpm-alpine",
"flomp/wanderer-db",
"flomp/wanderer-web",
"registry.k8s.io/kube-state-metrics/kube-state-metrics",
"ghcr.io/lukegus/termix"
],
"matchUpdateTypes": ["minor", "patch"],
"automerge": true,
"automergeType": "pr",
"platformAutomerge": true,
"minimumReleaseAge": "3 days"
},
{
"description": "Tier 1: major bumps require dashboard approval (no automerge)",
"matchPackageNames": [
"ghcr.io/thomiceli/opengist",
"louislam/uptime-kuma",
"f0rc3/gokapi",
"docker.io/calcom/cal.com",
"advplyr/audiobookshelf",
"arcadiatechnology/crafty-4",
"codercom/code-server",
"ghcr.io/gethomepage/homepage",
"ghcr.io/headlamp-k8s/headlamp",
"prom/node-exporter",
"rommapp/romm",
"ghcr.io/stakater/reloader",
"privatebin/nginx-fpm-alpine",
"flomp/wanderer-db",
"flomp/wanderer-web",
"registry.k8s.io/kube-state-metrics/kube-state-metrics",
"ghcr.io/lukegus/termix"
],
"matchUpdateTypes": ["major"],
"automerge": false,
"dependencyDashboardApproval": true
}
],
"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.197.0"
spec:
schedule: "0 4 * * 0"
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.197.0"
spec:
template:
metadata:
labels:
app.kubernetes.io/instance: renovate
app.kubernetes.io/name: renovate
app.kubernetes.io/version: "43.197.0"
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.197.0
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