minio: install mc in the runtime image, declare its region #62

Merged
jschoubben merged 11 commits from fix/minio-provisioner-missing-mc-cli into main 2026-09-25 15:25:19 +00:00
11 Commits
Author SHA1 Message Date
jschoubben b3de7e7944 minio: declare region eu-west, don't leave it as live-only drift
serves.s3-bucket.region still said us-east-1 (PR #58 already fixed this,
unmerged) while the live mesh-minio sidecar had MESH_MINIO_REGION=eu-west
set out-of-band, not in the manifest at all — and the actual minio server
had no region configured whatsoever (mc admin config get region: empty),
apparently lost across a container recreation since nothing declared it.
Every s3-bucket consumer binding ${bound:s3-bucket:region} was reading
the stale us-east-1 declaration regardless of what was actually live.

Declares MINIO_REGION on the server container and MESH_MINIO_REGION on
the sidecar, matching the static serves declaration, so this is mesh-
managed and durable rather than a manual mc admin config or docker env
override that the next recreation silently drops.
2026-09-25 15:10:30 +02:00
jschoubben 5d13a5078c minio: install mc in the runtime image — the provisioner needs it to run
mesh-minio's s3-bucket provisioner shells out to mc to create buckets and
service accounts on the live server, but mc was never in this module's own
runtime image, only in minio's own. It's been silently retrying 'spawn mc
ENOENT' forever, so every s3-bucket grant reached the control-plane layer
(store.json, sealed secret) without the credential ever actually existing
on minio — nextcloud's live instance just hit this as InvalidAccessKeyId
on a real user session.

Copies mc from minio's own image (docker.io/pgsty/minio, already pinned
and pulled as this module's server container) rather than introducing a
new base — mc there is a working, already-verified binary. /usr/bin/mc is
a symlink to mcli; both are copied so it resolves.
2026-09-25 14:37:23 +02:00
jschoubben 61eca75315 nextcloud: pull the S3 region from the binding, not a hardcoded literal
the s3-bucket binding already carries serves.region (same mechanism as
at/port); ${bound:s3-bucket:region} tracks whatever minio is actually
configured with instead of a copy that can drift
2026-09-25 14:15:40 +02:00
jschoubben df0e9017e0 nextcloud: set OBJECTSTORE_S3_REGION to match minio's actual region
minio runs with MINIO_REGION=eu-west; nextcloud's S3 config never set a
region, so every object write (avatars, file writes) failed signature
validation with AuthorizationHeaderMalformed, surfacing as Internal Server
Error on real page loads
2026-09-25 14:12:05 +02:00
jschoubben b60dd5e3e3 nextcloud: use a module-owned mesh-admin account instead of 'admin'
the migrated data has no literal 'admin' account — HAL's real admin login
is a personal account (jochens), not a generic one. Resetting that would
touch a real user's own credential, so the module gets its own dedicated
admin-group service account instead, same pattern as the minio per-module
service accounts. mesh-admin was created once by hand on novox to match
this manifest for the already-migrated data; a genuinely fresh install
seeds it automatically via NEXTCLOUD_ADMIN_USER/NEXTCLOUD_ADMIN_PASSWORD.
2026-09-25 13:51:40 +02:00
jschoubben b865978e19 nextcloud: use a named build stage for docker:cli, not ARG-in-COPY-from
the legacy (non-BuildKit) docker build this host runs doesn't expand ARGs
inside COPY --from — only FROM. Give it its own named stage instead
2026-09-25 13:49:02 +02:00
jschoubben cdbc850c52 nextcloud: declare docker:cli as a pinned build.on base
build refused to reach docker:cli implicitly (novox/hq ADR 0097); pin it by
digest and thread it through as DOCKER_CLI, redeclared in the final stage
since args declared before the first FROM don't carry past it
2026-09-25 13:48:00 +02:00
jschoubben e2b3723dd9 nextcloud: fix hardcoded sidecar port and missing docker CLI in runtime image
- MESH_NEXTCLOUD_URL hardcoded :80 instead of the mesh-assigned ${port:80}
- sidecar's occ() shells to docker exec but the docker CLI binary was never
  present in the runtime image, only the mounted socket
2026-09-25 13:47:03 +02:00
jschoubben 5f74c41a3e nextcloud: give the admin password a real _FILE variant, not an env-file
The mesh's own check caught it: an env-file-loaded secret still reaches
the process environment, readable via docker inspect and /proc (hq
04-ISSUES/041) -- the same class of exposure the file-based delivery
exists to avoid. Added MESH_NEXTCLOUD_ADMIN_PASSWORD_FILE support to the
client, matching the pattern the minio client already uses, and mounted
the sealed admin secret directly rather than writing it into an env-file.
2026-09-25 13:42:21 +02:00
jschoubben 4329ca9392 nextcloud: deliver the admin password to the sidecar too
The sidecar's own client needs MESH_NEXTCLOUD_ADMIN_PASSWORD to list
shares over the OCS API, but the runtime container's env/volumes never
carried it -- only the server container did. Delivered the same way every
other sealed value in this manifest already is: a generated env-file with
the ${secret:admin} substitution, not a raw value in the container's env.
2026-09-25 13:41:17 +02:00
jschoubben 066254e5c4 nextcloud: pin an image whose PHP matches this Nextcloud version
The pinned digest resolved to a PHP 8.5.10 image; Nextcloud 30 refuses to
run above PHP 8.4. Repinned to the current digest for the nextcloud:30 tag
(matches HAL's own NEXTCLOUD_VERSION), which carries PHP 8.3.28 -- the
same version the data being migrated was actually running under.
2026-09-25 13:39:16 +02:00