44 Commits
Author SHA1 Message Date
Jeffrey f53e8f5b00 jellyfin: upgrade to 12.0
All five installed plugins have 12.0.0.0 targetAbi builds available. The
archived 9p4 SSO Authentication plugin has been removed, since it has no
v12 build and is being replaced by an OIDC plugin later.

Plugins must be updated from the Jellyfin dashboard after the rollout;
the container upgrade does not touch /config/plugins.
2026-09-13 12:56:38 +02:00
Jeffrey 30f9c63c9b authentik: spell out API-defaulted fields on the LDAP route and listeners
The API server defaults group on allowedRoutes.kinds and certificateRefs,
and group, kind and weight on the TCPRoute backendRefs. Omitting them left
both ArgoCD apps permanently OutOfSync against the live objects. Matches
what authentik-httproute.yaml already does.
2026-09-13 11:39:35 +02:00
Jeffrey c1287fa343 authentik: serve LDAP via an outpost behind the internal gateway
Adds the LDAP outpost deployment and routes ports 389 and 636 on
gateway-internal to it. 636 is a TLS listener in Terminate mode so
cert-manager renews the LDAPS certificate automatically, and both
listeners forward to the outpost's plaintext 3389.

allowedRoutes.kinds is set explicitly on both listeners: a TCP listener
permits no route kinds by default and a TLS listener defaults to
TLSRoute, so the TCPRoute would not attach otherwise.
2026-09-13 11:24:23 +02:00
Jeffrey 7ee7db2346 minio-aistor: restore the backend traffic policy to its pre-4207459 state
Swept into d5e0731 by the same stray `git add -u`. Unlike argocd-install
this one is synced, so it went live; reverting here rolls the cluster back
to connectionIdleTimeout 3600s with no retry block.

The content is still reachable at d5e0731 if it is wanted back.
2026-08-29 19:08:17 +02:00
Jeffrey d5e073131d infisical: ignore every volumeClaimTemplate field the api server injects
The earlier rule covered creationTimestamp, volumeMode and status but missed
apiVersion and kind, which the API server also injects into
volumeClaimTemplates. Those two alone kept both StatefulSets permanently
OutOfSync: a sync would apply successfully and report Synced, then the very
next comparison flagged them again.
2026-08-29 18:16:25 +02:00
Jeffrey 7a937dae07 gitea: drop the orphaned runner pvc that could never bind
gitea-runner-pvc referenced volumeName gitea-runner-data, but neither that
PV nor a Longhorn volume of that name exists, so it sat Pending since May.
ArgoCD treats a Pending PVC as Progressing and rolled that up to the whole
app, which is why gitea never reported Healthy.

Nothing mounted it. The runner uses the PVC the gitea/actions chart
generates from its own volumeClaimTemplate.
2026-08-29 18:00:28 +02:00
Jeffrey f67cbf4465 netbox: send a Host header on the probes
The kubelet probes the pod IP, which Django rejects with a 400 because
ALLOWED_HOSTS is netbox.jsme.be. Setting the Host header keeps
ALLOWED_HOSTS tight instead of widening it to '*'.
2026-08-27 20:56:16 +02:00
Jeffrey cfd9317086 netbox: add NetBox 4.6.8 with postgres, valkey and rqworker
Five components under applications/netbox: the web pod, an rqworker,
a daily housekeeping CronJob, postgres 18 and two valkey instances.
The task queue runs appendonly on its own PVC so queued jobs survive a
restart, while the cache instance is disposable.

Worker and cronjob override args rather than command, which replaces
CMD while keeping tini as the entrypoint, so only the web pod runs
migrations. Media, reports and scripts share one RWX PVC via subPaths
because both the web pod and the worker mount them.

Exposed on the internal gateway only.
2026-08-27 20:46:34 +02:00
Jeffrey 2d078e10c0 pelican: expose wings-mc and wings-ark on the public gateway
The console will not work from outside without this. WebsocketController hands
the browser wss://<node fqdn>:443/api/servers/<uuid>/ws built from
Node::getConnectionAddress(), so the browser talks to wings directly and never
through the panel. Same for file upload and download, which FileUploadController
builds from the same address. Everything else (login, server list, file
browsing, power actions, sending console commands) already worked publicly,
because those go through the panel API.

Adds public listeners for both nodes reusing the existing wings-mc-tls and
wings-ark-tls certificates, and a gateway-public parentRef on each route.

Extends the wings ClientTrafficPolicy to the two new listeners. Without it the
public listeners would negotiate h2 and long-lived consoles would drop: wings
only speaks HTTP/1.1, and the idle timeout needs to be 3600s rather than the
default.

CrowdSec ext_authz already covers every listener on gateway-public, so both
nodes are behind the WAF and community blocklist from the moment they are live.
Wings itself is JWT-gated and returns 401 unauthenticated.
2026-08-26 21:54:49 +02:00
Jeffrey 1849703886 pelican: expose the panel on the public gateway
Adds a pelican listener to gateway-public and a gateway-public parentRef to
pelican-route. Reuses the existing pelican-tls certificate, which both
listeners reference.

Wings deliberately stays internal-only. That is a real functional limit, not
an oversight: the browser talks to wings directly for the console websocket
and for file upload/download, using the address from Node::getConnectionAddress.
From outside the LAN those calls will fail. Panel login, server list, file
browsing and editing, and power actions all go through the panel API and keep
working, because the panel reaches wings server-side over the internal gateway.

CrowdSec ext_authz already covers every listener on gateway-public, so the
panel is behind the WAF and community blocklist from the moment it is live.

Prerequisites completed first: TRUSTED_PROXIES=10.42.0.0/16 and
APP_2FA_REQUIRED=1 set in Infisical and verified live in the panel config.

pelican.jsme.be has no public DNS record yet, so this makes the panel reachable
through 10.8.11.105 but not from the internet. The Azure DNS CNAME in the
OpenTofu repo is the actual cutover.
2026-08-26 20:41:28 +02:00
Jeffrey 63056b313a pelican: move panel image to ghcr.io/pelican/panel and pin beta38
The ghcr.io/pelican-dev/panel package is no longer anonymously pullable
(token endpoint returns DENIED for every tag, package page 404s). Upstream
renamed the org to "pelican" in beta38 and compose.yml now points at
ghcr.io/pelican/panel. Verified a real pull of v1.0.0-beta38 from the new
location succeeds.

Pinning the tag also replaces :latest, which combined with IfNotPresent meant
the running version depended on whatever the node happened to have cached.
beta36 was clean against all six published advisories, but four of them landed
in the last five months, so a deliberate patch path matters here.

beta37/38 carry no breaking changes or manual migration steps. beta37 fixes
Passkeys origin validation, which is wanted before enrolling 2FA.
2026-08-26 16:59:06 +02:00
Jeffrey 023f233f99 Revert reactive-resume to v5.0
v5.2.8 aborts startup when OIDC discovery fails. Discovery URL points at
authentik.jsme.be, which pods cannot reach due to hairpin NAT.
2026-08-24 23:18:47 +02:00
Jeffrey a57860a576 Update application and chart versions to latest
Bumps every outdated image and chart except databases, which are
deliberately left on their current versions.

Applications:
  authentik       2026.5.2 -> 2026.8.0 (server and worker)
  immich          v2.7.5 -> v3.1.0
  gitea           1.25 -> 1.27.2
  gotify          2.9.1 -> 3.0.0
  uptime-kuma     2.2.1 -> 2.5.3
  zipline         4.5.3 -> 4.7.0
  outline         1.8.1 -> 1.9.2
  reactive-resume v5.0 -> v5.2.8
  netbootxyz      nbxyz18 -> nbxyz24
  bentopdf        v2.8.2 -> v2.8.7
  jellyfin        10.11.9 -> 10.11.11
  gitea runner init busybox 1.37.0 -> 1.38.0

Infra:
  kube-vip                    v0.9.1 -> v1.2.3
  victoria-metrics-k8s-stack  0.77.0 -> 0.91.2
  intel-device-plugins        v0.35.0 -> v0.36.0
  crowdsec-envoy-bouncer      0.6.3 -> 0.8.0

Immich v3 drops pgvecto.rs support. Verified the live database already
runs vchord 0.4.3 and pgvector 0.8.1 with no pgvecto.rs extension, both
inside the ranges v3 accepts, so no database change is required.

The victoria-metrics chart renamed defaultRules.create to
defaultRules.enabled at both the top level and per group. Migrated those
keys so the etcd, kubeScheduler, kubernetesSystemControllerManager and
kubernetesSystemScheduler exclusions keep applying. Without the rename
those groups revert to enabled and alert on control-plane components
that k3s runs embedded.

That chart also moved default rules and dashboards to a runtime sync job
instead of templating them, so ArgoCD will prune the VMRules and
dashboard ConfigMaps it currently owns and the job will recreate them.

kube-vip is not managed by ArgoCD. The manifest change is inert until
applied by hand.
2026-08-24 23:12:22 +02:00
Jeffrey 38a03bb131 infisical: add resource requests and limits to postgres and valkey
Both ran as BestEffort QoS, making them first in line for eviction under node memory pressure. Requests also give the scheduler real numbers to place them with.
2026-08-24 00:46:31 +02:00
Jeffrey 0177c73fa9 gitea: migrate to envFrom with per-container InfisicalSecrets
Flat CR narrowed to recursive: false; it still serves the SMB mount credentials and the Actions runner token, which the runner Helm chart reads via existingSecret.
2026-08-24 00:20:29 +02:00
Jeffrey 079830a8ff authentik: migrate to envFrom with per-container InfisicalSecrets
Server and worker share one Secret since their env is byte-identical. Database and SMTP values are Infisical references rather than copies.
2026-08-24 00:16:26 +02:00
Jeffrey 3e13b76c6a react-resume: migrate to envFrom with per-container InfisicalSecrets
Stores PRINTER_ENDPOINT pre-assembled instead of building it from CHROME_TOKEN via $() interpolation.
2026-08-23 23:47:13 +02:00
Jeffrey 3c24cd4b9d gotify: migrate to envFrom with per-container InfisicalSecrets
Stores the fully assembled database DSN in Infisical instead of building it from three helper vars with $() interpolation, which envFrom cannot feed.
2026-08-23 23:38:16 +02:00
Jeffrey f382c87f58 pelican: migrate to envFrom with per-container InfisicalSecrets
Folds the pelican-config ConfigMap into Infisical so the container has a single envFrom. Pins imagePullPolicy to IfNotPresent because ghcr.io/pelican-dev/panel no longer allows anonymous pulls.
2026-08-23 23:16:37 +02:00
Jeffrey 0329546d87 azure-ddns: migrate to envFrom with a per-container InfisicalSecret
Also moves the manifests into a component directory, matching the other migrated apps.
2026-08-23 22:42:09 +02:00
Jeffrey c408522988 immich: migrate to envFrom with per-container InfisicalSecrets
Flat CR narrowed to recursive: false so it keeps serving the SMB credentials that immich-data-smb references by name.
2026-08-23 22:15:10 +02:00
Jeffrey 77b8bd4475 passbolt: migrate to envFrom with per-container InfisicalSecrets
Also removes the now-stale flat CR files for searxng, outline and passbolt, which ArgoCD would otherwise recreate pointing at emptied folders.
2026-08-23 21:54:06 +02:00
Jeffrey fccf9074d2 outline: migrate to envFrom with per-container InfisicalSecrets
All 31 env entries, secrets and literals alike, now live in Infisical under /outline/outline and /outline/postgres. Manifest rationale carried across as Infisical secret comments.
2026-08-23 20:55:21 +02:00
Jeffrey 10545c03be searxng: migrate to envFrom; move remaining literals into Infisical
Non-secret config now lives in Infisical alongside the secrets, so containers carry envFrom only and no loose env entries.
2026-08-23 20:34:38 +02:00
Jeffrey 14ef1c6e91 zipline: migrate to envFrom with per-container InfisicalSecrets
Flat CR narrowed to recursive: false so it keeps serving the SMB mount credentials that zipline-uploads-pv references by name.
2026-08-23 20:08:43 +02:00
Jeffrey 3bec829396 infisical: repoint secret CRs at the rebuilt machine identity
Also tracks the auth ServiceAccounts and RBAC in Git so a namespace rebuild restores Kubernetes auth on its own.
2026-08-23 20:08:28 +02:00
Jeffrey 7956c6b1b9 Migrate to using EnvFrom with the use of Infisical Secret sync for env vars 2026-08-23 18:23:56 +02:00
Jeffrey 19bab56874 Revert "infisical: add resource requests and limits to postgres and valkey"
This reverts commit c72c6a322e.
2026-08-22 17:04:27 +02:00
Jeffrey c72c6a322e infisical: add resource requests and limits to postgres and valkey
Both ran as BestEffort QoS, making them first in line for eviction
under node memory pressure. Requests also give the scheduler real
numbers to place them with.
2026-08-22 16:55:50 +02:00
Jeffrey 1a4c765fec Bump technitium to 15.4.0 2026-08-22 13:12:34 +02:00
Jeffrey 43af4997ab pelican: wings-ark backend is live at 10.8.11.51 2026-08-16 21:19:22 +02:00
Jeffrey 17c84d2ba8 pelican: split wings into wings-mc and wings-ark domains 2026-08-16 21:09:00 +02:00
Jeffrey 7403edf7d5 argocd: manage namespaces via manifests instead of CreateNamespace 2026-08-16 21:08:41 +02:00
Jeffrey 39f8a78306 fix: point postgres PGDATA at the actual mounted PVC for zipline and immich 2026-08-02 12:55:18 +02:00
Jeffrey 37737670b5 infisical: bring self-hosted stack under GitOps (postgres, valkey, backend); secret.yaml excluded template 2026-07-16 21:47:28 +02:00
Jeffrey 1d026f8d57 infisical: migrate all InfisicalSecrets to Kubernetes auth; drop universal-auth secret 2026-07-16 21:18:47 +02:00
Jeffrey 7526ea0a1b infisical: route infisical.jsme.be to infisical-backend service 2026-07-15 22:20:12 +02:00
Jeffrey fc4ca1f3f1 infisical(netbootxyz): use autoCreateServiceAccountToken (short-lived k8s auth) 2026-07-15 22:07:22 +02:00
Jeffrey 596fa5380a infisical(netbootxyz): switch to Kubernetes auth (pilot) 2026-07-15 21:54:43 +02:00
Jeffrey 571c5d5d0b Move Jenkins and ntfy to deprecated 2026-07-08 09:07:03 +02:00
Jeffrey e467340edd Upgrade storage on Jellyfin 2026-07-04 17:41:36 +02:00
Jeffrey fc54063272 Increate PVC size Jellyfin 2026-06-27 14:17:55 +02:00
Jeffrey be9bd3a227 Add Outline 2026-06-22 23:32:35 +02:00
Jeffrey c40577589d Split manifests into infra/ and applications/ 2026-06-21 12:23:20 +02:00