#!/bin/bash generateRandomPassword() { local password="" local length=${CFG_GENERATED_PASS_LENGTH:-20} # Default to 20 if not set local attempt # Letters and numbers only, no special characters: these values are embedded # in connection URLs (Mattermost's Postgres DSN), interpolated into container # entrypoints and written into YAML, and a symbol would need different # escaping in each. # # Retry until the result carries at least one digit AND one letter. base64 of # urandom is alphanumeric but says nothing about the mix — measured over 2000 # draws at the default length, 1 in 40 came back with no digit at all, which # trips any policy that requires one. At that hit rate the retry is free. # Bounded rather than `while true` so a pathological length (or an empty # /dev/urandom read) can't spin forever; a sub-2 length can't hold both # classes at all, so it is accepted as-is. for attempt in {1..50}; do password=$(dd if=/dev/urandom bs=64 count=1 2>/dev/null | base64 | tr -d '+/=' | head -c $length) [[ ${#password} -eq $length ]] || continue [[ $length -lt 2 ]] && break [[ "$password" == *[0-9]* && "$password" == *[A-Za-z]* ]] && break done echo "$password" }