main-926ead0 includes ical-proxy PR #7 (REN-230): the upstream response
body is capped at 2 MiB, so an oversized feed gets 413 instead of being
buffered whole into a 256Mi pod. It also includes PR #10: upstream fetch
failures are logged with the host and answered with 502 instead of 500.
Refs: REN-294
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bump the pinned ical-proxy image from main-4783abe to main-73b5d97.
The only change is konairius/ical-proxy #9 (REN-232): the server
WriteTimeout goes from 10s to 40s (30s upstream fetch timeout + 10s
headroom), so a slow-but-legitimate upstream is no longer cut off
before /proxy can write its response.
Refs: REN-239, REN-232
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bump the pinned ical-proxy image from main-db90a59 to main-4783abe.
The new build adds two hardening changes from konairius/ical-proxy:
- #6: refuse upstreams and redirect hops that resolve to private,
loopback, link-local or CGNAT addresses. Public redirects are still
followed (up to 5).
- #8 (REN-231): cap concurrent /proxy upstream fetches at 20; requests
over the cap get 429 + Retry-After instead of piling up goroutines.
Refs: REN-238, REN-231
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ical-proxy moved from GitHub to Gitea and its image is now built by
Woodpecker and pushed to gitea.renner.uno/konairius/ical-proxy. The
ghcr.io image gets no new builds.
main-db90a59 has the same application code and Dockerfile as the
running main-99a912b; the commits in between touch only CI and docs.
The package pulls anonymously, so no imagePullSecret is added.
Revert: git revert this commit; Flux rolls the pods back to
ghcr.io/konairius/ical-proxy:main-99a912b.
Refs: REN-201
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
:latest never rolls. The tag moves when a build publishes, but nothing
tells the Deployment: the pod template is unchanged, so Kubernetes has
no reason to replace anything.
Nothing else covers it either. This image is deliberately not enrolled in
Flux image automation — kubernetes/infrastructure/image-automation/README.md
lists ghcr.io/konairius/ical-proxy as having "only main, latest, and
main-<sha> commit builds; no release tags", so no ImagePolicy watches it.
The two pods have been running a 21-day-old image while :latest moved
underneath them, and the only way to pick up a new build was a manual
restart, which leaves no record anywhere.
Pinning makes the rollout a git change. Flux applies the new pod
template, Kubernetes rolls it, and what is RUNNING becomes recoverable
from this repo instead of "whatever :latest meant the last time a pod
happened to restart".
main-99a912b is the merge of konairius/ical-proxy#12, which adds the
summary_match and summary_replace parameters. The waste calendar needs
them to strip "| Abfuhrkalender - Landkreis Amberg-Sulzbach" from every
collection — the feed repeats the whole calendar's name on each event,
and no consumer can shorten it after the fact.
Bumping this tag is now a manual, reviewed edit. Format is
main-<short-sha>, from docker/metadata-action type=sha with the branch
as prefix.
*.k.renner.uno was a temporary migration namespace and is banned (owner
directive 2026-07-14, documented in openbao/ingress.yaml) — it was never
the live naming. Removes the .k. hosts/SANs from ical-proxy, loki,
grafana and the mosquitto cert, renames syslog.k.renner.uno to
syslog.renner.uno (cert + external-dns annotation; any syslog sender
still configured with the k. name must be repointed), fixes the stale
comments, updates e2e-test.sh probes to the real names, and drops
k.renner.uno from the external-dns domainFilters so leftover k. records
get garbage-collected by policy: sync.
The migration script's historical docstring reference stays — it
documents what the migration did.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014S5CLfizEtzHS51kxJFQgc
gatus (status), ical-proxy, kube-prometheus-stack (alerts/dash/prometheus)
have no nginx-only annotations, so the migration is pure
ingressClassName: nginx → traefik plus apps/allow-from-ingress now
permitting the traefik label as a source. cloudflared retargets
status.renner.uno (the only WAN-exposed name in this batch); the rest
are LAN-only via external-dns-unifi.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a global cluster-settings ConfigMap (CLUSTER_IN_DEVELOPMENT,
ACME_SERVER) consumed via Flux postBuild substitution on the
infrastructure-crds Kustomization. A new letsencrypt-cluster
ClusterIssuer reads ACME_SERVER from the ConfigMap at reconcile time;
every Certificate / Ingress in the repo now references letsencrypt-
cluster instead of letsencrypt-{prod,staging} directly.
While CLUSTER_IN_DEVELOPMENT=true, ACME_SERVER points at acme-staging-
v02, so the only certs the cluster can issue are LE staging — sidesteps
the recurring 5-cert/168h prod rate-limit hit during back-to-back
rebuilds (latest occurrence: 2026-05-05 alloy-syslog + loki-ingress).
Flip both keys together when leaving development.
Per-app KSes intentionally do NOT enable postBuild — Grafana dashboards
and HA's deployment shell scripts contain unrelated \${VAR} markers
that would be clobbered. Substitution stays scoped to post-crds/ which
has no other variable expansions.
The standalone letsencrypt-prod / letsencrypt-staging ClusterIssuers
remain defined as escape hatches but are no longer referenced.
e2e-test.sh now also asserts letsencrypt-cluster Ready.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds <app>.renner.uno as a second host rule and TLS SAN on each test
Ingress (authentik, paperless/docs, audiobookshelf, ical-proxy, grafana).
With the external-dns domain filter now scoped to k.renner.uno, these
prod hostnames cannot be written back into UniFi by external-dns — the
prod CNAMEs managed by OpenTofu stay pointed at the Caddy VIP, while
the K8s ingress now accepts traffic arriving with a prod Host header
(e.g. from a Kasm session whose extra_hosts maps *.renner.uno to the
cluster LB 10.2.40.80).
Also removes *.k.renner.uno from app-level config where it was baked
in as cruft: PAPERLESS_URL, Grafana root_url, Grafana OIDC auth_url
are now prod hostnames — matching the architectural intent that the
K8s cluster IS the future prod. PAPERLESS_CSRF_TRUSTED_ORIGINS keeps
both variants during transition so existing *.k.renner.uno browsing
doesn't immediately break on form POSTs.
cert-manager will issue fresh letsencrypt-staging certs with the
expanded SAN set via DNS-01; no public DNS changes needed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Flip all ingress cert-manager.io/cluster-issuer annotations from
letsencrypt-prod to letsencrypt-staging. Five rebuilds in a week
tripped LE's per-identifier rate limit (5 certs / 168h) and left 3
hostnames with the ingress-nginx fake cert. Staging has ~30k/week,
so rebuilds stop being rate-limited. ClusterIssuer definitions for
both remain in post-crds; flip back per-ingress when ready for prod.
- Rework e2e-test.sh TLS check to validate the cert *issuer* contains
"Let's Encrypt" rather than chain-validating against the public CA
bundle. Same check works for both staging and prod, and still
catches the real failure mode (fake cert = cert-manager broken).
- HTTP checks now use -k since staging certs aren't publicly trusted;
the separate TLS check is what asserts cert-manager worked.
- Chain the e2e step onto .woodpecker/rebuild-k8s.yml so every rebuild
validates the resulting cluster end-to-end before reporting success.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stateless Go app from ghcr.io/konairius/ical-proxy:latest.
2 replicas, test ingress at ical-proxy.k.renner.uno.
No DB, no OIDC, no secrets needed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>