From 59ec0cdf842a762f60666bb48a59e10fe7f80552 Mon Sep 17 00:00:00 2001 From: Daniel Edgar Date: Fri, 23 Jan 2026 10:33:39 -0500 Subject: [PATCH 1/7] update extended glob pattern to use regex pattern which is more portable --- contrib/docker-compose/nginx-dapi.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/docker-compose/nginx-dapi.sh b/contrib/docker-compose/nginx-dapi.sh index b8f57576..97449d13 100755 --- a/contrib/docker-compose/nginx-dapi.sh +++ b/contrib/docker-compose/nginx-dapi.sh @@ -83,7 +83,7 @@ do esac done -if [ -z "${ACTION}" ] || [[ ! "${ACTION}" == +(start|stop|build) ]] +if [ -z "${ACTION}" ] || [[ ! "${ACTION}" =~ ^(start|stop|build)$ ]] then usage fi From b4422a8a058829664d65700fce2d59014e452388 Mon Sep 17 00:00:00 2001 From: Daniel Edgar Date: Fri, 23 Jan 2026 10:55:47 -0500 Subject: [PATCH 2/7] update docker compose script to be compat with osx shell and create port override options --- contrib/docker-compose/README.md | 35 ++++++++++++++++++---- contrib/docker-compose/docker-compose.yaml | 6 ++-- contrib/docker-compose/nginx-dapi.sh | 33 ++++++++++++++++---- 3 files changed, 60 insertions(+), 14 deletions(-) diff --git a/contrib/docker-compose/README.md b/contrib/docker-compose/README.md index 30a33a72..08db8ee1 100644 --- a/contrib/docker-compose/README.md +++ b/contrib/docker-compose/README.md @@ -23,14 +23,20 @@ NGINX Declarative API - https://github.com/f5devcentral/NGINX-Declarative-API/ === Options: - -h - This help - -c [start|stop|build] - Deployment command + -h - This help + -c [start|stop|build] - Deployment command + -a - Custom port for NGINX Declarative API (default: 5000) + -d - Custom port for Developer Portal (default: 5001) + -r - Custom port for Redis (default: 6379) === Examples: - Deploy NGINX Declarative API: ./nginx-dapi.sh -c start - Remove NGINX Declarative API: ./nginx-dapi.sh -c stop - Build docker images: ./nginx-dapi.sh -c build + Deploy NGINX Declarative API: ./nginx-dapi.sh -c start + Deploy with custom Declarative API port: ./nginx-dapi.sh -c start -a 8080 + Deploy with custom DevPortal port: ./nginx-dapi.sh -c start -d 8081 + Deploy with all custom ports: ./nginx-dapi.sh -c start -a 8080 -d 8081 -r 6380 + Remove NGINX Declarative API: ./nginx-dapi.sh -c stop + Build docker images: ./nginx-dapi.sh -c build ``` @@ -60,6 +66,25 @@ Starting: ```commandline $ ./nginx-dapi.sh -c start -> Deploying NGINX Declarative API + NGINX Declarative API port: 5000 + Developer Portal port: 5001 + Redis port: 6379 +[+] Building 0.0s (0/0) +[+] Running 4/4 + ✔ Network nginx-dapi_dapi-network Created + ✔ Container redis Started + ✔ Container devportal Started + ✔ Container nginx-dapi Started +``` + +Starting with custom ports (useful when default ports are in use): + +```commandline +$ ./nginx-dapi.sh -c start -a 8080 -d 8081 -r 6380 +-> Deploying NGINX Declarative API + NGINX Declarative API port: 8080 + Developer Portal port: 8081 + Redis port: 6380 [+] Building 0.0s (0/0) [+] Running 4/4 ✔ Network nginx-dapi_dapi-network Created diff --git a/contrib/docker-compose/docker-compose.yaml b/contrib/docker-compose/docker-compose.yaml index 8416e2d8..ad87ca9d 100644 --- a/contrib/docker-compose/docker-compose.yaml +++ b/contrib/docker-compose/docker-compose.yaml @@ -7,7 +7,7 @@ services: container_name: "redis" restart: always ports: - - "6379:6379" + - "${REDIS_PORT:-6379}:6379" networks: - dapi-network volumes: @@ -22,7 +22,7 @@ services: container_name: "devportal" restart: always ports: - - "5001:5000" + - "${DEVPORTAL_PORT:-5001}:5000" networks: - dapi-network @@ -37,7 +37,7 @@ services: depends_on: - redis ports: - - "5000:5000" + - "${DAPI_PORT:-5000}:5000" networks: - dapi-network diff --git a/contrib/docker-compose/nginx-dapi.sh b/contrib/docker-compose/nginx-dapi.sh index 97449d13..a06061dd 100755 --- a/contrib/docker-compose/nginx-dapi.sh +++ b/contrib/docker-compose/nginx-dapi.sh @@ -9,12 +9,18 @@ This script is used to deploy/undeploy NGINX Declarative API using docker-compos === Usage:\n\n $0 [options]\n\n === Options:\n\n --h\t\t\t- This help\n --c [start|stop|build]\t- Deployment command\n\n +-h\t\t\t\t- This help\n +-c [start|stop|build]\t\t- Deployment command\n +-a \t\t\t- Custom port for NGINX Declarative API (default: 5000)\n +-d \t\t\t- Custom port for Developer Portal (default: 5001)\n +-r \t\t\t- Custom port for Redis (default: 6379)\n\n === Examples:\n\n -Deploy NGINX Declarative API:\t$0 -c start\n -Remove NGINX Declarative API:\t$0 -c stop\n -Build docker images:\t\t$0 -c build\n +Deploy NGINX Declarative API:\t\t\t$0 -c start\n +Deploy with custom Declarative API port:\t$0 -c start -a 8080\n +Deploy with custom DevPortal port:\t\t$0 -c start -d 8081\n +Deploy with all custom ports:\t\t\t$0 -c start -a 8080 -d 8081 -r 6380\n +Remove NGINX Declarative API:\t\t\t$0 -c stop\n +Build docker images:\t\t\t\t$0 -c build\n " echo -e $BANNER 2>&1 @@ -30,8 +36,14 @@ nginx_dapi_start() { USERNAME=`whoami` export USERID=`id -u $USERNAME` export USERGROUP=`id -g $USERNAME` +export DAPI_PORT=${DAPI_PORT:-5000} +export DEVPORTAL_PORT=${DEVPORTAL_PORT:-5001} +export REDIS_PORT=${REDIS_PORT:-6379} echo "-> Deploying NGINX Declarative API" +echo " NGINX Declarative API port: $DAPI_PORT" +echo " Developer Portal port: $DEVPORTAL_PORT" +echo " Redis port: $REDIS_PORT" COMPOSE_HTTP_TIMEOUT=240 docker-compose -p $PROJECT_NAME -f $DOCKER_COMPOSE_YAML up -d --remove-orphans } @@ -71,7 +83,7 @@ COMPOSE_HTTP_TIMEOUT=240 docker-compose -p $PROJECT_NAME -f $DOCKER_COMPOSE_YAML DOCKER_COMPOSE_YAML="docker-compose.yaml" PROJECT_NAME="nginx-dapi" -while getopts 'hc:' OPTION +while getopts 'hc:a:d:r:' OPTION do case "$OPTION" in h) @@ -80,6 +92,15 @@ do c) ACTION=$OPTARG ;; + a) + DAPI_PORT=$OPTARG + ;; + d) + DEVPORTAL_PORT=$OPTARG + ;; + r) + REDIS_PORT=$OPTARG + ;; esac done From d366d97e197120009e66249c208d9f9708b49378 Mon Sep 17 00:00:00 2001 From: Daniel Edgar Date: Mon, 2 Mar 2026 07:59:36 -0500 Subject: [PATCH 3/7] Fix issue 99 --- webui/package-lock.json | 7 +++++++ webui/package.json | 1 + 2 files changed, 8 insertions(+) diff --git a/webui/package-lock.json b/webui/package-lock.json index 87f508ce..8f4f7b13 100644 --- a/webui/package-lock.json +++ b/webui/package-lock.json @@ -12,6 +12,7 @@ "@rjsf/core": "6.3.1", "@rjsf/utils": "6.3.1", "@rjsf/validator-ajv8": "6.3.1", + "@types/trusted-types": "2.0.7", "lucide-react": "^0.460.0", "react": "^19.2.0", "react-dom": "^19.2.0", @@ -1830,6 +1831,12 @@ "@types/react": "^19.2.0" } }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "7.18.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", diff --git a/webui/package.json b/webui/package.json index 9c5aef21..8cb51aca 100644 --- a/webui/package.json +++ b/webui/package.json @@ -19,6 +19,7 @@ "@rjsf/core": "6.3.1", "@rjsf/utils": "6.3.1", "@rjsf/validator-ajv8": "6.3.1", + "@types/trusted-types": "2.0.7", "lucide-react": "^0.460.0", "react": "^19.2.0", "react-dom": "^19.2.0", From 39a700165da531f43b004bb839a47cc388c83aa3 Mon Sep 17 00:00:00 2001 From: Daniel Edgar Date: Mon, 2 Mar 2026 14:07:17 -0500 Subject: [PATCH 4/7] add github actions for ci --- .github/workflows/README.md | 104 +++++++++++++++++++++++ .github/workflows/build-containers.yml | 106 +++++++++++++++++++++++ .github/workflows/build-pr.yml | 65 ++++++++++++++ .github/workflows/build-release.yml | 113 +++++++++++++++++++++++++ 4 files changed, 388 insertions(+) create mode 100644 .github/workflows/README.md create mode 100644 .github/workflows/build-containers.yml create mode 100644 .github/workflows/build-pr.yml create mode 100644 .github/workflows/build-release.yml diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 00000000..daa743cc --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,104 @@ +# GitHub Actions Workflows + +This directory contains GitHub Actions workflows for building and publishing container images to GitHub Container Registry (ghcr.io). + +## Workflows + +### build-containers.yml + +**Trigger:** Push to `main` branch +**Purpose:** Builds and publishes all container images with `latest` and SHA tags +**Images:** + +- `ghcr.io//:latest` - Main API container +- `ghcr.io//-webui:latest` - Web UI container +- `ghcr.io//-devportal:latest` - DevPortal container + +### build-pr.yml + +**Trigger:** Pull requests to `main` branch +**Purpose:** Builds all container images (without publishing) to verify they build correctly +**Images:** Same as above but not pushed to registry + +### build-release.yml + +**Trigger:** Git tags matching `v*.*.*` pattern (e.g., `v1.0.0`) +**Purpose:** Builds and publishes release versions with semantic versioning tags +**Images:** Same containers as above but tagged with: + +- Full version (e.g., `v1.2.3`) +- Major.minor version (e.g., `v1.2`) +- Major version (e.g., `v1`) +- SHA commit hash + +## Container Images + +### Main API (`Dockerfile`) + +The core NGINX Declarative API service built with Python and Alpine Linux. + +### Web UI (`webui/Dockerfile`) + +The web interface for managing the NGINX Declarative API, built with Node.js and served by NGINX. + +### DevPortal (`contrib/devportal/redocly/Dockerfile`) + +The Redocly-based developer portal for API documentation. + +## Usage + +### Pushing to Main Branch + +```bash +git push origin main +``` + +This triggers `build-containers.yml` and publishes images with the `latest` tag. + +### Creating a Release + +```bash +git tag v1.0.0 +git push origin v1.0.0 +``` + +This triggers `build-release.yml` and publishes versioned images. + +### Pull Requests + +When creating a pull request to `main`, the `build-pr.yml` workflow automatically runs to verify all containers build successfully. + +## Permissions + +The workflows require the following GitHub token permissions: + +- `contents: read` - To checkout the repository +- `packages: write` - To publish to GitHub Container Registry + +These are automatically provided by the `GITHUB_TOKEN` secret. + +## Registry Access + +Published images are available at: + +``` +ghcr.io// +ghcr.io//-webui +ghcr.io//-devportal +``` + +To pull images: + +```bash +docker pull ghcr.io//:latest +docker pull ghcr.io//-webui:latest +docker pull ghcr.io//-devportal:latest +``` + +For versioned releases: + +```bash +docker pull ghcr.io//:v1.0.0 +docker pull ghcr.io//-webui:v1.0.0 +docker pull ghcr.io//-devportal:v1.0.0 +``` diff --git a/.github/workflows/build-containers.yml b/.github/workflows/build-containers.yml new file mode 100644 index 00000000..60881864 --- /dev/null +++ b/.github/workflows/build-containers.yml @@ -0,0 +1,106 @@ +name: Create and publish container images + +on: + push: + branches: ["main"] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + test: + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 'lts/*' + cache: 'npm' + cache-dependency-path: webui/package-lock.json + + - name: Install WebUI dependencies + working-directory: webui + run: npm ci + + - name: Run WebUI tests + working-directory: webui + run: npm test -- --run + + build-and-push-images: + runs-on: ubuntu-latest + needs: test + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to the Container registry + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Build and push dapi container (main Dockerfile) + - name: Extract metadata (tags, labels) for dapi container + id: meta-dapi + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=sha + type=raw,value=latest + + - name: Build and push dapi image + uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 + with: + context: . + push: true + tags: ${{ steps.meta-dapi.outputs.tags }} + labels: ${{ steps.meta-dapi.outputs.labels }} + + # Build and push WebUI container + - name: Extract metadata (tags, labels) for WebUI container + id: meta-webui + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-webui + tags: | + type=sha + type=raw,value=latest + + - name: Build and push WebUI image + uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 + with: + context: webui/. + push: true + tags: ${{ steps.meta-webui.outputs.tags }} + labels: ${{ steps.meta-webui.outputs.labels }} + + # Build and push DevPortal container + - name: Extract metadata (tags, labels) for DevPortal container + id: meta-devportal + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-devportal + tags: | + type=sha + type=raw,value=latest + + - name: Build and push DevPortal image + uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 + with: + context: contrib/devportal/redocly/. + push: true + tags: ${{ steps.meta-devportal.outputs.tags }} + labels: ${{ steps.meta-devportal.outputs.labels }} diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml new file mode 100644 index 00000000..5fdcff9f --- /dev/null +++ b/.github/workflows/build-pr.yml @@ -0,0 +1,65 @@ +name: Build container images (PR) + +on: + pull_request: + branches: ["main"] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + test: + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 'lts/*' + cache: 'npm' + cache-dependency-path: webui/package-lock.json + + - name: Install WebUI dependencies + working-directory: webui + run: npm ci + + - name: Run WebUI tests + working-directory: webui + run: npm test -- --run + + build-images: + runs-on: ubuntu-latest + needs: test + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Build dapi container (main Dockerfile) + - name: Build dapi image + uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 + with: + context: . + push: false + + # Build WebUI container + - name: Build WebUI image + uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 + with: + context: webui/. + push: false + + # Build DevPortal container + - name: Build DevPortal image + uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 + with: + context: contrib/devportal/redocly/. + push: false diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml new file mode 100644 index 00000000..752b4641 --- /dev/null +++ b/.github/workflows/build-release.yml @@ -0,0 +1,113 @@ +name: Create and publish release container images + +on: + push: + tags: + - 'v*.*.*' + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + test: + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 'lts/*' + cache: 'npm' + cache-dependency-path: webui/package-lock.json + + - name: Install WebUI dependencies + working-directory: webui + run: npm ci + + - name: Run WebUI tests + working-directory: webui + run: npm test -- --run + + build-and-push-images: + runs-on: ubuntu-latest + needs: test + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to the Container registry + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Build and push dapi container (main Dockerfile) + - name: Extract metadata (tags, labels) for dapi container + id: meta-dapi + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha + + - name: Build and push dapi image + uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 + with: + context: . + push: true + tags: ${{ steps.meta-dapi.outputs.tags }} + labels: ${{ steps.meta-dapi.outputs.labels }} + + # Build and push WebUI container + - name: Extract metadata (tags, labels) for WebUI container + id: meta-webui + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-webui + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha + + - name: Build and push WebUI image + uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 + with: + context: webui/. + push: true + tags: ${{ steps.meta-webui.outputs.tags }} + labels: ${{ steps.meta-webui.outputs.labels }} + + # Build and push DevPortal container + - name: Extract metadata (tags, labels) for DevPortal container + id: meta-devportal + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-devportal + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha + + - name: Build and push DevPortal image + uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 + with: + context: contrib/devportal/redocly/. + push: true + tags: ${{ steps.meta-devportal.outputs.tags }} + labels: ${{ steps.meta-devportal.outputs.labels }} From 703e48c77d70cf45a5d9baf91dc284030a656c47 Mon Sep 17 00:00:00 2001 From: Daniel Edgar Date: Mon, 2 Mar 2026 16:28:50 -0500 Subject: [PATCH 5/7] update webui to use unpriv image and new port/mounts --- contrib/docker-compose/docker-compose.yaml | 2 +- .../templates/deployment-webui.yaml | 15 +++++++++++---- contrib/helm/nginx-declarative-api/values.yaml | 9 ++++++--- webui/Dockerfile | 8 +++++--- webui/nginx.conf | 2 +- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/contrib/docker-compose/docker-compose.yaml b/contrib/docker-compose/docker-compose.yaml index 4c0ae724..9f66f4e7 100644 --- a/contrib/docker-compose/docker-compose.yaml +++ b/contrib/docker-compose/docker-compose.yaml @@ -53,7 +53,7 @@ services: environment: - DAPI_PORT=5000 ports: - - "${WEBUI_PORT:-3000}:80" + - "${WEBUI_PORT:-3000}:8080" networks: - dapi-network diff --git a/contrib/helm/nginx-declarative-api/templates/deployment-webui.yaml b/contrib/helm/nginx-declarative-api/templates/deployment-webui.yaml index ec90b29b..f2f2762a 100644 --- a/contrib/helm/nginx-declarative-api/templates/deployment-webui.yaml +++ b/contrib/helm/nginx-declarative-api/templates/deployment-webui.yaml @@ -57,8 +57,14 @@ spec: {{- toYaml .Values.webui.resources | nindent 12 }} securityContext: {{- toYaml .Values.webui.containerSecurityContext | nindent 12 }} - {{- if or .Values.webui.persistence.enabled .Values.webui.extraVolumeMounts }} volumeMounts: + # nginx requires writable temp dirs. emptyDir mounts ensure chown is + # never needed, allowing the pod to run as a non-root user under any + # cluster admission policy. + - name: nginx-cache + mountPath: /var/cache/nginx + - name: nginx-run + mountPath: /var/run {{- if .Values.webui.persistence.enabled }} - name: data mountPath: /data @@ -66,9 +72,11 @@ spec: {{- with .Values.webui.extraVolumeMounts }} {{- toYaml . | nindent 12 }} {{- end }} - {{- end }} - {{- if or .Values.webui.persistence.enabled .Values.webui.extraVolumes }} volumes: + - name: nginx-cache + emptyDir: {} + - name: nginx-run + emptyDir: {} {{- if .Values.webui.persistence.enabled }} - name: data persistentVolumeClaim: @@ -77,7 +85,6 @@ spec: {{- with .Values.webui.extraVolumes }} {{- toYaml . | nindent 8 }} {{- end }} - {{- end }} {{- with .Values.webui.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} diff --git a/contrib/helm/nginx-declarative-api/values.yaml b/contrib/helm/nginx-declarative-api/values.yaml index 67ad67c5..dfe178e2 100644 --- a/contrib/helm/nginx-declarative-api/values.yaml +++ b/contrib/helm/nginx-declarative-api/values.yaml @@ -327,8 +327,8 @@ webui: replicaCount: 1 - # The webui container listens on port 80 (nginx serving the React build). - containerPort: 80 + # The webui container listens on port 8080 (nginx-unprivileged, non-root). + containerPort: 8080 service: type: ClusterIP @@ -379,7 +379,10 @@ webui: affinity: {} podSecurityContext: - runAsNonRoot: false + runAsNonRoot: true + # uid 101 matches the nginx user in nginxinc/nginx-unprivileged + runAsUser: 101 + fsGroup: 101 containerSecurityContext: allowPrivilegeEscalation: false diff --git a/webui/Dockerfile b/webui/Dockerfile index 43bba8ef..d14a454b 100644 --- a/webui/Dockerfile +++ b/webui/Dockerfile @@ -16,7 +16,9 @@ COPY . . RUN npm run build # Production stage -FROM nginx:alpine +# nginx-unprivileged runs as the nginx user (uid 101) with pre-configured +# cache directory permissions, avoiding chown failures in non-root Kubernetes pods. +FROM nginxinc/nginx-unprivileged:alpine # Copy custom nginx config COPY nginx.conf /etc/nginx/conf.d/default.conf @@ -28,8 +30,8 @@ RUN chmod +x /docker-entrypoint.sh # Copy built files from build stage COPY --from=build /app/dist /usr/share/nginx/html -# Expose port 80 -EXPOSE 80 +# Expose port 8080 (nginx-unprivileged listens on 8080 by default) +EXPOSE 8080 # Set environment variable for DAPI port (can be overridden) ENV DAPI_PORT=5000 diff --git a/webui/nginx.conf b/webui/nginx.conf index 18eaeaeb..77bf0207 100644 --- a/webui/nginx.conf +++ b/webui/nginx.conf @@ -1,5 +1,5 @@ server { - listen 80; + listen 8080; server_name localhost; root /usr/share/nginx/html; index index.html; From 2c95f93442eb6c19866f1cd0c1b66a57a808fac7 Mon Sep 17 00:00:00 2001 From: Daniel Edgar Date: Mon, 2 Mar 2026 16:37:34 -0500 Subject: [PATCH 6/7] update entrypoint ownership --- webui/Dockerfile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/webui/Dockerfile b/webui/Dockerfile index d14a454b..ee9be57e 100644 --- a/webui/Dockerfile +++ b/webui/Dockerfile @@ -1,5 +1,5 @@ # Build stage -FROM node:24-alpine as build +FROM node:24-alpine AS build WORKDIR /app @@ -24,8 +24,7 @@ FROM nginxinc/nginx-unprivileged:alpine COPY nginx.conf /etc/nginx/conf.d/default.conf # Copy entrypoint script -COPY docker-entrypoint.sh /docker-entrypoint.sh -RUN chmod +x /docker-entrypoint.sh +COPY --chmod=755 docker-entrypoint.sh /docker-entrypoint.sh # Copy built files from build stage COPY --from=build /app/dist /usr/share/nginx/html From 310f71480723fd4559681707632be669bdd7dce8 Mon Sep 17 00:00:00 2001 From: Daniel Edgar Date: Mon, 23 Mar 2026 16:15:08 +0100 Subject: [PATCH 7/7] add weekly dependabot action for all packages in solution --- .github/dependabot.yml | 55 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..48c74442 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,55 @@ +version: 2 +updates: + # Python dependencies + - package-ecosystem: "pip" + directory: "/src" + schedule: + interval: "weekly" + labels: + - "dependencies" + - "python" + + # npm dependencies (Web UI) + - package-ecosystem: "npm" + directory: "/webui" + schedule: + interval: "weekly" + labels: + - "dependencies" + - "javascript" + + # Root Dockerfile + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "weekly" + labels: + - "dependencies" + - "docker" + + # Web UI Dockerfile + - package-ecosystem: "docker" + directory: "/webui" + schedule: + interval: "weekly" + labels: + - "dependencies" + - "docker" + + # GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + labels: + - "dependencies" + - "github-actions" + + # Helm chart + - package-ecosystem: "helm" + directory: "/contrib/helm/nginx-declarative-api" + schedule: + interval: "weekly" + labels: + - "dependencies" + - "helm"