Compare commits

...

5 Commits

Author SHA1 Message Date
hsiegeln
1ef0016965 docs: update README and .env.example for SMTP removal
SMTP configuration is now managed at runtime via the vendor admin UI.
Remove SMTP config reference table, CLI flags from silent install example,
and env vars from .env.example.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-25 18:16:12 +02:00
hsiegeln
ec1c1f92d7 docs: update installer CLAUDE.md to reflect SMTP removal 2026-04-25 18:09:50 +02:00
hsiegeln
4037fb9dfb feat: remove SMTP configuration from PowerShell installer 2026-04-25 18:08:48 +02:00
hsiegeln
35240e0374 feat: remove SMTP configuration from bash installer 2026-04-25 18:08:44 +02:00
hsiegeln
4885c240e3 feat: remove SMTP env vars from Logto compose template
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 18:05:27 +02:00
6 changed files with 8 additions and 126 deletions

View File

@@ -25,11 +25,9 @@ The installer uses static docker-compose templates in `templates/`. Templates ar
## SMTP configuration
The installer prompts for SMTP settings in SaaS mode when the user opts in ("Configure SMTP for email verification?"). SMTP is required for self-service sign-up — without it, only admin-created users can sign in.
SMTP / email connector configuration has been moved from the installer to the SaaS vendor admin UI (Email Connector page at `/vendor/email`). The installer no longer prompts for or persists SMTP settings.
Env vars: `SMTP_HOST`, `SMTP_PORT` (default 587), `SMTP_USER`, `SMTP_PASS`, `SMTP_FROM_EMAIL` (default `noreply@<PUBLIC_HOST>`). Passed to the `cameleer-logto` container. The bootstrap script discovers the SMTP connector factory and creates the connector with Cameleer-branded email templates.
CLI args: `--smtp-host`, `--smtp-port`, `--smtp-user`, `--smtp-pass`, `--smtp-from-email`. Persisted in `cameleer.conf` for upgrades/reconfigure.
Previously, SMTP env vars (`SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASS`, `SMTP_FROM_EMAIL`) were passed to the `cameleer-logto` container and configured via the bootstrap script. This one-shot approach was fragile — email delivery is now configured at runtime through the Logto Management API.
## Registry configuration
@@ -45,7 +43,6 @@ For private registries, pass `--registry-user` / `--registry-token`. The install
- `CAMELEER_SERVER_*` — server config (consumed by cameleer-server)
- `CAMELEER_SAAS_*` — SaaS management plane config
- `CAMELEER_SAAS_PROVISIONING_*` — "SaaS forwards this to provisioned tenant servers"
- `SMTP_*` — email delivery config for Logto (consumed by bootstrap, SaaS mode only)
- No prefix (e.g. `POSTGRES_PASSWORD`, `PUBLIC_HOST`) — shared infrastructure, consumed by multiple components
## Development

View File

@@ -140,17 +140,11 @@ The Docker socket is required for tenant provisioning (SaaS mode) — the platfo
For private registries, provide credentials and the installer runs `docker login` before pulling. The registry prefix is applied to all container images.
### SMTP (SaaS Mode)
### Email / SMTP
| Setting | CLI Flag | Env Var | Config Key | Default |
|---------|----------|---------|------------|---------|
| SMTP host | `--smtp-host` | `SMTP_HOST` | `smtp_host` | — |
| SMTP port | `--smtp-port` | `SMTP_PORT` | `smtp_port` | `587` |
| SMTP username | `--smtp-user` | `SMTP_USER` | `smtp_user` | — |
| SMTP password | `--smtp-pass` | `SMTP_PASS` | `smtp_pass` | — |
| From email | `--smtp-from-email` | `SMTP_FROM_EMAIL` | `smtp_from_email` | `noreply@<PUBLIC_HOST>` |
Email connector configuration (SMTP, SES, etc.) is managed at runtime via the vendor admin UI at `/vendor/email`. The installer does not configure email delivery.
SMTP is required for self-service sign-up (email verification codes). Without it, only admin-created users can sign in.
Self-service registration is disabled by default and is enabled automatically when the admin configures an email connector.
### Monitoring
@@ -246,9 +240,6 @@ All services share a single hostname. Routing:
--tls-mode=custom \
--cert-file=/etc/ssl/cert.pem \
--key-file=/etc/ssl/key.pem \
--smtp-host=smtp.example.com \
--smtp-user=noreply@example.com \
--smtp-pass=mailpass \
--registry=registry.example.com/cameleer \
--registry-user=deploy \
--registry-token=ghp_xxx

View File

@@ -37,11 +37,6 @@ param(
[string]$DockerSocket,
[string]$NodeTlsReject,
[string]$DeploymentMode,
[string]$SmtpHost,
[string]$SmtpPort,
[string]$SmtpUser,
[string]$SmtpPass,
[string]$SmtpFromEmail,
[string]$Registry,
[string]$RegistryUser,
[string]$RegistryToken,
@@ -92,11 +87,6 @@ $_ENV_COMPOSE_PROJECT = $env:COMPOSE_PROJECT
$_ENV_DOCKER_SOCKET = $env:DOCKER_SOCKET
$_ENV_NODE_TLS_REJECT = $env:NODE_TLS_REJECT
$_ENV_DEPLOYMENT_MODE = $env:DEPLOYMENT_MODE
$_ENV_SMTP_HOST = $env:SMTP_HOST
$_ENV_SMTP_PORT = $env:SMTP_PORT
$_ENV_SMTP_USER = $env:SMTP_USER
$_ENV_SMTP_PASS = $env:SMTP_PASS
$_ENV_SMTP_FROM_EMAIL = $env:SMTP_FROM_EMAIL
$_ENV_REGISTRY = $env:REGISTRY
$_ENV_REGISTRY_USER = $env:REGISTRY_USER
$_ENV_REGISTRY_TOKEN = $env:REGISTRY_TOKEN
@@ -126,11 +116,6 @@ $script:cfg = @{
DockerSocket = $DockerSocket
NodeTlsReject = $NodeTlsReject
DeploymentMode = $DeploymentMode
SmtpHost = $SmtpHost
SmtpPort = $SmtpPort
SmtpUser = $SmtpUser
SmtpPass = $SmtpPass
SmtpFromEmail = $SmtpFromEmail
Registry = $Registry
RegistryUser = $RegistryUser
RegistryToken = $RegistryToken
@@ -302,11 +287,6 @@ function Load-ConfigFile {
'docker_socket' { if (-not $script:cfg.DockerSocket) { $script:cfg.DockerSocket = $val } }
'node_tls_reject' { if (-not $script:cfg.NodeTlsReject) { $script:cfg.NodeTlsReject = $val } }
'deployment_mode' { if (-not $script:cfg.DeploymentMode) { $script:cfg.DeploymentMode = $val } }
'smtp_host' { if (-not $script:cfg.SmtpHost) { $script:cfg.SmtpHost = $val } }
'smtp_port' { if (-not $script:cfg.SmtpPort) { $script:cfg.SmtpPort = $val } }
'smtp_user' { if (-not $script:cfg.SmtpUser) { $script:cfg.SmtpUser = $val } }
'smtp_pass' { if (-not $script:cfg.SmtpPass) { $script:cfg.SmtpPass = $val } }
'smtp_from_email' { if (-not $script:cfg.SmtpFromEmail) { $script:cfg.SmtpFromEmail = $val } }
'registry' { if (-not $script:cfg.Registry) { $script:cfg.Registry = $val } }
'registry_user' { if (-not $script:cfg.RegistryUser) { $script:cfg.RegistryUser = $val } }
'registry_token' { if (-not $script:cfg.RegistryToken) { $script:cfg.RegistryToken = $val } }
@@ -339,11 +319,6 @@ function Load-EnvOverrides {
if (-not $c.DockerSocket) { $c.DockerSocket = $_ENV_DOCKER_SOCKET }
if (-not $c.NodeTlsReject) { $c.NodeTlsReject = $_ENV_NODE_TLS_REJECT }
if (-not $c.DeploymentMode) { $c.DeploymentMode = $_ENV_DEPLOYMENT_MODE }
if (-not $c.SmtpHost) { $c.SmtpHost = $_ENV_SMTP_HOST }
if (-not $c.SmtpPort) { $c.SmtpPort = $_ENV_SMTP_PORT }
if (-not $c.SmtpUser) { $c.SmtpUser = $_ENV_SMTP_USER }
if (-not $c.SmtpPass) { $c.SmtpPass = $_ENV_SMTP_PASS }
if (-not $c.SmtpFromEmail) { $c.SmtpFromEmail = $_ENV_SMTP_FROM_EMAIL }
if (-not $c.Registry) { $c.Registry = $_ENV_REGISTRY }
if (-not $c.RegistryUser) { $c.RegistryUser = $_ENV_REGISTRY_USER }
if (-not $c.RegistryToken) { $c.RegistryToken = $_ENV_REGISTRY_TOKEN }
@@ -513,17 +488,6 @@ function Run-SimplePrompts {
$deployChoice = Read-Host ' Select mode [1]'
if ($deployChoice -eq '2') { $c.DeploymentMode = 'standalone' } else { $c.DeploymentMode = 'saas' }
# SMTP for email verification (SaaS mode only)
if ($c.DeploymentMode -eq 'saas') {
Write-Host ''
if (Prompt-YesNo 'Configure SMTP for email verification? (required for self-service sign-up)') {
$c.SmtpHost = Prompt-Value 'SMTP host' (Coalesce $c.SmtpHost '')
$c.SmtpPort = Prompt-Value 'SMTP port' (Coalesce $c.SmtpPort '587')
$c.SmtpUser = Prompt-Value 'SMTP username' (Coalesce $c.SmtpUser '')
$c.SmtpPass = Prompt-Password 'SMTP password' (Coalesce $c.SmtpPass '')
$c.SmtpFromEmail = Prompt-Value 'From email address' (Coalesce $c.SmtpFromEmail "noreply@$($c.PublicHost)")
}
}
}
function Run-ExpertPrompts {
@@ -774,19 +738,12 @@ CAMELEER_SAAS_PROVISIONING_RUNTIMEBASEIMAGE=$reg/cameleer-runtime-base:$($c.Vers
# JWT signing secret (forwarded to provisioned tenant servers, must be non-empty)
CAMELEER_SERVER_SECURITY_JWTSECRET=$jwtSecret
# SMTP (for email verification during registration)
SMTP_HOST=$($c.SmtpHost)
SMTP_PORT=$(if ($c.SmtpPort) { $c.SmtpPort } else { '587' })
SMTP_USER=$($c.SmtpUser)
SMTP_FROM_EMAIL=$(if ($c.SmtpFromEmail) { $c.SmtpFromEmail } else { "noreply@$($c.PublicHost)" })
"@
$content += $provisioningBlock
# Passwords appended with single-quoting for special character safety
$content += "`n$(Format-EnvVal 'POSTGRES_PASSWORD' $c.PostgresPassword)"
$content += "`n$(Format-EnvVal 'CLICKHOUSE_PASSWORD' $c.ClickhousePassword)"
$content += "`n$(Format-EnvVal 'SAAS_ADMIN_PASS' $c.AdminPass)"
$content += "`n$(Format-EnvVal 'SMTP_PASS' $c.SmtpPass)"
$composeFile = 'docker-compose.yml;docker-compose.saas.yml'
if ($c.TlsMode -eq 'custom') { $composeFile += ';docker-compose.tls.yml' }
if ($c.MonitoringNetwork) { $composeFile += ';docker-compose.monitoring.yml' }
@@ -1025,15 +982,10 @@ compose_project=$($c.ComposeProject)
docker_socket=$($c.DockerSocket)
node_tls_reject=$($c.NodeTlsReject)
deployment_mode=$($c.DeploymentMode)
smtp_host=$($c.SmtpHost)
smtp_port=$($c.SmtpPort)
smtp_user=$($c.SmtpUser)
smtp_from_email=$($c.SmtpFromEmail)
registry=$($c.Registry)
registry_user=$($c.RegistryUser)
"@
# Passwords appended with single-quoting for special character safety
$txt += "`n$(Format-EnvVal 'smtp_pass' $c.SmtpPass)"
$txt += "`n$(Format-EnvVal 'registry_token' $c.RegistryToken)"
Write-Utf8File $f $txt
Log-Info 'Saved installer config to cameleer.conf'

View File

@@ -46,11 +46,6 @@ _ENV_COMPOSE_PROJECT="${COMPOSE_PROJECT:-}"
_ENV_DOCKER_SOCKET="${DOCKER_SOCKET:-}"
_ENV_NODE_TLS_REJECT="${NODE_TLS_REJECT:-}"
_ENV_DEPLOYMENT_MODE="${DEPLOYMENT_MODE:-}"
_ENV_SMTP_HOST="${SMTP_HOST:-}"
_ENV_SMTP_PORT="${SMTP_PORT:-}"
_ENV_SMTP_USER="${SMTP_USER:-}"
_ENV_SMTP_PASS="${SMTP_PASS:-}"
_ENV_SMTP_FROM_EMAIL="${SMTP_FROM_EMAIL:-}"
_ENV_REGISTRY="${REGISTRY:-}"
_ENV_REGISTRY_USER="${REGISTRY_USER:-}"
_ENV_REGISTRY_TOKEN="${REGISTRY_TOKEN:-}"
@@ -77,11 +72,6 @@ COMPOSE_PROJECT=""
DOCKER_SOCKET=""
NODE_TLS_REJECT=""
DEPLOYMENT_MODE=""
SMTP_HOST=""
SMTP_PORT=""
SMTP_USER=""
SMTP_PASS=""
SMTP_FROM_EMAIL=""
REGISTRY=""
REGISTRY_USER=""
REGISTRY_TOKEN=""
@@ -194,11 +184,6 @@ parse_args() {
--docker-socket) DOCKER_SOCKET="$2"; shift ;;
--node-tls-reject) NODE_TLS_REJECT="$2"; shift ;;
--deployment-mode) DEPLOYMENT_MODE="$2"; shift ;;
--smtp-host) SMTP_HOST="$2"; shift ;;
--smtp-port) SMTP_PORT="$2"; shift ;;
--smtp-user) SMTP_USER="$2"; shift ;;
--smtp-pass) SMTP_PASS="$2"; shift ;;
--smtp-from-email) SMTP_FROM_EMAIL="$2"; shift ;;
--registry) REGISTRY="$2"; shift ;;
--registry-user) REGISTRY_USER="$2"; shift ;;
--registry-token) REGISTRY_TOKEN="$2"; shift ;;
@@ -293,11 +278,6 @@ load_config_file() {
docker_socket) [ -z "$DOCKER_SOCKET" ] && DOCKER_SOCKET="$value" ;;
node_tls_reject) [ -z "$NODE_TLS_REJECT" ] && NODE_TLS_REJECT="$value" ;;
deployment_mode) [ -z "$DEPLOYMENT_MODE" ] && DEPLOYMENT_MODE="$value" ;;
smtp_host) [ -z "$SMTP_HOST" ] && SMTP_HOST="$value" ;;
smtp_port) [ -z "$SMTP_PORT" ] && SMTP_PORT="$value" ;;
smtp_user) [ -z "$SMTP_USER" ] && SMTP_USER="$value" ;;
smtp_pass) [ -z "$SMTP_PASS" ] && SMTP_PASS="$value" ;;
smtp_from_email) [ -z "$SMTP_FROM_EMAIL" ] && SMTP_FROM_EMAIL="$value" ;;
registry) [ -z "$REGISTRY" ] && REGISTRY="$value" ;;
registry_user) [ -z "$REGISTRY_USER" ] && REGISTRY_USER="$value" ;;
registry_token) [ -z "$REGISTRY_TOKEN" ] && REGISTRY_TOKEN="$value" ;;
@@ -328,11 +308,6 @@ load_env_overrides() {
[ -z "$DOCKER_SOCKET" ] && DOCKER_SOCKET="$_ENV_DOCKER_SOCKET"
[ -z "$NODE_TLS_REJECT" ] && NODE_TLS_REJECT="$_ENV_NODE_TLS_REJECT"
[ -z "$DEPLOYMENT_MODE" ] && DEPLOYMENT_MODE="$_ENV_DEPLOYMENT_MODE"
[ -z "$SMTP_HOST" ] && SMTP_HOST="$_ENV_SMTP_HOST"
[ -z "$SMTP_PORT" ] && SMTP_PORT="$_ENV_SMTP_PORT"
[ -z "$SMTP_USER" ] && SMTP_USER="$_ENV_SMTP_USER"
[ -z "$SMTP_PASS" ] && SMTP_PASS="$_ENV_SMTP_PASS"
[ -z "$SMTP_FROM_EMAIL" ] && SMTP_FROM_EMAIL="$_ENV_SMTP_FROM_EMAIL"
[ -z "$REGISTRY" ] && REGISTRY="$_ENV_REGISTRY"
[ -z "$REGISTRY_USER" ] && REGISTRY_USER="$_ENV_REGISTRY_USER"
[ -z "$REGISTRY_TOKEN" ] && REGISTRY_TOKEN="$_ENV_REGISTRY_TOKEN"
@@ -496,17 +471,6 @@ run_simple_prompts() {
;;
esac
# SMTP for email verification (SaaS mode only)
if [ "$DEPLOYMENT_MODE" = "saas" ]; then
echo ""
if prompt_yesno "Configure SMTP for email verification? (required for self-service sign-up)"; then
prompt SMTP_HOST "SMTP host" "${SMTP_HOST:-}"
prompt SMTP_PORT "SMTP port" "${SMTP_PORT:-587}"
prompt SMTP_USER "SMTP username" "${SMTP_USER:-}"
prompt_password SMTP_PASS "SMTP password" "${SMTP_PASS:-}"
prompt SMTP_FROM_EMAIL "From email address" "${SMTP_FROM_EMAIL:-noreply@${PUBLIC_HOST}}"
fi
fi
}
run_expert_prompts() {
@@ -777,12 +741,6 @@ CAMELEER_SAAS_PROVISIONING_RUNTIMEBASEIMAGE=${REGISTRY}/cameleer-runtime-base:${
# JWT signing secret (forwarded to provisioned tenant servers, must be non-empty)
CAMELEER_SERVER_SECURITY_JWTSECRET=$(generate_password)
# SMTP (for email verification during registration)
SMTP_HOST=${SMTP_HOST}
SMTP_PORT=${SMTP_PORT:-587}
SMTP_USER=${SMTP_USER}
SMTP_FROM_EMAIL=${SMTP_FROM_EMAIL:-noreply@${PUBLIC_HOST}}
# Compose file assembly
COMPOSE_FILE=docker-compose.yml:docker-compose.saas.yml$([ "$TLS_MODE" = "custom" ] && echo ":docker-compose.tls.yml")$([ -n "$MONITORING_NETWORK" ] && echo ":docker-compose.monitoring.yml")
EOF
@@ -791,7 +749,6 @@ EOF
env_val "$f" POSTGRES_PASSWORD "$POSTGRES_PASSWORD"
env_val "$f" CLICKHOUSE_PASSWORD "$CLICKHOUSE_PASSWORD"
env_val "$f" SAAS_ADMIN_PASS "$ADMIN_PASS"
env_val "$f" SMTP_PASS "$SMTP_PASS"
if [ -n "$MONITORING_NETWORK" ]; then
echo "" >> "$f"
@@ -972,15 +929,10 @@ compose_project=${COMPOSE_PROJECT}
docker_socket=${DOCKER_SOCKET}
node_tls_reject=${NODE_TLS_REJECT}
deployment_mode=${DEPLOYMENT_MODE}
smtp_host=${SMTP_HOST}
smtp_port=${SMTP_PORT}
smtp_user=${SMTP_USER}
smtp_from_email=${SMTP_FROM_EMAIL}
registry=${REGISTRY}
registry_user=${REGISTRY_USER}
EOF
# Passwords appended with single-quoting for special character safety
env_val "$f" smtp_pass "$SMTP_PASS"
env_val "$f" registry_token "$REGISTRY_TOKEN"
log_info "Saved installer config to cameleer.conf"
}

View File

@@ -61,14 +61,10 @@ SAAS_ADMIN_PASS=CHANGE_ME
# BOOTSTRAP_TOKEN=CHANGE_ME
# ============================================================
# SMTP (for email verification during registration)
# Email / SMTP
# ============================================================
# Required for self-service sign-up. Without SMTP, only admin-created users can sign in.
SMTP_HOST=
SMTP_PORT=587
SMTP_USER=
SMTP_PASS=
SMTP_FROM_EMAIL=noreply@cameleer.io
# Email connector configuration is managed at runtime via the vendor
# admin UI (Email Connector page at /vendor/email). No SMTP env vars needed.
# ============================================================
# TLS

View File

@@ -27,12 +27,6 @@ services:
PG_DB_SAAS: cameleer_saas
SAAS_ADMIN_USER: ${SAAS_ADMIN_USER:-admin}
SAAS_ADMIN_PASS: ${SAAS_ADMIN_PASS:?SAAS_ADMIN_PASS must be set in .env}
# SMTP (for email verification during registration)
SMTP_HOST: ${SMTP_HOST:-}
SMTP_PORT: ${SMTP_PORT:-587}
SMTP_USER: ${SMTP_USER:-}
SMTP_PASS: ${SMTP_PASS:-}
SMTP_FROM_EMAIL: ${SMTP_FROM_EMAIL:-noreply@cameleer.io}
extra_hosts:
# Logto validates M2M tokens by fetching its own JWKS from ENDPOINT.
# Route the public hostname back to the Docker host (Traefik on :443)