- Introductie van static-files serving met standaard nginx (niet ons docker nginx image), en een rsync service om static files te synchroniseren. Nog niet volledig afgewerkt!
203 lines
7.1 KiB
Markdown
203 lines
7.1 KiB
Markdown
# Evie Object Storage Governance (Optie 3)
|
|
|
|
**Doel:** 1 bucket per omgeving (staging / prod), met **prefixen per
|
|
tenant**. Duidelijke scheiding van datatypes (documents vs assets), lage
|
|
beheerlast, goed schaalbaar.
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
## 1) Structuur & naamgeving
|
|
|
|
### Buckets (per omgeving)
|
|
|
|
- **staging:** `evie-staging`
|
|
- **prod:** `evie-prod`
|
|
|
|
> Buckets zijn S3-compatibel op Scaleway
|
|
> (`https://s3.<regio>.scw.cloud`). Houd buckets "plat" (alle tenants
|
|
> als prefix).
|
|
|
|
### Prefix layout (per tenant)
|
|
|
|
<bucket>/
|
|
tenant-<tenantId>/
|
|
documents/
|
|
<subfolders naar keuze>...
|
|
assets/
|
|
<subfolders naar keuze>...
|
|
|
|
**Conventies** - **Tenant prefix:** `tenant-<tenantId>` (tenantId =
|
|
interne stabiele sleutel; geen PII). - **Datatypes:** `documents/` en
|
|
`assets/` (harde scheiding). - **Bestandsnamen:** `snake-case` of
|
|
`kebab-case`; voeg optioneel datum/uuid toe bij uploads die kunnen
|
|
conflicteren.
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
## 2) Toegang & secrets
|
|
|
|
### IAM-model
|
|
|
|
- **Één IAM Application per omgeving**
|
|
- `evie-staging-app` → keys in **staging** k8s Secret\
|
|
- `evie-prod-app` → keys in **prod** k8s Secret\
|
|
- Toegang **alleen** tot het eigen bucket (`evie-staging` of
|
|
`evie-prod`).
|
|
|
|
### App-side secrets (env)
|
|
|
|
- `S3_ENDPOINT=https://s3.<regio>.scw.cloud`
|
|
- `S3_BUCKET=evie-<env>`
|
|
- `S3_ACCESS_KEY=***`
|
|
- `S3_SECRET_KEY=***`
|
|
- `S3_REGION=<regio>` (bv. `fr-par`)
|
|
- (optioneel) `S3_FORCE_PATH_STYLE=false`
|
|
|
|
> **Presigned uploads**: genereer **server-side** presigned URL's per
|
|
> tenant/prefix; geef nooit de master-keys aan de client.
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
## 3) Policies (conceptueel)
|
|
|
|
- **Bucket policy**: sta alleen requests toe met geldige credentials
|
|
van de Evie-app van die omgeving.
|
|
- **Prefix scope** (in app-logica): alle reads/writes **moeten** met
|
|
pad beginnen op `tenant-<tenantId>/...`.
|
|
- **Optioneel** (later): extra policy-groepen voor specifieke
|
|
workflows (vb. tijdelijke ingest job).
|
|
|
|
> **Belangrijk:** autorisatie op tenantniveau afdwingen in **je
|
|
> applicatie** (context = `tenantId`). Nooit paden samenstellen vanuit
|
|
> user input zonder whitelisting/validation.
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
## 4) Lifecycle & retentie
|
|
|
|
**Doel:** kosten beheersen, assets sneller "kouder", documenten langer
|
|
bewaren.
|
|
|
|
-----------------------------------------------------------------------
|
|
Scope (Filter) Regel
|
|
----------------------------------- -----------------------------------
|
|
`tenant-*/assets/` → One Zone-IA na 30 dagen
|
|
|
|
`tenant-*/assets/` → Glacier/Archive na 180 dagen
|
|
(optioneel)
|
|
|
|
`tenant-*/documents/` → Standard (geen transition) of IA
|
|
na 180d
|
|
|
|
`tenant-*/documents/` (tijdelijke Expire (delete) na 7--14 dagen
|
|
previews)
|
|
-----------------------------------------------------------------------
|
|
|
|
> Lifecycle definieer je **per bucket** met **prefix filters**, zodat
|
|
> regels verschillend zijn voor `assets/` en `documents/`.
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
## 5) CORS & distributie
|
|
|
|
- **CORS**: indien browser direct upload/download doet, whitelist de
|
|
domeinen van je app (origin), en methodes `GET, PUT, POST`. Alleen
|
|
benodigde headers toestaan.
|
|
- **Publieke distributie** (indien nodig):
|
|
- Kleine public-reads via presigned URL's (aanbevolen).\
|
|
- Of activeer publieke read op een **specifieke** `public/`-prefix
|
|
(niet op de hele bucket).\
|
|
- Overweeg een CDN/edge-lag via Scaleway Edge Services voor
|
|
veelgevraagde assets.
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
## 6) Observability & beheer
|
|
|
|
- **Logging/metrics**:
|
|
- App: log alle S3 calls met `tenantId` + object key.\
|
|
- Platform: gebruik Scaleway Cockpit voor capacity & request
|
|
metrics.
|
|
- **Quota & limieten**:
|
|
- 1 bucket per omgeving beperkt "bucket-sprawl".\
|
|
- Objecten en totale grootte zijn praktisch onbeperkt; plan wel
|
|
lifecycle om groei te managen.
|
|
- **Monitoring**:
|
|
- Alerts op snelgroeiende **assets**-prefixen, high error rates
|
|
(4xx/5xx), en mislukte lifecycle-transities.
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
## 7) Operationele workflows
|
|
|
|
### Tenant aanmaken
|
|
|
|
1. DB schema provisionen.
|
|
2. (S3) **Geen nieuwe bucket**; enkel **prefix**:
|
|
`tenant-<id>/documents/` en `tenant-<id>/assets/` zijn impliciet.
|
|
3. (Optioneel) Init bestanden/placeholder objecten.
|
|
4. App-config linkt de tenant aan zijn prefix (centrale mapping).
|
|
|
|
### Upload (app -\> S3)
|
|
|
|
1. App valideert `tenantId` en datatype (`documents|assets`).\
|
|
2. App construeert **canonical path**: `tenant-<id>/<datatype>/<...>`\
|
|
3. App genereert **presigned PUT** (tijdelijk) en geeft terug aan
|
|
frontend.\
|
|
4. Frontend uploadt rechtstreeks naar S3 met presigned URL.
|
|
|
|
### Download / Serve
|
|
|
|
- Interne downloads: app signed GET of server-side stream.\
|
|
- Externe/public: **presigned GET** met korte TTL of via public-only
|
|
prefix + CDN.
|
|
|
|
### Opruimen & lifecycle
|
|
|
|
- Tijdelijke artefacten: app scheduled cleanup (of lifecycle
|
|
"Expiration").\
|
|
- Archivering: lifecycle transitions per prefix.
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
## 8) Beveiliging
|
|
|
|
- **Least privilege**: IAM-keys enkel voor het bucket van de
|
|
omgeving.\
|
|
- **Encryptie**: server-side encryption (default) volstaat vaak;
|
|
overweeg KMS als apart key-beleid nodig is.\
|
|
- **Auditing**: log alle **write**-operaties met gebruikers- en
|
|
tenantcontext.\
|
|
- **Backups**: documenten zijn de "bron"? Zo ja, S3 is primaire opslag
|
|
en RAG-index kan herbouwd worden. Anders: definieer
|
|
export/replica-strategie.
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
## 9) Migratie van MinIO → Scaleway
|
|
|
|
1. **Freeze window** (kort): pauzeer uploads of werk met **duale
|
|
write** (MinIO + S3) gedurende migratie.\
|
|
2. **Sync**: gebruik `rclone` of `mc mirror` om
|
|
`minio://bucket/tenant-*/{documents,assets}/` →
|
|
`s3://evie-<env>/tenant-*/...`.\
|
|
3. **Verifieer**: random checksums / sample reads per tenant.\
|
|
4. **Switch**: zet `S3_ENDPOINT` en keys naar Scaleway; laat nieuwe
|
|
writes enkel naar S3 gaan.\
|
|
5. **Decom**: na grace-periode MinIO uitfaseren.
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
## 10) Checklist (TL;DR)
|
|
|
|
- [ ] Buckets: `evie-staging`, `evie-prod`.\
|
|
- [ ] Prefix: `tenant-<id>/{documents,assets}/`.\
|
|
- [ ] IAM: 1 Application per omgeving; keys in k8s Secret.\
|
|
- [ ] Policy: alleen app-toegang; app dwingt prefix-scope per tenant
|
|
af.\
|
|
- [ ] Lifecycle: assets sneller koud, docs langer.\
|
|
- [ ] CORS: alleen noodzakelijke origins/methods.\
|
|
- [ ] Presigned URLs voor browser interacties.\
|
|
- [ ] Logging/metrics/alerts ingericht.\
|
|
- [ ] Migratiepad van MinIO uitgewerkt en getest.
|