Compare commits

..
Author SHA1 Message Date
Mauricio SiuandClaude Fable 5 6786237720 fix(zitadel): wire EXTERNALDOMAIN/PORT/SECURE to the generated domain
Zitadel resolves its instance from the external domain/port/scheme, so the
template's ZITADEL_EXTERNALPORT=8080 made every generated URL (OIDC issuer,
login redirects) point at http://<domain>:8080 instead of the domain served
by Traefik, ending in {"code":5,"message":"Not Found"} (#516).

- Expose ZITADEL_EXTERNALDOMAIN / ZITADEL_EXTERNALPORT / ZITADEL_EXTERNALSECURE
  as template env vars, defaulting to the generated domain over HTTP
  (port 80, secure=false) so the routed domain and Zitadel's external config
  always match; HTTPS users flip them to 443/true in the Env tab.
- Pin image to v4.16.0 (was latest) and keep the built-in login v1 via
  ZITADEL_DEFAULTINSTANCE_FEATURES_LOGINV2_REQUIRED=false so no separate
  login-v2 container is needed.
- Add the official readiness healthcheck, drop the unused /app/data volume,
  bogus SMTP env keys, published port and obsolete compose version key.

Closes #516

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 11:12:30 -06:00
5 changed files with 70 additions and 39 deletions
+19 -15
View File
@@ -1,35 +1,39 @@
version: "3.8"
services:
kener:
image: rajnandan1/kener:latest
environment:
- TZ=${TZ}
- KENER_SECRET_KEY=${KENER_SECRET_KEY} # 🔐 API key / secret
- ORIGIN=${ORIGIN}
- REDIS_URL=${REDIS_URL}
- DATABASE_URL=${DATABASE_URL}
- KENER_BASE_PATH=${KENER_BASE_PATH}
- ORIGIN=${ORIGIN}
- RESEND_API_KEY=${RESEND_API_KEY} # 🔐 API key
- RESEND_SENDER_EMAIL=${RESEND_SENDER_EMAIL}
ports:
- 3000
volumes:
- kener_db:/app/database
depends_on:
redis:
condition: service_healthy
- ../files/uploads:/app/uploads
restart: unless-stopped
redis:
image: redis:7-alpine
volumes:
- kener_redis:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
postgres:
image: postgres:alpine
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD} # 🔐 DB password
- POSTGRES_DB=${POSTGRES_DB}
restart: unless-stopped
mysql:
image: mariadb:11
environment:
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD} # 🔐 DB password
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_RANDOM_ROOT_PASSWORD=true
restart: unless-stopped
volumes:
kener_db: {}
kener_redis: {}
+20 -2
View File
@@ -1,6 +1,8 @@
[variables]
main_domain = "${domain}"
KENER_SECRET_KEY = "${password:64}"
POSTGRES_PASSWORD = "${password:32}"
MYSQL_PASSWORD = "${password:32}"
[config]
[[config.domains]]
@@ -11,9 +13,25 @@ host = "${main_domain}"
[config.env]
TZ = "Etc/UTC"
KENER_SECRET_KEY = "${KENER_SECRET_KEY}" # 🔐 API key / secret
ORIGIN = "https://${main_domain}"
REDIS_URL = "redis://redis:6379"
DATABASE_URL = "sqlite://./database/kener.sqlite.db"
KENER_BASE_PATH = ""
ORIGIN = "http://localhost:3000"
RESEND_API_KEY = ""
RESEND_SENDER_EMAIL = "Accounts <accounts@resend.dev>"
POSTGRES_USER = "user"
POSTGRES_DB = "kener_db"
MYSQL_USER = "user"
MYSQL_DATABASE = "kener_db"
MYSQL_RANDOM_ROOT_PASSWORD = "true"
MYSQL_PASSWORD = "${MYSQL_PASSWORD}" # 🔐 DB password
POSTGRES_PASSWORD = "${POSTGRES_PASSWORD}" # 🔐 DB password
[[config.mounts]]
type = "volume"
source = "kener_db"
target = "/app/database"
[[config.mounts]]
type = "bind"
source = "../files/uploads"
target = "/app/uploads"
+19 -18
View File
@@ -1,9 +1,7 @@
version: '3.8'
services:
zitadel:
restart: 'always'
image: 'ghcr.io/zitadel/zitadel:latest'
image: 'ghcr.io/zitadel/zitadel:v4.16.0'
command: 'start-from-init --masterkey "${ZITADEL_MASTERKEY}" --tlsMode disabled'
environment:
# Database Configuration
@@ -17,33 +15,37 @@ services:
ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD: "${POSTGRES_PASSWORD}"
ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE: disable
# External Configuration for HTTP only - TLS mode disabled
ZITADEL_EXTERNALSECURE: false
ZITADEL_EXTERNALPORT: 8080
ZITADEL_EXTERNALDOMAIN: "${EXTERNAL_DOMAIN}"
# External access configuration. These MUST match the domain configured
# in the Domains tab and the scheme/port it is served on, otherwise
# Zitadel answers {"code":5,"message":"Not Found"}.
# HTTP -> ZITADEL_EXTERNALPORT=80, ZITADEL_EXTERNALSECURE=false
# HTTPS -> ZITADEL_EXTERNALPORT=443, ZITADEL_EXTERNALSECURE=true
ZITADEL_EXTERNALDOMAIN: "${ZITADEL_EXTERNALDOMAIN}"
ZITADEL_EXTERNALPORT: "${ZITADEL_EXTERNALPORT}"
ZITADEL_EXTERNALSECURE: "${ZITADEL_EXTERNALSECURE}"
ZITADEL_TLS_ENABLED: false
# Disable Email Notifications
ZITADEL_NOTIFICATIONS_SMTP_HOST: ""
ZITADEL_NOTIFICATIONS_SMTP_PORT: ""
# Custom Admin User Configuration
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_USERNAME: "${ZITADEL_FIRSTINSTANCE_ORG_HUMAN_USERNAME}"
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORD: "${ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORD}"
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_EMAIL_ADDRESS: "${ZITADEL_FIRSTINSTANCE_ORG_HUMAN_EMAIL_ADDRESS}"
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_FIRSTNAME: "${ZITADEL_FIRSTINSTANCE_ORG_HUMAN_FIRSTNAME}"
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_LASTNAME: "${ZITADEL_FIRSTINSTANCE_ORG_HUMAN_LASTNAME}"
# Default Instance Features
# Use the login UI built into the API container (no extra login-v2 service needed)
ZITADEL_DEFAULTINSTANCE_FEATURES_LOGINV2_REQUIRED: false
healthcheck:
test: ["CMD", "/app/zitadel", "ready"]
interval: '10s'
timeout: '30s'
retries: 12
start_period: '30s'
depends_on:
db:
condition: 'service_healthy'
ports:
- '8080'
volumes:
- zitadel_data:/app/data
expose:
- 8080
db:
restart: 'always'
@@ -63,4 +65,3 @@ services:
volumes:
postgres_data:
zitadel_data:
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "zitadel",
"name": "Zitadel",
"version": "latest",
"version": "4.16.0",
"description": "Open-source identity and access management platform with multi-tenancy, OpenID Connect, SAML, and OAuth 2.0 support.",
"logo": "zitadel.png",
"links": {
+11 -3
View File
@@ -7,6 +7,8 @@ admin_email = "${email}"
admin_password = "AdminPassword123!"
[config]
mounts = []
[[config.domains]]
serviceName = "zitadel"
port = 8080
@@ -16,7 +18,15 @@ path = "/"
[config.env]
POSTGRES_PASSWORD = "${postgres_password}"
ZITADEL_MASTERKEY = "${zitadel_masterkey}"
EXTERNAL_DOMAIN = "${main_domain}"
# ZITADEL_EXTERNALDOMAIN must always match the domain configured in the
# Domains tab. If you change the domain, update this variable too (and do it
# BEFORE the first deploy — Zitadel binds its instance to this domain on
# first start). For a domain served over HTTPS set ZITADEL_EXTERNALPORT=443
# and ZITADEL_EXTERNALSECURE=true.
ZITADEL_EXTERNALDOMAIN = "${main_domain}"
ZITADEL_EXTERNALPORT = "80"
ZITADEL_EXTERNALSECURE = "false"
# Custom Admin User Configuration
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_USERNAME = "${admin_username}"
@@ -24,5 +34,3 @@ ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORD = "${admin_password}"
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_EMAIL_ADDRESS = "${admin_email}"
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_FIRSTNAME = "Admin"
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_LASTNAME = "User"
[[config.mounts]]