#!/bin/bash cat << "EOF" ██████╗██╗ ██╗ █████╗ ███╗ ██╗ ██████╗ ███████╗ ██╔════╝██║ ██║██╔══██╗████╗ ██║██╔════╝ ██╔════╝ ██║ ███████║███████║██╔██╗ ██║██║ ███╗█████╗ ██║ ██╔══██║██╔══██║██║╚██╗██║██║ ██║██╔══╝ ╚██████╗██║ ██║██║ ██║██║ ╚████║╚██████╔╝███████╗ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ███╗ ███╗ █████╗ ██╗ ██╗███████╗██████╗ ████╗ ████║██╔══██╗██║ ██╔╝██╔════╝██╔══██╗ ██╔████╔██║███████║█████╔╝ █████╗ ██████╔╝ ██║╚██╔╝██║██╔══██║██╔═██╗ ██╔══╝ ██╔══██╗ ██║ ╚═╝ ██║██║ ██║██║ ██╗███████╗██║ ██║ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ Configuration Wizard EOF # Get the absolute path of the script directory SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" ENV_FILE="$SCRIPT_DIR/.env" SERVICES_YAML="$SCRIPT_DIR/configs/homepage/services.yaml" WIDGETS_YAML="$SCRIPT_DIR/configs/homepage/widgets.yaml" MKDOCS_MAIN_HTML="$SCRIPT_DIR/mkdocs/docs/overrides/main.html" MKDOCS_YML="$SCRIPT_DIR/mkdocs/mkdocs.yml" echo "Looking for .env file at: $ENV_FILE" # Initialize a new .env file if it doesn't exist if [ ! -f "$ENV_FILE" ]; then echo "No .env file found. Creating a new one from scratch." touch "$ENV_FILE" initialize_env_file else echo "Found existing .env file. Will update values." # Create a backup of the existing file backup_env_file fi # Function to update the services.yaml file with the new domain update_services_yaml() { local new_domain=$1 if [ ! -f "$SERVICES_YAML" ]; then echo "Warning: services.yaml file not found at $SERVICES_YAML" return 1 fi echo "Updating service URLs in services.yaml..." # Create a backup of the services.yaml file local timestamp=$(date +"%Y%m%d_%H%M%S") local backup_file="${SERVICES_YAML}.backup_${timestamp}" cp "$SERVICES_YAML" "$backup_file" echo "Created backup of services.yaml at $backup_file" # Get the content of the services.yaml file local content=$(cat "$SERVICES_YAML") # Extract all unique domains from the file using grep with a more robust pattern local domains=$(echo "$content" | grep -o 'https://[^[:space:]"]*' | cut -d'/' -f3 | sort | uniq) # Check if we found any domains if [ -z "$domains" ]; then echo "Warning: Could not find any URLs in services.yaml" return 1 fi echo "Found these domains in services.yaml:" echo "$domains" # Extract the base domain pattern (e.g., betteredmonton.org) local base_domain_pattern=$(echo "$domains" | head -1 | sed -E 's/^[^.]+\.//') if [ -z "$base_domain_pattern" ]; then echo "Warning: Could not extract base domain pattern from URLs" return 1 fi echo "Detected base domain pattern: $base_domain_pattern" echo "Will replace with: $new_domain" # Create a temporary file for the updated content local temp_file=$(mktemp) # Replace domain in all URLs if ! echo "$content" | sed "s|$base_domain_pattern|$new_domain|g" > "$temp_file"; then echo "Error: Failed to update domains in the file" rm -f "$temp_file" return 1 fi # Check if the file has any changes if ! grep -q "$new_domain" "$temp_file"; then echo "Warning: No domain replacements were made. Check the domain pattern matching." cat "$temp_file" | grep -o 'https://[^[:space:]"]*' | head -5 rm -f "$temp_file" return 1 fi # Count the number of URLs with the new domain local replacements=$(grep -o "https://[^[:space:]\"]*$new_domain" "$temp_file" | wc -l) # Move the modified file to replace the original mv "$temp_file" "$SERVICES_YAML" echo "Updated $replacements URLs in services.yaml to use $new_domain" echo "Examples of updated URLs:" grep -o "https://[^[:space:]\"]*$new_domain" "$SERVICES_YAML" | head -5 return 0 } # Function to update the login URL in MkDocs main.html update_mkdocs_main_html() { local new_domain=$1 if [ ! -f "$MKDOCS_MAIN_HTML" ]; then echo "Warning: MkDocs main.html not found at $MKDOCS_MAIN_HTML" return 1 fi echo "Updating login button URL in MkDocs main.html..." # Create a backup of the main.html file local timestamp=$(date +"%Y%m%d_%H%M%S") local backup_file="${MKDOCS_MAIN_HTML}.backup_${timestamp}" cp "$MKDOCS_MAIN_HTML" "$backup_file" echo "Created backup of main.html at $backup_file" # Create a new file for the modified content local new_file="${MKDOCS_MAIN_HTML}.new" # Extract the current login URL from the login button local login_line=$(grep -A 1 "{% block announce %}" "$MKDOCS_MAIN_HTML" | grep "login-button") local current_url=$(echo "$login_line" | grep -o 'https://[^"]*') if [ -z "$current_url" ] || [ -z "$login_line" ]; then echo "Warning: Could not find the login button URL in main.html" return 1 fi # Create the replacement login line with the new domain local new_login_line=$(echo "$login_line" | sed "s|$current_url|https://homepage.$new_domain|g") # Create the new file by replacing the login line while IFS= read -r line; do if [[ "$line" == "$login_line" ]]; then echo "$new_login_line" >> "$new_file" else echo "$line" >> "$new_file" fi done < "$MKDOCS_MAIN_HTML" # Move the new file to replace the original mv "$new_file" "$MKDOCS_MAIN_HTML" echo "Updated login button URL in main.html from '$current_url' to 'https://homepage.$new_domain'" return 0 } # Function to create a timestamped backup of the .env file backup_env_file() { if [ -f "$ENV_FILE" ]; then local timestamp=$(date +"%Y%m%d_%H%M%S") local backup_file="$ENV_FILE.backup_$timestamp" echo "Creating backup of current .env file to: $backup_file" if cp "$ENV_FILE" "$backup_file"; then echo "Backup created successfully!" return 0 else echo "Failed to create backup file. Proceeding with caution..." return 1 fi fi } # Function to initialize the .env file with default values initialize_env_file() { echo "Initializing new .env file with default values..." # Create the new .env file with header cat > "$ENV_FILE" << EOL # Never share this file publicly. It contains sensitive information. # This file is used to configure various applications and services. # Generated by Changemaker Config Wizard on $(date) # Domain Configuration DOMAIN=changeme.org BASE_DOMAIN=https://changeme.org # Listmonk Configuration LISTMONK_ADMIN_USER=admin LISTMONK_ADMIN_PASSWORD=strongpassword LISTMONK_PORT=9000 LISTMONK_HOSTNAME=listmonk.changeme.org # Database Credentials POSTGRES_USER=listmonk POSTGRES_PASSWORD=$(generate_password 20) POSTGRES_DB=listmonk # Monica CRM Configuration MONICA_APP_KEY=base64:$(openssl rand -base64 32) MONICA_DB_USERNAME=monica MONICA_DB_PASSWORD=$(generate_password 20) MONICA_MYSQL_DATABASE=monica MONICA_MYSQL_USER=monica MONICA_MYSQL_PASSWORD=$(generate_password 20) # MkDocs Configuration USER_ID=1000 GROUP_ID=1000 MKDOCS_PORT=4000 # Flatnotes Configuration FLATNOTES_PUID=1000 FLATNOTES_PGID=1000 FLATNOTES_AUTH_TYPE=password FLATNOTES_USERNAME=user FLATNOTES_PASSWORD=changeMe! FLATNOTES_SECRET_KEY=$(generate_password 32) FLATNOTES_PORT=8089 # Gitea Configuration GITEA_DB_TYPE=mysql GITEA_DB_HOST=gitea-db:3306 GITEA_DB_NAME=gitea GITEA_DB_USER=gitea GITEA_DB_PASSWD=$(generate_password 24) GITEA_DB_ROOT_PASSWORD=$(generate_password 24) GITEA_WEB_PORT=3030 GITEA_SSH_PORT=2225 GITEA_ROOT_URL=https://gitea.changeme.org GITEA_DOMAIN=gitea.changeme.org # Apache Answer Configuration ANSWER_APP_PORT=9080 # Excalidraw Configuration EXCALIDRAW_PORT=3333 EXCALIDRAW_LIBRARY_URL=https://libraries.excalidraw.com EXCALIDRAW_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries EXCALIDRAW_PUBLIC_URL=https://excalidraw.changeme.org EXCALIDRAW_PUBLIC_SOCKET_URL=https://excalidraw.changeme.org # Code Server Configuration CODE_SERVER_PORT=8888 USER_NAME=coder # Cloudflare Credentials CF_AUTH_EMAIL= CF_API_TOKEN= CF_ZONE_ID= CF_TUNNEL_ID= CF_DOMAIN=changeme.org # NocoDB Configuration NOCODB_PORT=8090 NOCODB_JWT_SECRET=$(generate_password 32) NOCODB_DB_NAME=nocodb NOCODB_DB_USER=noco NOCODB_DB_PASSWORD=$(generate_password 20) # OpenWebUI Configuration OPEN_WEBUI_PORT=3005 OPEN_WEBUI_URL=https://open-webui.changeme.org # N8N Configuration N8N_PORT=5678 N8N_HOST=n8n.changeme.org N8N_ENCRYPTION_KEY=$(generate_password 32) N8N_USER_EMAIL=admin@example.com N8N_USER_PASSWORD=changeMe GENERIC_TIMEZONE=UTC # ConvertX Configuration CONVERTX_PORT=3100 CONVERTX_JWT_SECRET=$(generate_password 48) # Rocket.Chat Configuration ROCKETCHAT_IMAGE=registry.rocket.chat/rocketchat/rocket.chat ROCKETCHAT_RELEASE=latest ROCKETCHAT_PORT=3004 ROCKETCHAT_CONTAINER_PORT=3000 ROCKETCHAT_ROOT_URL=https://rocket.changeme.org ROCKETCHAT_DEPLOYMENT_ENVIRONMENT=changemaker ROCKETCHAT_MONGODB_VERSION=6.0 ROCKETCHAT_MONGODB_HOST=mongodb-rocketchat ROCKETCHAT_MONGODB_PORT=27017 ROCKETCHAT_MONGODB_DATABASE=rocketchat ROCKETCHAT_MONGODB_REPLICA_SET=rs0 ROCKETCHAT_MONGODB_ENABLE_JOURNAL=true ROCKETCHAT_MONGODB_ALLOW_EMPTY_PASSWORD=yes # Additional Configuration EOL echo "New .env file created with default values." } # Function to generate a random secure password generate_password() { local length=${1:-16} openssl rand -base64 48 | tr -dc 'a-zA-Z0-9!@#$%^&*()-_=+' | head -c "$length" } # Function to generate a base64 encoded key for Monica generate_base64_key() { local length=${1:-32} local key=$(openssl rand -base64 48 | tr -dc 'a-zA-Z0-9!@#$%^&*()-_=+' | head -c "$length") echo "base64:$(echo -n "$key" | base64)" } # Function to safely update environment variables in .env file update_env_var() { local key=$1 local value=$2 local escaped_value=$(echo "$value" | sed 's/[\/&]/\\&/g') # Make a temporary backup of the .env file before modification cp "$ENV_FILE" "$ENV_FILE.bak_tmp" if grep -q "^$key=" "$ENV_FILE"; then # Use perl instead of sed for better handling of paths with spaces perl -i -pe "s/^$key=.*/$key=$escaped_value/" "$ENV_FILE" echo "Updated $key in .env file" else echo "$key=$escaped_value" >> "$ENV_FILE" echo "Added $key to .env file" fi # Check if update was successful if ! grep -q "^$key=$escaped_value" "$ENV_FILE"; then echo "Warning: Failed to update $key in .env file" echo "Restoring from backup..." cp "$ENV_FILE.bak_tmp" "$ENV_FILE" echo "Will try alternative method..." # Alternative update method local temp_file=$(mktemp) if grep -q "^$key=" "$ENV_FILE"; then while IFS= read -r line; do if [[ $line =~ ^$key= ]]; then echo "$key=$value" >> "$temp_file" else echo "$line" >> "$temp_file" fi done < "$ENV_FILE" else cat "$ENV_FILE" > "$temp_file" echo "$key=$value" >> "$temp_file" fi mv "$temp_file" "$ENV_FILE" fi # Remove the temporary backup file after successful update rm -f "$ENV_FILE.bak_tmp" } # Function to update the greeting widget in widgets.yaml update_widgets_yaml() { local new_domain=$1 if [ ! -f "$WIDGETS_YAML" ]; then echo "Warning: widgets.yaml file not found at $WIDGETS_YAML" return 1 fi echo "Updating greeting widget in widgets.yaml..." # Create a backup of the widgets.yaml file local timestamp=$(date +"%Y%m%d_%H%M%S") local backup_file="${WIDGETS_YAML}.backup_${timestamp}" cp "$WIDGETS_YAML" "$backup_file" echo "Created backup of widgets.yaml at $backup_file" # Extract the site name (domain without TLD) for the greeting text local site_name=$(echo "$new_domain" | cut -d. -f1) # Create a temporary file for the modified content local temp_file=$(mktemp) # Read the file and replace the greeting text and href awk -v site_name="$site_name" -v domain="$new_domain" ' /- greeting:/ { print $0; getline; print $0; # text_size line getline; gsub(/text: .*/, "text: " site_name); print $0; # text line getline; gsub(/href: .*/, "href: https://" domain); print $0; # href line next; } { print $0; } ' "$WIDGETS_YAML" > "$temp_file" # Move the temporary file to replace the original mv "$temp_file" "$WIDGETS_YAML" echo "Updated greeting widget in widgets.yaml:" echo " - Set text to: $site_name" echo " - Set href to: https://$new_domain" return 0 } # Function to update the site_url in mkdocs.yml update_mkdocs_yml() { local new_domain=$1 if [ ! -f "$MKDOCS_YML" ]; then echo "Warning: mkdocs.yml not found at $MKDOCS_YML" return 1 fi echo "Updating site_url in mkdocs.yml..." # Create a backup of the mkdocs.yml file local timestamp=$(date +"%Y%m%d_%H%M%S") local backup_file="${MKDOCS_YML}.backup_${timestamp}" cp "$MKDOCS_YML" "$backup_file" echo "Created backup of mkdocs.yml at $backup_file" # Update the site_url value sed -i "s|^site_url:.*|site_url: https://$new_domain|" "$MKDOCS_YML" if grep -q "site_url: https://$new_domain" "$MKDOCS_YML"; then echo "Updated site_url in mkdocs.yml to: https://$new_domain" return 0 else echo "Warning: Failed to update site_url in mkdocs.yml" return 1 fi } # Make sure the initialize_env_file function is available initialize_env_file echo -e "\n\nWelcome to Changemaker Config!\n" echo "This script will help you configure your Changemaker instance." echo "Please provide the following information:" # Domain configuration read -p "Enter your domain name (without protocol, e.g., example.com): " domain_name if [ -z "$domain_name" ]; then echo "Domain name cannot be empty. Using default: changeme.org" domain_name="changeme.org" fi echo -e "\nUpdating domain settings in .env file at: $ENV_FILE" # Update main domain settings update_env_var "DOMAIN" "$domain_name" update_env_var "BASE_DOMAIN" "https://$domain_name" # Update Listmonk hostname update_env_var "LISTMONK_HOSTNAME" "listmonk.$domain_name" # Update Gitea settings update_env_var "GITEA_ROOT_URL" "https://gitea.$domain_name" update_env_var "GITEA_DOMAIN" "gitea.$domain_name" # Update Excalidraw settings update_env_var "EXCALIDRAW_PUBLIC_URL" "https://excalidraw.$domain_name" update_env_var "EXCALIDRAW_PUBLIC_SOCKET_URL" "https://excalidraw.$domain_name" # Update OpenWebUI settings echo -e "\nConfiguring OpenWebUI..." update_env_var "OPEN_WEBUI_PORT" "3005" update_env_var "OPEN_WEBUI_URL" "https://open-web-ui.$domain_name" # Update service URLs in the services.yaml file echo -e "\nUpdating service URLs in services.yaml file..." update_services_yaml "$domain_name" # Update the greeting widget in widgets.yaml echo -e "\nUpdating greeting widget in widgets.yaml..." update_widgets_yaml "$domain_name" # After domain configuration and updating services.yaml, update the login button URL echo -e "\nUpdating login button URL in MkDocs main.html..." update_mkdocs_main_html "$domain_name" # Update the site_url in mkdocs.yml echo -e "\nUpdating site_url in mkdocs.yml..." update_mkdocs_yml "$domain_name" echo -e "Domain settings have been updated successfully!\n" # Listmonk Admin Credentials configuration echo -e "\n---- Listmonk Admin Credentials ----" read -p "Enter Listmonk admin username [default: admin]: " listmonk_user read -sp "Enter Listmonk admin password [default: strongpassword]: " listmonk_password echo # Add new line after password input if [ -z "$listmonk_user" ]; then echo "Using default Listmonk admin username: admin" listmonk_user="admin" fi if [ -z "$listmonk_password" ]; then echo "Using default Listmonk admin password" listmonk_password="strongpassword" fi # Update Listmonk credentials update_env_var "LISTMONK_ADMIN_USER" "$listmonk_user" update_env_var "LISTMONK_ADMIN_PASSWORD" "$listmonk_password" echo "Listmonk admin credentials updated." # Flatnotes User Credentials configuration echo -e "\n---- Flatnotes User Credentials ----" read -p "Enter Flatnotes username [default: user]: " flatnotes_user read -sp "Enter Flatnotes password [default: changeMe!]: " flatnotes_password echo # Add new line after password input if [ -z "$flatnotes_user" ]; then echo "Using default Flatnotes username: user" flatnotes_user="user" fi if [ -z "$flatnotes_password" ]; then echo "Using default Flatnotes password" flatnotes_password="changeMe!" fi # Update Flatnotes credentials update_env_var "FLATNOTES_USERNAME" "$flatnotes_user" update_env_var "FLATNOTES_PASSWORD" "$flatnotes_password" echo "Flatnotes user credentials updated." # N8N User Credentials configuration echo -e "\n---- N8N Admin Credentials ----" read -p "Enter N8N admin email [default: admin@example.com]: " n8n_email read -sp "Enter N8N admin password [default: changeMe]: " n8n_password echo # Add new line after password input if [ -z "$n8n_email" ]; then echo "Using default N8N admin email: admin@example.com" n8n_email="admin@example.com" fi if [ -z "$n8n_password" ]; then echo "Using default N8N admin password: changeMe" n8n_password="changeMe" fi # Update N8N host and other settings update_env_var "N8N_HOST" "n8n.$domain_name" update_env_var "N8N_USER_EMAIL" "$n8n_email" update_env_var "N8N_USER_PASSWORD" "$n8n_password" update_env_var "GENERIC_TIMEZONE" "UTC" echo "N8N admin credentials updated." # Rocket.Chat Configuration echo -e "\n---- Rocket.Chat Configuration ----" read -p "Enter Rocket.Chat URL (default: https://rocket.$domain_name): " rocketchat_url read -p "Enter Rocket.Chat port [default: 3004]: " rocketchat_port read -p "Enable production mode for Rocket.Chat? [Y/n]: " rocketchat_production if [ -z "$rocketchat_url" ]; then echo "Using default Rocket.Chat URL: https://rocket.$domain_name" rocketchat_url="https://rocket.$domain_name" fi if [ -z "$rocketchat_port" ]; then echo "Using default Rocket.Chat port: 3004" rocketchat_port="3004" fi rocketchat_environment="changemaker" if [[ "$rocketchat_production" =~ ^[Yy]$ ]] || [ -z "$rocketchat_production" ]; then echo "Enabling production mode for Rocket.Chat" rocketchat_environment="production" fi # Update Rocket.Chat settings update_env_var "ROCKETCHAT_PORT" "$rocketchat_port" update_env_var "ROCKETCHAT_CONTAINER_PORT" "3000" update_env_var "ROCKETCHAT_ROOT_URL" "$rocketchat_url" update_env_var "ROCKETCHAT_DEPLOYMENT_ENVIRONMENT" "$rocketchat_environment" echo "Rocket.Chat configuration updated." # Cloudflare Credentials Configuration echo -e "\n---- Cloudflare Credentials Configuration ----" echo "Please enter your Cloudflare credentials for DNS and tunnel management." read -p "Enter Cloudflare authentication email: " cf_auth_email read -p "Enter Cloudflare API token: " cf_api_token read -p "Enter Cloudflare Zone ID: " cf_zone_id read -p "Enter Cloudflare Tunnel ID: " cf_tunnel_id if [ -z "$cf_auth_email" ]; then echo "Warning: Cloudflare authentication email is empty. Some features may not work correctly." fi if [ -z "$cf_api_token" ]; then echo "Warning: Cloudflare API token is empty. Some features may not work correctly." fi if [ -z "$cf_zone_id" ]; then echo "Warning: Cloudflare Zone ID is empty. Some features may not work correctly." fi if [ -z "$cf_tunnel_id" ]; then echo "Warning: Cloudflare Tunnel ID is empty. Some features may not work correctly." fi # Update Cloudflare settings update_env_var "CF_AUTH_EMAIL" "$cf_auth_email" update_env_var "CF_API_TOKEN" "$cf_api_token" update_env_var "CF_ZONE_ID" "$cf_zone_id" update_env_var "CF_TUNNEL_ID" "$cf_tunnel_id" update_env_var "CF_DOMAIN" "$domain_name" echo "Cloudflare credentials have been updated." echo -e "\n---- Generating Random Strong Passwords ----" echo "Generating and updating passwords for all other services..." # Generate and update Monica app key monica_app_key=$(generate_base64_key 32) update_env_var "MONICA_APP_KEY" "$monica_app_key" # Generate and update Monica passwords monica_db_password=$(generate_password 20) update_env_var "MONICA_DB_PASSWORD" "$monica_db_password" update_env_var "MONICA_MYSQL_PASSWORD" "$monica_db_password" # Generate and update Flatnotes secret key flatnotes_secret_key=$(generate_password 32) update_env_var "FLATNOTES_SECRET_KEY" "$flatnotes_secret_key" # Generate and update Gitea passwords gitea_db_password=$(generate_password 24) gitea_root_password=$(generate_password 24) update_env_var "GITEA_DB_PASSWD" "$gitea_db_password" update_env_var "GITEA_DB_ROOT_PASSWORD" "$gitea_root_password" # Generate and update NocoDB JWT secret and database password nocodb_jwt_secret=$(generate_password 32) update_env_var "NOCODB_JWT_SECRET" "$nocodb_jwt_secret" nocodb_db_password=$(generate_password 20) update_env_var "NOCODB_DB_PASSWORD" "$nocodb_db_password" # Generate and update n8n encryption key and default admin password n8n_encryption_key=$(generate_password 32) update_env_var "N8N_ENCRYPTION_KEY" "$n8n_encryption_key" # Generate and update ConvertX JWT secret convertx_jwt_secret=$(generate_password 48) update_env_var "CONVERTX_JWT_SECRET" "$convertx_jwt_secret" echo "All service passwords have been updated with secure random strings." echo -e "\nAll settings have been configured successfully!" echo "Your Changemaker instance is now ready with the following:" echo "- Domain: $domain_name" echo "- Listmonk Admin: $listmonk_user" echo "- Flatnotes User: $flatnotes_user" echo "- N8N Admin Email: $n8n_email" echo "- All other service passwords have been randomized for security" echo -e "\nNote: The randomized passwords are stored in your .env file at: $ENV_FILE" echo -e "A backup of your original .env file was created before modifications." # Add a new function to write the complete .env file write_new_env_file() { local timestamp=$(date +"%Y%m%d_%H%M%S") local backup_file="$ENV_FILE.backup_$timestamp" echo "Creating final backup of the current .env file to: $backup_file" cp "$ENV_FILE" "$backup_file" echo "Creating new .env file with all updated settings..." # Get all variables from the current .env file local temp_env=$(mktemp) grep -v "^#" "$ENV_FILE" | grep "=" > "$temp_env" # Create the new .env file with header cat > "$ENV_FILE.new" << EOL # Never share this file publicly. It contains sensitive information. # This file is used to configure various applications and services. # Generated by Changemaker Config Wizard on $(date) EOL # Add all sections with their variables echo "# Domain Configuration" >> "$ENV_FILE.new" grep -E "^DOMAIN=|^BASE_DOMAIN=" "$temp_env" >> "$ENV_FILE.new" echo "" >> "$ENV_FILE.new" echo "# Listmonk Configuration" >> "$ENV_FILE.new" grep -E "^LISTMONK_" "$temp_env" >> "$ENV_FILE.new" echo "" >> "$ENV_FILE.new" echo "# Database Credentials" >> "$ENV_FILE.new" grep -E "^POSTGRES_" "$temp_env" >> "$ENV_FILE.new" echo "" >> "$ENV_FILE.new" echo "# Monica CRM Configuration" >> "$ENV_FILE.new" grep -E "^MONICA_" "$temp_env" >> "$ENV_FILE.new" echo "" >> "$ENV_FILE.new" echo "# MkDocs Configuration" >> "$ENV_FILE.new" grep -E "^USER_ID=|^GROUP_ID=|^MKDOCS_" "$temp_env" >> "$ENV_FILE.new" echo "" >> "$ENV_FILE.new" echo "# Flatnotes Configuration" >> "$ENV_FILE.new" grep -E "^FLATNOTES_" "$temp_env" >> "$ENV_FILE.new" echo "" >> "$ENV_FILE.new" echo "# Gitea Configuration" >> "$ENV_FILE.new" grep -E "^GITEA_" "$temp_env" >> "$ENV_FILE.new" echo "" >> "$ENV_FILE.new" echo "# Apache Answer Configuration" >> "$ENV_FILE.new" grep -E "^ANSWER_" "$temp_env" >> "$ENV_FILE.new" echo "" >> "$ENV_FILE.new" echo "# Excalidraw Configuration" >> "$ENV_FILE.new" grep -E "^EXCALIDRAW_" "$temp_env" >> "$ENV_FILE.new" echo "" >> "$ENV_FILE.new" echo "# Code Server Configuration" >> "$ENV_FILE.new" grep -E "^CODE_SERVER_|^USER_NAME=" "$temp_env" >> "$ENV_FILE.new" echo "" >> "$ENV_FILE.new" echo "# Cloudflare Credentials" >> "$ENV_FILE.new" grep -E "^CF_" "$temp_env" >> "$ENV_FILE.new" echo "" >> "$ENV_FILE.new" echo "# NocoDB Configuration" >> "$ENV_FILE.new" grep -E "^NOCODB_" "$temp_env" >> "$ENV_FILE.new" echo "" >> "$ENV_FILE.new" echo "# OpenWebUI Configuration" >> "$ENV_FILE.new" grep -E "^OPEN_WEBUI_" "$temp_env" >> "$ENV_FILE.new" echo "" >> "$ENV_FILE.new" echo "# N8N Configuration" >> "$ENV_FILE.new" grep -E "^N8N_|^GENERIC_TIMEZONE=" "$temp_env" >> "$ENV_FILE.new" echo "" >> "$ENV_FILE.new" echo "# ConvertX Configuration" >> "$ENV_FILE.new" grep -E "^CONVERTX_" "$temp_env" >> "$ENV_FILE.new" echo "" >> "$ENV_FILE.new" echo "# Rocket.Chat Configuration" >> "$ENV_FILE.new" grep -E "^ROCKETCHAT_" "$temp_env" >> "$ENV_FILE.new" echo "" >> "$ENV_FILE.new" # Any variables that didn't fit in the above categories echo "# Additional Configuration" >> "$ENV_FILE.new" grep -v -E "^DOMAIN=|^BASE_DOMAIN=|^LISTMONK_|^POSTGRES_|^MONICA_|^USER_ID=|^GROUP_ID=|^MKDOCS_|^FLATNOTES_|^GITEA_|^ANSWER_|^EXCALIDRAW_|^CODE_SERVER_|^USER_NAME=|^CF_|^NOCODB_|^OPEN_WEBUI_|^N8N_|^GENERIC_TIMEZONE=|^CONVERTX_|^ROCKETCHAT_" "$temp_env" >> "$ENV_FILE.new" # Replace the current .env with the new one mv "$ENV_FILE.new" "$ENV_FILE" # Clean up rm -f "$temp_env" echo "New .env file created and applied successfully!" } # Finalizing the configuration by creating a clean .env file... echo -e "\nFinalizing the configuration by creating a clean .env file..." write_new_env_file # Clean up any leftover temporary backup files rm -f "$ENV_FILE.bak_tmp" echo -e "Temporary backup files have been cleaned up."