Start Logto with localhost endpoints so bootstrap can reach the
Management API without going through Traefik. After bootstrap
completes, restart Logto with the real public endpoints for
production use. This eliminates the Traefik race condition entirely.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Management API requires the admin OIDC endpoint (ADMIN_ENDPOINT)
to be reachable. Since bootstrap now runs inside the Logto container
(not a separate container), Traefik may not have discovered the labels
yet. Wait for the admin endpoint to be routable before running bootstrap.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Newer Logto versions require `npm run cli db alteration deploy` after
seeding to apply schema migrations. Without this, Logto fails with
"relation systems does not exist".
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Logto base image (ghcr.io/logto-io/logto:latest) is Alpine-based,
not Debian. Switch from apt-get to apk for installing bootstrap deps.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mirrors install.sh structure and produces identical output files.
Uses native PowerShell idioms for parameters, prompts, and crypto.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Appends the main() entry point that wires together all installer phases:
arg parsing, config loading, rerun detection, prerequisites, auto-detect,
interactive prompts, config merge/validate, password generation, file
generation, docker pull/up, health verification, and output printing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds logto-entrypoint.sh that seeds DB, starts Logto, waits for health,
runs bootstrap, then keeps Logto running. Eliminates the separate
logto-bootstrap init container.
The entrypoint writes certs to /certs/ but the dynamic config
referenced /etc/traefik/certs/. Since both are baked into the image,
align the paths so only one volume mount is needed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bakes init.sql, users.xml (with from_env password), and prometheus.xml
into a custom ClickHouse image to eliminate 3 bind-mounted config files.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Resolve TBD placeholder (Docker minimum versions), clarify TLS cert
flow after traefik-certs init container merge, note Traefik env var
substitution for dynamic config, and document Docker socket path
differences between Linux and Windows.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Defines a professional installer for the Cameleer SaaS platform with
dual native scripts (bash + PowerShell), three installation modes
(simple/expert/silent), and a platform simplification that consolidates
7 services into 5 by baking all init logic into Docker images.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ClickHouse: enable built-in Prometheus exporter at :9363/metrics via
config.d/prometheus.xml with metrics, events, and async_metrics.
Docker labels added for docker_sd_configs auto-discovery.
Tenant servers: add prometheus.scrape/path/port labels to provisioned
server containers pointing to /api/v1/prometheus:8081.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Vendor has platform:admin scope globally and manages tenants through the
SaaS console — no need to be a member of each tenant's Logto org.
Removes the step that failed with Logto's varchar(21) user ID limit.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ClickHouse entrypoint needs write access to resolve from_env attribute
and apply CLICKHOUSE_PASSWORD to the default user config.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- ClickHouse: pass user/password via ProvisioningProperties instead of
baking into JDBC URLs. All consumers (InfrastructureService,
TenantDataCleanupService, DockerTenantProvisioner) use the same source.
- Bootstrap: remove dead tenant config (CAMELEER_AUTH_TOKEN, t-default
org, example tenant vars) — tenants are created dynamically by vendor.
- Bootstrap JSON: remove unused fields (tenantName, tenantSlug,
bootstrapToken, tenantAdminUser, organizationId).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ClickHouse default user had no password, causing auth failures on recent
CH versions. Set password via from_env in clickhouse-users.xml, pass
credentials in JDBC URLs to SaaS services and tenant server containers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace absolute UNIQUE constraint on tenants.slug with a partial unique
index that excludes DELETED rows. This allows re-creating a tenant with
the same slug after deletion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds CAMELEER_SERVER_SECURITY_INFRASTRUCTUREENDPOINTS=false to the env
var list injected into provisioned tenant server containers, disabling
the Database and ClickHouse admin endpoints (returns 404) on SaaS-
managed instances. The server defaults to true (standalone mode).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
architecture.md runtime/deployment section rewritten with correct
CAMELEER_SAAS_PROVISIONING_* and CAMELEER_SERVER_* env vars.
user-manual.md updated container resource env vars and removed
stale CAMELEER_TENANT_SLUG reference. HOWTO.md cleaned up.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Align DockerTenantProvisioner env vars with the server's new
cameleer.server.security.oidc.* namespace:
CAMELEER_SERVER_SECURITY_OIDC_ISSUERURI
CAMELEER_SERVER_SECURITY_OIDC_JWKSETURI
CAMELEER_SERVER_SECURITY_OIDC_AUDIENCE
CAMELEER_SERVER_SECURITY_OIDC_TLSSKIPVERIFY
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move all SaaS configuration properties under the cameleer.saas.*
namespace with all-lowercase dot-separated names and mechanical env var
mapping. Aligns with the server (cameleer.server.*) and agent
(cameleer.agent.*) conventions.
Changes:
- Move cameleer.identity.* → cameleer.saas.identity.*
- Move cameleer.provisioning.* → cameleer.saas.provisioning.*
- Move cameleer.certs.* → cameleer.saas.certs.*
- Rename kebab-case properties to concatenated lowercase
- Update all env vars to CAMELEER_SAAS_* mechanical mapping
- Update DockerTenantProvisioner to pass CAMELEER_SERVER_* env vars
to provisioned server containers (matching server's new convention)
- Spring JWT config now derives from SaaS properties via cross-reference
- Clean up orphaned properties in application-local.yml
- Update docker-compose.yml, docker-compose.dev.yml, .env.example
- Update CLAUDE.md, HOWTO.md, architecture.md, user-manual.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Traefik v3 ignores tls.stores.default in the static config, causing it
to serve its auto-generated fallback cert instead of the platform cert.
Moving the default certificate store to the dynamic config (file
provider) fixes this — Traefik now serves the correct cert and also
picks up cert rotations without a restart.
This was the root cause of OIDC PKIX failures: the server imported the
CA into its JVM truststore, but Traefik was serving a different cert
entirely.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PATCH /api/users/{id}/password, not /api/users/{id}. The general user
update endpoint rejected the password field with 422.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restart only stops/starts existing containers with the same image. The new
upgrade action removes server + UI containers, force-pulls the latest
Docker images, then re-provisions (preserving app containers, volumes, and
networks). Available to both vendor (tenant detail) and tenant admin
(dashboard).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- POST /api/tenant/server/admin-password — resets server's built-in
admin password via M2M API call to the tenant's server
- Settings page: "Server Admin Password" card
- ServerApiClient.resetServerAdminPassword() calls server's password
reset endpoint with M2M token
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- POST /api/tenant/password — change own Logto password
- POST /api/tenant/team/{userId}/password — reset team member password
- Settings page: "Change Password" card with confirm field
- Team page: "Reset Password" button per member with inline form
- LogtoManagementClient.updateUserPassword() via Logto Management API
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DockerTenantProvisioner.remove() now cleans up all tenant Docker resources:
containers (by cameleer.tenant label), env networks, tenant network, JAR volume.
TenantDataCleanupService drops the tenant's PostgreSQL schema and deletes all
ClickHouse data for GDPR compliance.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When no org is resolved, redirect to /tenant instead of the
non-existent /server/ path. Fixes login redirect loop.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>