mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 10:47:37 +00:00
Merge branch 'main' into feat/9053-list-users-by-meta
This commit is contained in:
@@ -8,9 +8,13 @@ ENV SHELL=/bin/bash \
|
||||
PNPM_HOME=/home/node/.local/share/pnpm \
|
||||
PATH=/home/node/.local/share/pnpm:$PATH
|
||||
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get --no-install-recommends install -y \
|
||||
# Cypress dependencies
|
||||
libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libnss3 libxss1 libasound2 libxtst6 xauth xvfb && \
|
||||
apt-get clean && \
|
||||
corepack enable && COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack prepare pnpm@9.1.2 --activate
|
||||
corepack enable && COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack prepare pnpm@10.13.1 --activate
|
||||
|
||||
COPY --chown=node:node commands /commands
|
||||
|
||||
USER node
|
||||
|
2
.devcontainer/base/Dockerfile.dockerignore
Normal file
2
.devcontainer/base/Dockerfile.dockerignore
Normal file
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!commands
|
39
.devcontainer/base/commands/login-integration.post-attach.sh
Executable file
39
.devcontainer/base/commands/login-integration.post-attach.sh
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ "$FAIL_COMMANDS_ON_ERRORS" == "true" ]; then
|
||||
set -e
|
||||
fi
|
||||
|
||||
echo
|
||||
echo
|
||||
echo
|
||||
echo -e "THANKS FOR CONTRIBUTING TO ZITADEL 🚀"
|
||||
echo
|
||||
echo "Your dev container is configured for fixing login integration tests."
|
||||
echo "The login is running in a separate container with the same configuration."
|
||||
echo "It calls the mock-zitadel container which provides a mocked Zitadel gRPC API."
|
||||
echo
|
||||
echo "Also the test suite is configured correctly."
|
||||
echo "For example, run a single test file:"
|
||||
echo "pnpm cypress run --spec integration/integration/login.cy.ts"
|
||||
echo
|
||||
echo "You can also run the test interactively."
|
||||
echo "However, this is only possible from outside the dev container."
|
||||
echo "On your host machine, run:"
|
||||
echo "cd apps/login"
|
||||
echo "pnpm cypress open"
|
||||
echo
|
||||
echo "If you want to change the login code, you can replace the login container by a hot reloading dev server."
|
||||
echo "docker stop login-integration"
|
||||
echo "pnpm turbo dev"
|
||||
echo "Navigate to the page you want to fix, for example:"
|
||||
echo "http://localhost:3001/ui/v2/login/verify?userId=221394658884845598&code=abc"
|
||||
echo "Change some code and reload the page for instant feedback."
|
||||
echo
|
||||
echo "When you are done, make sure all integration tests pass:"
|
||||
echo "pnpm cypress run"
|
||||
echo
|
||||
|
||||
if [ "$FAIL_COMMANDS_ON_ERRORS" != "true" ]; then
|
||||
exit 0
|
||||
fi
|
18
.devcontainer/base/commands/login-integration.update-content.sh
Executable file
18
.devcontainer/base/commands/login-integration.update-content.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ "$FAIL_COMMANDS_ON_ERRORS" == "true" ]; then
|
||||
echo "Running in fail-on-errors mode"
|
||||
set -e
|
||||
fi
|
||||
|
||||
pnpm install --frozen-lockfile \
|
||||
--filter @zitadel/login \
|
||||
--filter @zitadel/client \
|
||||
--filter @zitadel/proto \
|
||||
--filter zitadel-monorepo
|
||||
pnpm cypress install
|
||||
pnpm test:integration:login
|
||||
|
||||
if [ "$FAIL_COMMANDS_ON_ERRORS" != "true" ]; then
|
||||
exit 0
|
||||
fi
|
30
.devcontainer/base/commands/turbo-lint-unit.post-attach.sh
Executable file
30
.devcontainer/base/commands/turbo-lint-unit.post-attach.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ "$FAIL_COMMANDS_ON_ERRORS" == "true" ]; then
|
||||
set -e
|
||||
fi
|
||||
|
||||
echo
|
||||
echo
|
||||
echo
|
||||
echo -e "THANKS FOR CONTRIBUTING TO ZITADEL 🚀"
|
||||
echo
|
||||
echo "Your dev container is configured for fixing linting and unit tests."
|
||||
echo "No other services are running alongside this container."
|
||||
echo
|
||||
echo "To fix all auto-fixable linting errors, run:"
|
||||
echo "pnpm turbo lint:fix"
|
||||
echo
|
||||
echo "To watch console linting errors, run:"
|
||||
echo "pnpm turbo watch lint --filter console"
|
||||
echo
|
||||
echo "To watch @zitadel/client unit test failures, run:"
|
||||
echo "pnpm turbo watch test:unit --filter @zitadel/client"
|
||||
echo
|
||||
echo "To watch @zitadel/login relevant unit tests and linting failures, run:"
|
||||
echo "pnpm turbo watch lint test:unit --filter @zitadel/login..."
|
||||
echo
|
||||
|
||||
if [ "$FAIL_COMMANDS_ON_ERRORS" != "true" ]; then
|
||||
exit 0
|
||||
fi
|
12
.devcontainer/base/commands/turbo-lint-unit.update-content.sh
Executable file
12
.devcontainer/base/commands/turbo-lint-unit.update-content.sh
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ "$FAIL_COMMANDS_ON_ERRORS" == "true" ]; then
|
||||
set -e
|
||||
fi
|
||||
|
||||
pnpm install --frozen-lockfile --recursive
|
||||
pnpm turbo lint test:unit
|
||||
|
||||
if [ "$FAIL_COMMANDS_ON_ERRORS" != "true" ]; then
|
||||
exit 0
|
||||
fi
|
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
|
||||
"name": "devcontainer",
|
||||
"dockerComposeFile": "docker-compose.yml",
|
||||
"name": "Base: Build and Run the Components you need",
|
||||
"dockerComposeFile": "docker-compose.yaml",
|
||||
"service": "devcontainer",
|
||||
"runServices": [
|
||||
"devContainer",
|
||||
"db"
|
||||
],
|
||||
"workspaceFolder": "/workspaces",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/go:1": {
|
||||
"version": "1.24"
|
||||
},
|
||||
"ghcr.io/guiyomh/features/golangci-lint:0": {},
|
||||
"ghcr.io/jungaretti/features/make:1": {}
|
||||
"remoteEnv": {
|
||||
"DISPLAY": ""
|
||||
},
|
||||
"forwardPorts": [
|
||||
3000,
|
||||
@@ -17,12 +17,13 @@
|
||||
4200,
|
||||
8080
|
||||
],
|
||||
"onCreateCommand": "pnpm install -g sass@1.64.1",
|
||||
"customizations": {
|
||||
"jetbrains": {
|
||||
"settings": {
|
||||
"com.intellij:app:HttpConfigurable.use_proxy_pac": true
|
||||
}
|
||||
}
|
||||
"onCreateCommand": "pnpm install --frozen-lockfile --recursive --prefer-offline",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/go:1": {
|
||||
"version": "1.24"
|
||||
},
|
||||
"ghcr.io/guiyomh/features/golangci-lint:0": {},
|
||||
"ghcr.io/jungaretti/features/make:1": {},
|
||||
"ghcr.io/devcontainers/features/docker-outside-of-docker": {}
|
||||
}
|
||||
}
|
@@ -1,20 +1,11 @@
|
||||
x-build-cache: &build-cache
|
||||
cache_from:
|
||||
- type=gha
|
||||
cache_to:
|
||||
- type=gha,mode=max
|
||||
|
||||
services:
|
||||
|
||||
devcontainer:
|
||||
container_name: devcontainer
|
||||
build:
|
||||
context: .
|
||||
<<: *build-cache
|
||||
context: ../base
|
||||
volumes:
|
||||
- ../../:/workspaces:cached
|
||||
- /tmp/.X11-unix:/tmp/.X11-unix:cached
|
||||
- home-dir:/home/node:delegated
|
||||
command: sleep infinity
|
||||
working_dir: /workspaces
|
||||
environment:
|
||||
@@ -39,34 +30,9 @@ services:
|
||||
ports:
|
||||
- "5432:5432"
|
||||
|
||||
mock-zitadel:
|
||||
container_name: mock-zitadel
|
||||
build:
|
||||
context: ../../apps/login/integration/core-mock
|
||||
<<: *build-cache
|
||||
ports:
|
||||
- 22220:22220
|
||||
- 22222:22222
|
||||
|
||||
login-integration:
|
||||
container_name: login-integration
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: build/login/Dockerfile
|
||||
<<: *build-cache
|
||||
image: "${LOGIN_TAG:-zitadel-login:local}"
|
||||
env_file: ../../apps/login/.env.test
|
||||
network_mode: service:devcontainer
|
||||
environment:
|
||||
NODE_ENV: test
|
||||
PORT: 3001
|
||||
depends_on:
|
||||
mock-zitadel:
|
||||
condition: service_started
|
||||
|
||||
zitadel:
|
||||
image: "${ZITADEL_TAG:-ghcr.io/zitadel/zitadel:v4.0.0-rc.2}"
|
||||
container_name: zitadel
|
||||
image: "${ZITADEL_TAG:-ghcr.io/zitadel/zitadel:latest}"
|
||||
command: 'start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --config /zitadel.yaml --steps /zitadel.yaml'
|
||||
volumes:
|
||||
- ../../apps/login/acceptance/pat:/pat:delegated
|
||||
@@ -89,7 +55,6 @@ services:
|
||||
build:
|
||||
context: ../../apps/login/acceptance/setup
|
||||
dockerfile: ../go-command.Dockerfile
|
||||
<<: *build-cache
|
||||
entrypoint: "./setup.sh"
|
||||
network_mode: service:devcontainer
|
||||
environment:
|
||||
@@ -111,7 +76,7 @@ services:
|
||||
|
||||
login-acceptance:
|
||||
container_name: login
|
||||
image: "${LOGIN_TAG:-ghcr.io/zitadel/zitadel-login:v4.0.0-rc.2}"
|
||||
image: "${LOGIN_TAG:-ghcr.io/zitadel/zitadel-login:latest}"
|
||||
network_mode: service:devcontainer
|
||||
volumes:
|
||||
- ../../apps/login/.env.test.local:/env-files/.env:cached
|
||||
@@ -126,7 +91,6 @@ services:
|
||||
dockerfile: ../go-command.Dockerfile
|
||||
args:
|
||||
- LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
|
||||
<<: *build-cache
|
||||
environment:
|
||||
PORT: '3333'
|
||||
command:
|
||||
@@ -151,7 +115,6 @@ services:
|
||||
dockerfile: ../go-command.Dockerfile
|
||||
args:
|
||||
- LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
|
||||
<<: *build-cache
|
||||
network_mode: service:devcontainer
|
||||
environment:
|
||||
API_URL: 'http://localhost:8080'
|
||||
@@ -175,7 +138,6 @@ services:
|
||||
# dockerfile: ../../go-command.Dockerfile
|
||||
# args:
|
||||
# - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
|
||||
# <<: *build-cache
|
||||
# network_mode: service:devcontainer
|
||||
# environment:
|
||||
# API_URL: 'http://localhost:8080'
|
||||
@@ -197,7 +159,6 @@ services:
|
||||
dockerfile: ../go-command.Dockerfile
|
||||
args:
|
||||
- LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
|
||||
<<: *build-cache
|
||||
network_mode: service:devcontainer
|
||||
environment:
|
||||
API_URL: 'http://localhost:8080'
|
||||
@@ -219,7 +180,6 @@ services:
|
||||
# dockerfile: ../../go-command.Dockerfile
|
||||
# args:
|
||||
# - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
|
||||
# <<: *build-cache
|
||||
# network_mode: service:devcontainer
|
||||
# environment:
|
||||
# API_URL: 'http://localhost:8080'
|
||||
@@ -236,4 +196,3 @@ services:
|
||||
|
||||
volumes:
|
||||
postgres-data:
|
||||
home-dir:
|
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
|
||||
"name": "login-integration-debug",
|
||||
"dockerComposeFile": [
|
||||
"../base/docker-compose.yml",
|
||||
"docker-compose.yml"
|
||||
],
|
||||
"service": "login-integration-debug",
|
||||
"runServices": ["login-integration-debug"],
|
||||
"workspaceFolder": "/workspaces",
|
||||
"forwardPorts": [3001],
|
||||
"onCreateCommand": "pnpm install --recursive",
|
||||
"postAttachCommand": "pnpm turbo daemon clean; pnpm turbo @zitadel/login#dev test:integration:login:debug",
|
||||
"customizations": {
|
||||
"jetbrains": {
|
||||
"settings": {
|
||||
"com.intellij:app:HttpConfigurable.use_proxy_pac": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
services:
|
||||
login-integration-debug:
|
||||
extends:
|
||||
file: ../base/docker-compose.yml
|
||||
service: devcontainer
|
||||
container_name: login-integration-debug
|
||||
depends_on:
|
||||
mock-zitadel:
|
||||
condition: service_started
|
@@ -1,19 +1,26 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
|
||||
"name": "login-integration",
|
||||
"name": "Login Integration",
|
||||
"dockerComposeFile": [
|
||||
"../base/docker-compose.yml"
|
||||
"./docker-compose.yaml"
|
||||
],
|
||||
"service": "devcontainer",
|
||||
"runServices": ["login-integration"],
|
||||
"workspaceFolder": "/workspaces",
|
||||
"forwardPorts": [3001],
|
||||
"onCreateCommand": "pnpm install --frozen-lockfile --recursive && cd apps/login/packages/integration && pnpm cypress install && pnpm test:integration:login",
|
||||
"customizations": {
|
||||
"jetbrains": {
|
||||
"settings": {
|
||||
"com.intellij:app:HttpConfigurable.use_proxy_pac": true
|
||||
}
|
||||
}
|
||||
"service": "login-integration-dev",
|
||||
"runServices": [
|
||||
"login-integration"
|
||||
],
|
||||
"workspaceFolder": "/workspaces/apps/login",
|
||||
"forwardPorts": [
|
||||
22220,
|
||||
22222,
|
||||
3001
|
||||
],
|
||||
"remoteEnv": {
|
||||
"FAIL_COMMANDS_ON_ERRORS": "${localEnv:FAIL_COMMANDS_ON_ERRORS}",
|
||||
"DISPLAY": ""
|
||||
},
|
||||
"updateContentCommand": "/commands/login-integration.update-content.sh",
|
||||
"postAttachCommand": "/commands/login-integration.post-attach.sh",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/docker-outside-of-docker": {}
|
||||
}
|
||||
}
|
||||
|
35
.devcontainer/login-integration/docker-compose.yaml
Normal file
35
.devcontainer/login-integration/docker-compose.yaml
Normal file
@@ -0,0 +1,35 @@
|
||||
services:
|
||||
login-integration-dev:
|
||||
extends:
|
||||
file: ../base/docker-compose.yaml
|
||||
service: devcontainer
|
||||
container_name: login-integration-dev
|
||||
env_file: ../../apps/login/.env.test
|
||||
environment:
|
||||
CORE_MOCK_STUBS_URL: http://localhost:22220/v1/stubs
|
||||
LOGIN_BASE_URL: http://localhost:3001/ui/v2/login
|
||||
CYPRESS_CACHE_FOLDER: /workspaces/.artifacts/cypress
|
||||
network_mode: service:mock-zitadel
|
||||
depends_on:
|
||||
login-integration:
|
||||
condition: service_healthy
|
||||
|
||||
login-integration:
|
||||
container_name: login-integration
|
||||
image: "${LOGIN_TAG:-ghcr.io/zitadel/zitadel-login:latest}"
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: build/login/Dockerfile
|
||||
env_file: ../../apps/login/.env.test
|
||||
network_mode: service:mock-zitadel
|
||||
|
||||
mock-zitadel:
|
||||
container_name: mock-zitadel
|
||||
build:
|
||||
context: ../../apps/login/integration/core-mock
|
||||
additional_contexts:
|
||||
- zitadel-protos=../../proto
|
||||
ports:
|
||||
- 22220:22220
|
||||
- 22222:22222
|
||||
- 3001:3001
|
22
.devcontainer/login-subtree/devcontainer.json
Normal file
22
.devcontainer/login-subtree/devcontainer.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.base.schema.json",
|
||||
"image": "mcr.microsoft.com/devcontainers/typescript-node:20-bookworm",
|
||||
"name": "Login Subtree Container - Use the Login As If You Would Have Forked the Mirror Repo",
|
||||
"workspaceFolder": "/login",
|
||||
"workspaceMount": "source=${localWorkspaceFolder}/apps/login,target=/login,type=bind,consistency=cached",
|
||||
"mounts": [],
|
||||
"forwardPorts": [
|
||||
22220,
|
||||
22222,
|
||||
3000,
|
||||
3001
|
||||
],
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/go:1": {
|
||||
"version": "1.24"
|
||||
},
|
||||
"ghcr.io/guiyomh/features/golangci-lint:0": {},
|
||||
"ghcr.io/jungaretti/features/make:1": {},
|
||||
"ghcr.io/devcontainers/features/docker-outside-of-docker": {}
|
||||
}
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
|
||||
"name": "turbo-lint-unit-debug",
|
||||
"dockerComposeFile": [
|
||||
"../base/docker-compose.yml",
|
||||
"docker-compose.yml"
|
||||
],
|
||||
"service": "turbo-lint-unit-debug",
|
||||
"runServices": ["turbo-lint-unit-debug"],
|
||||
"workspaceFolder": "/workspaces",
|
||||
"forwardPorts": [3001],
|
||||
"onCreateCommand": "pnpm install --recursive",
|
||||
"postAttachCommand": "pnpm turbo daemon clean; pnpm turbo watch lint test:unit",
|
||||
"customizations": {
|
||||
"jetbrains": {
|
||||
"settings": {
|
||||
"com.intellij:app:HttpConfigurable.use_proxy_pac": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +0,0 @@
|
||||
services:
|
||||
turbo-lint-unit-debug:
|
||||
extends:
|
||||
file: ../base/docker-compose.yml
|
||||
service: devcontainer
|
||||
container_name: turbo-lint-unit-debug
|
@@ -1,18 +1,20 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
|
||||
"name": "turbo-lint-unit",
|
||||
"name": "Turbo Lint and Unit Tests",
|
||||
"dockerComposeFile": [
|
||||
"../base/docker-compose.yml"
|
||||
"../base/docker-compose.yaml"
|
||||
],
|
||||
"service": "devcontainer",
|
||||
"runServices": ["devcontainer"],
|
||||
"runServices": [
|
||||
"devcontainer"
|
||||
],
|
||||
"workspaceFolder": "/workspaces",
|
||||
"postStartCommand": "pnpm install --frozen-lockfile --recursive && pnpm turbo lint test:unit",
|
||||
"customizations": {
|
||||
"jetbrains": {
|
||||
"settings": {
|
||||
"com.intellij:app:HttpConfigurable.use_proxy_pac": true
|
||||
}
|
||||
}
|
||||
}
|
||||
"forwardPorts": [
|
||||
3001
|
||||
],
|
||||
"remoteEnv": {
|
||||
"FAIL_COMMANDS_ON_ERRORS": "${localEnv:FAIL_COMMANDS_ON_ERRORS}"
|
||||
},
|
||||
"updateContentCommand": "/commands/turbo-lint-unit.update-content.sh",
|
||||
"postAttachCommand": "/commands/turbo-lint-unit.post-attach.sh"
|
||||
}
|
@@ -1,11 +1,14 @@
|
||||
|
||||
# .git
|
||||
.codecov
|
||||
.github
|
||||
.gitignore
|
||||
.dockerignore
|
||||
**/Dockerfile
|
||||
/k8s/
|
||||
/node_modules/
|
||||
**/node_modules
|
||||
**/.pnpm-store
|
||||
**/.turbo
|
||||
**/.next
|
||||
/console/src/app/proto/generated/
|
||||
/console/.angular
|
||||
/console/tmp/
|
||||
@@ -24,5 +27,5 @@ console/.angular
|
||||
console/node_modules
|
||||
console/src/app/proto/generated/
|
||||
console/tmp/
|
||||
.vscode
|
||||
build/*.Dockerfile
|
||||
|
||||
|
7
.github/workflows/build.yml
vendored
7
.github/workflows/build.yml
vendored
@@ -102,6 +102,12 @@ jobs:
|
||||
login_build_image_name: "ghcr.io/zitadel/zitadel-login-build"
|
||||
node_version: "20"
|
||||
|
||||
login-integration-test:
|
||||
uses: ./.github/workflows/login-integration-test.yml
|
||||
needs: [login-container]
|
||||
with:
|
||||
login_build_image: ${{ needs.login-container.outputs.login_build_image }}
|
||||
|
||||
e2e:
|
||||
uses: ./.github/workflows/e2e.yml
|
||||
needs: [compile]
|
||||
@@ -121,6 +127,7 @@ jobs:
|
||||
lint,
|
||||
container,
|
||||
login-container,
|
||||
login-integration-test,
|
||||
e2e,
|
||||
]
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
|
1
.github/workflows/compile.yml
vendored
1
.github/workflows/compile.yml
vendored
@@ -77,6 +77,7 @@ jobs:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: executables
|
||||
pattern: 'zitadel-*-*'
|
||||
- name: move files one folder up
|
||||
run: mv */*.tar.gz . && find . -type d -empty -delete
|
||||
working-directory: executables
|
||||
|
19
.github/workflows/lint.yml
vendored
19
.github/workflows/lint.yml
vendored
@@ -53,14 +53,21 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Install Dev Container CLI
|
||||
run: npm install -g @devcontainers/cli@0.80.0
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Run lint and unit tests in dev container
|
||||
uses: devcontainers/ci@v0.3
|
||||
with:
|
||||
push: never
|
||||
configFile: .devcontainer/turbo-lint-unit/devcontainer.json
|
||||
runCmd: echo "Successfully ran lint and unit tests in dev container postStartCommand"
|
||||
- name: Lint and Unit Test All JavaScript Code
|
||||
run: npm run devcontainer:lint-unit
|
||||
- name: Fix Failures
|
||||
if: failure()
|
||||
run: |
|
||||
echo "Reproduce this check locally:"
|
||||
echo "npm run devcontainer:lint-unit"
|
||||
echo "If you have pnpm installed, most linting errors can be fixed automatically:"
|
||||
echo "pnpm turbo lint:fix"
|
||||
echo "In other cases, you can open the dev container called \"Turbo Lint and Unit Tests\"."
|
||||
echo "You will have the same environment as the pipeline check as well as some guidance on how to fix the errors."
|
||||
|
||||
core:
|
||||
name: core
|
||||
|
16
.github/workflows/login-container.yml
vendored
16
.github/workflows/login-container.yml
vendored
@@ -12,8 +12,8 @@ on:
|
||||
type: string
|
||||
outputs:
|
||||
login_build_image:
|
||||
description: 'The full image tag of the standalone login image'
|
||||
value: '${{ inputs.login_build_image_name }}:${{ github.sha }}'
|
||||
description: 'The full image tag of the standalone login image'
|
||||
value: ${{ inputs.login_build_image_name }}:${{ github.sha }}
|
||||
|
||||
permissions:
|
||||
packages: write
|
||||
@@ -30,6 +30,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write
|
||||
outputs:
|
||||
login_build_image: ${{ steps.short-sha.outputs.login_build_image }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Login meta
|
||||
@@ -41,7 +43,7 @@ jobs:
|
||||
annotations: |
|
||||
manifest:org.opencontainers.image.licenses=MIT
|
||||
tags: |
|
||||
type=sha,prefix=,suffix=,format=long
|
||||
type=sha,prefix=,format=long
|
||||
- name: Login to Docker registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
@@ -49,21 +51,19 @@ jobs:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Set up Docker Buildx
|
||||
id: setup-buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Bake login multi-arch
|
||||
uses: docker/bake-action@v6
|
||||
env:
|
||||
NODE_VERSION: ${{ inputs.node_version }}
|
||||
with:
|
||||
source: .
|
||||
push: true
|
||||
provenance: true
|
||||
sbom: true
|
||||
targets: login-standalone
|
||||
set: |
|
||||
*.cache-from=type=gha
|
||||
*.cache-to=type=gha,mode=max
|
||||
files: |
|
||||
./apps/login/docker-bake.hcl
|
||||
./apps/login/docker-bake-release.hcl
|
||||
${{ github.event_name == 'workflow_dispatch' && './apps/login/docker-bake-release.hcl' || '' }}
|
||||
./docker-bake.hcl
|
||||
cwd://${{ steps.login-meta.outputs.bake-file }}
|
||||
|
58
.github/workflows/login-integration-test.yml
vendored
Normal file
58
.github/workflows/login-integration-test.yml
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
name: Integration test core
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
login_build_image:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
login-integration-test:
|
||||
name: login-integration-test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Install Dev Container CLI
|
||||
run: npm install -g @devcontainers/cli@0.80.0
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Pull Login Build Image
|
||||
run: docker compose --file .devcontainer/login-integration/docker-compose.yaml pull
|
||||
env:
|
||||
LOGIN_TAG: ${{ inputs.login_build_image }}
|
||||
- name: Run Integration Tests against the Login and a Mocked Zitadel API
|
||||
run: npm run devcontainer:integration:login
|
||||
env:
|
||||
LOGIN_TAG: ${{ inputs.login_build_image }}
|
||||
DOCKER_BUILDKIT: 1
|
||||
- name: Fix Failures
|
||||
if: failure()
|
||||
run: |
|
||||
echo "Reproduce this check locally:"
|
||||
echo "LOGIN_TAG=${{ inputs.login_build_image }} npm run devcontainer:integration:login"
|
||||
echo "To fix the failures, open the dev container called \"Login Integration Tests\"."
|
||||
echo "You will have the same environment as the pipeline check as well as some guidance on how to fix the errors."
|
||||
- name: Show Compose Status
|
||||
if: failure()
|
||||
run: docker compose --file .devcontainer/base/docker-compose.yaml --file .devcontainer/login-integration-ci/docker-compose.yaml ps
|
||||
- name: Print Config
|
||||
if: failure()
|
||||
run: COMPOSE_BAKE=1 docker compose --file .devcontainer/base/docker-compose.yaml --file .devcontainer/login-integration-ci/docker-compose.yaml config login-integration
|
||||
env:
|
||||
LOGIN_TAG: ${{ inputs.login_build_image }}
|
||||
- name: Show Container Logs
|
||||
if: failure()
|
||||
run: docker compose --file .devcontainer/base/docker-compose.yaml --file .devcontainer/login-integration-ci/docker-compose.yaml logs --timestamps --no-color --tail 100 login-integration
|
||||
- name: Inspect All Failed Containers
|
||||
if: failure()
|
||||
run: |
|
||||
docker ps -a --filter "status=exited" --filter "status=created" --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Image}}"
|
||||
for container in $(docker ps -a --filter "status=exited" --filter "status=created" -q); do
|
||||
echo "Inspecting container $container"
|
||||
docker inspect $container || true
|
||||
done
|
@@ -100,9 +100,7 @@ linters:
|
||||
- .keys
|
||||
- .vscode
|
||||
- build
|
||||
- console
|
||||
- deploy
|
||||
- docs
|
||||
- guides
|
||||
- internal/api/ui/login/static
|
||||
- openapi
|
||||
@@ -111,6 +109,12 @@ linters:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
- apps
|
||||
- packages
|
||||
- console
|
||||
- docs
|
||||
- load-test
|
||||
|
||||
issues:
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
@@ -135,9 +139,7 @@ formatters:
|
||||
- .keys
|
||||
- .vscode
|
||||
- build
|
||||
- console
|
||||
- deploy
|
||||
- docs
|
||||
- guides
|
||||
- internal/api/ui/login/static
|
||||
- openapi
|
||||
@@ -146,3 +148,8 @@ formatters:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
- apps
|
||||
- packages
|
||||
- console
|
||||
- docs
|
||||
- load-test
|
||||
|
102
CONTRIBUTING.md
102
CONTRIBUTING.md
@@ -1,6 +1,5 @@
|
||||
# Contributing to Zitadel
|
||||
|
||||
|
||||
## Introduction
|
||||
|
||||
Thank you for your interest about how to contribute! As you might know there is more than code to contribute. You can find all information needed to start contributing here.
|
||||
@@ -150,51 +149,19 @@ The API is designed to be used by different clients, such as web applications, m
|
||||
Therefore, the API is designed to be easy to use, consistent, and reliable.
|
||||
Please check out the dedicated [API guidelines](./API_DESIGN.md) page when contributing to the API.
|
||||
|
||||
|
||||
#### <a name="dev-containers"></>Developing Zitadel with Dev Containers
|
||||
|
||||
You can use dev containers if you'd like to make sure you have the same development environment like the corresponding GitHub PR checks use.
|
||||
The following dev containers are available:
|
||||
|
||||
- **.devcontainer/base/devcontainer.json**: Contains everything you need to run whatever you want.
|
||||
- **.devcontainer/turbo-lint-unit/devcontainer.json**: Runs a dev container that executes frontent linting and unit tests and then exits. This is useful to reproduce the corresponding GitHub PR check.
|
||||
- **.devcontainer/turbo-lint-unit-debug/devcontainer.json**: Runs a dev container that executes frontent linting and unit tests in watch mode. You can fix the errors right away and have immediate feedback.
|
||||
- **.devcontainer/login-integration/devcontainer.json**: Runs a dev container that executes login integration tests and then exits. This is useful to reproduce the corresponding GitHub PR check.
|
||||
- **.devcontainer/login-integration-debug/devcontainer.json**: Runs a dev container that spins up the login in a hot-reloading dev server and executes login integration tests interactively. You can fix the errors right away and have immediate feedback.
|
||||
|
||||
You can also run the GitHub PR checks locally in dev containers without having to connect to a dev container.
|
||||
|
||||
|
||||
The following pnpm commands use the [devcontainer CLI](https://github.com/devcontainers/cli/) and exit when the checks are done.
|
||||
The minimal system requirements are having Docker and the devcontainers CLI installed.
|
||||
If you don't have the node_modules installed already, you need to install the devcontainers CLI manually. Run `npm i -g @devcontainers/cli`. Alternatively, the [official Microsoft VS Code extension for Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) offers a command `Dev Containers: Install devcontainer CLI`
|
||||
|
||||
|
||||
```bash
|
||||
npm run devcontainer:lint-unit
|
||||
npm run devcontainer:integration:login
|
||||
```
|
||||
|
||||
If you don't have NPM installed, copy and execute the scripts from the package.json directly.
|
||||
|
||||
To connect to a dev container to have full IDE support, follow the instructions provided by your code editor/IDE to initiate the dev container.
|
||||
This typically involves opening the "Command Palette" or similar functionality and searching for commands related to "Dev Containers" or "Remote Containers".
|
||||
The quick start guide for VS Code can found [here](https://code.visualstudio.com/docs/devcontainers/containers#_quick-start-open-an-existing-folder-in-a-container)
|
||||
|
||||
For example, to build and run the Zitadel binary in a dev container, connect your IDE to the dev container described in .devcontainer/base/devcontainer.json.
|
||||
Run the following commands inside the container to start Zitadel.
|
||||
|
||||
```bash
|
||||
make compile && ./zitadel start-from-init --masterkey MasterkeyNeedsToHave32Characters --tlsMode disabled
|
||||
```
|
||||
|
||||
Zitadel serves traffic as soon as you can see the following log line:
|
||||
|
||||
`INFO[0001] server is listening on [::]:8080`
|
||||
|
||||
## <a name="backend"></a>Contribute Backend Code
|
||||
|
||||
|
||||
|
||||
### <a name="backend-requirements"></a> Backend Requirements
|
||||
|
||||
By executing the commands from this section, you run everything you need to develop the Zitadel backend locally.
|
||||
|
||||
> [!INFO]
|
||||
> Some [dev containers are available](dev-containers) for remote development with docker and pipeline debugging in isolated environments.
|
||||
> If you don't want to use one of the dev containers, you can develop the backend components directly on your local machine.
|
||||
> To do so, proceed with installing the necessary dependencies.
|
||||
|
||||
Using [Docker Compose](https://docs.docker.com/compose/), you run a [PostgreSQL](https://www.postgresql.org/download/) on your local machine.
|
||||
With [make](https://www.gnu.org/software/make/), you build a debuggable Zitadel binary and run it using [delve](https://github.com/go-delve/delve).
|
||||
Then, you test your changes via the console your binary is serving at http://<span because="breaks the link"></span>localhost:8080 and by verifying the database.
|
||||
@@ -208,6 +175,8 @@ The commands in this section are tested against the following software versions:
|
||||
- [Go version 1.22](https://go.dev/doc/install)
|
||||
- [Delve 1.9.1](https://github.com/go-delve/delve/tree/v1.9.1/Documentation/installation)
|
||||
|
||||
### <a name="build-and-run-zitadel"></a>Build and Run Zitadel
|
||||
|
||||
Make some changes to the source code, then run the database locally.
|
||||
|
||||
```bash
|
||||
@@ -588,6 +557,48 @@ For the turbo commands, check your options with `pnpm turbo --help`
|
||||
| `pnpm turbo down` | Remove containers and volumes | Shut down containers from the integration test setup `pnpm turbo down` |
|
||||
| `pnpm turbo clean` | Remove downloaded dependencies and other generated files | Remove generated docs `pnpm turbo clean --filter zitadel-docs` |
|
||||
|
||||
## <a name="dev-containers"></>Developing Zitadel with Dev Containers
|
||||
|
||||
You can use dev containers if you'd like to make sure you have the same development environment like the corresponding GitHub PR checks use.
|
||||
The following dev containers are available:
|
||||
|
||||
- **.devcontainer/base/devcontainer.json**: Contains everything you need to run whatever you want.
|
||||
- **.devcontainer/turbo-lint-unit/devcontainer.json**: Runs a dev container that executes frontent linting and unit tests and then exits. This is useful to reproduce the corresponding GitHub PR check.
|
||||
- **.devcontainer/turbo-lint-unit-debug/devcontainer.json**: Runs a dev container that executes frontent linting and unit tests in watch mode. You can fix the errors right away and have immediate feedback.
|
||||
- **.devcontainer/login-integration/devcontainer.json**: Runs a dev container that executes login integration tests and then exits. This is useful to reproduce the corresponding GitHub PR check.
|
||||
- **.devcontainer/login-integration-debug/devcontainer.json**: Runs a dev container that spins up the login in a hot-reloading dev server and executes login integration tests interactively. You can fix the errors right away and have immediate feedback.
|
||||
|
||||
You can also run the GitHub PR checks locally in dev containers without having to connect to a dev container.
|
||||
|
||||
|
||||
The following pnpm commands use the [devcontainer CLI](https://github.com/devcontainers/cli/) and exit when the checks are done.
|
||||
The minimal system requirements are having Docker and the devcontainers CLI installed.
|
||||
If you don't have the node_modules installed already, you need to install the devcontainers CLI manually. Run `npm i -g @devcontainers/cli@0.80.0`. Alternatively, the [official Microsoft VS Code extension for Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) offers a command `Dev Containers: Install devcontainer CLI`
|
||||
|
||||
|
||||
```bash
|
||||
npm run devcontainer:lint-unit
|
||||
npm run devcontainer:integration:login
|
||||
```
|
||||
|
||||
If you don't have NPM installed, copy and execute the scripts from the package.json directly.
|
||||
|
||||
To connect to a dev container to have full IDE support, follow the instructions provided by your code editor/IDE to initiate the dev container.
|
||||
This typically involves opening the "Command Palette" or similar functionality and searching for commands related to "Dev Containers" or "Remote Containers".
|
||||
The quick start guide for VS Code can found [here](https://code.visualstudio.com/docs/devcontainers/containers#_quick-start-open-an-existing-folder-in-a-container)
|
||||
|
||||
For example, to build and run the Zitadel binary in a dev container, connect your IDE to the dev container described in .devcontainer/base/devcontainer.json.
|
||||
Run the following commands inside the container to start Zitadel.
|
||||
|
||||
```bash
|
||||
make compile && ./zitadel start-from-init --masterkey MasterkeyNeedsToHave32Characters --tlsMode disabled
|
||||
```
|
||||
|
||||
Zitadel serves traffic as soon as you can see the following log line:
|
||||
|
||||
`INFO[0001] server is listening on [::]:8080`
|
||||
|
||||
|
||||
## <a name="contribute-translations"></a>Contribute Translations
|
||||
|
||||
Zitadel loads translations from four files:
|
||||
@@ -608,11 +619,6 @@ You also have to add some changes to the following files:
|
||||
- [Customized Text Docs](./docs/docs/guides/manage/customize/texts.md)
|
||||
- [Add language option](./internal/api/ui/login/static/templates/external_not_found_option.html)
|
||||
|
||||
## Want to start Zitadel?
|
||||
|
||||
You can find an installation guide for all the different environments here:
|
||||
[https://zitadel.com/docs/self-hosting/deploy/overview](https://zitadel.com/docs/self-hosting/deploy/overview)
|
||||
|
||||
## **Did you find a security flaw?**
|
||||
|
||||
- Please read [Security Policy](./SECURITY.md).
|
||||
|
@@ -1,5 +1,6 @@
|
||||
NEXT_PUBLIC_BASE_PATH="/ui/v2/login"
|
||||
ZITADEL_API_URL=http://mock-zitadel:22222
|
||||
ZITADEL_API_URL=http://localhost:22222
|
||||
ZITADEL_SERVICE_USER_TOKEN="yolo"
|
||||
EMAIL_VERIFICATION=true
|
||||
DEBUG=true
|
||||
PORT=3001
|
||||
NEXT_PUBLIC_BASE_PATH=/ui/v2/login
|
||||
|
2
apps/login/.gitignore
vendored
2
apps/login/.gitignore
vendored
@@ -2,6 +2,7 @@ custom-config.js
|
||||
.env*.local
|
||||
standalone
|
||||
tsconfig.tsbuildinfo
|
||||
cypress
|
||||
|
||||
.DS_Store
|
||||
node_modules
|
||||
@@ -11,6 +12,5 @@ node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
.env
|
||||
.vscode
|
||||
/blob-report/
|
||||
|
@@ -3,21 +3,21 @@ FROM node:20-alpine AS base
|
||||
FROM base AS build
|
||||
ENV PNPM_HOME="/pnpm"
|
||||
ENV PATH="$PNPM_HOME:$PATH"
|
||||
RUN corepack enable && COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack prepare pnpm@9.1.2 --activate && \
|
||||
apk update && apk add --no-cache && \
|
||||
RUN corepack enable && COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack prepare pnpm@10.13.1 --activate && \
|
||||
apk update && \
|
||||
rm -rf /var/cache/apk/*
|
||||
WORKDIR /app
|
||||
COPY pnpm-lock.yaml ./
|
||||
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm fetch --frozen-lockfile
|
||||
COPY package.json ./
|
||||
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile --prod
|
||||
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile
|
||||
COPY . .
|
||||
RUN pnpm build:login:standalone
|
||||
|
||||
FROM scratch AS build-out
|
||||
COPY --from=build /app/.next/standalone /
|
||||
COPY --from=build /app/.next/static /.next/static
|
||||
COPY --from=build /app/public /public
|
||||
COPY public public
|
||||
|
||||
FROM base AS login-standalone
|
||||
WORKDIR /runtime
|
||||
@@ -25,12 +25,13 @@ RUN addgroup --system --gid 1001 nodejs && \
|
||||
adduser --system --uid 1001 nextjs
|
||||
# If /.env-file/.env is mounted into the container, its variables are made available to the server before it starts up.
|
||||
RUN mkdir -p /.env-file && touch /.env-file/.env && chown -R nextjs:nodejs /.env-file
|
||||
COPY ./scripts/ ./
|
||||
COPY --chown=nextjs:nodejs ./scripts/ ./
|
||||
COPY --chown=nextjs:nodejs --from=build-out / ./
|
||||
USER nextjs
|
||||
ENV HOSTNAME="0.0.0.0"
|
||||
ENV PORT=3000
|
||||
ENV HOSTNAME="0.0.0.0" \
|
||||
NEXT_PUBLIC_BASE_PATH="/ui/v2/login" \
|
||||
PORT=3000
|
||||
# TODO: Check healthy, not ready
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
CMD ["/bin/sh", "-c", "node ./healthcheck.js http://localhost:${PORT}/ui/v2/login/healthy"]
|
||||
ENTRYPOINT ["./entrypoint.sh"]
|
||||
CMD ["/bin/sh", "-c", "node /runtime/healthcheck.js http://localhost:${PORT}/ui/v2/login/healthy"]
|
||||
ENTRYPOINT ["/runtime/entrypoint.sh"]
|
||||
|
@@ -8,7 +8,8 @@
|
||||
!next.config.mjs
|
||||
!next-env-vars.d.ts
|
||||
!next-env.d.ts
|
||||
!tailwind.config.js
|
||||
!tailwind.config.mjs
|
||||
!postcss.config.cjs
|
||||
!tsconfig.json
|
||||
!package.json
|
||||
!pnpm-lock.yaml
|
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"name": "login-test-acceptance",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"test:acceptance": "dotenv -e ../login/.env.test.local playwright",
|
||||
"test:acceptance:setup": "cd ../.. && make login_test_acceptance_setup_env && NODE_ENV=test turbo run test:acceptance:setup:dev",
|
||||
"test:acceptance:setup:dev": "cd ../.. && make login_test_acceptance_setup_dev",
|
||||
"clean": "rm -rf .turbo node_modules"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^9.7.0",
|
||||
"@otplib/core": "^12.0.0",
|
||||
"@otplib/plugin-crypto": "^12.0.0",
|
||||
"@otplib/plugin-thirty-two": "^12.0.0",
|
||||
"@playwright/test": "^1.52.0",
|
||||
"dotenv-cli": "^8.0.0",
|
||||
"gaxios": "^7.1.0",
|
||||
"typescript": "^5.8.3"
|
||||
}
|
||||
}
|
@@ -2,11 +2,11 @@ import { defineConfig } from "cypress";
|
||||
|
||||
export default defineConfig({
|
||||
reporter: "list",
|
||||
|
||||
video: true,
|
||||
e2e: {
|
||||
baseUrl: process.env.LOGIN_BASE_URL || "http://localhost:3001/ui/v2/login",
|
||||
specPattern: "integration/**/*.cy.{js,jsx,ts,tsx}",
|
||||
supportFile: "support/e2e.{js,jsx,ts,tsx}",
|
||||
specPattern: "integration/integration/**/*.cy.{js,jsx,ts,tsx}",
|
||||
supportFile: "integration/support/e2e.{js,jsx,ts,tsx}",
|
||||
setupNodeEvents(on, config) {
|
||||
// implement node event listeners here
|
||||
},
|
@@ -1,8 +1,10 @@
|
||||
FROM bufbuild/buf:1.54.0 AS proto-files
|
||||
RUN buf export https://github.com/envoyproxy/protoc-gen-validate.git --path validate --output /proto-files && \
|
||||
buf export https://github.com/grpc-ecosystem/grpc-gateway.git --path protoc-gen-openapiv2 --output /proto-files && \
|
||||
buf export https://github.com/googleapis/googleapis.git --path protos/zitadelgoogle/api/annotations.proto --path google/api/http.proto --path google/api/field_behavior.proto --output /proto-files && \
|
||||
buf export https://github.com/zitadel/zitadel.git --path ./proto/zitadel --output /proto-files
|
||||
FROM bufbuild/buf:1.54.0 AS dependencies
|
||||
RUN buf export https://github.com/envoyproxy/protoc-gen-validate.git --path validate --output /proto && \
|
||||
buf export https://github.com/grpc-ecosystem/grpc-gateway.git --path protoc-gen-openapiv2 --output /proto && \
|
||||
buf export https://github.com/googleapis/googleapis.git --path google/api/annotations.proto --path google/api/http.proto --path google/api/field_behavior.proto --output /proto
|
||||
|
||||
FROM bufbuild/buf:1.54.0 AS zitadel-protos
|
||||
RUN buf export https://github.com/zitadel/zitadel.git --path ./proto/zitadel --output /zitadel
|
||||
|
||||
FROM golang:1.20.5-alpine3.18 AS mock-zitadel
|
||||
|
||||
@@ -10,6 +12,7 @@ RUN go install github.com/eliobischof/grpc-mock/cmd/grpc-mock@01b09f60db1b501178
|
||||
|
||||
COPY mocked-services.cfg .
|
||||
COPY initial-stubs initial-stubs
|
||||
COPY --from=proto-files /proto-files/ ./
|
||||
COPY --from=dependencies /proto/ ./
|
||||
COPY --from=zitadel-protos /zitadel/ ./zitadel/
|
||||
|
||||
ENTRYPOINT [ "sh", "-c", "grpc-mock -v 1 -proto $(tr '\n' ',' < ./mocked-services.cfg) -stub-dir ./initial-stubs -mock-addr :22222" ]
|
||||
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
@@ -22,22 +22,22 @@ describe("verify invite", () => {
|
||||
user: {
|
||||
userId: "221394658884845598",
|
||||
state: 1,
|
||||
username: "john@zitadel.com",
|
||||
loginNames: ["john@zitadel.com"],
|
||||
preferredLoginName: "john@zitadel.com",
|
||||
username: "john@example.com",
|
||||
loginNames: ["john@example.com"],
|
||||
preferredLoginName: "john@example.com",
|
||||
human: {
|
||||
userId: "221394658884845598",
|
||||
state: 1,
|
||||
username: "john@zitadel.com",
|
||||
loginNames: ["john@zitadel.com"],
|
||||
preferredLoginName: "john@zitadel.com",
|
||||
username: "john@example.com",
|
||||
loginNames: ["john@example.com"],
|
||||
preferredLoginName: "john@example.com",
|
||||
profile: {
|
||||
givenName: "John",
|
||||
familyName: "Doe",
|
||||
avatarUrl: "https://zitadel.com/avatar.jpg",
|
||||
avatarUrl: "https://example.com/avatar.jpg",
|
||||
},
|
||||
email: {
|
||||
email: "john@zitadel.com",
|
||||
email: "john@example.com",
|
||||
isVerified: false,
|
||||
},
|
||||
},
|
||||
@@ -68,7 +68,7 @@ describe("verify invite", () => {
|
||||
factors: {
|
||||
user: {
|
||||
id: "221394658884845598",
|
||||
loginName: "john@zitadel.com",
|
||||
loginName: "john@example.com",
|
||||
},
|
||||
password: undefined,
|
||||
webAuthN: undefined,
|
||||
@@ -93,7 +93,7 @@ describe("verify invite", () => {
|
||||
stub("zitadel.user.v2.UserService", "VerifyInviteCode");
|
||||
|
||||
cy.visit("/verify?userId=221394658884845598&code=abc&invite=true");
|
||||
cy.url({ timeout: 10_000 }).should("include", Cypress.config().baseUrl + "/authenticator/set");
|
||||
cy.url().should("include", Cypress.config().baseUrl + "/authenticator/set");
|
||||
});
|
||||
|
||||
it("shows an error if invite code validation failed", () => {
|
||||
|
@@ -33,7 +33,7 @@ describe("login", () => {
|
||||
factors: {
|
||||
user: {
|
||||
id: "221394658884845598",
|
||||
loginName: "john@zitadel.com",
|
||||
loginName: "john@example.com",
|
||||
},
|
||||
password: undefined,
|
||||
webAuthN: undefined,
|
||||
@@ -64,22 +64,22 @@ describe("login", () => {
|
||||
{
|
||||
userId: "221394658884845598",
|
||||
state: 1,
|
||||
username: "john@zitadel.com",
|
||||
loginNames: ["john@zitadel.com"],
|
||||
preferredLoginName: "john@zitadel.com",
|
||||
username: "john@example.com",
|
||||
loginNames: ["john@example.com"],
|
||||
preferredLoginName: "john@example.com",
|
||||
human: {
|
||||
userId: "221394658884845598",
|
||||
state: 1,
|
||||
username: "john@zitadel.com",
|
||||
loginNames: ["john@zitadel.com"],
|
||||
preferredLoginName: "john@zitadel.com",
|
||||
username: "john@example.com",
|
||||
loginNames: ["john@example.com"],
|
||||
preferredLoginName: "john@example.com",
|
||||
profile: {
|
||||
givenName: "John",
|
||||
familyName: "Doe",
|
||||
avatarUrl: "https://zitadel.com/avatar.jpg",
|
||||
avatarUrl: "https://example.com/avatar.jpg",
|
||||
},
|
||||
email: {
|
||||
email: "john@zitadel.com",
|
||||
email: "john@example.com",
|
||||
isVerified: true,
|
||||
},
|
||||
},
|
||||
@@ -94,8 +94,8 @@ describe("login", () => {
|
||||
});
|
||||
});
|
||||
it("should redirect a user with password authentication to /password", () => {
|
||||
cy.visit("/loginname?loginName=john%40zitadel.com&submit=true");
|
||||
cy.url({ timeout: 10_000 }).should("include", Cypress.config().baseUrl + "/password");
|
||||
cy.visit("/loginname?loginName=john%40example.com&submit=true");
|
||||
cy.url({ timeout: 5 * 60_000 }).should("include", Cypress.config().baseUrl + "/password");
|
||||
});
|
||||
describe("with passkey prompt", () => {
|
||||
beforeEach(() => {
|
||||
@@ -112,8 +112,8 @@ describe("login", () => {
|
||||
});
|
||||
});
|
||||
// it("should prompt a user to setup passwordless authentication if passkey is allowed in the login settings", () => {
|
||||
// cy.visit("/loginname?loginName=john%40zitadel.com&submit=true");
|
||||
// cy.location("pathname", { timeout: 10_000 }).should("eq", "/password");
|
||||
// cy.visit("/loginname?loginName=john%40example.com&submit=true");
|
||||
// cy.location("pathname", { timeout: 5 * 60_000 }).should("eq", "/password");
|
||||
// cy.get('input[type="password"]').focus().type("MyStrongPassword!1");
|
||||
// cy.get('button[type="submit"]').click();
|
||||
// cy.location("pathname", { timeout: 10_000 }).should(
|
||||
@@ -134,22 +134,22 @@ describe("login", () => {
|
||||
{
|
||||
userId: "221394658884845598",
|
||||
state: 1,
|
||||
username: "john@zitadel.com",
|
||||
loginNames: ["john@zitadel.com"],
|
||||
preferredLoginName: "john@zitadel.com",
|
||||
username: "john@example.com",
|
||||
loginNames: ["john@example.com"],
|
||||
preferredLoginName: "john@example.com",
|
||||
human: {
|
||||
userId: "221394658884845598",
|
||||
state: 1,
|
||||
username: "john@zitadel.com",
|
||||
loginNames: ["john@zitadel.com"],
|
||||
preferredLoginName: "john@zitadel.com",
|
||||
username: "john@example.com",
|
||||
loginNames: ["john@example.com"],
|
||||
preferredLoginName: "john@example.com",
|
||||
profile: {
|
||||
givenName: "John",
|
||||
familyName: "Doe",
|
||||
avatarUrl: "https://zitadel.com/avatar.jpg",
|
||||
avatarUrl: "https://example.com/avatar.jpg",
|
||||
},
|
||||
email: {
|
||||
email: "john@zitadel.com",
|
||||
email: "john@example.com",
|
||||
isVerified: true,
|
||||
},
|
||||
},
|
||||
@@ -165,8 +165,8 @@ describe("login", () => {
|
||||
});
|
||||
|
||||
it("should redirect a user with passwordless authentication to /passkey", () => {
|
||||
cy.visit("/loginname?loginName=john%40zitadel.com&submit=true");
|
||||
cy.url({ timeout: 10_000 }).should("include", Cypress.config().baseUrl + "/passkey");
|
||||
cy.visit("/loginname?loginName=john%40example.com&submit=true");
|
||||
cy.url().should("include", Cypress.config().baseUrl + "/passkey");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -15,7 +15,7 @@ describe("register idps", () => {
|
||||
cy.visit("/idp");
|
||||
cy.get('button[e2e="google"]').click();
|
||||
cy.origin(IDP_URL, { args: IDP_URL }, (url) => {
|
||||
cy.location("href", { timeout: 10_000 }).should("eq", url);
|
||||
cy.location("href").should("eq", url);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -48,7 +48,7 @@ describe("register", () => {
|
||||
factors: {
|
||||
user: {
|
||||
id: "221394658884845598",
|
||||
loginName: "john@zitadel.com",
|
||||
loginName: "john@example.com",
|
||||
},
|
||||
password: undefined,
|
||||
webAuthN: undefined,
|
||||
@@ -64,10 +64,10 @@ describe("register", () => {
|
||||
cy.visit("/register");
|
||||
cy.get('input[data-testid="firstname-text-input"]').focus().type("John");
|
||||
cy.get('input[data-testid="lastname-text-input"]').focus().type("Doe");
|
||||
cy.get('input[data-testid="email-text-input"]').focus().type("john@zitadel.com");
|
||||
cy.get('input[data-testid="email-text-input"]').focus().type("john@example.com");
|
||||
cy.get('input[type="checkbox"][value="privacypolicy"]').check();
|
||||
cy.get('input[type="checkbox"][value="tos"]').check();
|
||||
cy.get('button[type="submit"]').click();
|
||||
cy.url({ timeout: 10_000 }).should("include", Cypress.config().baseUrl + "/passkey/set");
|
||||
cy.url().should("include", Cypress.config().baseUrl + "/passkey/set");
|
||||
});
|
||||
});
|
||||
|
@@ -24,22 +24,22 @@ describe("verify email", () => {
|
||||
user: {
|
||||
userId: "221394658884845598",
|
||||
state: 1,
|
||||
username: "john@zitadel.com",
|
||||
loginNames: ["john@zitadel.com"],
|
||||
preferredLoginName: "john@zitadel.com",
|
||||
username: "john@example.com",
|
||||
loginNames: ["john@example.com"],
|
||||
preferredLoginName: "john@example.com",
|
||||
human: {
|
||||
userId: "221394658884845598",
|
||||
state: 1,
|
||||
username: "john@zitadel.com",
|
||||
loginNames: ["john@zitadel.com"],
|
||||
preferredLoginName: "john@zitadel.com",
|
||||
username: "john@example.com",
|
||||
loginNames: ["john@example.com"],
|
||||
preferredLoginName: "john@example.com",
|
||||
profile: {
|
||||
givenName: "John",
|
||||
familyName: "Doe",
|
||||
avatarUrl: "https://zitadel.com/avatar.jpg",
|
||||
avatarUrl: "https://example.com/avatar.jpg",
|
||||
},
|
||||
email: {
|
||||
email: "john@zitadel.com",
|
||||
email: "john@example.com",
|
||||
isVerified: false, // email is not verified yet
|
||||
},
|
||||
},
|
||||
@@ -70,7 +70,7 @@ describe("verify email", () => {
|
||||
factors: {
|
||||
user: {
|
||||
id: "221394658884845598",
|
||||
loginName: "john@zitadel.com",
|
||||
loginName: "john@example.com",
|
||||
},
|
||||
password: undefined,
|
||||
webAuthN: undefined,
|
||||
@@ -90,6 +90,6 @@ describe("verify email", () => {
|
||||
// TODO: Avoid uncaught exception in application
|
||||
cy.once("uncaught:exception", () => false);
|
||||
cy.visit("/verify?userId=221394658884845598&code=abc");
|
||||
cy.contains("Could not verify email", { timeout: 10_000 });
|
||||
cy.contains("Could not verify email");
|
||||
});
|
||||
});
|
||||
|
@@ -1,4 +1,4 @@
|
||||
const url = Cypress.env("CORE_MOCK_STUBS_URL") || "http://mock-zitadel:22220/v1/stubs";
|
||||
const url = Cypress.env("CORE_MOCK_STUBS_URL") || "http://localhost:22220/v1/stubs";
|
||||
|
||||
function removeStub(service: string, method: string) {
|
||||
return cy.request({
|
||||
|
@@ -4,5 +4,5 @@
|
||||
"lib": ["es5", "dom"],
|
||||
"types": ["cypress", "node"]
|
||||
},
|
||||
"include": ["**/*.ts"]
|
||||
"include": ["**/*.ts", "../cypress.config.ts"]
|
||||
}
|
||||
|
2
apps/login/next-env-vars.d.ts
vendored
2
apps/login/next-env-vars.d.ts
vendored
@@ -27,6 +27,8 @@ declare namespace NodeJS {
|
||||
/**
|
||||
* Optional: custom request headers to be added to every request
|
||||
* Split by comma, key value pairs separated by colon
|
||||
* For example: to call the Zitadel API at an internal address, you can set:
|
||||
* `CUSTOM_REQUEST_HEADERS=Host:http://zitadel-internal:8080`
|
||||
*/
|
||||
CUSTOM_REQUEST_HEADERS?: string;
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"packageManager": "pnpm@9.1.2+sha256.19c17528f9ca20bd442e4ca42f00f1b9808a9cb419383cd04ba32ef19322aba7",
|
||||
"packageManager": "pnpm@10.13.1",
|
||||
"name": "@zitadel/login",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
@@ -15,8 +15,7 @@
|
||||
"test:unit": "vitest --run",
|
||||
"lint-staged": "lint-staged",
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next",
|
||||
"test:integration:login": "cypress run",
|
||||
"test:integration:login:debug": "cypress open",
|
||||
"test:integration:login": "wait-on --simultaneous 1 http://localhost:3001/ui/v2/login/verify?userId=221394658884845598&code=abc && cypress run",
|
||||
"test:acceptance": "dotenv -e ../login/.env.test.local playwright",
|
||||
"test:acceptance:setup": "cd ../.. && make login_test_acceptance_setup_env && NODE_ENV=test turbo run test:acceptance:setup:dev",
|
||||
"test:acceptance:setup:dev": "cd ../.. && make login_test_acceptance_setup_dev"
|
||||
@@ -54,6 +53,11 @@
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "^7.23.0",
|
||||
"@bufbuild/buf": "^1.53.0",
|
||||
"@faker-js/faker": "^9.7.0",
|
||||
"@otplib/core": "^12.0.0",
|
||||
"@otplib/plugin-crypto": "^12.0.0",
|
||||
"@otplib/plugin-thirty-two": "^12.0.0",
|
||||
"@playwright/test": "^1.52.0",
|
||||
"@testing-library/jest-dom": "^6.6.3",
|
||||
"@testing-library/react": "^16.3.0",
|
||||
"@types/ms": "2.1.0",
|
||||
@@ -67,34 +71,30 @@
|
||||
"@vercel/git-hooks": "1.0.0",
|
||||
"@vitejs/plugin-react": "^4.4.1",
|
||||
"autoprefixer": "10.4.21",
|
||||
"concurrently": "^9.1.2",
|
||||
"cypress": "^14.5.2",
|
||||
"dotenv-cli": "^8.0.0",
|
||||
"env-cmd": "^10.0.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-next": "15.4.0-canary.86",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"gaxios": "^7.1.0",
|
||||
"grpc-tools": "1.13.0",
|
||||
"jsdom": "^26.1.0",
|
||||
"lint-staged": "15.5.1",
|
||||
"make-dir-cli": "4.0.0",
|
||||
"nodemon": "^3.1.9",
|
||||
"postcss": "8.5.3",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-plugin-organize-imports": "^3.2.0",
|
||||
"prettier-plugin-tailwindcss": "0.6.11",
|
||||
"sass": "^1.87.0",
|
||||
"start-server-and-test": "^2.0.11",
|
||||
"tailwindcss": "3.4.14",
|
||||
"ts-proto": "^2.7.0",
|
||||
"typescript": "^5.8.3",
|
||||
"vite-tsconfig-paths": "^5.1.4",
|
||||
"vitest": "^2.0.0",
|
||||
"concurrently": "^9.1.2",
|
||||
"cypress": "^14.5.2",
|
||||
"dotenv-cli": "^8.0.0",
|
||||
"env-cmd": "^10.0.0",
|
||||
"nodemon": "^3.1.9",
|
||||
"start-server-and-test": "^2.0.11",
|
||||
"@faker-js/faker": "^9.7.0",
|
||||
"@otplib/core": "^12.0.0",
|
||||
"@otplib/plugin-crypto": "^12.0.0",
|
||||
"@otplib/plugin-thirty-two": "^12.0.0",
|
||||
"@playwright/test": "^1.52.0",
|
||||
"gaxios": "^7.1.0"
|
||||
"wait-on": "^7.2.0"
|
||||
}
|
||||
}
|
9151
apps/login/pnpm-lock.yaml
generated
Normal file
9151
apps/login/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,4 @@ if [ -n "${ZITADEL_SERVICE_USER_TOKEN_FILE}" ] && [ -f "${ZITADEL_SERVICE_USER_T
|
||||
export ZITADEL_SERVICE_USER_TOKEN=$(cat "${ZITADEL_SERVICE_USER_TOKEN_FILE}")
|
||||
fi
|
||||
|
||||
|
||||
|
||||
exec node /runtime/apps/login/apps/login/server.js
|
||||
exec node /runtime/apps/login/server.js
|
||||
|
@@ -1,22 +1,57 @@
|
||||
{
|
||||
"extends": ["//"],
|
||||
"extends": [
|
||||
"//"
|
||||
],
|
||||
"tasks": {
|
||||
"build": {
|
||||
"outputs": ["dist/**", ".next/**", "!.next/cache/**"],
|
||||
"dependsOn": ["@zitadel/client#build"]
|
||||
"outputs": [
|
||||
"dist/**",
|
||||
".next/**",
|
||||
"!.next/cache/**"
|
||||
],
|
||||
"dependsOn": [
|
||||
"@zitadel/client#build"
|
||||
]
|
||||
},
|
||||
"build:login:standalone": {
|
||||
"outputs": ["dist/**", ".next/**", "!.next/cache/**"],
|
||||
"dependsOn": ["@zitadel/client#build"]
|
||||
"outputs": [
|
||||
"dist/**",
|
||||
".next/**",
|
||||
"!.next/cache/**"
|
||||
],
|
||||
"dependsOn": [
|
||||
"@zitadel/client#build"
|
||||
]
|
||||
},
|
||||
"dev": {
|
||||
"dependsOn": ["@zitadel/client#build"]
|
||||
"persistent": true,
|
||||
"cache": false,
|
||||
"dependsOn": [
|
||||
"@zitadel/client#build"
|
||||
]
|
||||
},
|
||||
"test": {
|
||||
"dependsOn": ["@zitadel/client#build"]
|
||||
"dependsOn": [
|
||||
"@zitadel/client#build"
|
||||
]
|
||||
},
|
||||
"test:unit": {
|
||||
"dependsOn": ["@zitadel/client#build"]
|
||||
"dependsOn": [
|
||||
"@zitadel/client#build"
|
||||
]
|
||||
},
|
||||
"test:integration:login": {
|
||||
"inputs": [
|
||||
".next/**",
|
||||
"!.next/cache/**",
|
||||
"integration/integration/**",
|
||||
"integration/support/**",
|
||||
"cypress.config.ts"
|
||||
],
|
||||
"outputs": [
|
||||
"cypress/videos/**",
|
||||
"cypress/screenshots/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,45 +1,55 @@
|
||||
FROM node:20-alpine AS base
|
||||
FROM node:20-alpine AS runtime
|
||||
|
||||
FROM base AS build
|
||||
FROM runtime AS pnpm-base
|
||||
RUN apk add --no-cache libc6-compat
|
||||
ENV PNPM_HOME="/pnpm"
|
||||
ENV PATH="$PNPM_HOME:$PATH"
|
||||
RUN corepack enable && COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack prepare pnpm@9.1.2 --activate && \
|
||||
apk update && apk add --no-cache && \
|
||||
rm -rf /var/cache/apk/*
|
||||
WORKDIR /app
|
||||
COPY pnpm-lock.yaml pnpm-workspace.yaml ./
|
||||
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm fetch --frozen-lockfile \
|
||||
--filter @zitadel/login \
|
||||
--filter @zitadel/client \
|
||||
--filter @zitadel/proto
|
||||
COPY package.json ./
|
||||
COPY apps/login/package.json ./apps/login/package.json
|
||||
COPY packages/zitadel-proto/package.json ./packages/zitadel-proto/package.json
|
||||
COPY packages/zitadel-client/package.json ./packages/zitadel-client/package.json
|
||||
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile \
|
||||
--filter @zitadel/login \
|
||||
--filter @zitadel/client \
|
||||
--filter @zitadel/proto
|
||||
RUN corepack enable && corepack prepare pnpm@10.13.1 --activate
|
||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
||||
pnpm add -g turbo@2.5.5
|
||||
|
||||
FROM pnpm-base AS pruner
|
||||
WORKDIR /prune
|
||||
COPY . .
|
||||
RUN pnpm turbo build:login:standalone
|
||||
RUN pnpm turbo prune @zitadel/login @zitadel/client @zitadel/proto --docker
|
||||
|
||||
FROM pnpm-base AS installer
|
||||
WORKDIR /install
|
||||
COPY --from=pruner /prune/out/pnpm-lock.yaml ./
|
||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
||||
pnpm fetch --frozen-lockfile
|
||||
COPY --from=pruner /prune/out/json/ .
|
||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
||||
pnpm install --frozen-lockfile --ignore-scripts
|
||||
|
||||
FROM pnpm-base AS builder
|
||||
WORKDIR /build
|
||||
COPY --from=installer /install/ .
|
||||
COPY --from=pruner /prune/out/full/ .
|
||||
COPY proto ./proto
|
||||
ENV CI=true
|
||||
RUN --mount=type=cache,id=turbo,target=/build/.turbo/cache \
|
||||
--mount=type=cache,id=next,target=/build/apps/login/.next/cache \
|
||||
pnpm turbo build:login:standalone --cache-dir=/build/.turbo/cache
|
||||
|
||||
FROM scratch AS build-out
|
||||
COPY --from=build /app/apps/login/.next/standalone /
|
||||
COPY --from=build /app/apps/login/.next/static /.next/static
|
||||
COPY --from=build /app/apps/login/public /public
|
||||
COPY /apps/login/public ./apps/login/public
|
||||
COPY --from=builder /build/apps/login/.next/standalone ./
|
||||
COPY --from=builder /build/apps/login/.next/static ./apps/login/.next/static
|
||||
|
||||
FROM base AS login-standalone
|
||||
FROM runtime AS login-standalone
|
||||
WORKDIR /runtime
|
||||
RUN addgroup --system --gid 1001 nodejs && \
|
||||
adduser --system --uid 1001 nextjs
|
||||
# If /.env-file/.env is mounted into the container, its variables are made available to the server before it starts up.
|
||||
RUN mkdir -p /.env-file && touch /.env-file/.env && chown -R nextjs:nodejs /.env-file
|
||||
COPY apps/login/scripts ./
|
||||
COPY --chown=nextjs:nodejs apps/login/scripts ./
|
||||
COPY --chown=nextjs:nodejs --from=build-out . .
|
||||
# Debug the final structure
|
||||
USER nextjs
|
||||
ENV HOSTNAME="0.0.0.0"
|
||||
ENV PORT=3000
|
||||
# TODO: Check healthy, not ready
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
CMD ["/bin/sh", "-c", "node ./healthcheck.js http://localhost:${PORT}/ui/v2/login/healthy"]
|
||||
ENTRYPOINT ["./entrypoint.sh"]
|
||||
CMD ["/bin/sh", "-c", "node /runtime/healthcheck.js http://localhost:${PORT}/ui/v2/login/healthy"]
|
||||
ENTRYPOINT ["/runtime/entrypoint.sh"]
|
||||
|
@@ -8,7 +8,8 @@
|
||||
!apps/login/next.config.mjs
|
||||
!apps/login/next-env-vars.d.ts
|
||||
!apps/login/next-env.d.ts
|
||||
!apps/login/tailwind.config.js
|
||||
!apps/login/tailwind.config.mjs
|
||||
!apps/login/postcss.config.cjs
|
||||
!apps/login/tsconfig.json
|
||||
!apps/login/package.json
|
||||
!apps/login/turbo.json
|
||||
@@ -23,6 +24,7 @@
|
||||
!packages/zitadel-proto/turbo.json
|
||||
|
||||
!packages/zitadel-client/package.json
|
||||
!packages/zitadel-client/**/package.json
|
||||
!packages/zitadel-client/src
|
||||
!packages/zitadel-client/tsconfig.json
|
||||
!packages/zitadel-client/tsup.config.ts
|
||||
@@ -30,8 +32,7 @@
|
||||
|
||||
!proto
|
||||
|
||||
*.md
|
||||
*.png
|
||||
node_modules
|
||||
*.test.ts
|
||||
*.test.tsx
|
||||
**/*.md
|
||||
**/node_modules
|
||||
**/*.test.ts
|
||||
**/*.test.tsx
|
@@ -524,7 +524,7 @@ OIDC:
|
||||
PollInterval: 5s # ZITADEL_OIDC_DEVICEAUTH_POLLINTERVAL
|
||||
UserCode:
|
||||
CharSet: "BCDFGHJKLMNPQRSTVWXZ" # ZITADEL_OIDC_DEVICEAUTH_USERCODE_CHARSET
|
||||
CharAmount: 8 # ZITADEL_OIDC_DEVICEAUTH_USERCODE_CHARARMOUNT
|
||||
CharAmount: 8 # ZITADEL_OIDC_DEVICEAUTH_USERCODE_CHARAMOUNT
|
||||
DashInterval: 4 # ZITADEL_OIDC_DEVICEAUTH_USERCODE_DASHINTERVAL
|
||||
DefaultLoginURLV2: "/ui/v2/login/login?authRequest=" # ZITADEL_OIDC_DEFAULTLOGINURLV2
|
||||
DefaultLogoutURLV2: "/ui/v2/login/logout?post_logout_redirect=" # ZITADEL_OIDC_DEFAULTLOGOUTURLV2
|
||||
|
@@ -34,6 +34,7 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/api"
|
||||
"github.com/zitadel/zitadel/internal/api/assets"
|
||||
internal_authz "github.com/zitadel/zitadel/internal/api/authz"
|
||||
action_v2 "github.com/zitadel/zitadel/internal/api/grpc/action/v2"
|
||||
action_v2_beta "github.com/zitadel/zitadel/internal/api/grpc/action/v2beta"
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/admin"
|
||||
app "github.com/zitadel/zitadel/internal/api/grpc/app/v2beta"
|
||||
@@ -509,6 +510,9 @@ func startAPIs(
|
||||
if err := apis.RegisterService(ctx, action_v2_beta.CreateServer(config.SystemDefaults, commands, queries, domain.AllActionFunctions, apis.ListGrpcMethods, apis.ListGrpcServices)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := apis.RegisterService(ctx, action_v2.CreateServer(config.SystemDefaults, commands, queries, domain.AllActionFunctions, apis.ListGrpcMethods, apis.ListGrpcServices)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := apis.RegisterService(ctx, project_v2beta.CreateServer(config.SystemDefaults, commands, queries, permissionCheck)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -66,18 +66,24 @@
|
||||
|
||||
.type-icon {
|
||||
color: $primary-color;
|
||||
}
|
||||
|
||||
.type-button-icon,
|
||||
.type-icon,
|
||||
span {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.type-icon,
|
||||
.type-button-icon {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
> span {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
button[mat-icon-button] {
|
||||
margin-right: 0;
|
||||
|
||||
.type-button-icon {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.trigger-wrapper {
|
||||
|
@@ -423,6 +423,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
|
||||
if (allowed) {
|
||||
this.oidcForm.enable();
|
||||
this.oidcForm.controls['clientId'].disable();
|
||||
this.oidcTokenForm.enable();
|
||||
this.apiForm.enable();
|
||||
this.samlForm.enable();
|
||||
|
@@ -6,8 +6,6 @@ target "login-standalone" {
|
||||
target "login-standalone-out" {
|
||||
inherits = ["login-standalone"]
|
||||
target = "build-out"
|
||||
output = [
|
||||
"type=local,dest=.artifacts/login"
|
||||
]
|
||||
output = ["type=local,dest=.artifacts/login"]
|
||||
}
|
||||
|
@@ -184,7 +184,7 @@ https://github.com/zitadel/actions/blob/main/examples/add_metadata.js
|
||||
|
||||
## Use provided fields of identity providers
|
||||
|
||||
If you want to ensure that the data of a user are always update you can automatically update user fields during authentication and safe time of your customers and your team. 🤯
|
||||
If you want to ensure that the data of a user are always up-to-date, you can automatically update user fields during authentication and save time of your customers and your team.
|
||||
|
||||
### Trigger
|
||||
|
||||
|
@@ -145,7 +145,7 @@ This object contains context information about the request to the [authorization
|
||||
- `requestedOrgDomain` *bool*
|
||||
- `applicationResourceOwner` *string*
|
||||
- `privateLabelingSetting` *Number*
|
||||
<ul><li>0: Unspecified</li><li>1: Enforce project resource owner policy</li><li>2: Allow login user resource owner policy</li></ul>
|
||||
<ul><li>0: Unspecified</li><li>1: Enforce project's policy</li><li>2: Allow user's organization login policy</li></ul>
|
||||
- `selectedIdpConfigId` *string*
|
||||
- `linkingUsers` Array of [*ExternalUser*](#external-user)
|
||||
- `passwordVerified` *bool*
|
||||
|
@@ -111,6 +111,6 @@ ZITADEL reserves some claims to assert certain data. Please check out the [reser
|
||||
| urn:zitadel:iam:org:project:roles | `{"urn:zitadel:iam:org:project:roles": [ {"user": {"id1": "acme.zitade.ch", "id2": "caos.ch"} } ] }` | When roles are asserted, ZITADEL does this by providing the `id` and `primaryDomain` below the role. This gives you the option to check in which organization a user has the role on the current project (where your client belongs to). |
|
||||
| urn:zitadel:iam:org:project:\{projectid}:roles | `{"urn:zitadel:iam:org:project:id3:roles": [ {"user": {"id1": "acme.zitade.ch", "id2": "caos.ch"} } ] }` | When roles are asserted, ZITADEL does this by providing the `id` and `primaryDomain` below the role. This gives you the option to check in which organization a user has the role on a specific project. |
|
||||
| urn:zitadel:iam:user:metadata | `{"urn:zitadel:iam:user:metadata": [ {"key": "VmFsdWU=" } ] }` | The metadata claim will include all metadata of a user. The values are base64 encoded. |
|
||||
| urn:zitadel:iam:user:resourceowner:id | `{"urn:zitadel:iam:user:resourceowner:id": "orgid"}` | This claim represents the id of the resource owner organisation of the user. |
|
||||
| urn:zitadel:iam:user:resourceowner:name | `{"urn:zitadel:iam:user:resourceowner:name": "ACME"}` | This claim represents the name of the resource owner organisation of the user. |
|
||||
| urn:zitadel:iam:user:resourceowner:primary_domain | `{"urn:zitadel:iam:user:resourceowner:primary_domain": "acme.ch"}` | This claim represents the primary domain of the resource owner organisation of the user. |
|
||||
| urn:zitadel:iam:user:resourceowner:id | `{"urn:zitadel:iam:user:resourceowner:id": "orgid"}` | This claim represents the user's organization ID. |
|
||||
| urn:zitadel:iam:user:resourceowner:name | `{"urn:zitadel:iam:user:resourceowner:name": "ACME"}` | This claim represents the user's organization's name. |
|
||||
| urn:zitadel:iam:user:resourceowner:primary_domain | `{"urn:zitadel:iam:user:resourceowner:primary_domain": "acme.ch"}` | This claim represents the user's organization's primary domain. |
|
||||
|
@@ -31,8 +31,8 @@ In addition to the standard compliant scopes we utilize the following scopes.
|
||||
| `urn:zitadel:iam:org:id:{id}` | `urn:zitadel:iam:org:id:178204173316174381` | When requesting this scope **ZITADEL** will enforce that the user is a member of the selected organization. If the organization does not exist a failure is displayed. It will assert the `urn:zitadel:iam:user:resourceowner` claims. |
|
||||
| `urn:zitadel:iam:org:domain:primary:{domainname}` | `urn:zitadel:iam:org:domain:primary:acme.ch` | When requesting this scope **ZITADEL** will enforce that the user is a member of the selected organization and the username is suffixed by the provided domain. If the organization does not exist a failure is displayed |
|
||||
| `urn:zitadel:iam:org:roles:id:{orgID}` | `urn:zitadel:iam:org:roles:id:178204173316174381` | This scope can be used one or more times to limit the granted organization IDs in the returned roles. Unknown organization IDs are ignored. When this scope is not used, all granted organizations are returned inside the roles. |
|
||||
| `urn:zitadel:iam:org:project:id:{projectid}:aud` | `urn:zitadel:iam:org:project:id:69234237810729019:aud` | By adding this scope, the requested projectid will be added to the audience of the access token |
|
||||
| `urn:zitadel:iam:org:project:id:zitadel:aud` | `urn:zitadel:iam:org:project:id:zitadel:aud` | By adding this scope, the ZITADEL project ID will be added to the audience of the access token |
|
||||
| `urn:zitadel:iam:org:project:id:{projectid}:aud` | `urn:zitadel:iam:org:project:id:69234237810729019:aud` | By adding this scope, the requested project id will be added to the audience of the access token |
|
||||
| `urn:zitadel:iam:org:project:id:zitadel:aud` | `urn:zitadel:iam:org:project:id:zitadel:aud` | By adding this scope, the ZITADEL project id will be added to the audience of the access token |
|
||||
| `urn:zitadel:iam:user:metadata` | `urn:zitadel:iam:user:metadata` | By adding this scope, the metadata of the user will be included in the token. The values are base64 encoded. |
|
||||
| `urn:zitadel:iam:user:resourceowner` | `urn:zitadel:iam:user:resourceowner` | By adding this scope: id, name and primary_domain of the resource owner (the users organization) will be included in the token. |
|
||||
| `urn:zitadel:iam:user:resourceowner` | `urn:zitadel:iam:user:resourceowner` | By adding this scope: id, name and primary_domain of the user's organization will be included in the token. |
|
||||
| `urn:zitadel:iam:org:idp:id:{idp_id}` | `urn:zitadel:iam:org:idp:id:76625965177954913` | By adding this scope the user will directly be redirected to the identity provider to authenticate. Make sure you also send the primary domain scope if a custom login policy is configured. Otherwise the system will not be able to identify the identity provider. |
|
||||
|
@@ -2,15 +2,6 @@
|
||||
title: SCIM v2.0 (Preview)
|
||||
---
|
||||
|
||||
:::info
|
||||
The SCIM v2 interface of Zitadel is currently in a [preview stage](/support/software-release-cycles-support#preview).
|
||||
It is not yet feature-complete, may contain bugs, and is not generally available.
|
||||
|
||||
Do not use it for production yet.
|
||||
|
||||
As long as the feature is in a preview state, it will be available for free, it will be put behind a commercial license once it is fully available.
|
||||
:::
|
||||
|
||||
The Zitadel [SCIM v2](https://scim.cloud/) service provider interface enables seamless integration of identity and
|
||||
access management (IAM) systems with Zitadel,
|
||||
following the System for Cross-domain Identity Management (SCIM) v2.0 specification.
|
||||
|
@@ -103,9 +103,7 @@ curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2beta/actions/executions' \
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"target": "<TargetID returned>"
|
||||
}
|
||||
"<TargetID returned>"
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
@@ -129,9 +129,7 @@ curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2beta/actions/executions' \
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"target": "<TargetID returned>"
|
||||
}
|
||||
"<TargetID returned>"
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
@@ -107,9 +107,7 @@ curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2beta/actions/executions' \
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"target": "<TargetID returned>"
|
||||
}
|
||||
"<TargetID returned>"
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
@@ -154,9 +154,7 @@ curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2beta/actions/executions' \
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"target": "<TargetID returned>"
|
||||
}
|
||||
"<TargetID returned>"
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
@@ -114,9 +114,7 @@ curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2beta/actions/executions' \
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"target": "<TargetID returned>"
|
||||
}
|
||||
"<TargetID returned>"
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
@@ -107,9 +107,7 @@ curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2beta/actions/executions' \
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"target": "<TargetID returned>"
|
||||
}
|
||||
"<TargetID returned>"
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
@@ -173,9 +173,7 @@ curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2beta/actions/executions' \
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"target": "<TargetID returned>"
|
||||
}
|
||||
"<TargetID returned>"
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
@@ -107,9 +107,7 @@ curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2beta/actions/executions' \
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"target": "<TargetID returned>"
|
||||
}
|
||||
"<TargetID returned>"
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
@@ -406,17 +406,11 @@ If you then have a call on `/zitadel.user.v2.UserService/UpdateHumanUser` the fo
|
||||
|
||||
And if you use a different service, for example `zitadel.session.v2.SessionService`, then the `all` Execution would still be used.
|
||||
|
||||
### Targets and Includes
|
||||
### Targets
|
||||
|
||||
:::info
|
||||
Includes are limited to 3 levels, which mean that include1->include2->include3 is the maximum for now.
|
||||
If you have feedback to the include logic, or a reason why 3 levels are not enough, please open [an issue on github](https://github.com/zitadel/zitadel/issues) or [start a discussion on github](https://github.com/zitadel/zitadel/discussions)/[start a topic on discord](https://zitadel.com/chat)
|
||||
:::
|
||||
An execution can contain only a list of Targets, and Targets are comma separated string values.
|
||||
|
||||
An execution can not only contain a list of Targets, but also Includes.
|
||||
The Includes can be defined in the Execution directly, which means you include all defined Targets by a before set Execution.
|
||||
|
||||
If you define 2 Executions as follows:
|
||||
Here's an example of a Target defined on a service (e.g. `zitadel.user.v2.UserService`)
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -426,13 +420,12 @@ If you define 2 Executions as follows:
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"target": "<TargetID1>"
|
||||
}
|
||||
"<TargetID1>"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Here's an example of a Target defined on a method (e.g. `/zitadel.user.v2.UserService/AddHumanUser`)
|
||||
```json
|
||||
{
|
||||
"condition": {
|
||||
@@ -441,21 +434,13 @@ If you define 2 Executions as follows:
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"target": "<TargetID2>"
|
||||
},
|
||||
{
|
||||
"include": {
|
||||
"request": {
|
||||
"service": "zitadel.user.v2.UserService"
|
||||
}
|
||||
}
|
||||
}
|
||||
"<TargetID2>",
|
||||
"<TargetID1>"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The called Targets on "/zitadel.user.v2.UserService/AddHumanUser" would be, in order:
|
||||
The called Targets on `/zitadel.user.v2.UserService/AddHumanUser` would be, in order:
|
||||
|
||||
1. `<TargetID2>`
|
||||
2. `<TargetID1>`
|
||||
|
@@ -77,8 +77,8 @@ You can choose from
|
||||
| Setting | Description |
|
||||
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| Unspecified | If nothing is specified the default will trigger. (System settings) |
|
||||
| Enforce project resource owner policy | This setting will enforce the private labeling of the organization (resource owner) of the project through the whole login process. |
|
||||
| Allow Login User resource owner policy | With this setting first the private labeling of the organization (resource owner) of the project will trigger. As soon as the user and its organization (resource owner) is identified by ZITADEL, the settings will change to the organization of the user. |
|
||||
| Enforce project's policy | This setting will enforce the private labeling of the organization of the project through the whole login process. |
|
||||
| Allow login user policy | With this setting first the private labeling of the organization of the project will trigger. As soon as the user and its organization is identified by ZITADEL, the settings will change to the organization of the user. |
|
||||
|
||||
In a B2B use case, you would typically use the organization setting. If you want to omit organization detection, you can preselect an organization with the [primary domain scope](/apis/openidoauth/scopes#reserved-scopes) (ex. `urn:zitadel:iam:org:domain:primary:{domainname}`).
|
||||
|
||||
|
@@ -2,15 +2,6 @@
|
||||
title: SCIM v2.0 (Preview)
|
||||
---
|
||||
|
||||
:::info
|
||||
The SCIM v2 interface of Zitadel is currently in a [preview stage](/support/software-release-cycles-support#preview).
|
||||
It is not yet feature-complete, may contain bugs, and is not generally available.
|
||||
|
||||
Do not use it for production yet.
|
||||
|
||||
As long as the feature is in a preview state, it will be available for free, it will be put behind a commercial license once it is fully available.
|
||||
:::
|
||||
|
||||
The Zitadel [SCIM v2](https://scim.cloud/) service provider interface enables seamless integration of identity and
|
||||
access management (IAM) systems with Zitadel,
|
||||
following the System for Cross-domain Identity Management (SCIM) v2.0 specification.
|
||||
|
@@ -80,7 +80,7 @@ curl --request POST \
|
||||
|
||||
| Field | Type | Description |
|
||||
| ---------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| org_ids | list of strings | provide a list of organizationIDs to select which organizations should be exported (eg, `[ "70669144072186707", "70671105999825752" ]`); leave empty to export all |
|
||||
| org_ids | list of strings | provide a list of Organization IDs to select which organizations should be exported (eg, `[ "70669144072186707", "70671105999825752" ]`); leave empty to export all |
|
||||
| excluded_org_ids | list of strings | to exclude several organization, if for example no organizations are selected |
|
||||
| with_passwords | bool | to include the hashed_passwords of the users in the export |
|
||||
| with_otp | bool | to include the OTP-code of the users in the export |
|
||||
@@ -143,7 +143,7 @@ curl --request POST \
|
||||
|
||||
| Field | Type | Description |
|
||||
| ---------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| org_ids | list of strings | provide a list of organizationIDs to select which organizations should be exported (eg, `[ "70669144072186707", "70671105999825752" ]`); leave empty to export all |
|
||||
| org_ids | list of strings | provide a list of Organization IDs to select which organizations should be exported (eg, `[ "70669144072186707", "70671105999825752" ]`); leave empty to export all |
|
||||
| excluded_org_ids | list of strings | to exclude several organization, if for example no organizations are selected |
|
||||
| with_passwords | bool | to include the hashed_passwords of the users in the export |
|
||||
| with_otp | bool | to include the OTP-code of the users in the export |
|
||||
|
@@ -43,7 +43,7 @@ In order to define the need of the **Portal Application** some planning consider
|
||||
|
||||
You can decide whether a organization is preselected for the login or if the user is redirected to the default login screen. Using OpenID Connect, you can send the user to a specific organization by defining the organization in a [reserved scope](/docs/apis/openidoauth/scopes#reserved-scopes) (primary domain).
|
||||
Settings to the branding or the login options of the organization can be made from the organization section in [Console](/docs/concepts/features/console).
|
||||
The behavior of the login branding can be set in your projects detail page. You can choose the branding of the selected organization, the user resource owner, or the projects resource owner.
|
||||
The behavior of the login branding can be set in your projects detail page. You can choose the branding of the selected organization, the user's organization, or the project's organization.
|
||||
|
||||
### Organizations
|
||||
|
||||
|
@@ -293,7 +293,7 @@ Excitingly, v3 introduces the foundational elements for Actions V2, opening up a
|
||||
|
||||
### v4.x
|
||||
|
||||
**Current State**: Implementation
|
||||
**Current State**: General Availability / Stable
|
||||
|
||||
|
||||
<details>
|
||||
@@ -311,9 +311,13 @@ Excitingly, v3 introduces the foundational elements for Actions V2, opening up a
|
||||
This change, along with standardized naming and improved documentation, will simplify integration, accelerate development, and create a more intuitive experience for our customers and community.
|
||||
|
||||
Resources integrated in this release:
|
||||
- Instances
|
||||
- Applications (in beta)
|
||||
- Authorizations (in beta)
|
||||
- Instances (in beta)
|
||||
- Organizations
|
||||
- Projects
|
||||
- Permissions (in beta)
|
||||
- Projects (in beta)
|
||||
- Settings (beta) now includes 3 new endpoints: `ListOrganizationSettings()`, `SetOrganizationSettings()` and `DeleteOrganizationSettings()`
|
||||
- Users
|
||||
|
||||
For more details read the [Github Issue](https://github.com/zitadel/zitadel/issues/6305)
|
||||
@@ -369,40 +373,123 @@ Excitingly, v3 introduces the foundational elements for Actions V2, opening up a
|
||||
|
||||
We're officially moving our new Login UI v2 from beta to General Availability.
|
||||
Starting now, it will be the default login experience for all new customers.
|
||||
With this release, 8.0we are also focused on implementing previously missing features, such as device authorization and LDAP IDP support, to make the new UI fully feature-complete.
|
||||
With this release, 8.0 we are also focused on implementing previously missing features, such as device authorization and LDAP IDP support, to make the new UI fully feature-complete.
|
||||
|
||||
- [Hosted Login V2](http://localhost:3000/docs/guides/integrate/login/hosted-login#hosted-login-version-2-beta)
|
||||
- [Hosted Login V2](../guides/integrate/login/hosted-login#hosted-login-version-2-beta)
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Web Keys</summary>
|
||||
<summary>Actions v2</summary>
|
||||
|
||||
Web Keys in ZITADEL are used to sign and verify JSON Web Tokens (JWT).
|
||||
ID tokens are created, signed and returned by ZITADEL when a OpenID connect (OIDC) or OAuth2 authorization flow completes and a user is authenticated.
|
||||
Based on customer and community feedback, we've updated our key management system. You now have full manual control over key generation and rotation, instead of the previous automatic process.
|
||||
This API enables you to manage custom executions and targets—formerly known as actions—across your entire ZITADEL instance.
|
||||
With Actions V2, you gain significantly more flexibility to tailor ZITADEL’s behavior compared to previous versions.
|
||||
Actions are now available instance-wide, eliminating the need to configure them for each organization individually.
|
||||
ZITADEL no longer restricts the implementation language, tooling, or runtime for action executions.
|
||||
Instead, you define external endpoints that are called by ZITADEL and maintained by you.
|
||||
|
||||
Read the full description about Web Keys in our [Documentation](https://zitadel.com/docs/guides/integrate/login/oidc/webkeys).
|
||||
- [Actions V2](../apis/resources/action_service_v2)
|
||||
</details>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Deprecated endpoints</summary>
|
||||
|
||||
<Deprecated/>
|
||||
|
||||
<details>
|
||||
<summary>Organization Objects V1 > Users V1</summary>
|
||||
|
||||
- `AddMachineKey()`
|
||||
- `AddMachineUser()`
|
||||
- `AddPersonalAccessToken()`
|
||||
- `BulkRemoveUserMetadata()`
|
||||
- `BulkSetUserMetadata()`
|
||||
- `GenerateMachineSecret()`
|
||||
- `GetMachineKeyByIDs()`
|
||||
- `GetOrgByDomainGlobal()`
|
||||
- `GetPersonalAccessTokenByIDs()`
|
||||
- `GetUserMetadata()`
|
||||
- `ListAppKeys()`
|
||||
- `ListMachineKeys()`
|
||||
- `ListPersonalAccessTokens()`
|
||||
- `ListUserMetadata()`
|
||||
- `RemoveMachineKey()`
|
||||
- `RemoveMachineSecret()`
|
||||
- `RemovePersonalAccessToken()`
|
||||
- `RemoveUserMetadata()`
|
||||
- `SetUserMetadata()`
|
||||
- `UpdateHumanPhone()`
|
||||
- `UpdateMachine()`
|
||||
- `UpdateUserName()`
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>SCIM 2.0 Server - User Resource</summary>
|
||||
<summary>Projects V1</summary>
|
||||
|
||||
The Zitadel SCIM v2 service provider interface enables seamless integration of identity and access management (IAM) systems with Zitadel, following the System for Cross-domain Identity Management (SCIM) v2.0 specification.
|
||||
This interface allows standardized management of IAM resources, making it easier to automate user provisioning and deprovisioning.
|
||||
|
||||
- [SCIM 2.0 API](https://zitadel.com/docs/apis/scim2)
|
||||
- [Manage Users Guide](https://zitadel.com/docs/guides/manage/user/scim2)
|
||||
- `AddProject()`
|
||||
- `AddProjectGrant()`
|
||||
- `AddProjectRole()`
|
||||
- `BulkAddProjectRoles()`
|
||||
- `DeactivateProject()`
|
||||
- `DeactivateProjectGrant()`
|
||||
- `GetGrantedProjectByID()`
|
||||
- `GetProjectByID()`
|
||||
- `GetProjectGrantByID()`
|
||||
- `ListAllProjectGrants()`
|
||||
- `ListGrantedProjectRoles()`
|
||||
- `ListGrantedProjects()`
|
||||
- `ListProjectGrants()`
|
||||
- `ListProjectRoles()`
|
||||
- `ListProjects()`
|
||||
- `ReactivateProject()`
|
||||
- `ReactivateProjectGrant()`
|
||||
- `RemoveProject()`
|
||||
- `RemoveProjectGrant()`
|
||||
- `RemoveProjectRole()`
|
||||
- `UpdateProject()`
|
||||
- `UpdateProjectGrant()`
|
||||
- `UpdateProjectRole()`
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Caches</summary>
|
||||
<summary>Members V1</summary>
|
||||
|
||||
ZITADEL supports the use of a caches to speed up the lookup of frequently needed objects.
|
||||
As opposed to HTTP caches which might reside between ZITADEL and end-user applications, the cache build into ZITADEL uses active invalidation when an object gets updated.
|
||||
Another difference is that HTTP caches only cache the result of a complete request and the built-in cache stores objects needed for the internal business logic.
|
||||
For example, each request made to ZITADEL needs to retrieve and set instance information in middleware.
|
||||
- `AddIAMMember()`
|
||||
- `AddOrgMember()`
|
||||
- `AddProjectGrantMember()`
|
||||
- `AddProjectMember()`
|
||||
- `ListIAMMembers()`
|
||||
- `ListOrgMembers()`
|
||||
- `ListProjectGrantMembers()`
|
||||
- `ListProjectMembers()`
|
||||
- `ListUserMemberships()`
|
||||
- `RemoveIAMMember()`
|
||||
- `RemoveOrgMember()`
|
||||
- `RemoveProjectGrantMember()`
|
||||
- `RemoveProjectMember()`
|
||||
- `UpdateIAMMember()`
|
||||
- `UpdateOrgMember()`
|
||||
- `UpdateProjectGrantMember()`
|
||||
- `UpdateProjectMember()`
|
||||
</details>
|
||||
|
||||
Read more about Zitadel Caches [here](https://zitadel.com/docs/self-hosting/manage/cache)
|
||||
<details>
|
||||
<summary>Instance Lifecycle V1 > System Service V1</summary>
|
||||
|
||||
- `AddInstanceTrustedDomain()`
|
||||
- `GetMyInstance()`
|
||||
- `ListInstanceDomains()`
|
||||
- `ListInstanceTrustedDomains()`
|
||||
- `RemoveInstanceTrustedDomain()`
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Instance Objects V1 > Organizations V1 </summary>
|
||||
|
||||
- `GetDefaultOrg()`
|
||||
- `GetOrgByID()`
|
||||
- `IsOrgUnique()`
|
||||
</details>
|
||||
</details>
|
||||
|
||||
|
1
docs/docs/self-hosting/deploy/.gitignore
vendored
Normal file
1
docs/docs/self-hosting/deploy/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.pat
|
@@ -1,8 +1,6 @@
|
||||
Open your favorite internet browser and navigate to [http://localhost:8080/ui/console](http://localhost:8080/ui/console).
|
||||
This is the default IAM admin users login:
|
||||
- **username**: *zitadel-admin@<span></span>zitadel.localhost*
|
||||
- **password**: *Password1!*
|
||||
Open your favorite internet browser and navigate to http://localhost:8080/ui/console?login_hint=zitadel-admin@zitadel.localhost.
|
||||
Enther the password *Password1!* to log in.
|
||||
|
||||
:::info
|
||||
|
||||
In the above username, replace localhost with your configured external domain, if any. e.g. with *zitadel-admin@<span></span>zitadel.sso.my.domain.tld*
|
||||
In the above login hint in the URL, replace localhost with your configured external domain, if any. e.g. with *zitadel-admin@<span></span>zitadel.sso.my.domain.tld*
|
||||
:::
|
@@ -1,18 +1,17 @@
|
||||
---
|
||||
title: Set up ZITADEL with Docker Compose
|
||||
title: Set up Zitadel with Docker Compose
|
||||
sidebar_label: Docker Compose
|
||||
---
|
||||
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import DockerComposeSource from '!!raw-loader!./docker-compose.yaml'
|
||||
import DockerComposeSaSource from '!!raw-loader!./docker-compose-sa.yaml'
|
||||
import Disclaimer from './_disclaimer.mdx'
|
||||
import DefaultUser from './_defaultuser.mdx'
|
||||
import Next from './_next.mdx'
|
||||
import NoteInstanceNotFound from './troubleshooting/_note_instance_not_found.mdx';
|
||||
|
||||
|
||||
The setup is tested against Docker version 20.10.17 and Docker Compose version v2.2.3
|
||||
The setup is tested against Docker version 28.3.2 and Docker Compose version v2.38.2
|
||||
|
||||
## Docker compose
|
||||
|
||||
@@ -27,41 +26,24 @@ By executing the commands below, you will download the following file:
|
||||
# Download the docker compose example configuration.
|
||||
wget https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/docker-compose.yaml
|
||||
|
||||
# Run the database and application containers.
|
||||
docker compose up --detach
|
||||
# Make sure you have the latest image versions
|
||||
docker compose pull
|
||||
|
||||
# Run the PostgreSQL database, the Zitadel API and the Zitadel login.
|
||||
docker compose up
|
||||
```
|
||||
|
||||
<DefaultUser components={props.components} />
|
||||
|
||||
<NoteInstanceNotFound/>
|
||||
|
||||
## VideoGuide
|
||||
<iframe width="100%" height="315" src="https://www.youtube.com/embed/-02FaoN9Fko" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
|
||||
## Docker compose with service account
|
||||
|
||||
By executing the commands below, you will download the following file:
|
||||
|
||||
<details>
|
||||
<summary>docker-compose-sa.yaml</summary>
|
||||
<CodeBlock language="yaml">{DockerComposeSaSource}</CodeBlock>
|
||||
</details>
|
||||
|
||||
:::info
|
||||
If you ran these commands for an existing instance that still uses the login v1, [create a login client for it to the now running v2 login](/self-hosting/manage/login-client#create-login-client).
|
||||
Move the login client PAT to `./login-client.pat` and restart the login container.
|
||||
```bash
|
||||
# Download the docker compose example configuration.
|
||||
wget https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/docker-compose-sa.yaml -O docker-compose.yaml
|
||||
|
||||
# create the machine key directory
|
||||
mkdir machinekey
|
||||
|
||||
# Run the database and application containers.
|
||||
docker compose up --detach
|
||||
|
||||
# then you can move your machine key
|
||||
mv ./machinekey/zitadel-admin-sa.json $HOME/zitadel-admin-sa.json
|
||||
docker compose restart login
|
||||
```
|
||||
Now, [enable the Login UI for all users](/self-hosting/manage/login-client#require-login-v2)
|
||||
:::
|
||||
|
||||
This key can be used to provision resources with for example [Terraform](/docs/guides/manage/terraform-provider).
|
||||
|
||||
<NoteInstanceNotFound/>
|
||||
<Next components={props.components} />
|
||||
<Disclaimer components={props.components} />
|
||||
|
@@ -1,49 +0,0 @@
|
||||
services:
|
||||
zitadel:
|
||||
# The user should have the permission to write to ./machinekey
|
||||
user: "${UID:-1000}"
|
||||
restart: 'always'
|
||||
networks:
|
||||
- 'zitadel'
|
||||
image: 'ghcr.io/zitadel/zitadel:latest'
|
||||
command: 'start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --tlsMode disabled'
|
||||
environment:
|
||||
ZITADEL_DATABASE_POSTGRES_HOST: db
|
||||
ZITADEL_DATABASE_POSTGRES_PORT: 5432
|
||||
ZITADEL_DATABASE_POSTGRES_DATABASE: zitadel
|
||||
ZITADEL_DATABASE_POSTGRES_USER_USERNAME: zitadel
|
||||
ZITADEL_DATABASE_POSTGRES_USER_PASSWORD: zitadel
|
||||
ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE: disable
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME: postgres
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD: postgres
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE: disable
|
||||
ZITADEL_EXTERNALSECURE: false
|
||||
ZITADEL_FIRSTINSTANCE_MACHINEKEYPATH: /machinekey/zitadel-admin-sa.json
|
||||
ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_USERNAME: zitadel-admin-sa
|
||||
ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_NAME: Admin
|
||||
ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINEKEY_TYPE: 1
|
||||
depends_on:
|
||||
db:
|
||||
condition: 'service_healthy'
|
||||
ports:
|
||||
- '8080:8080'
|
||||
volumes:
|
||||
- ./machinekey:/machinekey
|
||||
|
||||
db:
|
||||
restart: 'always'
|
||||
image: postgres:17-alpine
|
||||
environment:
|
||||
PGUSER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
networks:
|
||||
- 'zitadel'
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready", "-d", "zitadel", "-U", "postgres"]
|
||||
interval: '10s'
|
||||
timeout: '30s'
|
||||
retries: 5
|
||||
start_period: '20s'
|
||||
|
||||
networks:
|
||||
zitadel:
|
@@ -1,11 +1,11 @@
|
||||
services:
|
||||
zitadel:
|
||||
restart: 'always'
|
||||
networks:
|
||||
- 'zitadel'
|
||||
image: 'ghcr.io/zitadel/zitadel:latest'
|
||||
command: 'start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --tlsMode disabled'
|
||||
restart: unless-stopped
|
||||
image: ghcr.io/zitadel/zitadel:latest
|
||||
command: start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --tlsMode disabled
|
||||
environment:
|
||||
ZITADEL_EXTERNALSECURE: false
|
||||
ZITADEL_TLS_ENABLED: false
|
||||
ZITADEL_DATABASE_POSTGRES_HOST: db
|
||||
ZITADEL_DATABASE_POSTGRES_PORT: 5432
|
||||
ZITADEL_DATABASE_POSTGRES_DATABASE: zitadel
|
||||
@@ -15,27 +15,84 @@ services:
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME: postgres
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD: postgres
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE: disable
|
||||
ZITADEL_EXTERNALSECURE: false
|
||||
# By configuring a login client, the setup job creates a user of type machine with the role IAM_LOGIN_CLIENT.
|
||||
# It writes a PAT to the path specified in ZITADEL_FIRSTINSTANCE_LOGINCLIENTPATPATH.
|
||||
# The PAT is passed to the login container via the environment variable ZITADEL_SERVICE_USER_TOKEN_FILE.
|
||||
ZITADEL_FIRSTINSTANCE_LOGINCLIENTPATPATH: /current-dir/login-client.pat
|
||||
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORDCHANGEREQUIRED: false
|
||||
ZITADEL_FIRSTINSTANCE_ORG_LOGINCLIENT_MACHINE_USERNAME: login-client
|
||||
ZITADEL_FIRSTINSTANCE_ORG_LOGINCLIENT_MACHINE_NAME: Automatically Initialized IAM_LOGIN_CLIENT
|
||||
ZITADEL_FIRSTINSTANCE_ORG_LOGINCLIENT_PAT_EXPIRATIONDATE: '2029-01-01T00:00:00Z'
|
||||
ZITADEL_DEFAULTINSTANCE_FEATURES_LOGINV2_REQUIRED: true
|
||||
ZITADEL_DEFAULTINSTANCE_FEATURES_LOGINV2_BASEURI: http://localhost:3000/ui/v2/login
|
||||
ZITADEL_OIDC_DEFAULTLOGINURLV2: http://localhost:3000/ui/v2/login/login?authRequest=
|
||||
ZITADEL_OIDC_DEFAULTLOGOUTURLV2: http://localhost:3000/ui/v2/login/logout?post_logout_redirect=
|
||||
ZITADEL_SAML_DEFAULTLOGINURLV2: http://localhost:3000/ui/v2/login/login?samlRequest=
|
||||
# By configuring a machine, the setup job creates a user of type machine with the role IAM_OWNER.
|
||||
# It writes a personal access token (PAT) to the path specified in ZITADEL_FIRSTINSTANCE_PATPATH.
|
||||
# The PAT can be used to provision resources with [Terraform](/docs/guides/manage/terraform-provider), for example.
|
||||
ZITADEL_FIRSTINSTANCE_PATPATH: /current-dir/admin.pat
|
||||
ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_USERNAME: admin
|
||||
ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_NAME: Automatically Initialized IAM_OWNER
|
||||
ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINEKEY_TYPE: 1
|
||||
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
- /app/zitadel
|
||||
- ready
|
||||
interval: 10s
|
||||
timeout: 60s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
volumes:
|
||||
- .:/current-dir:delegated
|
||||
ports:
|
||||
- 8080:8080
|
||||
- 3000:3000
|
||||
networks:
|
||||
- zitadel
|
||||
depends_on:
|
||||
db:
|
||||
condition: 'service_healthy'
|
||||
ports:
|
||||
- '8080:8080'
|
||||
condition: service_healthy
|
||||
|
||||
login:
|
||||
restart: unless-stopped
|
||||
image: ghcr.io/zitadel/zitadel-login:latest
|
||||
# If you can't use the network_mode service:zitadel, you can pass the environment variable CUSTOM_REQUEST_HEADERS=Host:localhost instead.
|
||||
environment:
|
||||
- ZITADEL_API_URL=http://localhost:8080
|
||||
- NEXT_PUBLIC_BASE_PATH=/ui/v2/login
|
||||
- ZITADEL_SERVICE_USER_TOKEN_FILE=/current-dir/login-client.pat
|
||||
user: "${UID:-1000}"
|
||||
network_mode: service:zitadel
|
||||
volumes:
|
||||
- .:/current-dir:ro
|
||||
depends_on:
|
||||
zitadel:
|
||||
condition: service_healthy
|
||||
restart: false
|
||||
|
||||
db:
|
||||
restart: 'always'
|
||||
restart: unless-stopped
|
||||
image: postgres:17-alpine
|
||||
environment:
|
||||
PGUSER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
networks:
|
||||
- 'zitadel'
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready", "-d", "zitadel", "-U", "postgres"]
|
||||
interval: '10s'
|
||||
timeout: '30s'
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- pg_isready
|
||||
- -d
|
||||
- zitadel
|
||||
- -U
|
||||
- postgres
|
||||
interval: 10s
|
||||
timeout: 30s
|
||||
retries: 5
|
||||
start_period: '20s'
|
||||
start_period: 20s
|
||||
networks:
|
||||
- zitadel
|
||||
|
||||
networks:
|
||||
zitadel:
|
||||
|
@@ -1,67 +0,0 @@
|
||||
---
|
||||
title: Set up ZITADEL on Knative
|
||||
sidebar_label: Knative
|
||||
---
|
||||
|
||||
import Disclaimer from './_disclaimer.mdx'
|
||||
import DefaultUser from './_defaultuser.mdx'
|
||||
import Next from './_next.mdx'
|
||||
import NoteInstanceNotFound from './troubleshooting/_note_instance_not_found.mdx';
|
||||
|
||||
|
||||
## Install Knative
|
||||
|
||||
Follow the [Knative quickstart guide](https://knative.dev/docs/getting-started/quickstart-install/) to get a local kind/minikube environment with Knative capabilities.
|
||||
|
||||
For example, to install Knative on a kind cluster, run `kn quickstart kind`.
|
||||
|
||||
## Run PostgreSQL
|
||||
|
||||
If you are following the Knative Tutorial, you can deploy Postgres as a StatefulSet for the tutorials Bookstore sample app. For example:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/knative/docs.git
|
||||
kubectl apply -f docs/code-samples/eventing/bookstore-sample-app/solution/db-service/
|
||||
```
|
||||
|
||||
## Start Zitadel as a Knative Service
|
||||
|
||||
```bash
|
||||
kn service create zitadel \
|
||||
--image ghcr.io/zitadel/zitadel:latest \
|
||||
--port 8080 \
|
||||
--env ZITADEL_EXTERNALDOMAIN=zitadel.default.127.0.0.1.sslip.io \
|
||||
--env ZITADEL_EXTERNALSECURE=false \
|
||||
--env ZITADEL_EXTERNALPORT=80 \
|
||||
--env ZITADEL_TLS_ENABLED=false \
|
||||
--env ZITADEL_DATABASE_POSTGRES_HOST=postgresql \
|
||||
--env ZITADEL_DATABASE_POSTGRES_PORT=5432 \
|
||||
--env ZITADEL_DATABASE_POSTGRES_DATABASE=zitadel \
|
||||
--env ZITADEL_DATABASE_POSTGRES_USER_USERNAME=myzitadeluser \
|
||||
--env ZITADEL_DATABASE_POSTGRES_USER_PASSWORD=myzitadelpassword \
|
||||
--env ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE=disable \
|
||||
--env ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME=myuser \
|
||||
--env ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD=mypassword \
|
||||
--env ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE=disable \
|
||||
--env ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORDCHANGEREQUIRED=false \
|
||||
--env ZITADEL_DEFAULTINSTANCE_LOGINPOLICY_MFAINITSKIPLIFETIME="0s" \
|
||||
--arg "start-from-init" --arg "--masterkey=MasterkeyNeedsToHave32Characters"
|
||||
```
|
||||
|
||||
## Access ZITADEL
|
||||
|
||||
### Get the ZITADEL URL
|
||||
|
||||
```bash
|
||||
kn services list
|
||||
|
||||
NAME URL LATEST AGE CONDITIONS READY REASON
|
||||
zitadel http://zitadel.default.127.0.0.1.sslip.io zitadel-00001 10m 3 OK / 3 True
|
||||
```
|
||||
|
||||
Open your browser at http://zitadel.default.127.0.0.1.sslip.io/ui/console?login_hint=zitadel-admin@zitadel.zitadel.default.127.0.0.1.sslip.io and use the initial password _Password1!_
|
||||
|
||||
<NoteInstanceNotFound/>
|
||||
|
||||
<Next components={props.components} />
|
||||
<Disclaimer components={props.components} />
|
@@ -1 +0,0 @@
|
||||
.env-file
|
@@ -1,157 +0,0 @@
|
||||
services:
|
||||
|
||||
db:
|
||||
image: postgres:17-alpine
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- POSTGRES_USER=root
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
networks:
|
||||
- 'storage'
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready", "-d", "db_prod"]
|
||||
interval: 10s
|
||||
timeout: 60s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
volumes:
|
||||
- 'data:/var/lib/postgresql/data:rw'
|
||||
|
||||
zitadel-init:
|
||||
restart: 'no'
|
||||
networks:
|
||||
- 'storage'
|
||||
image: 'ghcr.io/zitadel/zitadel:latest'
|
||||
command: 'init --config /example-zitadel-config.yaml --config /example-zitadel-secrets.yaml'
|
||||
depends_on:
|
||||
db:
|
||||
condition: 'service_healthy'
|
||||
volumes:
|
||||
- './example-zitadel-config.yaml:/example-zitadel-config.yaml:ro'
|
||||
- './example-zitadel-secrets.yaml:/example-zitadel-secrets.yaml:ro'
|
||||
|
||||
zitadel-setup:
|
||||
restart: 'no'
|
||||
networks:
|
||||
- 'storage'
|
||||
# We use the debug image so we have the environment to
|
||||
# - create the .env file for the login to authenticate at Zitadel
|
||||
# - set the correct permissions for the .env-file folder
|
||||
image: 'ghcr.io/zitadel/zitadel:latest-debug'
|
||||
user: root
|
||||
entrypoint: '/bin/sh'
|
||||
command:
|
||||
- -c
|
||||
- >
|
||||
/app/zitadel setup
|
||||
--config /example-zitadel-config.yaml
|
||||
--config /example-zitadel-secrets.yaml
|
||||
--steps /example-zitadel-init-steps.yaml
|
||||
--masterkey ${ZITADEL_MASTERKEY} &&
|
||||
mv /pat /.env-file/pat || exit 0 &&
|
||||
echo ZITADEL_SERVICE_USER_TOKEN=$(cat /.env-file/pat) > /.env-file/.env &&
|
||||
chown -R 1001:${GID} /.env-file &&
|
||||
chmod -R 770 /.env-file
|
||||
environment:
|
||||
- GID
|
||||
depends_on:
|
||||
zitadel-init:
|
||||
condition: 'service_completed_successfully'
|
||||
restart: false
|
||||
volumes:
|
||||
- './.env-file:/.env-file:rw'
|
||||
- './example-zitadel-config.yaml:/example-zitadel-config.yaml:ro'
|
||||
- './example-zitadel-secrets.yaml:/example-zitadel-secrets.yaml:ro'
|
||||
- './example-zitadel-init-steps.yaml:/example-zitadel-init-steps.yaml:ro'
|
||||
|
||||
zitadel:
|
||||
restart: 'unless-stopped'
|
||||
networks:
|
||||
- 'backend'
|
||||
- 'storage'
|
||||
image: 'ghcr.io/zitadel/zitadel:latest'
|
||||
command: >
|
||||
start --config /example-zitadel-config.yaml
|
||||
--config /example-zitadel-secrets.yaml
|
||||
--masterkey ${ZITADEL_MASTERKEY}
|
||||
depends_on:
|
||||
zitadel-setup:
|
||||
condition: 'service_completed_successfully'
|
||||
restart: true
|
||||
volumes:
|
||||
- './example-zitadel-config.yaml:/example-zitadel-config.yaml:ro'
|
||||
- './example-zitadel-secrets.yaml:/example-zitadel-secrets.yaml:ro'
|
||||
ports:
|
||||
- "8080:8080"
|
||||
healthcheck:
|
||||
test: [
|
||||
"CMD", "/app/zitadel", "ready",
|
||||
"--config", "/example-zitadel-config.yaml",
|
||||
"--config", "/example-zitadel-secrets.yaml"
|
||||
]
|
||||
interval: 10s
|
||||
timeout: 60s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
|
||||
# The use-new-login service configures Zitadel to use the new login v2 for all applications.
|
||||
# It also gives the setupped machine user the necessary IAM_LOGIN_CLIENT role.
|
||||
use-new-login:
|
||||
restart: 'on-failure'
|
||||
user: "1001"
|
||||
networks:
|
||||
- 'backend'
|
||||
image: 'badouralix/curl-jq:alpine'
|
||||
entrypoint: '/bin/sh'
|
||||
command:
|
||||
- -c
|
||||
- >
|
||||
curl -X PUT -H "Host: 127.0.0.1.sslip.io" -H "Authorization: Bearer $(cat ./.env-file/pat)" --insecure http://zitadel:8080/v2/features/instance -d '{"loginV2": {"required": true}}' &&
|
||||
LOGIN_USER=$(curl --fail-with-body -H "Host: 127.0.0.1.sslip.io" -H "Authorization: Bearer $(cat ./.env-file/pat)" --insecure http://zitadel:8080/auth/v1/users/me | jq -r '.user.id') &&
|
||||
curl -X PUT -H "Host: 127.0.0.1.sslip.io" -H "Authorization: Bearer $(cat ./.env-file/pat)" --insecure http://zitadel:8080/admin/v1/members/$${LOGIN_USER} -d '{"roles": ["IAM_OWNER", "IAM_LOGIN_CLIENT"]}'
|
||||
volumes:
|
||||
- './.env-file:/.env-file:ro'
|
||||
depends_on:
|
||||
zitadel:
|
||||
condition: 'service_healthy'
|
||||
restart: false
|
||||
|
||||
login:
|
||||
restart: 'unless-stopped'
|
||||
networks:
|
||||
- 'backend'
|
||||
image: 'ghcr.io/zitadel/login:main'
|
||||
environment:
|
||||
- ZITADEL_API_URL=http://zitadel:8080
|
||||
- CUSTOM_REQUEST_HEADERS=Host:127.0.0.1.sslip.io
|
||||
- NEXT_PUBLIC_BASE_PATH="/ui/v2/login"
|
||||
user: "${UID:-1000}"
|
||||
volumes:
|
||||
- './.env-file:/.env-file:ro'
|
||||
depends_on:
|
||||
zitadel:
|
||||
condition: 'service_healthy'
|
||||
restart: false
|
||||
|
||||
traefik:
|
||||
restart: 'unless-stopped'
|
||||
networks:
|
||||
- 'backend'
|
||||
image: "traefik:latest"
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- "./example-traefik.yaml:/etc/traefik/traefik.yaml"
|
||||
depends_on:
|
||||
zitadel:
|
||||
condition: 'service_healthy'
|
||||
login:
|
||||
condition: 'service_started'
|
||||
|
||||
networks:
|
||||
storage:
|
||||
backend:
|
||||
|
||||
volumes:
|
||||
data:
|
@@ -1,40 +0,0 @@
|
||||
log:
|
||||
level: DEBUG
|
||||
|
||||
accessLog: {}
|
||||
|
||||
entrypoints:
|
||||
websecure:
|
||||
address: ":443"
|
||||
|
||||
providers:
|
||||
file:
|
||||
filename: /etc/traefik/traefik.yaml
|
||||
|
||||
http:
|
||||
routers:
|
||||
login:
|
||||
entryPoints:
|
||||
- websecure
|
||||
service: login
|
||||
rule: 'Host(`127.0.0.1.sslip.io`) && PathPrefix(`/ui/v2/login`)'
|
||||
tls: {}
|
||||
zitadel:
|
||||
entryPoints:
|
||||
- websecure
|
||||
service: zitadel
|
||||
rule: 'Host(`127.0.0.1.sslip.io`) && !PathPrefix(`/ui/v2/login`)'
|
||||
tls: {}
|
||||
|
||||
services:
|
||||
login:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: http://login:3000
|
||||
passHostHeader: true
|
||||
zitadel:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: h2c://zitadel:8080
|
||||
passHostHeader: true
|
||||
|
@@ -1,29 +0,0 @@
|
||||
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/main/cmd/defaults.yaml
|
||||
|
||||
ExternalSecure: true
|
||||
ExternalDomain: 127.0.0.1.sslip.io
|
||||
ExternalPort: 443
|
||||
|
||||
# Traefik terminates TLS. Inside the Docker network, we use plain text.
|
||||
TLS.Enabled: false
|
||||
|
||||
# If not using the docker compose example, adjust these values for connecting ZITADEL to your PostgreSQL
|
||||
Database:
|
||||
postgres:
|
||||
Host: 'db'
|
||||
Port: 5432
|
||||
Database: zitadel
|
||||
User.SSL.Mode: 'disable'
|
||||
Admin.SSL.Mode: 'disable'
|
||||
|
||||
# By default, ZITADEL should redirect to /ui/v2/login
|
||||
OIDC:
|
||||
DefaultLoginURLV2: "/ui/v2/login/login?authRequest=" # ZITADEL_OIDC_DEFAULTLOGINURLV2
|
||||
DefaultLogoutURLV2: "/ui/v2/login/logout?post_logout_redirect=" # ZITADEL_OIDC_DEFAULTLOGOUTURLV2
|
||||
SAML.DefaultLoginURLV2: "/ui/v2/login/login?authRequest=" # ZITADEL_SAML_DEFAULTLOGINURLV2
|
||||
|
||||
# Access logs allow us to debug Network issues
|
||||
LogStore.Access.Stdout.Enabled: true
|
||||
|
||||
# Skipping the MFA init step allows us to immediately authenticate at the console
|
||||
DefaultInstance.LoginPolicy.MfaInitSkipLifetime: "0s"
|
@@ -1,12 +0,0 @@
|
||||
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/main/cmd/setup/steps.yaml
|
||||
FirstInstance:
|
||||
PatPath: '/pat'
|
||||
Org:
|
||||
# We want to authenticate immediately at the console without changing the password
|
||||
Human:
|
||||
PasswordChangeRequired: false
|
||||
Machine:
|
||||
Machine:
|
||||
Username: 'login-container'
|
||||
Name: 'Login Container'
|
||||
Pat.ExpirationDate: '2029-01-01T00:00:00Z'
|
@@ -1,12 +0,0 @@
|
||||
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/main/cmd/defaults.yaml
|
||||
|
||||
# If not using the docker compose example, adjust these values for connecting ZITADEL to your PostgreSQL
|
||||
Database:
|
||||
postgres:
|
||||
User:
|
||||
# If the user doesn't exist already, it is created
|
||||
Username: 'zitadel_user'
|
||||
Password: 'zitadel'
|
||||
Admin:
|
||||
Username: 'root'
|
||||
Password: 'postgres'
|
@@ -1,74 +0,0 @@
|
||||
---
|
||||
title: A Zitadel Load Balancing Example
|
||||
---
|
||||
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import DockerComposeSource from '!!raw-loader!./docker-compose.yaml'
|
||||
import ExampleTraefikSource from '!!raw-loader!./example-traefik.yaml'
|
||||
import ExampleZITADELConfigSource from '!!raw-loader!./example-zitadel-config.yaml'
|
||||
import ExampleZITADELSecretsSource from '!!raw-loader!./example-zitadel-secrets.yaml'
|
||||
import ExampleZITADELInitStepsSource from '!!raw-loader!./example-zitadel-init-steps.yaml'
|
||||
|
||||
The stack consists of four long-running containers and a couple of short-lived containers:
|
||||
- A [Traefik](https://doc.traefik.io/traefik/) reverse proxy container with upstream HTTP/2 enabled, issuing a self-signed TLS certificate.
|
||||
- A Login container that is accessible via Traefik at `/ui/v2/login`
|
||||
- A Zitadel container that is accessible via Traefik at all other paths than `/ui/v2/login`.
|
||||
- An insecure [PostgreSQL](https://www.postgresql.org/docs/current/index.html).
|
||||
|
||||
The Traefik container and the login container call the Zitadel container via the internal Docker network at `h2c://zitadel:8080`
|
||||
|
||||
The setup is tested against Docker version 28.0.4 and Docker Compose version v2.34.0
|
||||
|
||||
By executing the commands below, you will download the following files:
|
||||
|
||||
<details>
|
||||
<summary>docker-compose.yaml</summary>
|
||||
<CodeBlock language="yaml">{DockerComposeSource}</CodeBlock>
|
||||
</details>
|
||||
<details>
|
||||
<summary>example-traefik.yaml</summary>
|
||||
<CodeBlock language="yaml">{ExampleTraefikSource}</CodeBlock>
|
||||
</details>
|
||||
<details>
|
||||
<summary>example-zitadel-config.yaml</summary>
|
||||
<CodeBlock language="yaml">{ExampleZITADELConfigSource}</CodeBlock>
|
||||
</details>
|
||||
<details>
|
||||
<summary>example-zitadel-secrets.yaml</summary>
|
||||
<CodeBlock language="yaml">{ExampleZITADELSecretsSource}</CodeBlock>
|
||||
</details>
|
||||
<details>
|
||||
<summary>example-zitadel-init-steps.yaml</summary>
|
||||
<CodeBlock language="yaml">{ExampleZITADELInitStepsSource}</CodeBlock>
|
||||
</details>
|
||||
|
||||
```bash
|
||||
# Download the docker compose example configuration.
|
||||
wget https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/loadbalancing-example/docker-compose.yaml
|
||||
|
||||
# Download the Traefik example configuration.
|
||||
wget https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/loadbalancing-example/example-traefik.yaml
|
||||
|
||||
# Download and adjust the example configuration file containing standard configuration.
|
||||
wget https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/loadbalancing-example/example-zitadel-config.yaml
|
||||
|
||||
# Download and adjust the example configuration file containing secret configuration.
|
||||
wget https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/loadbalancing-example/example-zitadel-secrets.yaml
|
||||
|
||||
# Download and adjust the example configuration file containing database initialization configuration.
|
||||
wget https://raw.githubusercontent.com/zitadel/zitadel/main/docs/docs/self-hosting/deploy/loadbalancing-example/example-zitadel-init-steps.yaml
|
||||
|
||||
# A single ZITADEL instance always needs the same 32 bytes long masterkey
|
||||
# Generate one to a file if you haven't done so already and pass it as environment variable
|
||||
LC_ALL=C tr -dc '[:graph:]' </dev/urandom | head -c 32 > ./zitadel-masterkey
|
||||
export ZITADEL_MASTERKEY="$(cat ./zitadel-masterkey)"
|
||||
|
||||
# Run the database and application containers
|
||||
docker compose up --detach --wait
|
||||
```
|
||||
|
||||
Open your favorite internet browser at https://127.0.0.1.sslip.io/ui/console?login_hint=zitadel-admin@zitadel.127.0.0.1.sslip.io.
|
||||
Your browser warns you about the insecure self-signed TLS certificate. As 127.0.0.1.sslip.io resolves to your localhost, you can safely proceed.
|
||||
Use the password *Password1!* to log in.
|
||||
|
||||
Read more about [the login process](/guides/integrate/login/oidc/login-users).
|
3
docs/docs/self-hosting/manage/.gitignore
vendored
Normal file
3
docs/docs/self-hosting/manage/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
**/*.pat
|
||||
**/selfsigned.crt
|
||||
**/selfsigned.key
|
47
docs/docs/self-hosting/manage/login-client.mdx
Normal file
47
docs/docs/self-hosting/manage/login-client.mdx
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: Connect your Self-Hosted Login UI to Zitadel
|
||||
sidebar_label: Create a Login Client
|
||||
---
|
||||
|
||||
To enable your self-hosted Login UI to connect to the Zitadel API, it needs a token for a user with the IAM_LOGIN_CLIENT role.
|
||||
On new installations, the Zitadel setup job can be configured to automatically write a Personal Access Token (PAT) for the login client.
|
||||
Check out [one of the deployment examples](https://zitadel.com/docs/self-hosting/deploy/overview) to learn how to do this.
|
||||
|
||||
However, if you want to replace the v1 login of an existing installation by a self-hosted v2 login, the setup job won't execute these steps.
|
||||
In that case, you can create a new PAT for the login client manually.
|
||||
|
||||
## Create a Login Client User{#create-login-client}
|
||||
|
||||
In the following URLs, replace the base URL and the user ID according to your environment.
|
||||
|
||||
1. Create a new machine user, for example at http://localhost:8080/ui/console/users/create-machine
|
||||
2. Create a PAT, for example at http://localhost:8080/ui/console/users/332169800719532035?new=true&id=pat
|
||||
3. Save the PAT to a file, for example `/path/on/your/host/login-client.pat`
|
||||
4. Make sure the user has the `Iam Login Client` role (internally called `IAM_LOGIN_CLIENT`), for example at http://localhost:8080/ui/console/instance/members
|
||||
|
||||
# Configure the Login UI
|
||||
|
||||
Make sure your Login UI has the environment variable `ZITADEL_SERVICE_USER_TOKEN` set with your PAT.
|
||||
If you run the Login UI with Docker, you can also mount the file into the container and reference it by passing the environment variable `ZITADEL_SERVICE_USER_TOKEN_FILE`.
|
||||
For example:
|
||||
|
||||
```bash
|
||||
docker run -p 3000:3000 -v /path/on/your/host/login-client.pat:/path/in/container/login-client.pat:ro -e ZITADEL_SERVICE_USER_TOKEN_FILE=/path/in/container/login-client.pat ghcr.io/zitadel/zitadel-login:latest
|
||||
```
|
||||
|
||||
# Enable the Login UI for all users{#require-login-v2}
|
||||
|
||||
:::caution
|
||||
Before doing this, make sure you have a working PAT for an Iam Owner user.
|
||||
In case something goes wrong and you lock yourself out from the login screen, you can revert the changes.
|
||||
Create a machine user PAT like you created the [login client PAT above](#create-login-client), but give the user the Iam Owner role (internally called `IAM_OWNER`).
|
||||
:::
|
||||
|
||||
Enable the `Login V2` feature flag, for example at the bottom of http://localhost:8080/ui/console/instance?id=features.
|
||||
Enter the base URI of your Login UI, for example `http://localhost:3000/ui/v2/login`.
|
||||
|
||||
# Test
|
||||
|
||||
That's it!
|
||||
Click your users avatar in the top right corner of the console and select `Log in With Another Account`.
|
||||
You should see the new Login UI.
|
@@ -1,25 +0,0 @@
|
||||
## TLS mode external
|
||||
|
||||
```
|
||||
https://localhost {
|
||||
reverse_proxy h2c://localhost:8080
|
||||
tls internal #only non production
|
||||
}
|
||||
```
|
||||
|
||||
## TLS mode enabled
|
||||
|
||||
```
|
||||
https://localhost {
|
||||
reverse_proxy https://localhost:8080
|
||||
tls internal #only non production
|
||||
}
|
||||
```
|
||||
|
||||
## TLS mode disabled
|
||||
|
||||
```
|
||||
http://localhost {
|
||||
reverse_proxy h2c://localhost:8080
|
||||
}
|
||||
```
|
@@ -1,2 +1,2 @@
|
||||
- [Read more about ZITADELs TLS Modes](/self-hosting/manage/tls_modes)
|
||||
- [Read more about how ZITADEL uses HTTP/2](/self-hosting/manage/http2)
|
||||
- [Read more about Zitadel's TLS Modes](/self-hosting/manage/tls_modes)
|
||||
- [Read more about how Zitadel uses HTTP/2](/self-hosting/manage/http2)
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import ComposeYaml from "!!raw-loader!./docker-compose.yaml";
|
||||
|
||||
<>With these examples, you create and run a minimal {props.link} configuration for ZITADEL with <a href="https://docs.docker.com/compose">Docker Compose</a>.
|
||||
Whereas the guide focuses on the configuration for {props.name}, you can inspect the configurations for ZITADEL and the database in the base Docker Compose file.</>
|
||||
<>With these examples, you create and run a minimal {props.link} configuration for Zitadel with <a href="https://docs.docker.com/compose">Docker Compose</a>.
|
||||
Whereas the guide focuses on the configuration for {props.name}, you can inspect the configurations for the Zitadel API, the Zitadel login and the database in the base Docker Compose file.</>
|
||||
<details>
|
||||
<summary>base docker-compose.yaml</summary>
|
||||
<CodeBlock language="yaml">{ComposeYaml}</CodeBlock>
|
||||
|
@@ -4,27 +4,27 @@ export const Description = ({mode, name}) => {
|
||||
let desc
|
||||
switch (mode) {
|
||||
case "disabled":
|
||||
desc = <>Neither {name} nor ZITADEL terminates TLS.
|
||||
Nevertheless, {name} forwards unencrypted HTTP/2 traffic, aka h2c, to ZITADEL.</>;
|
||||
desc = <>Neither {name} nor Zitadel terminates TLS.
|
||||
Nevertheless, {name} forwards unencrypted HTTP/2 traffic, aka h2c, to Zitadel.</>;
|
||||
break;
|
||||
case "external":
|
||||
desc = <>{name} terminates TLS and forwards the requests to ZITADEL via unencrypted h2c.
|
||||
desc = <>{name} terminates TLS and forwards the requests to Zitadel via unencrypted h2c.
|
||||
This example uses an unsafe self-signed certificate for {name}</>;
|
||||
break;
|
||||
case "enabled":
|
||||
desc = <>{name} terminates TLS and forwards the requests to ZITADEL via encrypted HTTP/2.
|
||||
This example uses an unsafe self-signed certificate for {name} and the same for ZITADEL.</>;
|
||||
desc = <>{name} terminates TLS and forwards the requests to Zitadel via encrypted HTTP/2.
|
||||
This example uses an unsafe self-signed certificate for {name} and the same for Zitadel.</>;
|
||||
break;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{desc}
|
||||
<>By executing the commands below, you will download the files necessary to run ZITADEL behind {name} with the following config:</>
|
||||
<>By executing the commands below, you will download the files necessary to run Zitadel behind {name} with the following config:</>
|
||||
</>)
|
||||
}
|
||||
|
||||
export const Commands = ({mode, name, lower, configfilename}) => {
|
||||
let genCert = '# Generate a self signed certificate and key.\nopenssl req -x509 -batch -subj "/CN=127.0.0.1.sslip.io/O=ZITADEL Demo" -nodes -newkey rsa:2048 -keyout ./selfsigned.key -out ./selfsigned.crt 2>/dev/null\n\n';
|
||||
let genCert = '# Generate a self signed certificate and key.\nopenssl req -x509 -batch -subj "/CN=127.0.0.1.sslip.io/O=Zitadel Demo" -nodes -newkey rsa:2048 -keyout ./selfsigned.key -out ./selfsigned.crt 2>/dev/null\n\n';
|
||||
let connPort = "443"
|
||||
let connInsecureFlag = "--insecure "
|
||||
let connScheme = "https"
|
||||
@@ -47,8 +47,8 @@ export const Commands = ({mode, name, lower, configfilename}) => {
|
||||
{'wget $\{ZITADEL_CONFIG_FILES\}/'}{lower}{'/'}{configfilename}{' -O '}{configfilename}{' --quiet \n'}
|
||||
{'\n'}
|
||||
{genCert}
|
||||
{'# Run the database, ZITADEL and '}{name}{'.'}{'\n'}
|
||||
{'docker compose --file docker-compose-base.yaml --file docker-compose-'}{lower}{'.yaml up --detach --wait db zitadel-init zitadel-'}{mode}{'-tls proxy-'}{mode}{'-tls'}{'\n'}
|
||||
{'# Run the database, and '}{name}{'.'}{'\n'}
|
||||
{'docker compose --file docker-compose-base.yaml --file docker-compose-'}{lower}{'.yaml up --detach --wait db zitadel-init zitadel-'}{mode}{'-tls login-'}{mode}{'-tls proxy-'}{mode}{'-tls'}{'\n'}
|
||||
{'\n'}
|
||||
{'# Test that gRPC and HTTP APIs work. Empty brackets like {} means success.\n'}
|
||||
{'# Make sure you have the grpcurl cli installed on your machine https://github.com/fullstorydev/grpcurl?tab=readme-ov-file#installation\n'}
|
||||
@@ -85,6 +85,6 @@ export const LoginURL = ({mode}) => {
|
||||
If the console loads normally, you know that the HTTP and gRPC-Web and gRPC APIs are working correctly.
|
||||
|
||||
<CodeBlock language="bash">
|
||||
{'# You can now stop the database, ZITADEL and '}{props.providername}{'.'}{'\n'}
|
||||
{'# You can now stop the database, the Zitadel API, the Zitadel login and '}{props.providername}{'.'}{'\n'}
|
||||
{'docker compose --file docker-compose-base.yaml --file docker-compose-'}{props.lower}{'.yaml down'}{'\n'}
|
||||
</CodeBlock>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Configure ZITADEL with Caddy
|
||||
title: Configure Zitadel with Caddy
|
||||
sidebar_label: Caddy
|
||||
---
|
||||
|
||||
@@ -19,7 +19,7 @@ export const link = <a href="https://caddyserver.com/">{providername}</a>
|
||||
|
||||
You can either setup your environment for <a href={'#tls-mode-external'}>TLS mode external</a> or <a href={'#tls-mode-enabled'}>TLS mode enabled</a>.
|
||||
|
||||
<!-- grpc NOT WORKING
|
||||
<!-- login NOT WORKING
|
||||
## TLS mode disabled
|
||||
|
||||
<ProxyGuideTLSMode mode="disabled" configfilename="disabled-tls.Caddyfile" configfilecontent={ConfigDisabled} providername={providername} link={link} lower={lower}></ProxyGuideTLSMode>
|
||||
|
@@ -1,3 +1,4 @@
|
||||
http://127.0.0.1.sslip.io {
|
||||
reverse_proxy /ui/v2/login/* http://login-disabled-tls:3000
|
||||
reverse_proxy h2c://zitadel-disabled-tls:8080
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ services:
|
||||
ports:
|
||||
- "80:80"
|
||||
networks:
|
||||
- 'zitadel'
|
||||
- app
|
||||
depends_on:
|
||||
zitadel-disabled-tls:
|
||||
condition: 'service_healthy'
|
||||
@@ -21,7 +21,7 @@ services:
|
||||
ports:
|
||||
- "443:443"
|
||||
networks:
|
||||
- 'zitadel'
|
||||
- app
|
||||
depends_on:
|
||||
zitadel-external-tls:
|
||||
condition: 'service_healthy'
|
||||
@@ -35,10 +35,7 @@ services:
|
||||
ports:
|
||||
- "443:443"
|
||||
networks:
|
||||
- 'zitadel'
|
||||
- app
|
||||
depends_on:
|
||||
zitadel-enabled-tls:
|
||||
condition: 'service_healthy'
|
||||
|
||||
networks:
|
||||
zitadel:
|
||||
|
@@ -1,5 +1,6 @@
|
||||
https://127.0.0.1.sslip.io {
|
||||
tls /etc/certs/selfsigned.crt /etc/certs/selfsigned.key
|
||||
reverse_proxy /ui/v2/login/* http://login-enabled-tls:3000
|
||||
reverse_proxy https://zitadel-enabled-tls:8080 {
|
||||
transport http {
|
||||
tls_insecure_skip_verify
|
||||
|
@@ -1,4 +1,5 @@
|
||||
https://127.0.0.1.sslip.io {
|
||||
tls /etc/certs/selfsigned.crt /etc/certs/selfsigned.key
|
||||
reverse_proxy /ui/v2/login/* http://login-external-tls:3000
|
||||
reverse_proxy h2c://zitadel-external-tls:8080
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Configure ZITADEL with Cloudflare
|
||||
title: Configure Zitadel with Cloudflare
|
||||
sidebar_label: Cloudflare
|
||||
---
|
||||
|
||||
@@ -8,7 +8,7 @@ sidebar_label: Cloudflare
|
||||
- [Make sure HTTP/2 is enabled](https://support.cloudflare.com/hc/en-us/articles/200168076-Understanding-Cloudflare-HTTP-2-and-HTTP-3-Support)
|
||||
- [Verify that gRPC is enabled](https://support.cloudflare.com/hc/en-us/articles/360050483011-Understanding-Cloudflare-gRPC-support)
|
||||
- [Verify that traffic is proxied through cloudflare](https://developers.cloudflare.com/dns/manage-dns-records/reference/proxied-dns-records/)
|
||||
- [Configure ZITADEL to use the TLS Mode enabled](/self-hosting/manage/tls_modes#enabled)
|
||||
- [Configure Zitadel to use the TLS Mode enabled](/self-hosting/manage/tls_modes#enabled)
|
||||
|
||||
:::info
|
||||
[Cloudflare does only support gRPC with TLS!](https://support.cloudflare.com/hc/en-us/articles/360050483011-Understanding-Cloudflare-gRPC-support)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Configure ZITADEL with Cloudflare Tunnel
|
||||
title: Configure Zitadel with Cloudflare Tunnel
|
||||
sidebar_label: Cloudflare Tunnel
|
||||
---
|
||||
|
||||
|
@@ -3,23 +3,14 @@ services:
|
||||
zitadel-disabled-tls:
|
||||
extends:
|
||||
service: zitadel-init
|
||||
command: 'start-from-setup --init-projections --masterkey "MasterkeyNeedsToHave32Characters" --config /zitadel.yaml --steps /zitadel.yaml'
|
||||
command: 'start-from-setup --masterkey "MasterkeyNeedsToHave32Characters"'
|
||||
environment:
|
||||
ZITADEL_EXTERNALPORT: 80
|
||||
ZITADEL_EXTERNALSECURE: false
|
||||
ZITADEL_TLS_ENABLED: false
|
||||
# database configuration
|
||||
ZITADEL_DATABASE_POSTGRES_HOST: db
|
||||
ZITADEL_DATABASE_POSTGRES_PORT: 5432
|
||||
ZITADEL_DATABASE_POSTGRES_DATABASE: zitadel
|
||||
ZITADEL_DATABASE_POSTGRES_USER_USERNAME: zitadel_user
|
||||
ZITADEL_DATABASE_POSTGRES_USER_PASSWORD: zitadel_pw
|
||||
ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE: disable
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME: postgres
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD: postgres
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE: disable
|
||||
networks:
|
||||
- 'zitadel'
|
||||
- app
|
||||
- db
|
||||
depends_on:
|
||||
zitadel-init:
|
||||
condition: 'service_completed_successfully'
|
||||
@@ -29,23 +20,14 @@ services:
|
||||
zitadel-external-tls:
|
||||
extends:
|
||||
service: zitadel-init
|
||||
command: 'start-from-setup --init-projections --masterkey "MasterkeyNeedsToHave32Characters" --config /zitadel.yaml --steps /zitadel.yaml'
|
||||
command: 'start-from-setup --masterkey "MasterkeyNeedsToHave32Characters"'
|
||||
environment:
|
||||
ZITADEL_EXTERNALPORT: 443
|
||||
ZITADEL_EXTERNALSECURE: true
|
||||
ZITADEL_TLS_ENABLED: false
|
||||
# database configuration
|
||||
ZITADEL_DATABASE_POSTGRES_HOST: db
|
||||
ZITADEL_DATABASE_POSTGRES_PORT: 5432
|
||||
ZITADEL_DATABASE_POSTGRES_DATABASE: zitadel
|
||||
ZITADEL_DATABASE_POSTGRES_USER_USERNAME: zitadel_user
|
||||
ZITADEL_DATABASE_POSTGRES_USER_PASSWORD: zitadel_pw
|
||||
ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE: disable
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME: postgres
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD: postgres
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE: disable
|
||||
networks:
|
||||
- 'zitadel'
|
||||
- app
|
||||
- db
|
||||
depends_on:
|
||||
db:
|
||||
condition: 'service_healthy'
|
||||
@@ -55,28 +37,19 @@ services:
|
||||
zitadel-enabled-tls:
|
||||
extends:
|
||||
service: zitadel-init
|
||||
command: 'start-from-setup --init-projections --masterkey "MasterkeyNeedsToHave32Characters" --config /zitadel.yaml --steps /zitadel.yaml'
|
||||
command: 'start-from-setup --masterkey "MasterkeyNeedsToHave32Characters"'
|
||||
environment:
|
||||
ZITADEL_EXTERNALPORT: 443
|
||||
ZITADEL_EXTERNALSECURE: true
|
||||
ZITADEL_TLS_ENABLED: true
|
||||
ZITADEL_TLS_CERTPATH: /etc/certs/selfsigned.crt
|
||||
ZITADEL_TLS_KEYPATH: /etc/certs/selfsigned.key
|
||||
# database configuration
|
||||
ZITADEL_DATABASE_POSTGRES_HOST: db
|
||||
ZITADEL_DATABASE_POSTGRES_PORT: 5432
|
||||
ZITADEL_DATABASE_POSTGRES_DATABASE: zitadel
|
||||
ZITADEL_DATABASE_POSTGRES_USER_USERNAME: zitadel_user
|
||||
ZITADEL_DATABASE_POSTGRES_USER_PASSWORD: zitadel_pw
|
||||
ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE: disable
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME: postgres
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD: postgres
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE: disable
|
||||
volumes:
|
||||
- ./selfsigned.crt:/etc/certs/selfsigned.crt
|
||||
- ./selfsigned.key:/etc/certs/selfsigned.key
|
||||
networks:
|
||||
- 'zitadel'
|
||||
- app
|
||||
- db
|
||||
depends_on:
|
||||
zitadel-init:
|
||||
condition: 'service_completed_successfully'
|
||||
@@ -84,15 +57,14 @@ services:
|
||||
condition: 'service_healthy'
|
||||
|
||||
zitadel-init:
|
||||
user: '$UID'
|
||||
image: '${ZITADEL_IMAGE:-ghcr.io/zitadel/zitadel:latest}'
|
||||
command: 'init --config /zitadel.yaml'
|
||||
command: 'init'
|
||||
depends_on:
|
||||
db:
|
||||
condition: 'service_healthy'
|
||||
environment:
|
||||
# Using an external domain other than localhost proofs, that the proxy configuration works.
|
||||
# If ZITADEL can't resolve a requests original host to this domain,
|
||||
# If Zitadel can't resolve a requests original host to this domain,
|
||||
# it will return a 404 Instance not found error.
|
||||
ZITADEL_EXTERNALDOMAIN: 127.0.0.1.sslip.io
|
||||
# In case something doesn't work as expected,
|
||||
@@ -102,22 +74,23 @@ services:
|
||||
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORDCHANGEREQUIRED: false
|
||||
# database configuration
|
||||
ZITADEL_DATABASE_POSTGRES_HOST: db
|
||||
ZITADEL_DATABASE_POSTGRES_PORT: 5432
|
||||
ZITADEL_DATABASE_POSTGRES_DATABASE: zitadel
|
||||
ZITADEL_DATABASE_POSTGRES_USER_USERNAME: zitadel_user
|
||||
ZITADEL_DATABASE_POSTGRES_USER_PASSWORD: zitadel_pw
|
||||
ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE: disable
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME: postgres
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD: postgres
|
||||
ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE: disable
|
||||
# Set up a service account with IAM_LOGIN_CLIENT role and write the PAT to the file ./login-client.pat
|
||||
ZITADEL_FIRSTINSTANCE_LOGINCLIENTPATPATH: /current-dir/login-client.pat
|
||||
ZITADEL_FIRSTINSTANCE_ORG_LOGINCLIENT_MACHINE_USERNAME: login-client
|
||||
ZITADEL_FIRSTINSTANCE_ORG_LOGINCLIENT_MACHINE_NAME: Automatically Initialized IAM Login Client
|
||||
ZITADEL_FIRSTINSTANCE_ORG_LOGINCLIENT_PAT_EXPIRATIONDATE: '2029-01-01T00:00:00Z'
|
||||
# The master key is used to
|
||||
networks:
|
||||
- 'zitadel'
|
||||
- db
|
||||
healthcheck:
|
||||
test: ["CMD", "/app/zitadel", "ready"]
|
||||
test: [ "CMD", "/app/zitadel", "ready" ]
|
||||
interval: '10s'
|
||||
timeout: '5s'
|
||||
retries: 5
|
||||
start_period: '10s'
|
||||
volumes:
|
||||
- '.:/current-dir:rw'
|
||||
|
||||
db:
|
||||
restart: 'always'
|
||||
@@ -125,18 +98,69 @@ services:
|
||||
environment:
|
||||
POSTGRES_PASSWORD: postgres
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready"]
|
||||
test: [ "CMD-SHELL", "pg_isready" ]
|
||||
interval: 5s
|
||||
timeout: 60s
|
||||
retries: 10
|
||||
start_period: 5s
|
||||
networks:
|
||||
- 'zitadel'
|
||||
- db
|
||||
volumes:
|
||||
- 'data:/var/lib/postgresql/data:rw'
|
||||
|
||||
login-disabled-tls:
|
||||
restart: 'unless-stopped'
|
||||
image: 'ghcr.io/zitadel/zitadel-login:latest'
|
||||
environment:
|
||||
- ZITADEL_API_URL=http://zitadel-disabled-tls:8080
|
||||
- NEXT_PUBLIC_BASE_PATH=/ui/v2/login
|
||||
- ZITADEL_SERVICE_USER_TOKEN_FILE=/current-dir/login-client.pat
|
||||
- CUSTOM_REQUEST_HEADERS=Host:127.0.0.1.sslip.io
|
||||
- NODE_ENV=test
|
||||
volumes:
|
||||
- '.:/current-dir:ro'
|
||||
networks:
|
||||
- app
|
||||
depends_on:
|
||||
zitadel-disabled-tls:
|
||||
condition: 'service_healthy'
|
||||
|
||||
login-external-tls:
|
||||
restart: 'unless-stopped'
|
||||
image: 'ghcr.io/zitadel/zitadel-login:latest'
|
||||
environment:
|
||||
- ZITADEL_API_URL=http://zitadel-external-tls:8080
|
||||
- NEXT_PUBLIC_BASE_PATH=/ui/v2/login
|
||||
- ZITADEL_SERVICE_USER_TOKEN_FILE=/current-dir/login-client.pat
|
||||
- CUSTOM_REQUEST_HEADERS=Host:127.0.0.1.sslip.io
|
||||
volumes:
|
||||
- '.:/current-dir:ro'
|
||||
networks:
|
||||
- app
|
||||
depends_on:
|
||||
zitadel-external-tls:
|
||||
condition: 'service_healthy'
|
||||
|
||||
login-enabled-tls:
|
||||
restart: 'unless-stopped'
|
||||
image: 'ghcr.io/zitadel/zitadel-login:latest'
|
||||
environment:
|
||||
- ZITADEL_API_URL=https://zitadel-enabled-tls:8080
|
||||
- NEXT_PUBLIC_BASE_PATH=/ui/v2/login
|
||||
- ZITADEL_SERVICE_USER_TOKEN_FILE=/current-dir/login-client.pat
|
||||
- CUSTOM_REQUEST_HEADERS=Host:127.0.0.1.sslip.io
|
||||
- NODE_TLS_REJECT_UNAUTHORIZED=0
|
||||
volumes:
|
||||
- '.:/current-dir:ro'
|
||||
networks:
|
||||
- app
|
||||
depends_on:
|
||||
zitadel-enabled-tls:
|
||||
condition: 'service_healthy'
|
||||
|
||||
networks:
|
||||
zitadel:
|
||||
app:
|
||||
db:
|
||||
|
||||
volumes:
|
||||
data:
|
||||
|
@@ -1,35 +1,41 @@
|
||||
services:
|
||||
|
||||
proxy-disabled-tls:
|
||||
image: "httpd:2.4.58-alpine"
|
||||
image: "httpd:latest"
|
||||
volumes:
|
||||
- "./httpd-disabled-tls.conf:/usr/local/apache2/conf/httpd.conf"
|
||||
ports:
|
||||
- "80:80"
|
||||
networks:
|
||||
- app
|
||||
depends_on:
|
||||
zitadel-disabled-tls:
|
||||
condition: 'service_healthy'
|
||||
|
||||
proxy-external-tls:
|
||||
image: "httpd:2.4.58-alpine"
|
||||
image: "httpd:latest"
|
||||
volumes:
|
||||
- "./httpd-external-tls.conf:/usr/local/apache2/conf/httpd.conf"
|
||||
- "./selfsigned.crt:/etc/certs/selfsigned.crt:ro"
|
||||
- "./selfsigned.key:/etc/certs/selfsigned.key:ro"
|
||||
ports:
|
||||
- "443:443"
|
||||
networks:
|
||||
- app
|
||||
depends_on:
|
||||
zitadel-external-tls:
|
||||
condition: 'service_healthy'
|
||||
|
||||
proxy-enabled-tls:
|
||||
image: "httpd:2.4.58-alpine"
|
||||
image: "httpd:latest"
|
||||
volumes:
|
||||
- "./httpd-enabled-tls.conf:/usr/local/apache2/conf/httpd.conf"
|
||||
- "./selfsigned.crt:/etc/certs/selfsigned.crt:ro"
|
||||
- "./selfsigned.key:/etc/certs/selfsigned.key:ro"
|
||||
ports:
|
||||
- "443:443"
|
||||
networks:
|
||||
- app
|
||||
depends_on:
|
||||
zitadel-enabled-tls:
|
||||
condition: 'service_healthy'
|
||||
|
@@ -34,6 +34,19 @@ CustomLog /proc/self/fd/1 "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Ag
|
||||
Listen 80
|
||||
|
||||
<VirtualHost *:80>
|
||||
ProxyPass / h2c://zitadel-disabled-tls:8080/
|
||||
# Enable HTTP/2 for gRPC support (cleartext)
|
||||
Protocols h2c http/1.1
|
||||
|
||||
# Proxy settings
|
||||
ProxyPreserveHost on
|
||||
ProxyAddHeaders on
|
||||
RequestHeader set X-Forwarded-Proto "http"
|
||||
|
||||
# Route login UI first (more specific path)
|
||||
ProxyPass /ui/v2/login http://login-disabled-tls:3000/ui/v2/login
|
||||
ProxyPassReverse /ui/v2/login http://login-disabled-tls:3000/ui/v2/login
|
||||
|
||||
# Route everything else to Zitadel
|
||||
ProxyPass / h2c://zitadel-disabled-tls:8080/
|
||||
ProxyPassReverse / h2c://zitadel-disabled-tls:8080/
|
||||
</VirtualHost>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user