Skip to content

feat: Removed SQL Lite for Valkey storage for server scalability. Perfomed full UI security review and addressed findings#69

Merged
tonedefdev merged 11 commits into
mainfrom
fix/stats-db-as-crd
Jun 1, 2026
Merged

feat: Removed SQL Lite for Valkey storage for server scalability. Perfomed full UI security review and addressed findings#69
tonedefdev merged 11 commits into
mainfrom
fix/stats-db-as-crd

Conversation

@tonedefdev

@tonedefdev tonedefdev commented May 31, 2026

Copy link
Copy Markdown
Owner

Overview

This PR replaces the SQLite-backed statistics store with Valkey (Redis-compatible) for horizontal scalability, migrates the Valkey deployment to the official valkey-io/valkey-helm subchart, and performs a complete first-ever security review of the UI service.


Changes

Stats store: SQLite → Valkey

  • Removed services/server/stats_db.go and stats_db_test.go (316 + 126 lines of SQLite implementation)
  • Added services/server/stats_valkey.go and stats_valkey_test.go — full Valkey-backed stats implementation with connection pooling, pipeline support, and test coverage
  • Updated services/server/main.go, ui_browse.go, ui_stats.go, storage.go, types.go to wire the new stats backend
  • Removed chart/opendepot/templates/server-stats-pvc.yaml — PVC no longer needed without SQLite
  • Updated e2e tests in services/server/test/e2e/e2e_test.go to cover the Valkey stats path

Helm chart: Valkey subchart migration

  • Replaced charts/dex-0.24.0.tgzdex-0.24.1.tgz (patch update)
  • Added charts/valkey-0.9.4.tgz — official valkey-io/valkey-helm subchart (replaces inline deployment)
  • Updated chart/opendepot/Chart.yaml and Chart.lock for new dependencies
  • Updated chart/opendepot/values.yaml with Valkey subchart configuration including opt-in ACL auth and image tag pinned to "8" (LTS)
  • Updated chart/opendepot/templates/server-deployment.yaml for new Valkey connection env vars
  • Scoped Valkey RBAC and resource limits per security review

UI security review (first-ever)

All findings from the full review of services/ui/ are resolved in this PR.

Image CVEs (32 fixed — 2 CRITICAL, 30 HIGH):

  • Added apk upgrade --no-cache in Dockerfile runner stage — resolves CVEs in libcrypto3/libssl3, musl, zlib, libpng, libxml2, libexpat, nghttp2-libs

NGINX hardening (services/ui/nginx.conf + chart/opendepot/templates/ui-configmap.yaml):

  • Added client_max_body_size 10m to prevent large-upload DoS
  • Replaced $http_host with $host by default to prevent Host header injection
  • Added ui.nginx.preserveHostPort flag (default: false) — set to true in local dev/e2e targets where opendepot.localtest.me:PORT requires the port in the Host header
  • Added HSTS header (Strict-Transport-Security) when server.tls.enabled=true
  • Added justification comment above proxy_ssl_verify off (self-signed cert path)

Session hardening (chart/opendepot/templates/ui-deployment.yaml):

  • ui.sessionPasswordSecretName now enforced at helm install time via required — prevents silently broken deployments with no encryption key

Next.js binding (services/ui/entrypoint.sh):

  • Bind to 127.0.0.1 instead of 0.0.0.0 — prevents in-cluster workloads from bypassing NGINX security headers by hitting port 3000 directly

Sidebar component (services/ui/src/components/Sidebar.tsx):

  • Removed undocumented NEXT_PUBLIC_API_BASE_URL — hardcoded relative URL prevents accidental internal hostname exposure in the browser bundle

Trivy suppressions (.trivyignore)

Security agent (.github/agents/security-review.agent.md)

  • Expanded coverage from Go/Helm/K8s only to include TypeScript/React, NGINX, Valkey, iron-session, GPG signing, and cloud storage credentials
  • Added yarn audit step, TypeScript-specific checks, NGINX review checklist, and GitHub Issue policy for unfixable CVEs

Documentation

  • Updated docs/getting-started/installation.md, docs/guides/migration.md, docs/guides/registry-explorer.md, docs/helm-chart.md, docs/reference/api.md to reflect Valkey subchart, new values, and UI changes
  • Updated overrides/main.html to reflect current chart version

Scan Results

Scan Result
trivy image ghcr.io/tonedefdev/opendepot/ui:dev ✅ 0 CRITICAL, 0 HIGH
yarn npm audit --severity high ✅ Clean
trivy config chart/opendepot/ ✅ Clean
trivy fs --scanners secret,misconfig services/ui/ ✅ Clean

tonedefdev added 11 commits May 31, 2026 13:02
- Replace custom splitN/indexOf helpers with strings.SplitN
- Restore nil guard for mostDownloaded in ui_stats.go after error
- Add readinessProbe (valkey-cli ping) to valkey-deployment.yaml
- Remove out-of-scope pkg/registry line from services/version/go.mod
- Add stats smoke e2e test: Module CR + Version CR download + totalDownloads/mostDownloaded assertions
- Run go mod tidy to move go-redis/v9 and miniredis/v2 to direct require block
- Add browse resources assertion to smoke test: assert totalDownloads >= 1 via /opendepot/ui/v1/resources after download
…L auth

- Replace 4 hand-rolled Valkey templates (deployment, service, serviceaccount,
  PVC) with the official valkey-io/valkey-helm v0.9.4 subchart committed as
  chart/opendepot/charts/valkey-0.9.4.tgz
- Add fullnameOverride: valkey so the generated Service name stays 'valkey',
  preserving the existing --stats-valkey-addr flag in server-deployment.yaml
- Replace valkey.persistence.* values with subchart-native valkey.dataStorage.*
  keys in values.yaml; update all 3 e2e --set flags accordingly
- Add opt-in ACL password authentication:
  - values.yaml: valkey.auth.{enabled,usersExistingSecret,aclUsers} + server.stats.valkeyPasswordSecretName
  - server-deployment.yaml: conditional env block injecting OPENDEPOT_VALKEY_PASSWORD from secretKeyRef
  - services/server/main.go: redis.Options.Password from os.Getenv("OPENDEPOT_VALKEY_PASSWORD")
- Add e2e test Context 'with Valkey ACL auth enabled' in Server Authentication
  Describe: creates BYO Secret, deploys with auth flags, asserts /opendepot/ui/v1/stats returns 200
- Makefile: add chart-deps target (helm dependency update); wire into ui-setup
  and ui-setup-oidc prerequisites; remove stale server.stats.emptyDir flags
- CONTRIBUTING.md: add Chart Dependencies callout explaining make chart-deps

All 63 e2e specs pass.
- Replace valkey.persistence.* with valkey.dataStorage.* in all docs
- Add valkey.auth.{enabled,usersExistingSecret,aclUsers} and
  server.stats.valkeyPasswordSecretName rows to helm-chart.md and installation.md
- Add production security callout recommending ACL auth and ESO/Vault
- Fix registry-explorer.md YAML snippet
- Fix migration.md persistence key reference
… NGINX configmap

## Changes

### Dockerfile (services/ui/Dockerfile)
- Add `apk upgrade --no-cache` in runner stage to resolve 32 Alpine CVEs
  (2 CRITICAL, 30 HIGH) in libcrypto3/libssl3, musl, zlib, libpng,
  libxml2, libexpat, and nghttp2-libs

### Entrypoint (services/ui/entrypoint.sh)
- Bind Next.js standalone server to 127.0.0.1 instead of 0.0.0.0
  to prevent in-cluster workloads from bypassing NGINX security headers

### NGINX (services/ui/nginx.conf + chart/opendepot/templates/ui-configmap.yaml)
- Add `client_max_body_size 10m` to prevent large-upload DoS
- Replace `$http_host` with `$host` by default to prevent Host header
  injection; new `ui.nginx.preserveHostPort` flag (default: false) opts
  in to `$http_host` for local dev at non-standard ports
- Add HSTS header (`Strict-Transport-Security`) when server.tls.enabled
- Add justification comment above `proxy_ssl_verify off`

### Helm chart (chart/opendepot/templates/ui-deployment.yaml)
- Enforce `ui.sessionPasswordSecretName` at install time via Helm
  `required` — prevents silently broken deployments with no session key

### Helm values (chart/opendepot/values.yaml)
- Add `ui.nginx.preserveHostPort: false` (secure default)

### Makefile
- Set `ui.nginx.preserveHostPort=true` in `ui-deploy-anon` and full
  e2e targets where localtest.me:port requires the port in the Host header

### Sidebar component (services/ui/src/components/Sidebar.tsx)
- Remove undocumented `NEXT_PUBLIC_API_BASE_URL` variable; use hardcoded
  relative URL to prevent accidental internal hostname exposure

### Security agent (\.github/agents/security-review.agent.md)
- Expand coverage to include TypeScript/React, NGINX, Valkey, iron-session,
  GPG signing, and cloud storage credentials
@tonedefdev tonedefdev merged commit 7110c92 into main Jun 1, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant