add mc sidecar and WebDAV service backed by RustFS S3 for Zotero

refs #94 #95 #96 #97

- Add rustfs/Dockerfile.mc: least-privilege mc sidecar (non-root,
  read-only fs, all caps dropped, tmpfs for config)
- Add mc service to compose.yml with storage network access only
- Add rclone WebDAV service using env-based S3 config, serving
  the zotero bucket with HTTP basic auth
- Add Traefik route at webdav.homelab.fhirworx.io
- Add zotero.json IAM policy for bucket access
- Add mc image to deploy, infra-ci, and rebuild-all pipelines
- Add WEBDAV_* env vars to .env.example
This commit is contained in:
kert
2026-03-22 00:57:48 -04:00
parent 97778e338f
commit dd721e8497
5 changed files with 101 additions and 1 deletions

View File

@@ -176,6 +176,25 @@ steps:
depends_on: depends_on:
- build-push-api - build-push-api
# ── MC (MinIO Client) sidecar ────────────────────────────────
- name: build-push-mc
image: woodpeckerci/plugin-docker-buildx
settings:
repo: localhost:3000/homelab/mc
dockerfile: rustfs/Dockerfile.mc
context: rustfs/
tags:
- "sha-${CI_COMMIT_SHA:0:8}"
- latest
daemon_off: true
insecure: true
username:
from_secret: registry_user
password:
from_secret: registry_pass
volumes:
- /run/user/1000/docker.sock:/var/run/docker.sock
# ── Upload scan results ───────────────────────────────────── # ── Upload scan results ─────────────────────────────────────
- name: upload-notebooks-scan - name: upload-notebooks-scan
image: woodpeckerci/plugin-s3 image: woodpeckerci/plugin-s3

View File

@@ -84,6 +84,29 @@ steps:
when: when:
- path: "docs/**" - path: "docs/**"
# ── MC (MinIO Client) sidecar ─────────────────────────────────
- name: hadolint-mc
image: hadolint/hadolint:latest-debian
commands:
- hadolint rustfs/Dockerfile.mc
when:
- path: "rustfs/**"
- name: build-mc
image: woodpeckerci/plugin-docker-buildx
settings:
dockerfile: rustfs/Dockerfile.mc
context: rustfs/
tags: ["ci-test"]
daemon_off: true
dry_run: true
volumes:
- /run/user/1000/docker.sock:/var/run/docker.sock
depends_on:
- hadolint-mc
when:
- path: "rustfs/**"
# ── API image ───────────────────────────────────────────────── # ── API image ─────────────────────────────────────────────────
- name: hadolint-api - name: hadolint-api
image: hadolint/hadolint:latest-debian image: hadolint/hadolint:latest-debian

View File

@@ -84,6 +84,24 @@ steps:
volumes: volumes:
- /run/user/1000/docker.sock:/var/run/docker.sock - /run/user/1000/docker.sock:/var/run/docker.sock
- name: build-push-mc
image: woodpeckerci/plugin-docker-buildx
settings:
repo: localhost:3000/homelab/mc
dockerfile: rustfs/Dockerfile.mc
context: rustfs/
tags:
- "sha-${CI_COMMIT_SHA:0:8}"
- latest
daemon_off: true
insecure: true
username:
from_secret: registry_user
password:
from_secret: registry_pass
volumes:
- /run/user/1000/docker.sock:/var/run/docker.sock
- name: scan-notebooks - name: scan-notebooks
image: woodpeckerci/plugin-trivy image: woodpeckerci/plugin-trivy
settings: settings:

View File

@@ -61,6 +61,29 @@ services:
- no-new-privileges:true - no-new-privileges:true
restart: unless-stopped restart: unless-stopped
mc:
image: fhirworx/mc:${COMMIT_SHA:-latest}
container_name: mc
build:
context: rustfs
dockerfile: Dockerfile.mc
networks:
- storage
environment:
- MC_HOST_local=http://${RUSTFS_ACCESS_KEY}:${RUSTFS_SECRET_KEY}@rustfs:9000
user: "10002:10002"
read_only: true
tmpfs:
- /home/mc/.mc:uid=10002,gid=10002
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
entrypoint: ["sleep", "infinity"]
depends_on:
- rustfs
restart: unless-stopped
postgres: postgres:
image: fhirworx/postgresql:${COMMIT_SHA:-latest} image: fhirworx/postgresql:${COMMIT_SHA:-latest}
container_name: postgres container_name: postgres
@@ -255,10 +278,17 @@ services:
networks: networks:
- storage - storage
- gateway - gateway
environment:
- RCLONE_CONFIG_S3_TYPE=s3
- RCLONE_CONFIG_S3_PROVIDER=Minio
- RCLONE_CONFIG_S3_ACCESS_KEY_ID=${RUSTFS_ACCESS_KEY}
- RCLONE_CONFIG_S3_SECRET_ACCESS_KEY=${RUSTFS_SECRET_KEY}
- RCLONE_CONFIG_S3_ENDPOINT=http://rustfs:9000
- RCLONE_CONFIG_S3_FORCE_PATH_STYLE=true
command: command:
- serve - serve
- webdav - webdav
- ":s3,provider=Minio,access_key_id=${WEBDAV_S3_ACCESS_KEY},secret_access_key=${WEBDAV_S3_SECRET_KEY},endpoint=http://rustfs:9000,force_path_style=true:zotero" - "s3:zotero"
- --addr=:8080 - --addr=:8080
- --user=${WEBDAV_USER:-zotero} - --user=${WEBDAV_USER:-zotero}
- --pass=${WEBDAV_PASS} - --pass=${WEBDAV_PASS}

10
rustfs/Dockerfile.mc Normal file
View File

@@ -0,0 +1,10 @@
# syntax=docker/dockerfile:1
# MinIO Client (mc) sidecar — least-privilege admin helper for RustFS.
# Runs as non-root, read-only filesystem, no capabilities.
FROM minio/mc:latest AS mc
FROM alpine:3
RUN addgroup -g 10002 -S mc && adduser -u 10002 -S mc -G mc
COPY --from=mc /usr/bin/mc /usr/bin/mc
USER mc:mc
ENTRYPOINT ["mc"]