From 0fdf44312fd9660e5de286e26292f0cf4343902c Mon Sep 17 00:00:00 2001 From: Matt Jenkinson <75292329+mattdjenkinson@users.noreply.github.com> Date: Thu, 19 Mar 2026 15:29:46 +0000 Subject: [PATCH] chore: add nextjs action encryption key --- .github/workflows/build-authui.yml | 1 + Makefile | 1 + README.md | 19 +++++++++++++++++++ docker-bake.hcl | 5 ++++- dockerfiles/login-standalone.Dockerfile | 2 ++ 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-authui.yml b/.github/workflows/build-authui.yml index c71581d37..1eb0569b5 100644 --- a/.github/workflows/build-authui.yml +++ b/.github/workflows/build-authui.yml @@ -49,6 +49,7 @@ jobs: - name: Build Auth UI Docker image env: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + NEXT_SERVER_ACTIONS_ENCRYPTION_KEY: ${{ secrets.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY }} run: make login_standalone_build - name: Tag and push image to GHCR diff --git a/Makefile b/Makefile index 0d29b957e..8ae8e85e7 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ export LOGIN_TEST_ACCEPTANCE_BUILD_CONTEXT := $(LOGIN_DIR)apps/login-test-accept export DOCKER_METADATA_OUTPUT_VERSION ?= local export SENTRY_AUTH_TOKEN ?= +export NEXT_SERVER_ACTIONS_ENCRYPTION_KEY ?= export LOGIN_TAG ?= zitadel-login:${DOCKER_METADATA_OUTPUT_VERSION} export LOGIN_TEST_UNIT_TAG := login-test-unit:${DOCKER_METADATA_OUTPUT_VERSION} export LOGIN_TEST_INTEGRATION_TAG := login-test-integration:${DOCKER_METADATA_OUTPUT_VERSION} diff --git a/README.md b/README.md index d95b5663b..0d3268b4d 100644 --- a/README.md +++ b/README.md @@ -260,6 +260,8 @@ To run the production build of the Login UI locally, follow these steps: This command will build the Docker image for the production-ready Login UI. + For multi-replica or rolling deployments, set `NEXT_SERVER_ACTIONS_ENCRYPTION_KEY` to prevent "Failed to find Server Action" errors. Generate a key with: `openssl rand -base64 32` + 2. **Prepare your environment file:** Create or update your environment file (e.g., `.env.production`) with the necessary environment variables. At a minimum, you will need: @@ -284,6 +286,23 @@ To run the production build of the Login UI locally, follow these steps: Open your browser and navigate to [localhost:3000/ui/v2/login/register](localhost:3000/ui/v2/login/register) to view the production registration component running locally as example. +### Docker / Kubernetes deployment + +When deploying with multiple replicas or rolling updates, configure `NEXT_SERVER_ACTIONS_ENCRYPTION_KEY` at **build time** to prevent "Failed to find Server Action" errors. Next.js encrypts Server Action IDs; without a fixed key, different pods may use different keys and fail to decrypt form submissions. + +**GitHub Actions:** Add a repository secret `NEXT_SERVER_ACTIONS_ENCRYPTION_KEY` (Settings → Secrets → Actions). Generate a value with: + +```sh +openssl rand -base64 32 +``` + +**Local Docker builds:** Export the variable before running `make login_standalone_build`: + +```sh +export NEXT_SERVER_ACTIONS_ENCRYPTION_KEY=$(openssl rand -base64 32) +make login_standalone_build +``` + ### Run Login UI Acceptance tests To run the acceptance tests you need a running ZITADEL environment and a component which receives HTTP requests for the emails and sms's. diff --git a/docker-bake.hcl b/docker-bake.hcl index e6dbdf3b6..68d9f9760 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -148,7 +148,10 @@ target "login-standalone" { contexts = { login-client = "target:login-client" } - secret = ["id=sentry_auth_token,env=SENTRY_AUTH_TOKEN"] + secret = [ + "id=sentry_auth_token,env=SENTRY_AUTH_TOKEN", + "id=next_server_actions_encryption_key,env=NEXT_SERVER_ACTIONS_ENCRYPTION_KEY", + ] } target "login-standalone-out" { diff --git a/dockerfiles/login-standalone.Dockerfile b/dockerfiles/login-standalone.Dockerfile index ebc6d1889..203087f30 100644 --- a/dockerfiles/login-standalone.Dockerfile +++ b/dockerfiles/login-standalone.Dockerfile @@ -8,7 +8,9 @@ RUN --mount=type=cache,id=pnpm,target=/pnpm/store \ pnpm install --frozen-lockfile RUN cp -r ../out/full/* . RUN --mount=type=secret,id=sentry_auth_token,required=false \ + --mount=type=secret,id=next_server_actions_encryption_key,required=false \ if [ -s /run/secrets/sentry_auth_token ]; then export SENTRY_AUTH_TOKEN="$(cat /run/secrets/sentry_auth_token)"; fi; \ + if [ -s /run/secrets/next_server_actions_encryption_key ]; then export NEXT_SERVER_ACTIONS_ENCRYPTION_KEY="$(cat /run/secrets/next_server_actions_encryption_key)"; fi; \ pnpm exec turbo run build:login:standalone FROM scratch AS login-standalone-out