Commit Graph
1387 Commits
Author SHA1 Message Date
Ruben Hensen 348cce6d5d gatus: check immich's ping endpoint for foto.scoutingmbg.nl
Without sol-auth in front, /_app is no longer the open path to check;
/api/server/ping answers without a login.
2026-10-24 14:01:23 +02:00
Ruben Hensen abed11dbaa immich: log in with Scouts Online only
foto.scoutingmbg.nl now goes straight to immich instead of through
sol-auth. immich starts the Scouts Online login right away, the password
login is off and the login page no longer shows the password of the
shared viewing account. share-sync is on, so everyone gets every album
and the group's library in their timeline.

sol-auth stays deployed for now, so switching the route back is the way
back.
2026-10-24 14:01:23 +02:00
Ruben Hensen 86a0c59c6b immich: add share-sync, suspended
immich has no user groups, so a CronJob shares the group account's
albums with every user, as editor when they may upload (quota other than
0, which authentik sets from Scouts Online) and as viewer otherwise. It
also shares the group account's library as a partner and shows it in
every timeline, since immich only searches your own and your timeline
partners' photos; hides the album invitations for albums older than a
week; and ends OAuth sessions older than 30 days, so people who left the
group lose access at their next login.

Suspended until immich logs in through Scouts Online only.
2026-10-24 13:48:07 +02:00
Ruben Hensen ebf28c1bf1 docs: step B of the Scouts Online login is live 2026-10-24 13:43:24 +02:00
Ruben Hensen 135bca4a83 authentik: log in to immich with Scouts Online
Adds Scouts Online 3 (login.scouting.nl) as an OIDC source. Its userinfo
has the member's roles within the group; a property mapping puts every
member in "MBG leden" and those with an active Kaderlid role also in
"MBG kader", on every login. Members become external users. Family
members can share an email address and immich needs a unique one, so
those get a plus address with their member number.

The immich provider now authenticates through a flow whose only stage
is an identification stage with this one source and no fields, which
sends people straight on to Scouts Online. The source's own flows only
run through the source.
2026-10-24 13:37:12 +02:00
Ruben Hensen 1c6b42b20b docs: step A of the Scouts Online login is live 2026-10-24 13:25:02 +02:00
Ruben Hensen f3f36c3718 docs: plan the immich login with Scouts Online
Building blocks, design and the three steps towards personal accounts with upload rights from Scouts Online roles.
2026-10-24 13:19:52 +02:00
Ruben Hensen 399387bfb7 immich: configure through a config file with OAuth
immich gets its settings from a Secret that ESO renders with the OAuth
client secret from Vault. It keeps the settings that were in the database
(external domain, login page message, storage template) and adds OAuth
through authentik next to the password login, with auto register. With a
config file the settings are read-only in the admin UI.
2026-10-24 13:19:52 +02:00
Ruben Hensen 48b0873ca3 authentik: add an OIDC provider for immich
The Scouting MBG photos (immich) will log in through this authentik,
which later passes on Scouts Online. The provider issues immich_role and
immich_quota: admins and the members of "MBG kader" may upload (-1),
everyone else gets a quota of 0, which makes immich refuse uploads.
"MBG leden" and "MBG kader" are filled by the Scouts Online source in a
next step; until then only authentik Admins can use the app.

The scouting blueprints and their secrets are mounted as directories
rather than with subPath, and the blueprint reads the client secret with
!File instead of !Env, so later changes reach authentik without a restart.
2026-10-24 13:19:52 +02:00
Ruben Hensen 278f6fc55f authentik: limit personal apps to authentik Admins
Actual Budget, Argo CD, FreshRSS, Stalwart and Vault had no policy
binding, so any authentik user could sign in to them. Scouts Online
members are about to get accounts in this authentik for immich; bind
each app to the authentik Admins group, as Longhorn already was.
2026-10-24 13:04:33 +02:00
Ruben Hensen f4e74a9503 docs: record the immich 3 upgrade
v3.3.5 with chart 0.13.4 is running; note the safety net to clean up later and the optional revised ML models.
2026-10-24 12:33:43 +02:00
Ruben Hensen c270bcc12b immich: upgrade to v3.3.5 and chart 0.13.4
immich 3 drops pgvecto.rs, which the database no longer uses since the
move to PostgreSQL 17 with VectorChord 1.1.1 (supported range >=0.3 <2)
and pgvector 0.8.6 (>=0.7 <0.9). None of the removed environment
variables are set here. The mobile app cannot pass sol-auth, so there are
no app clients to upgrade first.

Charts after 0.12.0 are only published to the OCI registry. Since 0.13.0
the chart validates its values, and emptyDir volumes no longer accept
size, accessMode or storageClass; they did nothing anyway. Valkey follows
the chart's new default, 9.1.2. Each component now gets its own
ServiceAccount without a mounted token.

Safety net: Longhorn snapshot immich-pg17-pre-v3 and a pg_dump in
~/immich-pg17-pre-v3.dump on opti1, since immich cannot be downgraded.
2026-10-24 12:29:35 +02:00
Ruben Hensen 14e61ee5ee gateway: retry requests on dropped backend connections
When a backend closes a kept-alive connection just as Envoy sends a
request over it, Envoy returns a 503 (response flag UC) and does not
retry by default. ingress-nginx retried these, so the race never showed.

The Apache in front of immich (sol-auth) recycles its processes after 30
connections, which made this happen during page loads: three chunks got
a 503 and immich failed with "error loading dynamically imported module".
authentik and ntfy saw it too, less often.

Retry up to twice on connection failures and resets, for every route on
the Gateway.
2026-10-24 12:19:37 +02:00
Ruben Hensen e7696107c0 docs: record the immich database migration
immich now runs v2.7.5 on PostgreSQL 17 with VectorChord. The PostgreSQL 14 cluster stays for a few days as a fallback.
2026-10-24 02:19:57 +02:00
Ruben Hensen a8a186b4d3 immich: upgrade to v2.7.5
v2.4.1 only accepts VectorChord >=0.3 <0.6 and refused to start on the new PostgreSQL 17 cluster with VectorChord 1.1.1; from v2.5.0 the range is >=0.3 <2. v2.7.5 is the last 2.x release; the 3.x upgrade comes separately.
2026-10-24 02:12:53 +02:00
Ruben Hensen 8596e8a428 immich: use the PostgreSQL 17 cluster and start the server again
The import into immich-postgres-17 matched the old database table for table (assets, embeddings, faces, people, albums, migrations). On start immich builds its VectorChord indexes.
2026-10-24 02:06:41 +02:00
Ruben Hensen 251f22c46f immich: add a PostgreSQL 17 cluster with VectorChord
Imported once from the PostgreSQL 14 cluster, whose embeddings were converted to real[] and whose pgvecto.rs extension was dropped first (immich's manual migration). After the import the columns become vector(512) again under VectorChord 1.1.1 with pgvector 0.8.6. A logical import because CNPG can't upgrade in place from the bullseye-based pgvecto.rs image to the bookworm-based VectorChord one.
2026-10-24 02:02:02 +02:00
Ruben Hensen 60ff978b1b immich: stop the server for the database migration
The database moves from PostgreSQL 14 with pgvecto.rs to a new PostgreSQL 17 cluster with VectorChord. Immich 3 no longer supports pgvecto.rs, and PostgreSQL 14 reaches end of life on 2026-11-12.
2026-10-24 00:18:28 +02:00
Ruben Hensen 6517c21937 mbgwp: remove the unused wordpress-external NodePort
It selected pods of the old mbgwp-helm release, so since the move to the official chart it had no endpoints and only held node port 30989 open.
2026-10-24 00:08:19 +02:00
Ruben Hensen 8357d31f9c docs: record the Longhorn NetworkPolicies and poll interval 2026-10-24 00:05:44 +02:00
Ruben Hensen 5208379310 longhorn: enable the internal NetworkPolicies
With them only Longhorn's own components can reach the longhorn-manager API, which any pod could otherwise call without authentication to manage volumes. 1.12 was kept off because its instance-manager policy left the host-side iSCSI initiator out; 1.13 opens port 3260 to any source while v1DataEngineInitiatorSourceCIDRs is empty.
2026-10-24 00:02:32 +02:00
Ruben Hensen f2936e69ec docs: record the switch to annotation tracking 2026-10-24 00:01:16 +02:00
Ruben Hensen 7c8cd28f71 argocd: track resources by annotation
Drops the label tracking pin kept through the 3.x upgrades, so Argo CD uses its default argocd.argoproj.io/tracking-id annotation. Labels can be copied by other tools (cert-manager's ingress-shim copied app.kubernetes.io/instance onto Certificates); the annotation names the exact resource. Every app gets synced once right after, so resources removed later are still recognised for pruning.
2026-10-23 23:54:06 +02:00
Ruben Hensen f901beea4c docs: record the ESO storedVersions cleanup 2026-10-23 23:53:16 +02:00
Ruben Hensen 04a2a2aed2 gatus: let Argo CD prune old resources
configMapGenerator gives every config change a new gatus-config-<hash> ConfigMap, and without prune the old one stayed behind and left the app OutOfSync.
2026-10-23 23:42:58 +02:00
Ruben Hensen 947a705016 longhorn: poll the backup store every 30 minutes
Each poll updates the backupvolume objects, which made up about 8% of the k8s-dqlite writes at the 300s interval. The recurring backup runs once a night, so 30 minutes is plenty.
2026-10-23 23:39:49 +02:00
Ruben Hensen 416356b4d5 Remove the disabled apps and a stray Argo CD patch copy
Nothing deploys disable/: the apps in it (ente-photos, minio, mist, owntracks, traccar, ttrss, whisper and others) are gone from the cluster apart from some old TLS secrets. git history keeps them. The argocd-cm patch copy was an old leftover that kustomize never used.
2026-10-23 23:39:49 +02:00
Ruben Hensen d747530f52 docs: tick off the 1.36 component recheck 2026-10-23 23:37:17 +02:00
Ruben Hensen f0519d1b70 docs: record the CVE-2026-2270 patch
microk8s now runs 1.36/edge (v1.36.5) and stays held; it goes back to 1.36/stable once that channel catches up.
2026-10-23 23:35:32 +02:00
Ruben Hensen acc3d7eabb docs: tick off microk8s 1.36
v1.36.2 with containerd 2.2.3, and the snap is held. The CVE-2026-2270 patch release is still to come to the stable channel.
2026-10-23 23:24:06 +02:00
Ruben Hensen 96870af92f docs: prepare microk8s 1.36
Nothing changes in microk8s between 1.35 and 1.36 for this setup. The stable channels lag upstream patches, including the CVE-2026-2270 fix, so the snap gets held and patch updates become a deliberate step.
2026-10-23 23:18:51 +02:00
Ruben Hensen a0fcf9ec3f docs: tick off Longhorn 1.13 2026-10-23 23:15:04 +02:00
Ruben Hensen b19c776728 longhorn: upgrade to 1.13.0
1.13 needs Kubernetes 1.34 or later. It adds a longhorn-global-manager Deployment, set to one replica on this single node, and by default lets the CSI controller read every Secret for provisioner-secret StorageClass parameters; neither StorageClass uses those, so that grant stays off.
2026-10-23 23:06:08 +02:00
Ruben Hensen 514fcd8dd4 longhorn: upgrade to 1.12.1
First step from 1.11.2 to 1.13 now that the cluster runs Kubernetes 1.35. The internal NetworkPolicies that 1.12 enables by default stay off: Calico would enforce them, and the instance-manager policy only admits Longhorn pods while the iSCSI initiator connects from the host.

Also lifts the Renovate hold below 1.11.3, which only existed for Kubernetes 1.33.
2026-10-23 22:58:29 +02:00
Ruben Hensen bd8643c00b docs: tick off Velero 1.18 2026-10-23 22:48:57 +02:00
Ruben Hensen 1926ccc42a velero: upgrade to 1.18.2 (chart 12.2.1)
No breaking changes for this setup: the chart renders the same resources and server flags, and chart 12 only dropped the Bitnami kubectl image from the CRD hook, which stays off because Argo CD applies the CRDs. The AWS plugin goes to v1.14.4, the line for Velero 1.18.
2026-10-23 22:47:27 +02:00
Ruben Hensen e3074b43ad velero: upgrade to 1.17.1 (chart 11.4.0)
1.17 drops restic, which nothing here uses (all 411 pod volume backups and 20 repositories are kopia), and moves the maintenance job settings from server flags into the velero-repo-maintenance ConfigMap, which the chart now renders with keepLatestMaintenanceJobs: 3. The AWS plugin goes to v1.13.2, the line for Velero 1.17.
2026-10-23 22:45:00 +02:00
Ruben Hensen 04ac64f956 docs: tick off Argo CD 3.5 2026-10-23 22:42:00 +02:00
Ruben Hensen e490c79e78 argocd: upgrade to v3.5.6
3.5 is tested on Kubernetes 1.32 to 1.36; 3.4 stops at 1.35. It renders Helm charts with Helm 4.2.1 instead of 3.19; rendering all thirteen Helm apps with both gave the same manifests apart from whitespace, comments and document order.
2026-10-23 22:35:00 +02:00
Ruben Hensen e95d78e160 docs: tick off microk8s 1.35
v1.35.6 with containerd 2.1.6. containerd converted the old config without warnings, and the fixed hosts.toml now parses.
2026-10-23 22:29:32 +02:00
Ruben Hensen b60d3b5589 docs: record the VACUUM and prepare microk8s 1.35
The database went from 709 MB to 44 MB, the first snapshot after it is 8.3 MB instead of 150 MB, and k8s-dqlite uses 403 MB instead of 1,346 MB.
2026-10-23 22:21:46 +02:00
Ruben Hensen 175769d36c Add a tool to VACUUM the k8s-dqlite database
dqlite supports VACUUM from v1.18.2, which microk8s 1.34 ships, but the dqlite shell wraps every statement in a transaction and SQLite refuses to VACUUM inside one. dqlite-vacuum sends it through the go-dqlite driver instead and otherwise just prints page statistics. dqlite-vacuum.sh makes the backups first.

Rehearsed on opti1 on a throwaway node in /dev/shm: 657 MB to 41 MB in 0.6s, with concurrent writes unaffected and the data intact after restarts.
2026-10-23 22:03:30 +02:00
Ruben Hensen c55b7ceab5 docs: tick off microk8s 1.34
v1.34.9 runs with the dqlite snapshot tuning intact. LIST latency is unchanged from 1.33, so the ConsistentListFromCache stalls of canonical/microk8s#5568 don't show here.
2026-10-23 21:42:44 +02:00
Ruben Hensen 67abb0b972 docs: prepare the move to microk8s 1.34
k8s-dqlite v1.8.1 in microk8s 1.34 already bundles dqlite 1.18.2, so the database can be vacuumed from 1.34 on. Also notes the containerd 2 jump at 1.35, the feature gates the 1.34 hook adds for kine, and the front-proxy certificate that expired in 2025.
2026-10-23 21:35:16 +02:00
Ruben Hensen a07ef664cb docs: tick off the Envoy Gateway migration 2026-10-23 21:29:37 +02:00
Ruben Hensen 0a810817b6 gatus: expect the authentik redirect for Longhorn
Longhorn now sits behind an authentik login on the Gateway instead of nginx basic auth, so the check expects a 302 without following it. Same change for s1 on node001.
2026-10-23 21:24:00 +02:00
Ruben Hensen 1f04831a97 Replace the Ingresses with Certificate resources
ingress-nginx is gone and every app is served by the Envoy Gateway. The certificates were created by cert-manager's ingress-shim and are owned by the Ingresses, so each app now declares its Certificate itself, with the same name, secret and usages, so nothing gets reissued. gateway-shim can't take over because the certificates live in the app namespaces.

immich drops mbg.hensen.io, which has no route, so that one certificate is reissued through the Gateway's HTTP-01 solver.

Also removes the Longhorn test-port redirect URI and updates comments that still described nginx.
2026-10-23 21:20:25 +02:00
Ruben Hensen 48f5c7d894 docs: tick off the switch to Envoy Gateway and the Longhorn login 2026-10-23 21:17:04 +02:00
Ruben Hensen 910b792452 longhorn: log in through authentik on the Gateway
Longhorn has no users of its own; nginx guarded it with basic auth using apr1 hashes, which Envoy Gateway does not support. An Envoy Gateway SecurityPolicy now sends visitors through an authentik OIDC application that only admins may use. The client secret lives in Vault at kv/longhorn-oidc and reaches both authentik and Envoy through External Secrets.
2026-10-23 21:07:31 +02:00
Ruben Hensen 009b8ce510 gateway: take over ports 80 and 443 from ingress-nginx
Envoy moves from the test ports to 80 and 443, and Let's Encrypt HTTP-01 challenges go through an HTTPRoute on the Gateway. Push only after sudo microk8s disable ingress, since both want the same host ports.
2026-10-23 21:02:52 +02:00