OpenReel Video
OpenReel Video is a browser-based video editor. The HelmForge chart serves the static application with hardened runtime defaults and modern Kubernetes exposure options.
Key Features
- HelmForge-maintained
docker.io/helmforge/openreel-video:v0.5.0image - Static hosting for the upstream browser-based editor
- WebCodecs-ready deployment with writable temporary volume support
- Ingress, Gateway API through the single
gatewayvalues block, dual-stack Service fields, HPA, PDB, NetworkPolicy, and Helm tests - Non-root runtime with dropped Linux capabilities
Installation
helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install openreel-video helmforge/openreel-video --namespace openreel-video --create-namespace
helm install openreel-video oci://ghcr.io/helmforgedev/helm/openreel-video --namespace openreel-video --create-namespace
Examples
Ingress:
ingress:
enabled: true
ingressClassName: nginx
hosts:
- host: video.example.com
paths:
- path: /
pathType: Prefix
Gateway API:
gateway:
enabled: true
parentRefs:
- name: public
hostnames:
- video.example.com
Operations
The chart is stateless by default. Scale horizontally with HPA when the ingress layer can distribute requests across replicas.
Architecture
OpenReel Video is deployed as a stateless web workload. The chart is designed for browser-based editing frontends and WebCodecs-ready static hosting, so the main operational concerns are routing, cache behavior, temporary writable storage, and safe horizontal scaling.
Runtime flow:
- Ingress or Gateway API receives public HTTPS traffic.
- The Service load-balances requests across OpenReel Video pods.
- The container serves static assets and browser application code.
- Temporary files are written only to the configured
tmpVolume. - Optional HPA and PDB keep the frontend available during rollouts.
Production Values
Use multiple replicas, explicit resources, NetworkPolicy, and either Ingress or Gateway API:
replicaCount: 2
service:
ipFamilyPolicy: PreferDualStack
ipFamilies:
- IPv4
- IPv6
ingress:
enabled: true
ingressClassName: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: openreel.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: openreel-video-tls
hosts:
- openreel.example.com
networkPolicy:
enabled: true
extraEgress: []
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
ExternalName Compatibility
When the Kubernetes Service should point clients at an externally hosted OpenReel endpoint, use ExternalName and keep
Ingress/Gateway disabled:
service:
type: ExternalName
externalName: openreel-static.example.com
ingress:
enabled: false
gateway:
enabled: false
This is useful during migration from external hosting into the cluster, or when consumers need a stable Kubernetes DNS name for a service that remains outside Kubernetes.
ExternalName changes only the Service into a DNS alias. The chart still renders
its local Deployment and Helm test, but the Service no longer selects those
pods. helm test follows the alias and expects the external target to provide
OpenReel’s /healthz, landing page, and COEP response header; the test fails
when the external service does not satisfy that contract.
Gateway API
Gateway API is first-class and uses the shared HelmForge gateway shape:
gateway:
enabled: true
parentRefs:
- name: public
namespace: gateway-system
hostnames:
- openreel.example.com
path: /
pathType: PathPrefix
Scaling And Rollouts
The chart is stateless, so HPA is safe when the edge layer can distribute requests:
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 6
pdb:
enabled: true
minAvailable: 1
Keep tmpVolume.enabled=true unless your custom image does not need writable temporary storage. The root filesystem can
remain read-only while /tmp stays writable.
Security Contract
The pinned image declares user 101, exposes port 8080, and starts
unprivileged NGINX. The chart runs it with RuntimeDefault seccomp, no Service
Account token, no privilege escalation, a read-only root filesystem, and all
Linux capabilities dropped. A bounded emptyDir at /tmp is the only writable
runtime path required by the image.
The NGINX listener is fixed at 8080. Keep service.targetPort=8080; changing
the Kubernetes port value alone does not reconfigure the process and causes
probes and traffic to fail. Preserve the image’s COOP and COEP response headers
through any Ingress, Gateway, CDN, or reverse proxy.
Upgrade Compatibility
The quality update preserves the rendered workload defaults. Upgrades from
chart 1.0.4 were validated through both a normal Helm upgrade and an upgrade
with --reuse-values. Both paths preserved the image, pod and container
security contexts, /tmp volume, Service ports, and Ready replica count.
Review stored values before upgrading:
helm get values openreel-video -n openreel-video
helm upgrade openreel-video helmforge/openreel-video \
--namespace openreel-video \
--reuse-values
Validation
After deployment:
helm test openreel-video -n openreel-video
kubectl get pods -n openreel-video -l app.kubernetes.io/name=openreel-video
kubectl logs -n openreel-video deploy/openreel-video --since=10m
kubectl get events -n openreel-video --sort-by=.lastTimestamp
For public routes, validate that static assets load with the same host, scheme, and path used by the browser.
Common Issues
| Symptom | Likely Cause | Fix |
|---|---|---|
| Blank page after route exposure | Base URL or static asset path does not match the route | Check browser network errors and Gateway/Ingress path settings. |
| Pods fail with read-only filesystem errors | Application writes outside tmpVolume |
Mount an explicit writable volume for the path or fix the image. |
| HPA scales but requests still hit one pod | Edge proxy affinity or cache behavior | Review ingress/gateway load-balancing settings. |
| ExternalName has no endpoints | Expected Kubernetes behavior | Validate DNS resolution from a client pod instead of checking Endpoints. |
Values
| Parameter | Default | Description |
|---|---|---|
global |
{} |
Parent-chart and platform integration values. |
nameOverride, fullnameOverride |
"" |
Resource naming overrides. |
commonLabels |
{} |
Labels added to chart resources. |
replicaCount |
1 |
Pod count when autoscaling is disabled. |
revisionHistoryLimit |
3 |
Retained Deployment revisions. |
image.repository |
docker.io/helmforge/openreel-video |
HelmForge OpenReel Video image. |
image.tag |
v0.5.0 |
Pinned image tag. |
image.pullPolicy |
IfNotPresent |
Container image pull policy. |
imagePullSecrets |
[] |
Private registry credentials. |
serviceAccount.create |
true |
Create a dedicated ServiceAccount. |
serviceAccount.name |
"" |
Existing or generated ServiceAccount name. |
serviceAccount.annotations |
{} |
ServiceAccount annotations. |
serviceAccount.automountServiceAccountToken |
false |
Mount Kubernetes API credentials. |
service.type |
ClusterIP |
Kubernetes Service type. |
service.externalName |
"" |
Required DNS name for ExternalName mode. |
service.port |
80 |
Client-facing Service port. |
service.targetPort |
8080 |
Fixed NGINX target; keep this at 8080. |
service.annotations |
{} |
Service annotations. |
service.ipFamilyPolicy |
"" |
Optional dual-stack policy. |
service.ipFamilies |
[] |
Optional IP family list. |
ingress.enabled |
false |
Render Ingress. |
ingress.ingressClassName |
"" |
Ingress controller class. |
ingress.annotations, ingress.tls |
{}, [] |
Ingress metadata and TLS entries. |
ingress.hosts |
openreel.local |
Ingress hosts and paths. |
gateway.enabled |
false |
Render a Gateway API HTTPRoute. |
gateway.parentRefs, gateway.hostnames |
[], [] |
HTTPRoute parents and hostnames. |
gateway.path, gateway.pathType |
/, PathPrefix |
HTTPRoute path match. |
networkPolicy.enabled |
false |
Restrict ingress and deny egress by default. |
networkPolicy.ingress |
[] |
Custom inbound rules. |
networkPolicy.egress |
[] |
Custom egress rules. |
networkPolicy.extraEgress |
[] |
Additional full egress rules. |
autoscaling.enabled |
false |
Render HPA. |
autoscaling.minReplicas, maxReplicas |
1, 4 |
Autoscaling range. |
autoscaling.targetCPUUtilizationPercentage |
70 |
CPU utilization target. |
autoscaling.targetMemoryUtilizationPercentage |
80 |
Memory utilization target. |
pdb.enabled, pdb.minAvailable |
true, 1 |
Disruption protection. |
probes.liveness, probes.readiness |
enabled | /healthz probe flags, paths, and timing. |
resources |
small requests and limits | Container CPU and memory budget. |
podSecurityContext |
UID/GID 101 |
Verified non-root pod identity and seccomp. |
securityContext |
hardened | Read-only root, no escalation, drop all capabilities. |
podAnnotations, podLabels |
{}, {} |
Pod metadata. |
priorityClassName |
"" |
PriorityClass name. |
terminationGracePeriodSeconds |
30 |
Graceful shutdown period. |
nodeSelector, tolerations, affinity |
{}, [], {} |
Pod placement controls. |
topologySpreadConstraints |
[] |
Topology distribution rules. |
tmpVolume.enabled, tmpVolume.sizeLimit |
true, 64Mi |
Writable NGINX temporary volume. |
test.image |
busybox:1.37.0 |
Helm test image and pull policy. |
extraObjects |
[] |
Additional templated Kubernetes manifests. |