feat(installer): add --registry, --registry-user, --registry-token
All checks were successful
CI / build (push) Successful in 1m21s
CI / docker (push) Successful in 15s

Both installers (bash + PS1) now support pulling images from a
custom Docker registry. Writes *_IMAGE env vars to .env so compose
templates use the configured registry. Runs docker login before
pull when credentials are provided. Persisted in cameleer.conf
for upgrades/reconfigure.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-25 02:10:48 +02:00
parent 180644f0df
commit e1a9f6d225
3 changed files with 117 additions and 9 deletions

View File

@@ -42,6 +42,9 @@ param(
[string]$SmtpUser,
[string]$SmtpPass,
[string]$SmtpFromEmail,
[string]$Registry,
[string]$RegistryUser,
[string]$RegistryToken,
[switch]$Reconfigure,
[switch]$Reinstall,
[switch]$ConfirmDestroy,
@@ -55,7 +58,7 @@ $ErrorActionPreference = 'Stop'
$CAMELEER_INSTALLER_VERSION = '1.0.0'
$CAMELEER_DEFAULT_VERSION = 'latest'
$REGISTRY = 'gitea.siegeln.net/cameleer'
$DEFAULT_REGISTRY = 'gitea.siegeln.net/cameleer'
$DEFAULT_INSTALL_DIR = './cameleer'
$DEFAULT_PUBLIC_PROTOCOL = 'https'
@@ -94,6 +97,9 @@ $_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
# --- Mutable config state ---
@@ -125,6 +131,9 @@ $script:cfg = @{
SmtpUser = $SmtpUser
SmtpPass = $SmtpPass
SmtpFromEmail = $SmtpFromEmail
Registry = $Registry
RegistryUser = $RegistryUser
RegistryToken = $RegistryToken
}
if ($Silent) { $script:Mode = 'silent' }
@@ -180,6 +189,11 @@ function Show-Help {
Write-Host ' -Config FILE Load config from file'
Write-Host ' -Help Show this help'
Write-Host ''
Write-Host 'Registry options:'
Write-Host ' -Registry REGISTRY Image registry (default: gitea.siegeln.net/cameleer)'
Write-Host ' -RegistryUser USER Registry username for docker login'
Write-Host ' -RegistryToken TOKEN Registry token/password for docker login'
Write-Host ''
Write-Host 'Expert options:'
Write-Host ' -PostgresPassword, -ClickhousePassword, -HttpPort,'
Write-Host ' -HttpsPort, -LogtoConsolePort, -LogtoConsoleExposed,'
@@ -280,6 +294,9 @@ function Load-ConfigFile {
'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 } }
}
}
}
@@ -314,6 +331,9 @@ function Load-EnvOverrides {
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 }
}
# --- Prerequisites ---
@@ -542,6 +562,7 @@ function Merge-Config {
if (-not $c.LogtoConsoleExposed) { $c.LogtoConsoleExposed = $DEFAULT_LOGTO_CONSOLE_EXPOSED }
if (-not $c.Version) { $c.Version = $CAMELEER_DEFAULT_VERSION }
if (-not $c.DockerSocket) { $c.DockerSocket = $DEFAULT_DOCKER_SOCKET }
if (-not $c.Registry) { $c.Registry = $DEFAULT_REGISTRY }
if (-not $c.ComposeProject) {
if ($c.DeploymentMode -eq 'standalone') {
@@ -662,6 +683,12 @@ DOCKER_SOCKET=$($c.DockerSocket)
DOCKER_GID=$gid
POSTGRES_IMAGE=postgres:16-alpine
# Registry
TRAEFIK_IMAGE=$($c.Registry)/cameleer-traefik
CLICKHOUSE_IMAGE=$($c.Registry)/cameleer-clickhouse
SERVER_IMAGE=$($c.Registry)/cameleer-server
SERVER_UI_IMAGE=$($c.Registry)/cameleer-server-ui
"@
if ($c.TlsMode -eq 'custom') {
$content += "`nCERT_FILE=/user-certs/cert.pem"
@@ -712,16 +739,24 @@ NODE_TLS_REJECT=$($c.NodeTlsReject)
$content += "`nKEY_FILE=/user-certs/key.pem"
if ($c.CaFile) { $content += "`nCA_FILE=/user-certs/ca.pem" }
}
$reg = $c.Registry
$provisioningBlock = @"
# Docker
DOCKER_SOCKET=$($c.DockerSocket)
DOCKER_GID=$gid
# Registry
TRAEFIK_IMAGE=$reg/cameleer-traefik
POSTGRES_IMAGE=$reg/cameleer-postgres
CLICKHOUSE_IMAGE=$reg/cameleer-clickhouse
LOGTO_IMAGE=$reg/cameleer-logto
CAMELEER_IMAGE=$reg/cameleer-saas
# Provisioning images
CAMELEER_SAAS_PROVISIONING_SERVERIMAGE=${REGISTRY}/cameleer-server:$($c.Version)
CAMELEER_SAAS_PROVISIONING_SERVERUIIMAGE=${REGISTRY}/cameleer-server-ui:$($c.Version)
CAMELEER_SAAS_PROVISIONING_RUNTIMEBASEIMAGE=${REGISTRY}/cameleer-runtime-base:$($c.Version)
CAMELEER_SAAS_PROVISIONING_SERVERIMAGE=$reg/cameleer-server:$($c.Version)
CAMELEER_SAAS_PROVISIONING_SERVERUIIMAGE=$reg/cameleer-server-ui:$($c.Version)
CAMELEER_SAAS_PROVISIONING_RUNTIMEBASEIMAGE=$reg/cameleer-runtime-base:$($c.Version)
# JWT signing secret (forwarded to provisioned tenant servers, must be non-empty)
CAMELEER_SERVER_SECURITY_JWTSECRET=$jwtSecret
@@ -778,7 +813,18 @@ function Copy-Templates {
}
# --- Docker operations ---
function Invoke-RegistryLogin {
$c = $script:cfg
if ($c.RegistryUser -and $c.RegistryToken) {
$registryHost = $c.Registry.Split('/')[0]
Log-Info "Logging in to registry ${registryHost}..."
$c.RegistryToken | docker login $registryHost -u $c.RegistryUser --password-stdin
if ($LASTEXITCODE -ne 0) { Log-Error 'Registry login failed.'; exit 1 }
Log-Success 'Registry login successful.'
}
}
function Invoke-ComposePull {
$c = $script:cfg
Log-Info 'Pulling Docker images...'
@@ -964,6 +1010,9 @@ smtp_port=$($c.SmtpPort)
smtp_user=$($c.SmtpUser)
smtp_pass=$($c.SmtpPass)
smtp_from_email=$($c.SmtpFromEmail)
registry=$($c.Registry)
registry_user=$($c.RegistryUser)
registry_token=$($c.RegistryToken)
"@
Write-Utf8File $f $txt
Log-Info 'Saved installer config to cameleer.conf'
@@ -1393,6 +1442,7 @@ function Handle-Rerun {
$script:cfg.InstallDir = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(
$script:cfg.InstallDir)
Copy-Templates
Invoke-RegistryLogin
Invoke-ComposePull
Invoke-ComposeDown
Invoke-ComposeUp
@@ -1477,10 +1527,11 @@ function Main {
Copy-Templates
Write-ConfigFile
Invoke-RegistryLogin
Invoke-ComposePull
Invoke-ComposeUp
Verify-Health
Generate-CredentialsFile
Generate-InstallDoc