501 lines
20 KiB
Bash
501 lines
20 KiB
Bash
|
|
#!/bin/bash
|
||
|
|
#
|
||
|
|
# LetsBe Cloud Environment Setup Script
|
||
|
|
# Non-interactive version for Orchestrator/SysAdmin Agent integration
|
||
|
|
#
|
||
|
|
# Usage:
|
||
|
|
# ./env_setup.sh --customer "acme" --domain "acme.com" --company "Acme Corp"
|
||
|
|
# ./env_setup.sh --json '{"customer":"acme","domain":"acme.com","company_name":"Acme Corp"}'
|
||
|
|
# ./env_setup.sh --config /path/to/config.json
|
||
|
|
#
|
||
|
|
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
# ============================================================================
|
||
|
|
# CONFIGURATION
|
||
|
|
# ============================================================================
|
||
|
|
|
||
|
|
LETSBE_BASE="/opt/letsbe"
|
||
|
|
STACKS_DIR="${LETSBE_BASE}/stacks"
|
||
|
|
NGINX_DIR="${LETSBE_BASE}/nginx"
|
||
|
|
ENV_DIR="${LETSBE_BASE}/env"
|
||
|
|
SCRIPTS_DIR="${LETSBE_BASE}/scripts"
|
||
|
|
|
||
|
|
# ============================================================================
|
||
|
|
# HELPER FUNCTIONS
|
||
|
|
# ============================================================================
|
||
|
|
|
||
|
|
usage() {
|
||
|
|
cat <<EOF
|
||
|
|
Usage: $0 [OPTIONS]
|
||
|
|
|
||
|
|
Required (one of):
|
||
|
|
--customer NAME Customer name (lowercase, no spaces/hyphens/numbers)
|
||
|
|
--domain DOMAIN Main domain without subdomains (lowercase)
|
||
|
|
--company NAME Company name (can include spaces)
|
||
|
|
|
||
|
|
Or provide all via JSON:
|
||
|
|
--json JSON_STRING JSON object with customer, domain, company_name
|
||
|
|
--config FILE Path to JSON config file
|
||
|
|
|
||
|
|
Example:
|
||
|
|
$0 --customer acme --domain acme.com --company "Acme Corporation"
|
||
|
|
$0 --json '{"customer":"acme","domain":"acme.com","company_name":"Acme Corp"}'
|
||
|
|
$0 --config /opt/letsbe/config/setup.json
|
||
|
|
|
||
|
|
EOF
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
|
||
|
|
log_info() {
|
||
|
|
echo "[INFO] $*"
|
||
|
|
}
|
||
|
|
|
||
|
|
log_error() {
|
||
|
|
echo "[ERROR] $*" >&2
|
||
|
|
}
|
||
|
|
|
||
|
|
die() {
|
||
|
|
log_error "$*"
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
|
||
|
|
# Generate random string of specified length
|
||
|
|
generate_random_string() {
|
||
|
|
local length=$1
|
||
|
|
tr -dc A-Za-z0-9 </dev/urandom | head -c "${length}"
|
||
|
|
echo ''
|
||
|
|
}
|
||
|
|
|
||
|
|
# Validate required variables are set
|
||
|
|
validate_required() {
|
||
|
|
local var_name=$1
|
||
|
|
local var_value=$2
|
||
|
|
if [[ -z "${var_value}" ]]; then
|
||
|
|
die "Required variable '${var_name}' is not set"
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
# Parse JSON input using jq
|
||
|
|
parse_json() {
|
||
|
|
local json_input=$1
|
||
|
|
|
||
|
|
if ! command -v jq &> /dev/null; then
|
||
|
|
die "jq is required for JSON parsing. Install with: apt-get install jq"
|
||
|
|
fi
|
||
|
|
|
||
|
|
customer=$(echo "${json_input}" | jq -r '.customer // empty')
|
||
|
|
domain=$(echo "${json_input}" | jq -r '.domain // empty')
|
||
|
|
company_name=$(echo "${json_input}" | jq -r '.company_name // empty')
|
||
|
|
}
|
||
|
|
|
||
|
|
# ============================================================================
|
||
|
|
# ARGUMENT PARSING
|
||
|
|
# ============================================================================
|
||
|
|
|
||
|
|
customer=""
|
||
|
|
domain=""
|
||
|
|
company_name=""
|
||
|
|
|
||
|
|
while [[ $# -gt 0 ]]; do
|
||
|
|
case $1 in
|
||
|
|
--customer)
|
||
|
|
customer="$2"
|
||
|
|
shift 2
|
||
|
|
;;
|
||
|
|
--domain)
|
||
|
|
domain="$2"
|
||
|
|
shift 2
|
||
|
|
;;
|
||
|
|
--company)
|
||
|
|
company_name="$2"
|
||
|
|
shift 2
|
||
|
|
;;
|
||
|
|
--json)
|
||
|
|
parse_json "$2"
|
||
|
|
shift 2
|
||
|
|
;;
|
||
|
|
--config)
|
||
|
|
if [[ ! -f "$2" ]]; then
|
||
|
|
die "Config file not found: $2"
|
||
|
|
fi
|
||
|
|
parse_json "$(cat "$2")"
|
||
|
|
shift 2
|
||
|
|
;;
|
||
|
|
--help|-h)
|
||
|
|
usage
|
||
|
|
;;
|
||
|
|
*)
|
||
|
|
log_error "Unknown option: $1"
|
||
|
|
usage
|
||
|
|
;;
|
||
|
|
esac
|
||
|
|
done
|
||
|
|
|
||
|
|
# ============================================================================
|
||
|
|
# VALIDATION
|
||
|
|
# ============================================================================
|
||
|
|
|
||
|
|
validate_required "customer" "${customer}"
|
||
|
|
validate_required "domain" "${domain}"
|
||
|
|
validate_required "company_name" "${company_name}"
|
||
|
|
|
||
|
|
# Validate customer format (lowercase, no spaces/hyphens/numbers)
|
||
|
|
if [[ ! "${customer}" =~ ^[a-z]+$ ]]; then
|
||
|
|
die "Customer name must be lowercase letters only, no spaces/hyphens/numbers: ${customer}"
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Validate domain format
|
||
|
|
if [[ ! "${domain}" =~ ^[a-z0-9.-]+\.[a-z]{2,}$ ]]; then
|
||
|
|
die "Invalid domain format: ${domain}"
|
||
|
|
fi
|
||
|
|
|
||
|
|
log_info "Configuration validated"
|
||
|
|
log_info " Customer: ${customer}"
|
||
|
|
log_info " Domain: ${domain}"
|
||
|
|
log_info " Company: ${company_name}"
|
||
|
|
|
||
|
|
# ============================================================================
|
||
|
|
# DERIVED VARIABLES
|
||
|
|
# ============================================================================
|
||
|
|
|
||
|
|
# Email for Let's Encrypt
|
||
|
|
letsencrypt_email="postmaster@${domain}"
|
||
|
|
|
||
|
|
# Subdomains per tool
|
||
|
|
domain_html="html.${domain}"
|
||
|
|
domain_wordpress="${domain}"
|
||
|
|
domain_squidex="contenthub.${domain}"
|
||
|
|
domain_chatwoot="support.${domain}"
|
||
|
|
domain_chatwoot_helpdesk="helpdesk.${domain}"
|
||
|
|
domain_gitea="code.${domain}"
|
||
|
|
domain_gitea_drone="ci.${domain}"
|
||
|
|
domain_glitchtip="debug.${domain}"
|
||
|
|
domain_listmonk="newsletters.${domain}"
|
||
|
|
domain_n8n="n8n.${domain}"
|
||
|
|
domain_nextcloud="cloud.${domain}"
|
||
|
|
domain_penpot="design.${domain}"
|
||
|
|
domain_poste="mail.${domain}"
|
||
|
|
domain_umami="analytics.${domain}"
|
||
|
|
domain_uptime_kuma="uptime.${domain}"
|
||
|
|
domain_windmill="flows.${domain}"
|
||
|
|
domain_calcom="bookings.${domain}"
|
||
|
|
domain_odoo="crm.${domain}"
|
||
|
|
domain_collabora="collabora.${domain}"
|
||
|
|
domain_whiteboard="whiteboard.${domain}"
|
||
|
|
domain_activepieces="automation.${domain}"
|
||
|
|
domain_minio="minio.${domain}"
|
||
|
|
domain_s3="s3.${domain}"
|
||
|
|
domain_librechat="ai.${domain}"
|
||
|
|
domain_bot_viewer="bots.${domain}"
|
||
|
|
domain_botlab="botlab.${domain}"
|
||
|
|
domain_nocodb="database.${domain}"
|
||
|
|
domain_redash="data.${domain}"
|
||
|
|
domain_documenso="signatures.${domain}"
|
||
|
|
domain_keycloak="auth.${domain}"
|
||
|
|
domain_pdf="pdf.${domain}"
|
||
|
|
domain_ghost="${domain}"
|
||
|
|
|
||
|
|
# ============================================================================
|
||
|
|
# GENERATED SECRETS
|
||
|
|
# ============================================================================
|
||
|
|
|
||
|
|
log_info "Generating secrets and credentials..."
|
||
|
|
|
||
|
|
# WordPress
|
||
|
|
wordpresss_mariadb_root_password=$(generate_random_string 20)
|
||
|
|
wordpress_db_user=$(generate_random_string 10 | tr '[:upper:]' '[:lower:]')
|
||
|
|
wordpress_db_password=$(generate_random_string 20)
|
||
|
|
|
||
|
|
# Squidex
|
||
|
|
squidex_adminemail="postmaster@${domain}"
|
||
|
|
squidex_adminpassword=$(generate_random_string 20)
|
||
|
|
|
||
|
|
# Listmonk
|
||
|
|
listmonk_admin_username=$(generate_random_string 10 | tr '[:upper:]' '[:lower:]')
|
||
|
|
listmonk_admin_password=$(generate_random_string 20)
|
||
|
|
listmonk_db_user=$(generate_random_string 10 | tr '[:upper:]' '[:lower:]')
|
||
|
|
listmonk_db_password=$(generate_random_string 20)
|
||
|
|
|
||
|
|
# Gitea
|
||
|
|
gitea_postgres_user=$(generate_random_string 10 | tr '[:upper:]' '[:lower:]')
|
||
|
|
gitea_postgres_password=$(generate_random_string 20)
|
||
|
|
|
||
|
|
# Umami
|
||
|
|
umami_app_secret=$(generate_random_string 32)
|
||
|
|
umami_postgres_user=$(generate_random_string 10 | tr '[:upper:]' '[:lower:]')
|
||
|
|
umami_postgres_password=$(generate_random_string 20)
|
||
|
|
|
||
|
|
# Drone/Gitea
|
||
|
|
drone_gitea_rpc_secret=$(generate_random_string 32)
|
||
|
|
|
||
|
|
# Windmill
|
||
|
|
windmill_database_password=$(generate_random_string 20)
|
||
|
|
|
||
|
|
# Glitchtip
|
||
|
|
glitchtip_database_password=$(generate_random_string 20)
|
||
|
|
glitchtip_secret_key=$(generate_random_string 32)
|
||
|
|
|
||
|
|
# Penpot
|
||
|
|
penpot_secret_key=$(generate_random_string 32)
|
||
|
|
penpot_db_user=$(generate_random_string 10 | tr '[:upper:]' '[:lower:]')
|
||
|
|
penpot_db_password=$(generate_random_string 20)
|
||
|
|
|
||
|
|
# Nextcloud
|
||
|
|
nextcloud_postgres_user=$(generate_random_string 10 | tr '[:upper:]' '[:lower:]')
|
||
|
|
nextcloud_postgres_password=$(generate_random_string 20)
|
||
|
|
nextcloud_jwt_secret=$(generate_random_string 64 | tr '[:upper:]' '[:lower:]')
|
||
|
|
nextcloud_admin_password=$(generate_random_string 20)
|
||
|
|
|
||
|
|
# Collabora
|
||
|
|
collabora_password=$(generate_random_string 20)
|
||
|
|
collabora_user=$(generate_random_string 10 | tr '[:upper:]' '[:lower:]')
|
||
|
|
|
||
|
|
# Chatwoot
|
||
|
|
chatwoot_secret_key_base=$(generate_random_string 32)
|
||
|
|
chatwoot_redis_password=$(generate_random_string 20)
|
||
|
|
chatwoot_postgres_username=$(generate_random_string 10 | tr '[:upper:]' '[:lower:]')
|
||
|
|
chatwoot_postgres_password=$(generate_random_string 20)
|
||
|
|
chatwoot_rails_inbound_email_password=$(generate_random_string 20)
|
||
|
|
|
||
|
|
# N8N
|
||
|
|
n8n_postgres_user=$(generate_random_string 10 | tr '[:upper:]' '[:lower:]')
|
||
|
|
n8n_postgres_password=$(generate_random_string 20)
|
||
|
|
|
||
|
|
# Cal.com
|
||
|
|
calcom_nextauth_secret=$(generate_random_string 32)
|
||
|
|
calcom_postgres_user=$(generate_random_string 10 | tr '[:upper:]' '[:lower:]')
|
||
|
|
calcom_postgres_password=$(generate_random_string 20)
|
||
|
|
|
||
|
|
# Odoo
|
||
|
|
odoo_postgres_user=$(generate_random_string 10 | tr '[:upper:]' '[:lower:]')
|
||
|
|
odoo_postgres_password=$(generate_random_string 20)
|
||
|
|
|
||
|
|
# Activepieces
|
||
|
|
activepieces_api_key=$(generate_random_string 32)
|
||
|
|
activepieces_encryption_key=$(generate_random_string 32 | tr '[:upper:]' '[:lower:]')
|
||
|
|
activepieces_jwt_secret=$(generate_random_string 64 | tr '[:upper:]' '[:lower:]')
|
||
|
|
activepieces_postgres_password=$(generate_random_string 32)
|
||
|
|
|
||
|
|
# MinIO
|
||
|
|
minio_root_user=$(generate_random_string 16)
|
||
|
|
minio_root_password=$(generate_random_string 32)
|
||
|
|
|
||
|
|
# Typebot
|
||
|
|
typebot_encryption_secret=$(generate_random_string 32)
|
||
|
|
typebot_postgres_password=$(generate_random_string 20)
|
||
|
|
|
||
|
|
# NocoDB
|
||
|
|
nocodb_postgres_password=$(generate_random_string 32)
|
||
|
|
|
||
|
|
# LibreChat
|
||
|
|
librechat_postgres_password=$(generate_random_string 20)
|
||
|
|
librechat_postgres_user=$(generate_random_string 10 | tr '[:upper:]' '[:lower:]')
|
||
|
|
librechat_jwt_secret=$(generate_random_string 64 | tr '[:upper:]' '[:lower:]')
|
||
|
|
librechat_jwt_refresh_secret=$(generate_random_string 64 | tr '[:upper:]' '[:lower:]')
|
||
|
|
|
||
|
|
# Redash
|
||
|
|
redash_secret_key=$(generate_random_string 32)
|
||
|
|
redash_cookie_secret=$(generate_random_string 32)
|
||
|
|
redash_postgres_password=$(generate_random_string 20)
|
||
|
|
redash_postgres_user=$(generate_random_string 10 | tr '[:upper:]' '[:lower:]')
|
||
|
|
|
||
|
|
# Documenso
|
||
|
|
documenso_postgres_user=$(generate_random_string 10 | tr '[:upper:]' '[:lower:]')
|
||
|
|
documenso_postgres_password=$(generate_random_string 40)
|
||
|
|
documenso_nextauth_secret=$(generate_random_string 32)
|
||
|
|
documenso_encryption_key=$(generate_random_string 64 | tr '[:upper:]' '[:lower:]')
|
||
|
|
documenso_encryption_secondary_key=$(generate_random_string 64 | tr '[:upper:]' '[:lower:]')
|
||
|
|
|
||
|
|
# Ghost
|
||
|
|
ghost_mysql_password=$(generate_random_string 40)
|
||
|
|
ghost_s3_access_key=$(generate_random_string 20)
|
||
|
|
ghost_s3_secret_key=$(generate_random_string 40)
|
||
|
|
|
||
|
|
# Keycloak
|
||
|
|
keycloak_postgres_password=$(generate_random_string 40)
|
||
|
|
keycloak_admin_password=$(generate_random_string 40)
|
||
|
|
keycloak_grafana_password=$(generate_random_string 40)
|
||
|
|
|
||
|
|
# StirlingPDF
|
||
|
|
stirlingpdf_postgres_user=$(generate_random_string 10 | tr '[:upper:]' '[:lower:]')
|
||
|
|
stirlingpdf_postgres_password=$(generate_random_string 40)
|
||
|
|
stirlingpdf_api_key=$(generate_random_string 40)
|
||
|
|
|
||
|
|
# Sysadmin Agent
|
||
|
|
sysadmin_agent_token=$(generate_random_string 64)
|
||
|
|
|
||
|
|
# ============================================================================
|
||
|
|
# TEMPLATE REPLACEMENT
|
||
|
|
# ============================================================================
|
||
|
|
|
||
|
|
log_info "Replacing placeholders in template files..."
|
||
|
|
|
||
|
|
# Process all template files
|
||
|
|
for file in "${STACKS_DIR}"/*/* "${STACKS_DIR}"/*/.* "${NGINX_DIR}"/* "${SCRIPTS_DIR}"/backups.sh; do
|
||
|
|
if [[ -f "${file}" ]]; then
|
||
|
|
# Core variables
|
||
|
|
sed -i "s/{{ customer }}/${customer}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain }}/${domain}/g" "${file}"
|
||
|
|
sed -i "s/{{ company_name }}/${company_name}/g" "${file}"
|
||
|
|
sed -i "s/{{ letsencrypt_email }}/${letsencrypt_email}/g" "${file}"
|
||
|
|
|
||
|
|
# Domain variables
|
||
|
|
sed -i "s/{{ domain_html }}/${domain_html}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_wordpress }}/${domain_wordpress}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_squidex }}/${domain_squidex}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_chatwoot }}/${domain_chatwoot}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_chatwoot_helpdesk }}/${domain_chatwoot_helpdesk}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_gitea }}/${domain_gitea}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_gitea_drone }}/${domain_gitea_drone}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_glitchtip }}/${domain_glitchtip}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_listmonk }}/${domain_listmonk}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_librechat }}/${domain_librechat}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_n8n }}/${domain_n8n}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_nextcloud }}/${domain_nextcloud}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_penpot }}/${domain_penpot}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_poste }}/${domain_poste}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_umami }}/${domain_umami}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_uptime_kuma }}/${domain_uptime_kuma}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_windmill }}/${domain_windmill}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_calcom }}/${domain_calcom}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_odoo }}/${domain_odoo}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_collabora }}/${domain_collabora}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_activepieces }}/${domain_activepieces}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_bot_viewer }}/${domain_bot_viewer}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_botlab }}/${domain_botlab}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_minio }}/${domain_minio}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_s3 }}/${domain_s3}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_nocodb }}/${domain_nocodb}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_whiteboard }}/${domain_whiteboard}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_redash }}/${domain_redash}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_documenso }}/${domain_documenso}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_keycloak }}/${domain_keycloak}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_pdf }}/${domain_pdf}/g" "${file}"
|
||
|
|
sed -i "s/{{ domain_ghost }}/${domain_ghost}/g" "${file}"
|
||
|
|
|
||
|
|
# Credential variables
|
||
|
|
sed -i "s/{{ wordpresss_mariadb_root_password }}/${wordpresss_mariadb_root_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ wordpress_db_user }}/${wordpress_db_user}/g" "${file}"
|
||
|
|
sed -i "s/{{ wordpress_db_password }}/${wordpress_db_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ squidex_adminemail }}/${squidex_adminemail}/g" "${file}"
|
||
|
|
sed -i "s/{{ squidex_adminpassword }}/${squidex_adminpassword}/g" "${file}"
|
||
|
|
sed -i "s/{{ listmonk_admin_username }}/${listmonk_admin_username}/g" "${file}"
|
||
|
|
sed -i "s/{{ listmonk_admin_password }}/${listmonk_admin_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ listmonk_db_user }}/${listmonk_db_user}/g" "${file}"
|
||
|
|
sed -i "s/{{ listmonk_db_password }}/${listmonk_db_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ gitea_postgres_user }}/${gitea_postgres_user}/g" "${file}"
|
||
|
|
sed -i "s/{{ gitea_postgres_password }}/${gitea_postgres_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ umami_app_secret }}/${umami_app_secret}/g" "${file}"
|
||
|
|
sed -i "s/{{ umami_postgres_user }}/${umami_postgres_user}/g" "${file}"
|
||
|
|
sed -i "s/{{ umami_postgres_password }}/${umami_postgres_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ drone_gitea_rpc_secret }}/${drone_gitea_rpc_secret}/g" "${file}"
|
||
|
|
sed -i "s/{{ windmill_database_password }}/${windmill_database_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ glitchtip_database_password }}/${glitchtip_database_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ glitchtip_secret_key }}/${glitchtip_secret_key}/g" "${file}"
|
||
|
|
sed -i "s/{{ penpot_secret_key }}/${penpot_secret_key}/g" "${file}"
|
||
|
|
sed -i "s/{{ penpot_db_user }}/${penpot_db_user}/g" "${file}"
|
||
|
|
sed -i "s/{{ penpot_db_password }}/${penpot_db_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ nextcloud_postgres_user }}/${nextcloud_postgres_user}/g" "${file}"
|
||
|
|
sed -i "s/{{ nextcloud_postgres_password }}/${nextcloud_postgres_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ nextcloud_admin_password }}/${nextcloud_admin_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ nextcloud_jwt_secret }}/${nextcloud_jwt_secret}/g" "${file}"
|
||
|
|
sed -i "s/{{ collabora_password }}/${collabora_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ collabora_user }}/${collabora_user}/g" "${file}"
|
||
|
|
sed -i "s/{{ chatwoot_secret_key_base }}/${chatwoot_secret_key_base}/g" "${file}"
|
||
|
|
sed -i "s/{{ chatwoot_redis_password }}/${chatwoot_redis_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ chatwoot_postgres_username }}/${chatwoot_postgres_username}/g" "${file}"
|
||
|
|
sed -i "s/{{ chatwoot_postgres_password }}/${chatwoot_postgres_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ chatwoot_rails_inbound_email_password }}/${chatwoot_rails_inbound_email_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ n8n_postgres_user }}/${n8n_postgres_user}/g" "${file}"
|
||
|
|
sed -i "s/{{ n8n_postgres_password }}/${n8n_postgres_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ calcom_nextauth_secret }}/${calcom_nextauth_secret}/g" "${file}"
|
||
|
|
sed -i "s/{{ calcom_postgres_user }}/${calcom_postgres_user}/g" "${file}"
|
||
|
|
sed -i "s/{{ calcom_postgres_password }}/${calcom_postgres_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ odoo_postgres_user }}/${odoo_postgres_user}/g" "${file}"
|
||
|
|
sed -i "s/{{ odoo_postgres_password }}/${odoo_postgres_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ activepieces_api_key }}/${activepieces_api_key}/g" "${file}"
|
||
|
|
sed -i "s/{{ activepieces_encryption_key }}/${activepieces_encryption_key}/g" "${file}"
|
||
|
|
sed -i "s/{{ activepieces_jwt_secret }}/${activepieces_jwt_secret}/g" "${file}"
|
||
|
|
sed -i "s/{{ activepieces_postgres_password }}/${activepieces_postgres_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ minio_root_user }}/${minio_root_user}/g" "${file}"
|
||
|
|
sed -i "s/{{ minio_root_password }}/${minio_root_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ typebot_encryption_secret }}/${typebot_encryption_secret}/g" "${file}"
|
||
|
|
sed -i "s/{{ nocodb_postgres_password }}/${nocodb_postgres_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ typebot_postgres_password }}/${typebot_postgres_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ redash_secret_key }}/${redash_secret_key}/g" "${file}"
|
||
|
|
sed -i "s/{{ redash_cookie_secret }}/${redash_cookie_secret}/g" "${file}"
|
||
|
|
sed -i "s/{{ redash_postgres_user }}/${redash_postgres_user}/g" "${file}"
|
||
|
|
sed -i "s/{{ redash_postgres_password }}/${redash_postgres_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ librechat_postgres_password }}/${librechat_postgres_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ librechat_postgres_user }}/${librechat_postgres_user}/g" "${file}"
|
||
|
|
sed -i "s/{{ librechat_jwt_secret }}/${librechat_jwt_secret}/g" "${file}"
|
||
|
|
sed -i "s/{{ librechat_jwt_refresh_secret }}/${librechat_jwt_refresh_secret}/g" "${file}"
|
||
|
|
sed -i "s/{{ documenso_postgres_user }}/${documenso_postgres_user}/g" "${file}"
|
||
|
|
sed -i "s/{{ documenso_postgres_password }}/${documenso_postgres_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ documenso_nextauth_secret }}/${documenso_nextauth_secret}/g" "${file}"
|
||
|
|
sed -i "s/{{ documenso_encryption_key }}/${documenso_encryption_key}/g" "${file}"
|
||
|
|
sed -i "s/{{ documenso_encryption_secondary_key }}/${documenso_encryption_secondary_key}/g" "${file}"
|
||
|
|
sed -i "s/{{ ghost_mysql_password }}/${ghost_mysql_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ ghost_s3_access_key }}/${ghost_s3_access_key}/g" "${file}"
|
||
|
|
sed -i "s/{{ ghost_s3_secret_key }}/${ghost_s3_secret_key}/g" "${file}"
|
||
|
|
sed -i "s/{{ keycloak_postgres_password }}/${keycloak_postgres_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ keycloak_admin_password }}/${keycloak_admin_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ keycloak_grafana_password }}/${keycloak_grafana_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ stirlingpdf_postgres_user }}/${stirlingpdf_postgres_user}/g" "${file}"
|
||
|
|
sed -i "s/{{ stirlingpdf_postgres_password }}/${stirlingpdf_postgres_password}/g" "${file}"
|
||
|
|
sed -i "s/{{ stirlingpdf_api_key }}/${stirlingpdf_api_key}/g" "${file}"
|
||
|
|
sed -i "s/{{ sysadmin_agent_token }}/${sysadmin_agent_token}/g" "${file}"
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
|
||
|
|
log_info "All placeholders replaced successfully."
|
||
|
|
|
||
|
|
# ============================================================================
|
||
|
|
# GENERATE ENV FILES
|
||
|
|
# ============================================================================
|
||
|
|
|
||
|
|
log_info "Generating centralized environment files..."
|
||
|
|
|
||
|
|
mkdir -p "${ENV_DIR}"
|
||
|
|
|
||
|
|
# Write master credentials file for reference
|
||
|
|
cat > "${ENV_DIR}/credentials.env" <<EOF
|
||
|
|
# LetsBe Cloud Credentials - Generated $(date -Iseconds)
|
||
|
|
# Customer: ${customer}
|
||
|
|
# Domain: ${domain}
|
||
|
|
# Company: ${company_name}
|
||
|
|
#
|
||
|
|
# KEEP THIS FILE SECURE - Contains all generated passwords
|
||
|
|
#
|
||
|
|
|
||
|
|
# WordPress
|
||
|
|
WORDPRESS_DB_USER=${wordpress_db_user}
|
||
|
|
WORDPRESS_DB_PASSWORD=${wordpress_db_password}
|
||
|
|
WORDPRESS_MARIADB_ROOT_PASSWORD=${wordpresss_mariadb_root_password}
|
||
|
|
|
||
|
|
# Nextcloud
|
||
|
|
NEXTCLOUD_ADMIN_PASSWORD=${nextcloud_admin_password}
|
||
|
|
NEXTCLOUD_POSTGRES_USER=${nextcloud_postgres_user}
|
||
|
|
NEXTCLOUD_POSTGRES_PASSWORD=${nextcloud_postgres_password}
|
||
|
|
|
||
|
|
# Listmonk
|
||
|
|
LISTMONK_ADMIN_USER=${listmonk_admin_username}
|
||
|
|
LISTMONK_ADMIN_PASSWORD=${listmonk_admin_password}
|
||
|
|
|
||
|
|
# MinIO
|
||
|
|
MINIO_ROOT_USER=${minio_root_user}
|
||
|
|
MINIO_ROOT_PASSWORD=${minio_root_password}
|
||
|
|
|
||
|
|
# Keycloak
|
||
|
|
KEYCLOAK_ADMIN_PASSWORD=${keycloak_admin_password}
|
||
|
|
|
||
|
|
# Sysadmin Agent
|
||
|
|
SYSADMIN_AGENT_TOKEN=${sysadmin_agent_token}
|
||
|
|
EOF
|
||
|
|
|
||
|
|
chmod 640 "${ENV_DIR}/credentials.env"
|
||
|
|
|
||
|
|
log_info "Environment setup complete."
|
||
|
|
log_info "Credentials saved to: ${ENV_DIR}/credentials.env"
|