Encore.go backend and Vite React frontend for creating temporary File Browser viewer sessions over Kubernetes PVCs.
Do not commit local credentials or generated runtime config:
config/kubeconfig.dev.yamlconfig/kubeconfig.management.yamlconfig/viewer.yamlconfig/viewer.debug.yamlconfig/viewer.integration.yamlconfig/*.local.yaml
Use the committed templates for local files:
cp config/viewer.example.yaml config/viewer.yaml
cp config/viewer.debug.example.yaml config/viewer.debug.yaml
cp config/viewer.integration.example.yaml config/viewer.integration.yamlmake fmt
make verifyTop-level Makefile targets cover backend and frontend where both sides have a matching check. Use scoped targets when you only need one side:
make backend-verify
make web-verify
make backend-test
make web-testOptional tools used by the full plan:
make lint
make security
make build-images TAG=dev
make deploy-verifymake test-integration uses a real Kubernetes cluster and reads
debug.management_kubeconfig_path plus optional debug.forced_namespace from
config/viewer.integration.yaml. Local kubeconfigs and integration config
files are ignored by git.
This repository is configured for self-hosted Encore development without
Encore Cloud. Keep encore.app unlinked ("id": "") so Encore CLI commands
use the local app identity and do not fetch development secrets from Encore
Cloud.
make devmake dev starts the backend Encore server and the Vite frontend dev server in
parallel. The backend serves on 0.0.0.0:4000 and reads business configuration
from config/viewer.yaml. The frontend dev server receives:
VITE_API_BASE_URL="http://localhost:4000"
VITE_DEV_KUBECONFIG="$(cat ../config/kubeconfig.dev.yaml)"In Vite dev mode, VITE_API_BASE_URL takes precedence over
/runtime-config.js, so local development talks directly to the Encore server
without needing the production /api/* nginx rewrite.
Production builds reject VITE_API_BASE_URL; use runtime-config.js for
deploy-time API root overrides.
Override those defaults when needed:
make web-dev WEB_DEV_API_BASE_URL=http://localhost:4000 WEB_DEV_KUBECONFIG=../config/kubeconfig.dev.yamlUse scoped dev targets when you only need one process:
make backend-dev
make web-devUse the Makefile targets for local validation so tests run through Encore's code generation and runtime setup:
make test
make backend-test
make web-test
make test-race
make test-integrationmake test runs backend Encore tests and frontend Vitest tests. make test-race wraps backend encore test -race; Encore CLI v1.57.4 currently
crashes in its race runtime on macOS arm64, so the default make verify gate
uses make backend-test instead.
The backend config path is selected by the CONFIG environment variable. The
Makefile sets it for local Encore commands:
make dev CONFIG=config/viewer.debug.yaml
make test-integration INTEGRATION_CONFIG=config/viewer.integration.yamlFrontend commands can be reached through Makefile wrappers:
make web-install
make web-generate-api
make web-typecheck
make web-build
make web-check-css
make web-e2eFrontend VITE_* variables only affect the Vite workspace under web/.
Self-hosted runtime variables referenced by infra-config.json, such as
PROMETHEUS_REMOTE_WRITE_URL, stay separate from viewer business config.
Keep local development kubeconfigs under config/: use
config/kubeconfig.dev.yaml for frontend user authorization and
config/kubeconfig.management.yaml for backend debug/integration management
access.
All public endpoints are typed Encore APIs so OpenAPI/client generation includes request and response schemas:
encore gen client --lang=openapi --output openapi.jsonGET /metrics is the only raw endpoint. It is reserved for Prometheus text
scraping and local debugging, so it is exempt from the business endpoint schema
rule.
Application metrics use encore.dev/metrics counters. In self-hosted images,
Encore exports them according to infra-config.json, for example through the
Prometheus remote_write_url environment reference. Operation logs use
encore.dev/rlog; Encore attaches those logs to its built-in distributed traces
when log_config is set to trace in the infra config.
External distributed tracing is optional and limited to traces. It reuses the
existing operation instrumentation and wraps File Browser and Kubernetes HTTP
clients with OpenTelemetry propagation. Keep it disabled for fully local
offline development, or enable the OTLP HTTP exporter in viewer.yaml:
observability:
service_name: storage-manager-viewer
logs:
exporter: encore
level: info
traces:
exporter: otlp
endpoint: http://otel-collector:4318/v1/traces
sample_ratio: 1
batch_timeout: 5s
export_timeout: 5sEncore MCP is intentionally not configured for offline development because it requires a Cloud app id. Do not put kubeconfig, token, or cluster secrets in MCP configuration.
Build both deployable images:
make build-images TAG=devThis creates:
storage-manager-backend:devstorage-manager-web:dev
Push both images to a registry:
make push-images REGISTRY=ghcr.io IMAGE_PREFIX=owner/storage-manager TAG=devThe legacy backend-only image target remains available when needed:
make build-image IMAGE=registry.example.com/viewer-backend:devdeploy/charts/storage-manager/ is the Helm chart for self-hosted
deployment. Validate it before shipping changes:
make deploy-verifyIn Sealos-managed installs, deploy/entrypoint.sh injects install-time
HTTP/TLS settings into Helm from environment overrides and
sealos-system/sealos-config. The chart defaults intentionally omit those
cluster-specific values.
The chart derives:
- File Browser auth callback URL:
https://<web host>/internal/filebrowser-hook/verify - File Browser viewer host template:
<hostPrefix>-{{ .PodSessionID }}.<cloudDomain>
Override config.hookClientToken before exposing the service. The committed
value is a placeholder token.
Expose viewer-web as the public entrypoint. The chart renders nginx config
that serves the SPA, rewrites public /api/* requests to the backend's
unprefixed routes, and proxies /metrics plus
/internal/filebrowser-hook/verify to the internal viewer-backend service.
Use charts/storage-manager/storage-manager-values.yaml as the user-level
override entrypoint for Sealos installs. It exposes product-facing config.*
values such as config.adminUserIds, config.hookClientToken,
config.integrations.*, config.filebrowser.*, config.storageQuota.*,
config.pvcMetrics.*, config.viewer.*, config.web.*,
config.runtimeConfig.*, config.nginx.*, config.features.*, and
desktopApp.create. Use config.* for every field represented there; keep
desktopApp.create as the single Desktop App creation switch. The chart's
internal backend.*, web.*, rbac.*, and other desktopApp.* paths remain
available for low-level Helm wiring and fields outside the packaged user
surface.
The default config.web.apiBaseUrl is /api, which keeps browser API requests on
the same origin as the web app and lets the frontend service own the public
rewrite.
deploy/ is also the Sealos cluster image build context. It contains:
Kubefile, which packages cached runtime images, charts, and the install entrypoint.entrypoint.sh, which sources/root/.sealos/cloud/scripts/tools.sh, reads install-time HTTP/TLS settings fromsealos-system/sealos-config, initializes/root/.sealos/cloud/values/apps/storage-manager/with the packagedstorage-manager-values.yamlwhen that app values directory is missing, loads all*-values.yamlfiles from that app values directory, and runshelm upgrade -i ... --create-namespace. The chart does not render aNamespaceresource.charts/storage-manager/storage-manager-values.yaml, the user-level packaged values used by Sealos app installs.
The images workflow publishes:
ghcr.io/<owner>/<repo>/<repo>:<tag>for the backend runtimeghcr.io/<owner>/<repo>/<repo>-web:<tag>for the web runtimeghcr.io/<owner>/<repo>/<repo>-cluster:<tag>for the Sealos cluster image
For each cluster image build, the workflow caches runtime images with
sealos registry save --registry-dir=registry_<arch> --arch <arch> ., saves
storage-manager-cluster-<tag>-<arch>.tar.gz, generates an md5 file,
and uploads both artifacts to OSS.