From 527bdb3f667ce0004b916833880ecc0aaacbdb00 Mon Sep 17 00:00:00 2001 From: Andrii Kostenko Date: Sun, 22 Feb 2026 14:23:40 +0000 Subject: [PATCH 1/2] Harden deployment security context - Pod: runAsNonRoot, seccomp RuntimeDefault profile - Container: read-only root filesystem, drop all capabilities, no privilege escalation - Add emptyDir volumes for writable paths needed by nginx and node (/tmp, /var/lib/nginx, /var/log/nginx, /run, node_modules/.cache) - Fix strategy placement (was incorrectly nested under pod spec) Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 80 ++++++++++++++++++++ charts/rocketadmin/templates/deployment.yaml | 49 ++++++++---- charts/rocketadmin/values.yaml | 19 +++-- 3 files changed, 124 insertions(+), 24 deletions(-) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..46b16ed --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,80 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Helm chart for deploying **RocketAdmin** (a web-based database administration tool) on Kubernetes. The chart is published to https://charts.rocketadmin.com via GitHub Pages. + +- **Chart path:** `charts/rocketadmin/` +- **Current chart version:** defined in `charts/rocketadmin/Chart.yaml` +- **App version:** tracks upstream `rocketadmin/rocketadmin` Docker image tags + +## Common Commands + +```bash +# Lint the chart +helm lint ./charts/rocketadmin + +# Render templates locally (debug) +helm template my-release ./charts/rocketadmin + +# Render with custom values +helm template my-release ./charts/rocketadmin -f charts/rocketadmin/ci/rocketadmin-values.yaml + +# Dry-run install (validates against K8s API) +helm install --dry-run --debug my-release ./charts/rocketadmin + +# Update dependencies (PostgreSQL subchart) +helm dependency update ./charts/rocketadmin + +# Run Helm test (requires a running release) +helm test my-release +``` + +CI uses [chart-testing](https://github.com/helm/chart-testing) (`ct lint` and `ct install`) with a kind cluster. Test values live in `charts/rocketadmin/ci/rocketadmin-values.yaml`. + +## Architecture + +### Storage Modes (mutually exclusive) + +- **pglite (default since v1.0):** Embedded PostgreSQL using a PVC (10Gi). Forces `Recreate` deployment strategy since pglite is single-writer. Storage mounts at `/app/backend/dist/pglite-storage`. +- **PostgreSQL subchart:** Optional Bitnami PostgreSQL (`postgresql.enabled: true`). Uses the bundled `charts/postgresql-15.5.20.tgz`. + +### Secret Management + +`templates/secret.yaml` auto-generates JWT_SECRET and PRIVATE_KEY (65-char random strings) on first install. The `gen.secret` helper in `_helpers.tpl` uses Helm `lookup` to preserve existing secrets across upgrades — never regenerates if the secret already exists. + +A separate `postgres-secret.yaml` handles PostgreSQL credentials when that subchart is enabled. + +### Key Templates + +| Template | Conditional on | +|---|---| +| `deployment.yaml` | pglite volumes/strategy when `pglite.enabled` | +| `pvc.yaml` | `pglite.enabled` | +| `postgres-secret.yaml` | `postgresql.enabled` | +| `ingress.yaml` | `ingress.enabled` | +| `hpa.yaml` | `autoscaling.enabled` | +| `secret.yaml` | always | +| `service.yaml` | always | +| `serviceaccount.yaml` | `serviceAccount.create` | + +### Template Helpers (`_helpers.tpl`) + +Key helpers beyond standard Helm boilerplate: +- `app-domain-address` — resolves domain from `hostname`, first ingress host, or falls back to service name +- `gen.secret` — generates random secret only if not already present in cluster (lookup-based) +- `rocketadmin.dbPassword` — random 16-char password for PostgreSQL + +## CI/CD + +Three GitHub Actions workflows in `.github/workflows/`: + +1. **test.yaml** — Runs on PRs. Lints with `ct lint`, installs in a kind cluster with `ct install`. +2. **release.yaml** — Runs on push to main. Packages and publishes the chart via `chart-releaser-action`. +3. **update-chart-version.yml** — Daily cron (9 AM UTC). Checks upstream RocketAdmin releases, bumps `appVersion` and chart patch version, creates a PR automatically. + +## Versioning Convention + +Chart version and appVersion are independent. Chart patch version increments when appVersion changes (automated via `update-chart-version.yml`). PRs follow the pattern: "Update RocketAdmin to {version}". diff --git a/charts/rocketadmin/templates/deployment.yaml b/charts/rocketadmin/templates/deployment.yaml index 67914f4..464f29c 100644 --- a/charts/rocketadmin/templates/deployment.yaml +++ b/charts/rocketadmin/templates/deployment.yaml @@ -8,6 +8,10 @@ spec: {{- if not .Values.autoscaling.enabled }} replicas: {{ .Values.replicaCount }} {{- end }} + {{- if .Values.pglite.enabled }} + strategy: + type: Recreate + {{- end }} selector: matchLabels: {{- include "rocketadmin.selectorLabels" . | nindent 6 }} @@ -27,17 +31,23 @@ spec: serviceAccountName: {{ include "rocketadmin.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} -{{- if .Values.pglite.enabled }} - strategy: - type: Recreate volumes: - - name: rocketadmin-data - persistentVolumeClaim: - claimName: rocketadmin-data-pvc - - name: tmp - emptyDir: - medium: Memory - sizeLimit: 64Mi + - name: tmp + emptyDir: + medium: Memory + sizeLimit: 64Mi + - name: nginx-cache + emptyDir: {} + - name: nginx-log + emptyDir: {} + - name: nginx-run + emptyDir: {} + - name: node-cache + emptyDir: {} +{{- if .Values.pglite.enabled }} + - name: rocketadmin-data + persistentVolumeClaim: + claimName: rocketadmin-data-pvc {{- end }} containers: - name: {{ .Chart.Name }} @@ -52,13 +62,20 @@ spec: - name: http containerPort: 8080 protocol: TCP -{{- if .Values.pglite.enabled }} volumeMounts: - - name: rocketadmin-data - mountPath: /app/backend/dist/pglite-storage - - mountPath: /tmp - name: tmp - subPath: tmp + - name: tmp + mountPath: /tmp + - name: nginx-cache + mountPath: /var/lib/nginx + - name: nginx-log + mountPath: /var/log/nginx + - name: nginx-run + mountPath: /run + - name: node-cache + mountPath: /app/backend/node_modules/.cache +{{- if .Values.pglite.enabled }} + - name: rocketadmin-data + mountPath: /app/backend/dist/pglite-storage {{- end }} livenessProbe: httpGet: diff --git a/charts/rocketadmin/values.yaml b/charts/rocketadmin/values.yaml index c825fa5..6551b3f 100644 --- a/charts/rocketadmin/values.yaml +++ b/charts/rocketadmin/values.yaml @@ -39,15 +39,18 @@ serviceAccount: podAnnotations: {} podSecurityContext: + runAsNonRoot: true fsGroup: 999 - -securityContext: {} - # capabilities: - # drop: - # - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + +securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: + - ALL service: type: ClusterIP From 46576b7a4d7d37c26b54982c057e3b786f90b026 Mon Sep 17 00:00:00 2001 From: Andrii Kostenko Date: Sun, 22 Feb 2026 14:30:19 +0000 Subject: [PATCH 2/2] Bump chart version to 1.0.33 Co-Authored-By: Claude Opus 4.6 --- charts/rocketadmin/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/rocketadmin/Chart.yaml b/charts/rocketadmin/Chart.yaml index 4ca0e63..3a37e07 100644 --- a/charts/rocketadmin/Chart.yaml +++ b/charts/rocketadmin/Chart.yaml @@ -3,7 +3,7 @@ name: rocketadmin description: Rocketadmin is a web-based application for creating admin panels for your projects. type: application icon: https://avatars.githubusercontent.com/u/84132223 -version: 1.0.32 +version: 1.0.33 home: https://rocketadmin.com sources: - https://github.com/rocket-admin/rocketadmin