freealberta/config.sh
2025-05-28 09:47:43 -06:00

563 lines
18 KiB
Bash
Executable File

#!/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"
MKDOCS_YML="$SCRIPT_DIR/mkdocs/docs/mkdocs.yml"
echo "Looking for .env file at: $ENV_FILE"
# 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 safely update environment variables in .env file
update_env_var() {
local key=$1
local value=$2
local escaped_value=$(echo "$value" | sed 's/[\/&]/\\&/g')
if grep -q "^$key=" "$ENV_FILE"; then
sed -i "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
}
# 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..."
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)
# User and Group Configuration
USER_NAME=coder
USER_ID=1000
GROUP_ID=1000
# Port Configuration
CODE_SERVER_PORT=8888
LISTMONK_PORT=9000
LISTMONK_DB_PORT=5432
MKDOCS_PORT=4000
MKDOCS_SITE_SERVER_PORT=4001
N8N_PORT=5678
NOCODB_PORT=8090
HOMEPAGE_PORT=3010
SILEX_PORT=6805
# Domain Configuration
BASE_DOMAIN=https://changeme.org
DOMAIN=changeme.org
LISTMONK_HOSTNAME=listmonk.changeme.org
N8N_HOST=n8n.changeme.org
SILEX_HOST=silex.changeme.org
# Cloudflare Configuration
CF_API_TOKEN=your_cloudflare_api_token
CF_ZONE_ID=your_cloudflare_zone_id
CF_TUNNEL_ID=your_cloudflared_tunnel_id
CF_DOMAIN=changeme.org
# Database Configuration (PostgreSQL for Listmonk)
POSTGRES_USER=listmonk
POSTGRES_PASSWORD=changeMe
POSTGRES_DB=listmonk
# Listmonk Admin Configuration
LISTMONK_ADMIN_USER=admin
LISTMONK_ADMIN_PASSWORD=changeMe
# N8N Configuration
N8N_USER_EMAIL=admin@example.com
N8N_USER_PASSWORD=changeMe
N8N_ENCRYPTION_KEY=changeMe
GENERIC_TIMEZONE=UTC
# Nocodb Configuration
NOCODB_PORT=8090
NOCODB_JWT_SECRET=changeMe
NOCODB_DB_NAME=nocodb
NOCODB_DB_USER=noco
NOCODB_DB_PASSWORD=changeMe
# Listmonk SMTP Configuration
LISTMONK_SMTP_HOST=smtp.example.com
LISTMONK_SMTP_PORT=587
LISTMONK_SMTP_AUTH_PROTOCOL=plain
LISTMONK_SMTP_USERNAME=your-smtp-username
LISTMONK_SMTP_PASSWORD=your-smtp-password
LISTMONK_SMTP_HELLO_HOSTNAME=listmonk.changeme.org
LISTMONK_SMTP_TLS_ENABLED=true
LISTMONK_SMTP_TLS_SKIP_VERIFY=false
LISTMONK_SMTP_MAX_CONNS=10
LISTMONK_SMTP_MAX_MSG_RETRIES=2
LISTMONK_SMTP_IDLE_TIMEOUT=10s
LISTMONK_SMTP_WAIT_TIMEOUT=5s
LISTMONK_SMTP_EMAIL_HEADERS=List-Unsubscribe-Post=List-Unsubscribe=One-Click
EOL
echo "New .env file created with default values."
}
# 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
}
# Function to check if a port is in use
check_port() {
local port=$1
if command -v ss >/dev/null 2>&1; then
ss -tuln | grep -q ":$port "
elif command -v netstat >/dev/null 2>&1; then
netstat -tuln | grep -q ":$port "
else
# Fallback to lsof if available
if command -v lsof >/dev/null 2>&1; then
lsof -i ":$port" >/dev/null 2>&1
else
echo "Warning: Cannot check port availability. Please ensure ports are free manually."
return 1
fi
fi
}
# Function to check all service ports for conflicts
check_port_conflicts() {
echo "Checking for port conflicts..."
local ports_to_check=(
"${CODE_SERVER_PORT:-8888}:Code Server"
"${LISTMONK_PORT:-9000}:Listmonk"
"${LISTMONK_DB_PORT:-5432}:Listmonk Database"
"${MKDOCS_PORT:-4000}:MkDocs"
"${MKDOCS_SITE_SERVER_PORT:-4001}:MkDocs Site Server"
"${N8N_PORT:-5678}:N8N"
"${NOCODB_PORT:-8090}:NocoDB"
"${HOMEPAGE_PORT:-3010}:Homepage"
"${SILEX_PORT:-6805}:Silex"
)
local conflicts_found=false
for port_info in "${ports_to_check[@]}"; do
local port=$(echo "$port_info" | cut -d: -f1)
local service=$(echo "$port_info" | cut -d: -f2)
if check_port "$port"; then
echo "⚠️ Port conflict detected: $port is already in use (assigned to $service)"
conflicts_found=true
else
echo "✅ Port $port is available for $service"
fi
done
if [ "$conflicts_found" = true ]; then
echo ""
echo "Port conflicts detected! Please choose alternative ports or stop conflicting services."
read -p "Do you want to configure alternative ports? [Y/n]: " configure_ports
if [[ "$configure_ports" =~ ^[Nn]$ ]]; then
echo "Configuration cancelled. Please resolve port conflicts and try again."
exit 1
else
configure_alternative_ports
fi
else
echo "✅ All ports are available!"
fi
}
# Function to configure alternative ports
configure_alternative_ports() {
echo ""
echo "---- Port Configuration ----"
# Code Server
if check_port "${CODE_SERVER_PORT:-8888}"; then
read -p "Enter alternative port for Code Server [current: ${CODE_SERVER_PORT:-8888}]: " new_code_port
if [ ! -z "$new_code_port" ]; then
update_env_var "CODE_SERVER_PORT" "$new_code_port"
fi
fi
# Listmonk
if check_port "${LISTMONK_PORT:-9000}"; then
read -p "Enter alternative port for Listmonk [current: ${LISTMONK_PORT:-9000}]: " new_listmonk_port
if [ ! -z "$new_listmonk_port" ]; then
update_env_var "LISTMONK_PORT" "$new_listmonk_port"
fi
fi
# Listmonk DB
if check_port "${LISTMONK_DB_PORT:-5432}"; then
read -p "Enter alternative port for Listmonk Database [current: ${LISTMONK_DB_PORT:-5432}]: " new_db_port
if [ ! -z "$new_db_port" ]; then
update_env_var "LISTMONK_DB_PORT" "$new_db_port"
fi
fi
# MkDocs
if check_port "${MKDOCS_PORT:-4000}"; then
read -p "Enter alternative port for MkDocs [current: ${MKDOCS_PORT:-4000}]: " new_mkdocs_port
if [ ! -z "$new_mkdocs_port" ]; then
update_env_var "MKDOCS_PORT" "$new_mkdocs_port"
fi
fi
# MkDocs Site Server
if check_port "${MKDOCS_SITE_SERVER_PORT:-4001}"; then
read -p "Enter alternative port for MkDocs Site Server [current: ${MKDOCS_SITE_SERVER_PORT:-4001}]: " new_site_port
if [ ! -z "$new_site_port" ]; then
update_env_var "MKDOCS_SITE_SERVER_PORT" "$new_site_port"
fi
fi
# N8N
if check_port "${N8N_PORT:-5678}"; then
read -p "Enter alternative port for N8N [current: ${N8N_PORT:-5678}]: " new_n8n_port
if [ ! -z "$new_n8n_port" ]; then
update_env_var "N8N_PORT" "$new_n8n_port"
fi
fi
# NocoDB
if check_port "${NOCODB_PORT:-8090}"; then
read -p "Enter alternative port for NocoDB [current: ${NOCODB_PORT:-8090}]: " new_nocodb_port
if [ ! -z "$new_nocodb_port" ]; then
update_env_var "NOCODB_PORT" "$new_nocodb_port"
fi
fi
# Homepage
if check_port "${HOMEPAGE_PORT:-3010}"; then
read -p "Enter alternative port for Homepage [current: ${HOMEPAGE_PORT:-3010}]: " new_homepage_port
if [ ! -z "$new_homepage_port" ]; then
update_env_var "HOMEPAGE_PORT" "$new_homepage_port"
fi
fi
# Silex
if check_port "${SILEX_PORT:-6805}"; then
read -p "Enter alternative port for Silex [current: ${SILEX_PORT:-6805}]: " new_silex_port
if [ ! -z "$new_silex_port" ]; then
update_env_var "SILEX_PORT" "$new_silex_port"
fi
fi
echo "Port configuration completed."
}
# 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."
backup_env_file
fi
echo -e "\n\nWelcome to Changemaker Config!\n"
echo "This script will help you configure your .env file for Changemaker."
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..."
# Update main domain settings
update_env_var "DOMAIN" "$domain_name"
update_env_var "BASE_DOMAIN" "https://$domain_name"
update_env_var "LISTMONK_HOSTNAME" "listmonk.$domain_name"
update_env_var "N8N_HOST" "n8n.$domain_name"
update_env_var "SILEX_HOST" "silex.$domain_name"
update_env_var "CF_DOMAIN" "$domain_name"
echo "Domain settings updated successfully!"
# Cloudflare Configuration
echo -e "\n---- Cloudflare Configuration ----"
echo "To use the DNS setup script, you'll need Cloudflare credentials."
echo "You can find these values in your Cloudflare dashboard:"
echo " - API Token: https://dash.cloudflare.com/profile/api-tokens"
echo " (Create a token with Zone:DNS:Edit and Access:Apps:Edit permissions)"
echo " - Zone ID: On your domain's overview page"
echo " - Tunnel ID: In the Zero Trust dashboard under Access > Tunnels"
echo ""
read -p "Do you want to configure Cloudflare settings now? [Y/n]: " configure_cf
if [[ ! "$configure_cf" =~ ^[Nn]$ ]]; then
echo ""
echo "Please enter your Cloudflare credentials:"
# CF API Token
read -p "Enter your Cloudflare API Token: " cf_api_token
if [ ! -z "$cf_api_token" ]; then
# Basic validation for API token format
if [[ "$cf_api_token" =~ ^[A-Za-z0-9_-]{40}$ ]]; then
update_env_var "CF_API_TOKEN" "$cf_api_token"
echo "✅ Cloudflare API Token updated"
else
echo "⚠️ Warning: API Token format seems incorrect (should be 40 characters)"
update_env_var "CF_API_TOKEN" "$cf_api_token"
fi
else
echo "⚠️ Cloudflare API Token left unchanged"
fi
# CF Zone ID
read -p "Enter your Cloudflare Zone ID: " cf_zone_id
if [ ! -z "$cf_zone_id" ]; then
# Basic validation for Zone ID format
if [[ "$cf_zone_id" =~ ^[a-f0-9]{32}$ ]]; then
update_env_var "CF_ZONE_ID" "$cf_zone_id"
echo "✅ Cloudflare Zone ID updated"
else
echo "⚠️ Warning: Zone ID format seems incorrect (should be 32 hex characters)"
update_env_var "CF_ZONE_ID" "$cf_zone_id"
fi
else
echo "⚠️ Cloudflare Zone ID left unchanged"
fi
# CF Tunnel ID
read -p "Enter your Cloudflare Tunnel ID: " cf_tunnel_id
if [ ! -z "$cf_tunnel_id" ]; then
# Basic validation for Tunnel ID format (UUID)
if [[ "$cf_tunnel_id" =~ ^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$ ]]; then
update_env_var "CF_TUNNEL_ID" "$cf_tunnel_id"
echo "✅ Cloudflare Tunnel ID updated"
else
echo "⚠️ Warning: Tunnel ID format seems incorrect (should be UUID format)"
update_env_var "CF_TUNNEL_ID" "$cf_tunnel_id"
fi
else
echo "⚠️ Cloudflare Tunnel ID left unchanged"
fi
echo ""
echo "Cloudflare configuration completed!"
echo "You can now run './add-cname-records.sh' to set up DNS records."
else
echo "Skipping Cloudflare configuration. You can run this script again later to configure it."
fi
# Update the site_url in mkdocs.yml
echo -e "\nUpdating site_url in mkdocs.yml..."
update_mkdocs_yml "$domain_name"
# Check for port conflicts
echo -e "\n---- Checking Port Availability ----"
check_port_conflicts
# 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
listmonk_user="admin"
fi
if [ -z "$listmonk_password" ]; then
listmonk_password="strongpassword"
fi
update_env_var "LISTMONK_ADMIN_USER" "$listmonk_user"
update_env_var "LISTMONK_ADMIN_PASSWORD" "$listmonk_password"
echo "Listmonk admin 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
n8n_email="admin@example.com"
fi
if [ -z "$n8n_password" ]; then
n8n_password="changeMe"
fi
update_env_var "N8N_USER_EMAIL" "$n8n_email"
update_env_var "N8N_USER_PASSWORD" "$n8n_password"
echo "N8N admin credentials updated."
# SMTP Configuration
echo -e "\n---- SMTP Configuration ----"
echo "Configure SMTP settings for sending emails through Listmonk."
read -p "Do you want to configure SMTP settings now? [Y/n]: " configure_smtp
if [[ ! "$configure_smtp" =~ ^[Nn]$ ]]; then
echo ""
echo "Please enter your SMTP server details:"
read -p "SMTP Host (e.g., smtp.gmail.com, smtp.sendgrid.net): " smtp_host
read -p "SMTP Port [default: 587]: " smtp_port
read -p "SMTP Username/Email: " smtp_username
read -sp "SMTP Password: " smtp_password
echo
read -p "Hello Hostname [default: ${LISTMONK_HOSTNAME:-listmonk.changeme.org}]: " smtp_hello
read -p "Enable TLS? [Y/n]: " smtp_tls
# Set defaults
if [ -z "$smtp_port" ]; then
smtp_port="587"
fi
if [ -z "$smtp_hello" ]; then
smtp_hello="${LISTMONK_HOSTNAME:-listmonk.changeme.org}"
fi
if [[ "$smtp_tls" =~ ^[Nn]$ ]]; then
smtp_tls_enabled="false"
else
smtp_tls_enabled="true"
fi
# Update SMTP settings in .env
if [ ! -z "$smtp_host" ]; then
update_env_var "LISTMONK_SMTP_HOST" "$smtp_host"
fi
update_env_var "LISTMONK_SMTP_PORT" "$smtp_port"
if [ ! -z "$smtp_username" ]; then
update_env_var "LISTMONK_SMTP_USERNAME" "$smtp_username"
fi
if [ ! -z "$smtp_password" ]; then
update_env_var "LISTMONK_SMTP_PASSWORD" "$smtp_password"
fi
update_env_var "LISTMONK_SMTP_HELLO_HOSTNAME" "$smtp_hello"
update_env_var "LISTMONK_SMTP_TLS_ENABLED" "$smtp_tls_enabled"
update_env_var "LISTMONK_SMTP_AUTH_PROTOCOL" "plain"
update_env_var "LISTMONK_SMTP_TLS_SKIP_VERIFY" "false"
update_env_var "LISTMONK_SMTP_MAX_CONNS" "10"
update_env_var "LISTMONK_SMTP_MAX_MSG_RETRIES" "2"
update_env_var "LISTMONK_SMTP_IDLE_TIMEOUT" "10s"
update_env_var "LISTMONK_SMTP_WAIT_TIMEOUT" "5s"
echo "✅ SMTP configuration completed!"
else
echo "Skipping SMTP configuration. You can configure this later in the Listmonk admin interface."
fi
# Generate secure passwords for database and encryption
echo -e "\n---- Generating Secure Passwords ----"
echo "Generating secure passwords for database and encryption keys..."
# Generate and update database password
postgres_password=$(generate_password 20)
update_env_var "POSTGRES_PASSWORD" "$postgres_password"
# Generate and update N8N encryption key
n8n_encryption_key=$(generate_password 32)
update_env_var "N8N_ENCRYPTION_KEY" "$n8n_encryption_key"
# Generate and update NocoDB passwords
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"
echo "Secure passwords generated and updated."
echo -e "\n✅ Configuration completed successfully!"
echo "Your .env file has been configured with:"
echo "- Domain: $domain_name"
echo "- Listmonk Admin: $listmonk_user"
echo "- N8N Admin Email: $n8n_email"
echo "- Secure random passwords for database, encryption, and NocoDB"
if [[ ! "$configure_cf" =~ ^[Nn]$ ]]; then
echo "- Cloudflare credentials for DNS management"
fi
echo -e "\nYour .env file is located at: $ENV_FILE"
echo "A backup of your original .env file was created before modifications."
echo -e "\nNext steps:"
echo "1. Run 'docker-compose up -d' to start your services"
if [[ ! "$configure_cf" =~ ^[Nn]$ ]]; then
echo "2. Run './add-cname-records.sh' to set up DNS records and access policies"
fi