feat(monitoring): automate Prometheus web config generation

Remove manual password hashing and web.yml setup in favor of automated generation. Add scripts for both Unix and Windows to create `monitoring/web.yml` using credentials from `.env`.

This improves maintainability and reduces manual intervention during setup and configuration.
This commit is contained in:
Egor Pavlovich Gorbunov 2026-02-22 00:17:55 +03:00
parent 069d416585
commit 7efc19e081
11 changed files with 97 additions and 11 deletions

1
.gitignore vendored
View file

@ -194,6 +194,7 @@ engine/core/vendors/docs/*
.initialized
./queries
./nginx.conf
monitoring/web.yml
# AI assistants
.claude/

View file

@ -1,9 +0,0 @@
import getpass
import bcrypt
print(
bcrypt.hashpw(
getpass.getpass("Password: ").encode("utf-8"), bcrypt.gensalt()
).decode()
)

View file

@ -1,2 +0,0 @@
basic_auth_users:
schon: $2b$12$0HraDYmrZnJ089LcH9Vsn.Wv5V5a8oDlucTNm0.5obhULjPyLiYoy

View file

@ -81,6 +81,10 @@ case "$install_choice" in
fi
log_success "Images built successfully"
# Generate Prometheus web config from .env
log_step "Generating Prometheus web config..."
generate_prometheus_web_config
echo
log_result "Docker installation complete!"
log_info "You can now use: make run"

View file

@ -3,6 +3,10 @@ set -euo pipefail
source ./scripts/Unix/starter.sh
# Generate Prometheus web config from .env
log_step "Generating Prometheus web config..."
generate_prometheus_web_config
# Shutdown services
log_step "Shutting down..."
if ! output=$(docker compose down 2>&1); then

View file

@ -20,6 +20,10 @@ else
log_warning "jq is not installed; skipping image verification step."
fi
# Generate Prometheus web config from .env
log_step "Generating Prometheus web config..."
generate_prometheus_web_config
# Start services
log_step "Spinning services up..."
if ! output=$(docker compose up --no-build --detach --wait 2>&1); then

View file

@ -42,5 +42,9 @@ if ($LASTEXITCODE -ne 0) {
}
Write-Success "Images built successfully"
# Generate Prometheus web config from .env
Write-Step "Generating Prometheus web config..."
New-PrometheusWebConfig
Write-Result ""
Write-Result "You can now use run.ps1 script or run: make run"

View file

@ -10,6 +10,10 @@ if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
# Generate Prometheus web config from .env
Write-Step "Generating Prometheus web config..."
New-PrometheusWebConfig
# Shutdown services
Write-Step "Shutting down..."
$output = docker compose down 2>&1

View file

@ -35,6 +35,10 @@ foreach ($prop in $config.services.PSObject.Properties)
Write-Info " Found image: $image"
}
# Generate Prometheus web config from .env
Write-Step "Generating Prometheus web config..."
New-PrometheusWebConfig
# Start services
Write-Step "Spinning services up..."
$output = docker compose up --no-build --detach --wait 2>&1

View file

@ -277,6 +277,43 @@ function Test-SystemRequirements
return $true
}
# Generate monitoring/web.yml from PROMETHEUS_USER and PROMETHEUS_PASSWORD in .env
function New-PrometheusWebConfig
{
if (-not (Test-Path '.env')) { return }
$envContent = Get-Content '.env'
$promUserLine = $envContent | Where-Object { $_ -match '^PROMETHEUS_USER=' } | Select-Object -First 1
$promPassLine = $envContent | Where-Object { $_ -match '^PROMETHEUS_PASSWORD=' } | Select-Object -First 1
if (-not $promUserLine -or -not $promPassLine) {
Write-Warning-Custom "PROMETHEUS_USER or PROMETHEUS_PASSWORD not set in .env, skipping web.yml generation"
return
}
$promUser = ($promUserLine -replace '^PROMETHEUS_USER=', '').Trim('"')
$promPassword = ($promPassLine -replace '^PROMETHEUS_PASSWORD=', '').Trim('"')
if ([string]::IsNullOrEmpty($promUser) -or [string]::IsNullOrEmpty($promPassword)) {
Write-Warning-Custom "PROMETHEUS_USER or PROMETHEUS_PASSWORD is empty, skipping web.yml generation"
return
}
$rawHash = docker run --rm httpd:2-alpine htpasswd -nbBC 12 "" "$promPassword" 2>$null
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrEmpty($rawHash)) {
Write-Warning-Custom "Failed to generate Prometheus password hash"
return
}
# htpasswd outputs ":$2y$..." - strip leading colon and whitespace
$hash = $rawHash.TrimStart(':').Trim()
$content = "basic_auth_users:`n ${promUser}: ${hash}`n"
[System.IO.File]::WriteAllText((Join-Path $PWD 'monitoring/web.yml'), $content)
Write-Success "Prometheus web config generated"
}
# Confirm action
function Confirm-Action
{

View file

@ -201,6 +201,41 @@ check_system_requirements() {
return 0
}
# Generate monitoring/web.yml from PROMETHEUS_USER and PROMETHEUS_PASSWORD in .env
generate_prometheus_web_config() {
if [ ! -f .env ]; then
return 0
fi
local prom_user prom_password
prom_user=$(grep '^PROMETHEUS_USER=' .env | head -1 | cut -d= -f2- | tr -d '"')
prom_password=$(grep '^PROMETHEUS_PASSWORD=' .env | head -1 | cut -d= -f2- | tr -d '"')
if [ -z "$prom_user" ] || [ -z "$prom_password" ]; then
log_warning "PROMETHEUS_USER or PROMETHEUS_PASSWORD not set in .env, skipping web.yml generation"
return 0
fi
local raw_hash hash
raw_hash=$(docker run --rm httpd:2-alpine htpasswd -nbBC 12 "" "$prom_password" 2>/dev/null)
if [ -z "$raw_hash" ]; then
log_warning "Failed to generate Prometheus password hash"
return 0
fi
# htpasswd outputs ":$2y$..." — strip leading colon and trailing whitespace
hash="${raw_hash#:}"
hash="${hash%%[[:space:]]*}"
cat > monitoring/web.yml <<EOF
basic_auth_users:
${prom_user}: ${hash}
EOF
log_success "Prometheus web config generated"
}
# Confirm action (returns 0 for yes, 1 for no)
confirm() {
local prompt="${1:-Are you sure?}"