El pase de las 04:58 UTC dejó todos los feeds a 0 pendientes, así que la
bajada temporal a 3 h del commit 134449e ya no hace falta. En régimen
normal entra ~1 episodio al día: revisar cada 3 h solo repetiría la
descarga del RSS ocho veces para no encontrar nada.
El comentario deja de ser un aviso pendiente y pasa a explicar por qué 24
es lo correcto y cuándo conviene volver a bajarlo.
Las copias remotas se purgaron a mano el 2026-07-27 (8 objetos en Mega, 3 en
B2, con --mega-hard-delete y --b2-hard-delete para que no se queden en papelera
ni como versiones ocultas). Sin subdirectorio remoto que preservar, el exclude
solo era ruido en la orden.
Verificado: el ConfigMap parsea y los cuatro scripts pasan `sh -n`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Los manifiestos que amparaba ya no existen, así que la excepción solo podía
envejecer. La auditoría queda en 0 hallazgos nuevos y 4 esperados (antes 13:
los otros 8 eran precisamente reddit-intel inactivo).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
El servicio se decomisó (Reddit denegó el acceso a la API), así que su CronJob
de n97 estaría empaquetando cada noche un directorio que ya nadie escribe, y
backup-verify seguiría exigiendo una copia fresca que nunca va a llegar: en
tres días habría empezado a sumar ERRORS y a disparar la alerta por una avería
que no existe.
Se van el CronJob, el script reddit-intel.sh y su comprobación en verify.sh.
El `--exclude /reddit-intel/**` de rclone-mega SE QUEDA a propósito: sync es un
espejo exacto y quitarlo borraría de un tirón las copias que aún viven en Mega.
Se retirará cuando se decida purgar ese remoto a mano.
Verificado: el ConfigMap sigue parseando y los cuatro scripts pasan `sh -n`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reddit nos ha denegado el acceso a la API —la misma respuesta que a
roswell-corpus—, así que la promoción a k3s que describía PROMOTION.md no va a
ocurrir nunca. Estos manifiestos nunca llegaron a aplicarse (el app-of-apps no
es recursivo y no había Application), así que quitarlos no cambia nada en el
clúster; el namespace vacío se ha borrado a mano.
El contenedor de n97 se paró el 2026-07-27 tras once días devolviendo 401, con
la base de datos vacía: nunca registró un solo post. Copia final en
~/decommissioned/reddit-intel-final-2026-07-27.tar.gz y el código sigue en su
repo.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
45 episodios pendientes = 33,8 h de audio ≈ 20 h de CPU, pero a una pasada
cada 24 h con tope de 5 el pod transcribía ~4 h y descansaba ~20: el atraso
tardaba 5 días. Con 3 h encadena pasadas y se va en algo más de un día.
No cambia el pico de memoria (sigue transcribiendo de una en una, y el
troceado en ventanas ya lo acotó). Revertir a 24 al terminar.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
El límite subió 4→6→8Gi persiguiendo episodios largos porque el pico de
whisper escalaba con la duración. Con el troceado en ventanas (roswell-corpus
c869b61) el pico dejó de depender del episodio, así que 8Gi pasa de ser el
siguiente escalón a tener margen de sobra. Se deja escrito para que nadie lo
suba por inercia sin mirar antes si el troceado sigue vivo.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Los dos estaban en git sin ninguna Application que los gestionara: editar el
repo no desplegaba nada. De ahi que un pin de imagen de abril nunca llegara
al cluster y gitea se subiera solo de 1.25.5 a 1.27.0, y que vaultwarden se
parcheara con kubectl replace. A partir de ahora manda git.
Verificado en frio antes de adoptar: los 17 manifiestos coincidian campo a
campo con lo vivo, asi que la adopcion no revierte nada. Con
ServerSideApply/ServerSideDiff, igual que el kube-prometheus-stack: estos
objetos arrastran un last-applied viejo y el merge clasico intentaria borrar
lo que ese blob declaraba y git ya no; en un PVC eso es un campo inmutable y
el sync falla.
Limpieza que iba en el mismo paquete:
- Fuera la basura de export de 5 ficheros: last-applied-configuration, la
revision del Deployment y las anotaciones que pone el provisionador en los
PVC (bind-completed, selected-node...). Es lo que dejaba los recursos
OutOfSync para siempre. Verificado que el resto del manifiesto no cambia.
- Fuera serviceaccount-default y kube-root-ca.crt de los dos: los crea k8s
solo en cada namespace.
- RESCATADO configmap-gitea-runner-config: config del act_runner escrita a
mano en abril, montada por el runner y que NO estaba en git. Reconstruir
gitea desde el repo levantaba el runner sin configuracion.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Las dos alertas de B2 llevaban desde esta manana en el ConfigMap y MUERTAS:
Grafana lee el provisioning de alerting solo al arrancar y el pod era del
dia 22. El sidecar de kiwigrid recarga dashboards y datasources, pero el
alerting entra por extraConfigmapMounts y ese camino no lo toca nadie.
Reiniciado Grafana: 7 reglas cargadas -> 9. Queda el aviso en la cabecera
del fichero, con el comando de reinicio y el de comprobacion contra la API,
que es la unica fuente de verdad aqui (el ConfigMap mentia).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
43 eran el render del kube-prometheus-stack, volcados con kubectl get -o yaml
y sin que nadie los aplicara: decoracion que solo servia para creerse que git
describia el cluster. Ahora los genera el chart desde la Application de la
Fase 2, que es su unico dueño.
Los 6 restantes los fabrica un controlador y en git no pintan nada:
rulefiles-0 (154KB que genera el prometheus-operator desde los
PrometheusRule), el StatefulSet, el service prometheus-operated y el PVC de
datos (los tres nacen del CR Prometheus / su volumeClaimTemplate), mas
serviceaccount-default y kube-root-ca.crt, que k8s crea solo en cada
namespace.
Ninguno estaba en la lista blanca del app de monitoring, asi que borrarlos de
git no toca el cluster. Clasificados uno a uno antes de borrar (render del
chart vs ownerReferences vivas), no a bulto.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
El chart era un release Helm gestionado a mano (helm upgrade) desde abril.
Ahora lo gestiona su propia Application con source Helm, version clavada a
83.2.0 (la que ya corria: esto es una adopcion, no una actualizacion).
Los valores se mudan de values-kube-prometheus-stack.yaml al valuesObject de
la Application, con sus comentarios: ahi esta el historial de los retoques a
mano que se recuperaron en julio (alerting, SSO de Authentik, token de
Telegram), y perderlo seria perder el mapa. Inline y no multi-source $values
porque ese montaje se auto-podo la Application de infisical el 2026-06-18, y
tener los valores en dos sitios es la deriva que veniamos a matar.
La adopcion se verifico ANTES de activar el auto-sync: aplicada sin
syncPolicy, ArgoCD daba 96/97 Synced sin haber sincronizado nunca. El que
faltaba era el Deployment de Grafana, y no por deriva: el render del subchart
no declara managed-by: Helm ni el restartedAt del podTemplate, asi que el
merge a 3 bandas del cliente los habria BORRADO (reinicio de Grafana + Helm
perdiendo la propiedad del objeto). Con ServerSideApply/ServerSideDiff ArgoCD
solo toca lo que declara: 97/97 Synced, cero operaciones de sync, cero pods
reiniciados. selfHeal probado con replicas 1->2 en kube-state-metrics,
revertido en 11s.
skipCrds: true a proposito: ArgoCD pasa --include-crds por defecto y los 10
CRD de monitoring.coreos.com no los gestiona nadie hoy. Contrapartida
documentada en el fichero: al subir de chart hay que aplicarlos a mano.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Basura del volcado con kubectl get -o yaml. Al estar versionada se muerde la
cola: ArgoCD la aplica, k8s genera una nueva que ya incluye el tracking-id, y
git y cluster no coinciden nunca -> los 4 recursos se quedaban OutOfSync para
siempre. Verificado que el resto del manifiesto queda byte a byte igual.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Hasta ahora las alertas de Grafana se aplicaban a mano con kubectl apply,
asi que dependian de que alguien se acordara (se vio hoy al anadir las de B2).
Lista blanca explicita en vez del directorio entero: monitoring/ mezcla tres
duenos y solo uno es nuestro. Fuera quedan los ~40 renderizados del chart
kube-prometheus-stack (release Helm viva -> dos duenos del mismo objeto) y los
generados por controladores (rulefiles-0 del prometheus-operator, etc).
Adoptar el chart via source Helm queda como Fase 2.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Gemelas de las de MEGA: avisan si B2 factura >80% de los 10GB gratis
(b2_billed_bytes) o si las versiones ocultas pasan de 2GB (b2_hidden_bytes,
lo que indicaria que algun borrado no usa --b2-hard-delete).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
B2 tiene el mismo fallo que la papelera de MEGA con otro nombre: al
borrar/espejar no elimina, oculta la version vieja y la sigue facturando.
Las versiones ocultas llegaron al ~88% del tramo gratis de 10GB el
2026-07-25 (8.78 GiB facturados vs 1.75 GiB visibles).
- --b2-hard-delete en el sync de crown-jewels y en el delete de reddit-intel
- mega-quota-exporter ahora tambien exporta b2_visible/billed/hidden_bytes
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
El incidente del 2026-07-25 (MEGA lleno -> dos CronJobs de backup caídos)
solo se detectó por el síntoma. La causa llevaba meses creciendo sin que
nada la mirase.
- backup-system/mega-quota-exporter: Deployment que sondea `rclone about`
y `rclone size` cada 15 min y los sirve a Prometheus vía ServiceMonitor.
mega_trash_bytes (usado - visible) es la métrica que habría cazado esto.
- monitoring: dos reglas de Grafana, cuota > 80% y papelera > 2GB.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
La papelera de MEGA cuenta cuota. Los `rclone sync`/`rclone delete` de
rotación diaria enviaban ahí las copias antiguas, acumulando 16.6 GiB de
basura hasta llenar los 20 GiB de la cuenta. El 2026-07-25 eso tumbó los
jobs rclone-mega-backup y reddit-intel-backup con "Request over quota".
Papelera vaciada a mano (375 objetos); este flag evita que se repita.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
La key de IndexNow solo autoriza URLs bajo su directorio, así que debe
vivir en /{key}.txt. Ghost no sirve ficheros arbitrarios en la raíz: el
middleware reescribe la ruta al fichero real en content/files/indexnow/
(PVC de Ghost, colocado con kubectl cp). El envío de URLs lo hace
~/seo-tools/indexnow_watch.py (timer horario en el master).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CronJob externo a n8n que lee la SQLite en solo-lectura por el hostPath y avisa
si el workflow del autopost desaparece (firma de la reversión del 2026-07-16) o
si el total de workflows se desploma. La reversión SUBE el nº de activos, así que
un umbral de activos no la cazaría; el disparador es la desaparición del autopost.
Cada 6h. Reutiliza telegram-notify-infisical.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Borrados qwen2.5:3b y nomic-embed-text (sin consumidores tras subir a 7b/bge-m3).
El script de arranque solo traía 3b: tras perder el PVC, un reinicio dejaba a
researchowl y roswell sin el modelo de embeddings. Ahora trae los dos reales.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Los 3990+ chunks existentes se re-embebieron a 1024d in situ antes de este
cambio; sin eso el coseno daría 0.0 por dimensión distinta y rompería la
recuperación. bge-m3 alinea researchowl con roswell (mismo modelo, multilingüe).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
La versión actual del generic-device-plugin registra devic.es/gpu por
defecto; con squat.ai/gpu el pod se quedaba Pending.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Ingress con forward-auth de Authentik (la API estaba abierta a internet)
- generic-device-plugin entrega card0+renderD128 como squat.ai/gpu con el
cgroup de dispositivos bien configurado — lo que el hostPath nunca dio
- fuera los 3 hostPath de dispositivos (ya no hacen falta)
- OLLAMA_NUM_CTX→OLLAMA_CONTEXT_LENGTH (la real); fuera OLLAMA_METRICS (no existe)
Sonda temporal confirmó: con cgroup, Vulkan enumera la Radeon 780M (17 GiB).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Con HSA_OVERRIDE_GFX_VERSION y HIP_VISIBLE_DEVICES puestas, ollama
arranca avisando 'user overrode visible devices / if GPUs are not
correctly discovered, unset and try again' y solo encuentra la CPU.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
La GPU nunca se usaba: ollama/ollama:0.20.7 no trae ROCm, asi que
HSA_OVERRIDE_GFX_VERSION/HIP_VISIBLE_DEVICES eran inertes. La imagen si
trae el backend Vulkan y el driver RADV, que cubre las iGPU AMD.
De paso se declara la deriva: todo el paso de dispositivos vivia solo en
el objeto del cluster, no en git, y sobrevivia por el merge de tres vias.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Iba fijado por digest porque su tag "latest" no es una release sino una build
de la rama main (org.opencontainers.image.version=main). Al mirarlo de cerca,
ese digest resultó ser EXACTAMENTE v1.70.0: el commit 4b351bb es su propio
release commit. O sea, ya corría el código de una release, sólo que sin poder
saberlo desde el manifiesto.
Se sube a v1.71.0 (17-jul), una menor por delante, en vez de quedarse en la
v1.70.0 equivalente: es la última publicada y arregla justo algo de base de
datos — "restore widget_secret migration journal entries accidentally removed".
Sin cambios rompedores en las notas.
Homarr guarda una SQLite en homarr-db-pvc, así que esto aplica migraciones y no
es un pin inocuo como los otros seis. Copia consistente antes de tocar, con el
pod parado para no copiar una escritura a medias:
/data/backups/backups/homarr_pre-v1.71.0_2026-07-22_10-02-23.tar.gz
(además del backup diario, que ya cubría homarr).
Verificado tras arrancar: "Migration complete" en el log, 200 en
home.chemavx.xyz, OIDC contra Authentik intacto, y los datos en su sitio —
consultada la SQLite en solo lectura: el tablero Dashboard_ChemaVX con sus 7
items, 7 apps, 1 integración y los 2 usuarios.
Los dos "Board not found" del log llevan la hora exacta de mis curl anónimos:
un visitante sin sesión no tiene tablero. No es un fallo.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Con el SSO ya funcionando (379af6d), a la web sólo se entra por Authentik.
Ayer se dejó abierto a propósito porque el SSO acababa de estar 15 días roto en
silencio y no quería quedarme sin puerta; hoy, verificado que funciona, se
cierra.
Lo que NO cierra, y es lo que importa: la auth básica de la API sigue abierta.
De ella cuelgan los dos sidecars —que es exactamente lo que se rompió mudo el
21 y dejó de recargar dashboards y datasources— y la puerta de emergencia con
la contraseña del secret grafana-admin.
Sí desaparece la otra: el POST /login pasa a devolver 400. Comprobado antes y
después, porque era la salida que uno supondría disponible y ya no lo está.
El procedimiento de rescate queda escrito junto al valor: la API con
grafana-admin, y disable_login_form: false + helm upgrade para recuperar el
formulario en un minuto.
Verificado: SSO entra como akadmin; la auth básica entra como admin;
disableLoginForm=true y authProxyEnabled=true en /api/frontend/settings; desde
fuera sigue el 302 a Authentik; y los DOS sidecars probados con ConfigMaps
reales, con 200 OK y el dashboard de prueba llegando de verdad a Grafana (y
desapareciendo al retirar el ConfigMap). 0 errores en el arranque.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Los tres puntos ciegos que quedaban. El gitea-runner se dejó fuera del panel de
gitea a propósito, porque si cae se paran los builds pero Gitea sigue sirviendo
y pintar "gitea: Down" sería una falsa alarma; pero su caída es de las mudas y
merecía el suyo. Prometheus y Uptime Kuma se quedaron sin representar cuando el
panel "grafana" pasó a mirar sólo a su deployment en vez de a todo el namespace
monitoring (5d0078c).
Misma forma que los otros doce, con el selector acotado al workload concreto;
para Prometheus, que es un StatefulSet, la rama de deployment sale vacía y
resuelve la de statefulset. La fila de servicios estaba llena, así que se abre
una tercera y todo lo de debajo baja 4 filas de rejilla.
Verificado antes de escribirlo: las tres consultas dan 1 ahora y 0 con escasez
de réplicas simulada. Y después, los 15 estados a través del proxy de datasource
de Grafana, no consultando yo a Prometheus por otro lado.
Nota conocida, no un fallo: si kube-state-metrics cae, los 15 paneles se ponen
en rojo a la vez, porque todos dependen de sus métricas. Un tablero entero en
rojo hay que leerlo como "se ha caído el que mide", no como quince caídas.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sábados 07:00 UTC como servicio de host en chemavx-k8, fuera del cluster, igual
que seo-watch y el canario de hermes. Separado a propósito de esos dos (domingo
06:00 y lunes 05:30): si algo falla, se sabe cuál sin desenredar tres avisos de
la misma mañana.
Callado por diseño: sólo escribe a Telegram si hay hallazgos nuevos Y cambian
respecto a la semana anterior. Si la deriva sigue igual porque aún no se ha
arreglado, no insiste — un aviso semanal que siempre llega deja de leerse, que
es el fallo que se ha estado corrigiendo estos días.
Rompen el silencio cuatro cosas: deriva nueva; el repo local por detrás de
origin (se habría comparado contra ficheros viejos); excepciones que ya no se
disparan; y que el propio auditor haya fallado, porque un vigilante roto no es
un "todo bien".
Probado viéndolo hacer las cuatro, no sólo la buena, y por el camino real
(systemctl start, con el entorno del unit, no desde mi shell). Dos cosas que
salieron de probarlo:
- La primera versión avisaba de "cambios sin commitear". Es estado de trabajo
normal y la copia local es justo la intención que hay que comparar, así que
habría mandado ruido cada semana. Ahora eso es contexto, no motivo.
- Un error de sintaxis en el auditor hace que Python salga con código 1, EL
MISMO que "hay deriva": el aviso habría dicho "los ficheros no coinciden" con
el volcado de una traza. Ya no basta el código de salida, se exige además que
el informe traiga su línea de resumen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Deja en el repo lo que hoy destapó que argocd-redis, el daemon.json de gitea y
siete imágenes llevaban meses diciendo una cosa mientras el cluster hacía otra.
Compara cada manifiesto con el objeto vivo, en las dos direcciones (el fichero
afirma algo falso / hay algo desplegado que el fichero no menciona / el objeto no
existe). Sólo mira los directorios fuera de ArgoCD, que es donde no hay nadie
comprobando: en los demás ArgoCD ya marca OutOfSync cada 3 minutos. La lista de
directorios se deduce preguntando a ArgoCD por los paths de sus Applications, así
que si mañana un namespace entra en GitOps el script se ajusta solo.
Las excepciones conocidas van en excepciones-auditoria.yaml CON su motivo, para
que lo normal sea "hallazgos NUEVOS: 0" y cualquier cosa que asome merezca una
mirada. Un informe que siempre saca ruido deja de leerse — que es justo el fallo
que se ha estado corrigiendo estos días. El script también avisa cuando una
excepción ya no se dispara: se arregló y la entrada sobra.
Probado viéndolo fallar, no sólo pasar: inyectadas a propósito una avería de cada
tipo (imagen cambiada, env borrada del fichero, objeto inexistente) y las caza
las tres saliendo con código 1. Al probarlo apareció un fallo propio: con -d
marcaba como sobrantes las excepciones de los directorios no barridos; ahora sólo
lo afirma tras un barrido completo.
No toca nada (sólo lectura), nunca compara valores de Secret —sólo nombres de
clave— y se salta lo que ignora .gitignore.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Tres ficheros describían algo distinto de lo desplegado, y aplicarlos rompía
cosas. Ahora coinciden campo por campo (verificado con kubectl diff vacío).
argocd/deployment-argocd-redis.yaml decía `resources: {}` y el nodeSelector por
defecto. Lo vivo lleva el anclaje a chemavx-k8 y límites de 200m/128Mi, sin los
cuales este pod muere con Exit Code 255 tras días de uptime. El arreglo sólo
constaba en argocd-patches/redis-patch.yaml, así que el fichero que uno
aplicaría primero era justo el que deshacía el arreglo. Queda el comentario
explicando por qué el anclaje está ahí, y el parche lleva cabecera diciendo que
es parcial y que no debe compararse con el cluster.
gitea/configmap-daemon-json.yaml le faltaban dos insecure-registries que sí
están vivos (git.chemavx.xyz y gitea.gitea.svc.cluster.local:3000). Comprobado
que lo vivo es lo correcto: el buildkitd.toml declara ese registro como
http/insecure y los workflows de CI empujan ahí. Aplicar el fichero viejo habría
dejado a la CI sin poder subir imágenes.
gitea/configmap-buildkitd-config.yaml es nuevo: ese ConfigMap llevaba 90 días
vivo sin manifiesto ninguno.
Restos de polymarket, decomisado el 2026-07-17: fuera su Namespace de
cluster-wide/namespaces.yaml (11 quedan) y borrado el directorio
polymarket-bot/, que resultó no estar en git siquiera — sus dos ficheros los
descarta .gitignore por autogenerados, así que eran basura local del export de
abril. De paso, namespaces.yaml pierde las anotaciones de último apply y gana
una cabecera: no es la lista completa del cluster (16 apps de ArgoCD crean su
propio namespace) y aplicarlo no lo reconstruye.
La auditoría baja de 26 hallazgos a 13, y ninguno de los 13 es deriva real:
8 son reddit-intel, inactivo a propósito (ver reddit-intel/PROMOTION.md), 3 son
el fichero de parche parcial, uno es un `group: ''` equivalente a estar ausente
y el último era una anotación del controlador, ya fuera del export.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
El commit 22ae5d7 (15-abr) fijó estos tags EN GIT pero nunca se aplicó al
cluster: estos namespaces no están en ArgoCD, así que un cambio en git no llega
solo. Tres meses después git decía 1.25.5 y gitea corría 1.27.0, subido en algún
reinicio sin que nadie lo decidiera. Ahora se fija a los dos lados.
gitea gitea/gitea:latest -> gitea/gitea:1.27.0
gitea (init) busybox -> busybox:1.38.0
gitea-runner gitea/act_runner:latest -> gitea/act_runner:0.6.1
gitea-runner docker:24-dind -> docker:24.0.9-dind
authentik-redis redis:alpine -> redis:8.8.0-alpine
uptime-kuma louislam/uptime-kuma:1 -> louislam/uptime-kuma:1.23.17
homarr homarr:latest -> homarr@sha256:80ee593c...
Los seis primeros se fijan a la MISMA imagen que ya corría: verificado
comparando el repoDigest del tag flotante con el del tag candidato, así que el
reinicio no cambió de versión. Homarr va por digest porque su "latest" es una
build de la rama main (org.opencontainers.image.version=main): no existe un tag
de release que describa lo que corre. Moverlo a una release es otra decisión.
Trampa que casi me come, anotada para la próxima: el imageID de un pod NO
siempre es el digest del registro. Si viene como "repo@sha256:..." lo es; si es
un "sha256:..." pelado es el id local de containerd y NO se puede descargar.
Fijar uptime-kuma a ese id dio ImagePullBackOff; el pod viejo aguantó sirviendo
(maxUnavailable 0 para 1 réplica) y se revirtió sin corte. La comparación buena
es repoDigest contra repoDigest.
De paso, al regenerar gitea-runner desde lo vivo quedan documentados el volumen
buildkitd-config y su montaje, que existían en el cluster y no en git.
Verificado tras cada cambio: rollout completo, versión de la app dentro del pod,
y los cinco servicios respondiendo desde fuera (git 200, home 200, status/auth/
grafana 302 por Authentik). El runner se ha vuelto a registrar en Gitea. Sigue
sin haber pods fuera de Running y las 18 apps de ArgoCD Synced+Healthy.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Grafana llevaba ~15 días sin SSO: ignoraba la cabecera X-authentik-username, de
modo que Authentik te dejaba pasar y Grafana te pedía credenciales igual. El
último acceso de akadmin (el usuario que crea auto_sign_up) es de hace 15 días.
El bloque [auth.proxy] estaba en el ConfigMap vivo en abril — así consta en el
export de git de aquel momento — pero el chart NUNCA lo ha generado en ninguna
de sus 7 revisiones, así que era un retoque a mano que se perdió por el camino.
Ahora va declarado en values y sobrevive a una reconstrucción.
Aparecida al arreglarlo, otra pieza del mismo tipo: la anotación
router.middlewares que engancha el forward-auth de Authentik al Ingress. Vivía
sólo por el three-way merge de Helm, igual que el montaje de alerting (0501aab)
y el token de Telegram (28f1631). Reconstruir el release habría dejado Grafana
en internet SIN autenticación de Authentik, con sólo su formulario delante.
NO se restaura disable_login_form, que sí traía la config de abril: el
formulario local se queda como puerta de emergencia, con la contraseña del
secret grafana-admin. Que el SSO fallara en silencio es justo lo que pasó aquí.
Verificado: con la cabecera, autentica como akadmin; sin ella sigue dando 401;
una petición externa a grafana.chemavx.xyz redirige (302) al authorize de
Authentik; el formulario local responde 200 y la contraseña de emergencia entra;
0 errores en el arranque. Exports regenerados: el auditor deja monitoring en 2
hallazgos, ambos conocidos (una anotación del controlador y el tag de
uptime-kuma, pendiente de decidir con el resto de tags flotantes).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Todos los fallos del log eran el mismo: cada ciclo de 5 min intentaba detectar
la IP v6 contra api.cloudflare.com/cdn-cgi/trace, agotaba los 5s de
DETECTION_TIMEOUT y terminaba en "No valid IPv6 addresses were detected".
34 de 34 errores en las últimas 400 líneas; ni uno solo de IPv4.
Aquí no hay IPv6: la única dirección v6 global de los nodos es la ULA de
Tailscale (fd7a:115c:a1e0::/48) y no hay ruta a internet por v6. IP6_PROVIDER
no estaba puesto y cae por defecto en cloudflare.trace, así que lo intentaba
igual. Ahora va explícito a "none".
No se pierde ningún registro: no hay AAAA de origen que mantener. Los AAAA que
publica theexclusionzone.com son de Cloudflare (2606:4700::/32), sintetizados
por ser proxied, y el DDNS nunca los tocó.
Importa más de lo que parece: ese ruido constante es lo que haría invisible un
fallo de verdad en el servicio del que dependen los tres dominios.
De paso, fuera del fichero dos anotaciones que no son configuración deseada
sino estado del controlador: last-applied-configuration (además describía la
config de una sola zona, anterior al alta de los dos blogs) y
deployment.kubernetes.io/revision, que el fichero fijaba en 1 cuando la viva
iba por la 8.
Verificado con kubectl diff antes de aplicar (único cambio: +IP6_PROVIDER), y
después: el arranque ya no anuncia proveedor IPv6, comprueba los 7 registros A
y lleva 0 errores.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Los paneles heredados preguntaban "cuántos pods hay Running en el namespace".
Para n8n u ollama da igual, pero el panel llamado "grafana" contaba los 7 pods
de monitoring y el de "argocd" los suyos: se habrían quedado en verde con
Grafana muerta mientras Prometheus siguiera en pie. Lo mismo en "authentik" y
"gitea", que sumaban su Postgres, su Redis y el runner.
Ahora los 12 usan la misma forma: ¿están en pie TODOS los componentes de los
que depende el servicio?
min((kube_deployment_status_replicas_available{SEL} >= bool 1)
or (kube_statefulset_status_replicas_ready{SEL} >= bool 1)) or vector(0)
El selector define qué es el servicio: el namespace entero cuando el namespace
ES el servicio (argocd, authentik); acotado cuando alberga varias cosas
(grafana dentro de monitoring, researchowl/searxng); y en gitea sólo el
StatefulSet, porque si cae el runner se paran los builds pero Gitea sigue
sirviendo — pintarlo "Down" sería una falsa alarma.
Cambio invisible salvo cuando algo falla: los 12 mapean 0 -> "Down" y >=1 ->
"Running", así que en pantalla nunca se vio el número. Y además exige réplicas
*disponibles*, no pods en fase Running: un pod arrancado pero que no pasa el
readiness ya no cuenta como sano.
Verificado los 12 en verde y los 12 en rojo (simulando escasez de réplicas), y
el caso que de verdad importa: UN solo componente caído entre sanos arrastra el
panel a 0 (probado con dex-server en argocd y con el Postgres de authentik).
Después, los 12 otra vez a través del proxy de datasource de Grafana.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>