824 lines
28 KiB
Bash
Executable File
824 lines
28 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/mkdocs.yml" # Fixed path - removed extra 'docs' directory
|
|
TUNNEL_CONFIG_DIR="$SCRIPT_DIR/configs/cloudflare"
|
|
TUNNEL_CONFIG_FILE="$TUNNEL_CONFIG_DIR/tunnel-config.yml"
|
|
SERVICES_YAML="$SCRIPT_DIR/configs/homepage/services.yaml"
|
|
MAIN_HTML="$SCRIPT_DIR/mkdocs/docs/overrides/main.html"
|
|
MAP_ENV_FILE="$SCRIPT_DIR/map/.env" # Add the map's .env file path
|
|
|
|
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
|
|
|
|
# More robust method to handle special characters in passwords
|
|
if grep -q "^$key=" "$ENV_FILE"; then
|
|
# Create a temporary file
|
|
local tmpfile=$(mktemp)
|
|
|
|
# Process the .env file line by line
|
|
while IFS= read -r line; do
|
|
if [[ "$line" =~ ^$key= ]]; then
|
|
echo "$key=$value" >> "$tmpfile"
|
|
else
|
|
echo "$line" >> "$tmpfile"
|
|
fi
|
|
done < "$ENV_FILE"
|
|
|
|
# Replace the original file with the temporary file
|
|
mv "$tmpfile" "$ENV_FILE"
|
|
echo "Updated $key in .env file"
|
|
else
|
|
# Add new key-value pair if it doesn't exist
|
|
echo "$key=$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 get all used ports on the system
|
|
get_used_ports() {
|
|
local used_ports=()
|
|
|
|
# Try different methods to get used ports, in order of preference
|
|
if command -v ss >/dev/null 2>&1; then
|
|
# Use ss (preferred, modern replacement for netstat)
|
|
while IFS= read -r line; do
|
|
if [[ "$line" =~ :([0-9]+)[[:space:]] ]]; then
|
|
used_ports+=("${BASH_REMATCH[1]}")
|
|
fi
|
|
done < <(ss -tuln 2>/dev/null | grep -E ':[0-9]+[[:space:]]')
|
|
elif command -v netstat >/dev/null 2>&1; then
|
|
# Use netstat (fallback)
|
|
while IFS= read -r line; do
|
|
if [[ "$line" =~ :([0-9]+)[[:space:]] ]]; then
|
|
used_ports+=("${BASH_REMATCH[1]}")
|
|
fi
|
|
done < <(netstat -tuln 2>/dev/null | grep -E ':[0-9]+[[:space:]]')
|
|
elif command -v lsof >/dev/null 2>&1; then
|
|
# Use lsof (another fallback)
|
|
while IFS= read -r line; do
|
|
if [[ "$line" =~ :([0-9]+)[[:space:]] ]]; then
|
|
used_ports+=("${BASH_REMATCH[1]}")
|
|
fi
|
|
done < <(lsof -i -P -n 2>/dev/null | grep LISTEN | grep -E ':[0-9]+[[:space:]]')
|
|
else
|
|
echo "Warning: No port scanning tools available (ss, netstat, or lsof)"
|
|
return 1
|
|
fi
|
|
|
|
# Remove duplicates and sort
|
|
printf '%s\n' "${used_ports[@]}" | sort -nu
|
|
}
|
|
|
|
# Function to check if a specific port is available
|
|
is_port_available() {
|
|
local port=$1
|
|
local used_ports_list=$2
|
|
|
|
# Check if port is in the used ports list
|
|
if echo "$used_ports_list" | grep -q "^$port$"; then
|
|
return 1 # Port is in use
|
|
else
|
|
return 0 # Port is available
|
|
fi
|
|
}
|
|
|
|
# Function to find next available port starting from a given port
|
|
find_next_available_port() {
|
|
local start_port=$1
|
|
local used_ports_list=$2
|
|
local max_attempts=${3:-100} # Maximum ports to check
|
|
|
|
for ((i=0; i<max_attempts; i++)); do
|
|
local test_port=$((start_port + i))
|
|
|
|
# Skip ports below 1024 (system ports) and above 65535
|
|
if [ "$test_port" -lt 1024 ] || [ "$test_port" -gt 65535 ]; then
|
|
continue
|
|
fi
|
|
|
|
if is_port_available "$test_port" "$used_ports_list"; then
|
|
echo "$test_port"
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
echo "Error: Could not find available port starting from $start_port" >&2
|
|
return 1
|
|
}
|
|
|
|
# Function to initialize available ports for services
|
|
initialize_available_ports() {
|
|
echo "Scanning system for used ports to avoid conflicts..."
|
|
|
|
# Get list of all used ports
|
|
local used_ports_list
|
|
used_ports_list=$(get_used_ports)
|
|
|
|
if [ $? -ne 0 ] || [ -z "$used_ports_list" ]; then
|
|
echo "Warning: Could not scan system ports. Using default ports."
|
|
echo "You may need to manually resolve conflicts later."
|
|
return 1
|
|
fi
|
|
|
|
echo "Found $(echo "$used_ports_list" | wc -l) ports currently in use"
|
|
|
|
# Define desired starting ports for each service
|
|
local -A service_ports=(
|
|
["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
|
|
["GITEA_WEB_PORT"]=3030
|
|
["GITEA_SSH_PORT"]=2222
|
|
["MAP_PORT"]=3000
|
|
["MINI_QR_PORT"]=8089
|
|
)
|
|
|
|
# Find available ports for each service
|
|
local -A available_ports
|
|
for service in "${!service_ports[@]}"; do
|
|
local preferred_port=${service_ports[$service]}
|
|
local available_port
|
|
|
|
if is_port_available "$preferred_port" "$used_ports_list"; then
|
|
available_port=$preferred_port
|
|
echo "✅ $service: Using preferred port $preferred_port"
|
|
else
|
|
available_port=$(find_next_available_port "$preferred_port" "$used_ports_list")
|
|
if [ $? -eq 0 ]; then
|
|
echo "⚠️ $service: Port $preferred_port in use, using $available_port instead"
|
|
else
|
|
echo "❌ $service: Could not find available port, using $preferred_port (may conflict)"
|
|
available_port=$preferred_port
|
|
fi
|
|
fi
|
|
|
|
available_ports[$service]=$available_port
|
|
# Add the assigned port to used_ports_list to avoid double-assignment
|
|
used_ports_list=$(printf '%s\n%s' "$used_ports_list" "$available_port" | sort -nu)
|
|
done
|
|
|
|
# Export the available ports as global variables
|
|
for service in "${!available_ports[@]}"; do
|
|
export "$service=${available_ports[$service]}"
|
|
done
|
|
|
|
echo "Port assignment completed successfully!"
|
|
return 0
|
|
}
|
|
|
|
# Function to initialize the .env file with default values
|
|
initialize_env_file() {
|
|
echo "Initializing new .env file with available ports..."
|
|
|
|
# Initialize available ports before creating the .env file
|
|
initialize_available_ports
|
|
|
|
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 (automatically assigned to avoid conflicts)
|
|
CODE_SERVER_PORT=${CODE_SERVER_PORT:-8888}
|
|
LISTMONK_PORT=${LISTMONK_PORT:-9000}
|
|
LISTMONK_DB_PORT=${LISTMONK_DB_PORT:-5432}
|
|
MKDOCS_PORT=${MKDOCS_PORT:-4000}
|
|
MKDOCS_SITE_SERVER_PORT=${MKDOCS_SITE_SERVER_PORT:-4001}
|
|
N8N_PORT=${N8N_PORT:-5678}
|
|
NOCODB_PORT=${NOCODB_PORT:-8090}
|
|
HOMEPAGE_PORT=${HOMEPAGE_PORT:-3010}
|
|
GITEA_WEB_PORT=${GITEA_WEB_PORT:-3030}
|
|
GITEA_SSH_PORT=${GITEA_SSH_PORT:-2222}
|
|
MAP_PORT=${MAP_PORT:-3000}
|
|
MINI_QR_PORT=${MINI_QR_PORT:-8089}
|
|
|
|
# Domain Configuration
|
|
BASE_DOMAIN=https://changeme.org
|
|
DOMAIN=changeme.org
|
|
LISTMONK_HOSTNAME=listmonk.changeme.org
|
|
N8N_HOST=n8n.changeme.org
|
|
GITEA_DOMAIN=git.changeme.org
|
|
GITEA_ROOT_URL=https://git.changeme.org
|
|
HOMEPAGE_VAR_BASE_URL=https://changeme.org
|
|
|
|
# Cookie and CORS Configuration
|
|
COOKIE_DOMAIN=.changeme.org
|
|
ALLOWED_ORIGINS=https://map.changeme.org,http://localhost:3000
|
|
|
|
# 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
|
|
CF_ACCOUNT_ID=your_cloudflare_account_id
|
|
|
|
# Database Configuration (PostgreSQL for Listmonk)
|
|
POSTGRES_USER=listmonk
|
|
POSTGRES_PASSWORD=changeMe
|
|
POSTGRES_DB=listmonk
|
|
|
|
# Listmonk Database Performance Settings
|
|
LISTMONK_DB_MAX_OPEN=25
|
|
LISTMONK_DB_MAX_IDLE=25
|
|
LISTMONK_DB_MAX_LIFETIME=300s
|
|
|
|
# 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_JWT_SECRET=changeMe
|
|
NOCODB_DB_NAME=nocodb
|
|
NOCODB_DB_USER=noco
|
|
NOCODB_DB_PASSWORD=changeMe
|
|
|
|
# Gitea Database Configuration
|
|
GITEA_DB_PASSWD=changeMe
|
|
GITEA_DB_ROOT_PASSWORD=changeMe
|
|
EOL
|
|
|
|
echo "New .env file created with conflict-free port assignments."
|
|
|
|
# Show port assignments summary
|
|
echo ""
|
|
echo "=== Port Assignments Summary ==="
|
|
echo "Code Server: ${CODE_SERVER_PORT:-8888}"
|
|
echo "Listmonk: ${LISTMONK_PORT:-9000}"
|
|
echo "Listmonk DB: ${LISTMONK_DB_PORT:-5432}"
|
|
echo "MkDocs: ${MKDOCS_PORT:-4000}"
|
|
echo "MkDocs Site: ${MKDOCS_SITE_SERVER_PORT:-4001}"
|
|
echo "N8N: ${N8N_PORT:-5678}"
|
|
echo "NocoDB: ${NOCODB_PORT:-8090}"
|
|
echo "Homepage: ${HOMEPAGE_PORT:-3010}"
|
|
echo "Gitea Web: ${GITEA_WEB_PORT:-3030}"
|
|
echo "Gitea SSH: ${GITEA_SSH_PORT:-2222}"
|
|
echo "Map: ${MAP_PORT:-3000}"
|
|
echo "Mini QR: ${MINI_QR_PORT:-8089}"
|
|
echo "================================"
|
|
}
|
|
|
|
# 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 - handle both http and https
|
|
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 update service URLs in services.yaml
|
|
update_services_yaml() {
|
|
local new_domain=$1
|
|
|
|
if [ ! -f "$SERVICES_YAML" ]; then
|
|
echo "Warning: services.yaml 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"
|
|
|
|
# Update all href values with the new domain
|
|
# Replace any existing domain patterns with the new domain
|
|
sed -i "s|href: \"https://code\.[^\"]*\"|href: \"https://code.$new_domain\"|g" "$SERVICES_YAML"
|
|
sed -i "s|href: \"https://listmonk\.[^\"]*\"|href: \"https://listmonk.$new_domain\"|g" "$SERVICES_YAML"
|
|
sed -i "s|href: \"https://db\.[^\"]*\"|href: \"https://db.$new_domain\"|g" "$SERVICES_YAML"
|
|
sed -i "s|href: \"https://map\.[^\"]*\"|href: \"https://map.$new_domain\"|g" "$SERVICES_YAML"
|
|
sed -i "s|href: \"https://docs\.[^\"]*\"|href: \"https://docs.$new_domain\"|g" "$SERVICES_YAML"
|
|
sed -i "s|href: \"https://n8n\.[^\"]*\"|href: \"https://n8n.$new_domain\"|g" "$SERVICES_YAML"
|
|
sed -i "s|href: \"https://git\.[^\"]*\"|href: \"https://git.$new_domain\"|g" "$SERVICES_YAML"
|
|
sed -i "s|href: \"https://qr\.[^\"]*\"|href: \"https://qr.$new_domain\"|g" "$SERVICES_YAML"
|
|
|
|
# Update the main site href (matches pattern without subdomain)
|
|
sed -i "s|href: \"https://[a-zA-Z0-9.-]*\.\(org\|com\|net\|edu\)\"|href: \"https://$new_domain\"|g" "$SERVICES_YAML"
|
|
|
|
# Also update any remaining domain references that might exist
|
|
sed -i "s|cmlite\.org|$new_domain|g" "$SERVICES_YAML"
|
|
sed -i "s|changeme\.org|$new_domain|g" "$SERVICES_YAML"
|
|
sed -i "s|albertademocracytaskforce\.org|$new_domain|g" "$SERVICES_YAML"
|
|
|
|
echo "✅ Updated service URLs in services.yaml to use domain: $new_domain"
|
|
return 0
|
|
}
|
|
|
|
# Function to update the login URL in main.html
|
|
update_main_html() {
|
|
local new_domain=$1
|
|
|
|
if [ ! -f "$MAIN_HTML" ]; then
|
|
echo "Warning: main.html not found at $MAIN_HTML"
|
|
return 1
|
|
fi
|
|
|
|
echo "Updating login URL in main.html..."
|
|
|
|
# Create a backup of the main.html file
|
|
local timestamp=$(date +"%Y%m%d_%H%M%S")
|
|
local backup_file="${MAIN_HTML}.backup_${timestamp}"
|
|
cp "$MAIN_HTML" "$backup_file"
|
|
echo "Created backup of main.html at $backup_file"
|
|
|
|
# Update the login button href - handle current domain
|
|
sed -i "s|href=\"https://homepage\.[^\"]*\"|href=\"https://homepage.$new_domain\"|g" "$MAIN_HTML"
|
|
|
|
# Also update any albertademocracytaskforce.org references
|
|
sed -i "s|albertademocracytaskforce\.org|$new_domain|g" "$MAIN_HTML"
|
|
|
|
# Update any test.com or changeme.org references
|
|
sed -i "s|test\.com|$new_domain|g" "$MAIN_HTML"
|
|
sed -i "s|changeme\.org|$new_domain|g" "$MAIN_HTML"
|
|
|
|
echo "✅ Updated login URL in main.html to: https://homepage.$new_domain"
|
|
return 0
|
|
}
|
|
|
|
# Function to get Cloudflare API Token and Zone ID
|
|
get_cloudflare_credentials() {
|
|
echo ""
|
|
echo "To use Cloudflare tunnels, you'll need to configure your credentials."
|
|
echo ""
|
|
echo "=== Cloudflare Configuration ==="
|
|
echo ""
|
|
echo "You'll need:"
|
|
echo "1. Your Cloudflare API Token (with Zone.DNS and Account.Cloudflare Tunnel permissions)"
|
|
echo "2. Your Cloudflare Zone ID (found in the Cloudflare dashboard overview)"
|
|
echo "3. Your Cloudflare Account ID (found in the Cloudflare dashboard)"
|
|
echo ""
|
|
echo "These credentials will be used for:"
|
|
echo "- Creating and configuring tunnels"
|
|
echo "- Managing DNS records"
|
|
echo "- Setting up access policies"
|
|
echo ""
|
|
}
|
|
|
|
# Function to update the tunnel configuration file with new domain
|
|
update_tunnel_config() {
|
|
local new_domain=$1
|
|
local tunnel_id=${2:-"(insert-tunnel-id)"}
|
|
local creds_path=${3:-"/path/to/credentials/file"}
|
|
|
|
# Create directory if it doesn't exist
|
|
mkdir -p "$TUNNEL_CONFIG_DIR"
|
|
|
|
echo "Updating tunnel configuration with new domain..."
|
|
|
|
# Create a backup if file exists
|
|
if [ -f "$TUNNEL_CONFIG_FILE" ]; then
|
|
local timestamp=$(date +"%Y%m%d_%H%M%S")
|
|
local backup_file="${TUNNEL_CONFIG_FILE}.backup_${timestamp}"
|
|
cp "$TUNNEL_CONFIG_FILE" "$backup_file"
|
|
echo "Created backup of tunnel-config.yml at $backup_file"
|
|
fi
|
|
|
|
# Load current environment variables to get port numbers
|
|
load_env_vars
|
|
|
|
# Create/update the tunnel configuration
|
|
cat > "$TUNNEL_CONFIG_FILE" << EOL
|
|
# filepath: /home/bunker-admin/changemaker.lite/configs/cloudflare/tunnel-config.yml
|
|
# Cloudflare Tunnel Configuration
|
|
# Auto-generated by Changemaker Configuration Wizard
|
|
|
|
tunnel: $tunnel_id # e.g. 1234567890abcdef
|
|
credentials-file: $creds_path # e.g. /home/bunker-admin/.cloudflared/[insert tunnel number].json
|
|
ingress:
|
|
|
|
- hostname: homepage.$new_domain
|
|
service: http://localhost:${HOMEPAGE_PORT:-3010}
|
|
|
|
- hostname: code.$new_domain
|
|
service: http://localhost:${CODE_SERVER_PORT:-8888}
|
|
|
|
- hostname: listmonk.$new_domain
|
|
service: http://localhost:${LISTMONK_PORT:-9001}
|
|
|
|
- hostname: docs.$new_domain
|
|
service: http://localhost:${MKDOCS_PORT:-4000}
|
|
|
|
- hostname: $new_domain
|
|
service: http://localhost:${MKDOCS_SITE_SERVER_PORT:-4002}
|
|
|
|
- hostname: n8n.$new_domain
|
|
service: http://localhost:${N8N_PORT:-5678}
|
|
|
|
- hostname: db.$new_domain
|
|
service: http://localhost:${NOCODB_PORT:-8090}
|
|
|
|
- hostname: git.$new_domain
|
|
service: http://localhost:${GITEA_WEB_PORT:-3030}
|
|
|
|
- hostname: map.$new_domain
|
|
service: http://localhost:${MAP_PORT:-3000}
|
|
|
|
- hostname: qr.$new_domain
|
|
service: http://localhost:${MINI_QR_PORT:-8089}
|
|
|
|
# Catch-all rule (required)
|
|
- service: http_status:404
|
|
EOL
|
|
|
|
echo "✅ Updated tunnel configuration for domain: $new_domain"
|
|
return 0
|
|
}
|
|
|
|
# Function to load environment variables from .env file
|
|
load_env_vars() {
|
|
if [ -f "$ENV_FILE" ]; then
|
|
# Load variables from .env file, ignoring comments and empty lines
|
|
while IFS= read -r line; do
|
|
if [[ "$line" =~ ^[A-Za-z_][A-Za-z0-9_]*= ]]; then
|
|
export "$line"
|
|
fi
|
|
done < <(grep -E '^[A-Za-z_][A-Za-z0-9_]*=' "$ENV_FILE")
|
|
fi
|
|
}
|
|
|
|
# Function to update or create the map's .env file with domain settings
|
|
update_map_env() {
|
|
local new_domain=$1
|
|
|
|
# If the map .env file does not exist, create it with defaults
|
|
if [ ! -f "$MAP_ENV_FILE" ]; then
|
|
echo "Map .env file not found at $MAP_ENV_FILE, creating a new one with defaults."
|
|
cat > "$MAP_ENV_FILE" <<EOL
|
|
NOCODB_API_URL=https://db.$new_domain/api/v1
|
|
NOCODB_API_TOKEN=changeme
|
|
|
|
# NocoDB View URL is the URL to your NocoDB view where the map data is stored.
|
|
NOCODB_VIEW_URL=https://db.$new_domain/dashboard/#/nc/your_project_id/your_view_id
|
|
|
|
# NOCODB_LOGIN_SHEET is the URL to your NocoDB login sheet.
|
|
NOCODB_LOGIN_SHEET=https://db.$new_domain/dashboard/#/nc/your_project_id/your_login_sheet_id
|
|
|
|
# NOCODB_SETTINGS_SHEET is the URL to your NocoDB settings sheet.
|
|
NOCODB_SETTINGS_SHEET=https://db.$new_domain/dashboard/#/nc/your_project_id/your_settings_sheet_id
|
|
|
|
# Server Configuration
|
|
PORT=3000
|
|
NODE_ENV=production
|
|
|
|
# Session Secret (IMPORTANT: Generate a secure random string for production)
|
|
# You can generate one with: openssl rand -hex 32
|
|
SESSION_SECRET=$(openssl rand -hex 32 2>/dev/null || echo "changeme")
|
|
|
|
# Map Defaults (Edmonton, Alberta, Canada)
|
|
DEFAULT_LAT=53.5461
|
|
DEFAULT_LNG=-113.4938
|
|
DEFAULT_ZOOM=11
|
|
|
|
# Optional: Map Boundaries (prevents users from adding points outside area)
|
|
# BOUND_NORTH=53.7
|
|
# BOUND_SOUTH=53.4
|
|
# BOUND_EAST=-113.3
|
|
# BOUND_WEST=-113.7
|
|
|
|
# Cloudflare Settings
|
|
TRUST_PROXY=true
|
|
COOKIE_DOMAIN=.$new_domain
|
|
|
|
# Update NODE_ENV to production for HTTPS
|
|
NODE_ENV=production
|
|
|
|
# Add allowed origin
|
|
ALLOWED_ORIGINS=https://map.$new_domain,http://localhost:3000
|
|
EOL
|
|
echo "✅ Created new map .env file at $MAP_ENV_FILE"
|
|
return 0
|
|
fi
|
|
|
|
echo "Updating map .env file with new domain settings..."
|
|
|
|
# Create a backup of the map's .env file
|
|
local timestamp=$(date +"%Y%m%d_%H%M%S")
|
|
local backup_file="${MAP_ENV_FILE}.backup_${timestamp}"
|
|
cp "$MAP_ENV_FILE" "$backup_file"
|
|
echo "Created backup of map .env at $backup_file"
|
|
|
|
# Update COOKIE_DOMAIN
|
|
if grep -q "^COOKIE_DOMAIN=" "$MAP_ENV_FILE"; then
|
|
sed -i "s|^COOKIE_DOMAIN=.*|COOKIE_DOMAIN=.$new_domain|" "$MAP_ENV_FILE"
|
|
else
|
|
echo "COOKIE_DOMAIN=.$new_domain" >> "$MAP_ENV_FILE"
|
|
fi
|
|
|
|
# Update ALLOWED_ORIGINS
|
|
local allowed_origins="https://map.$new_domain,http://localhost:3000"
|
|
if grep -q "^ALLOWED_ORIGINS=" "$MAP_ENV_FILE"; then
|
|
sed -i "s|^ALLOWED_ORIGINS=.*|ALLOWED_ORIGINS=$allowed_origins|" "$MAP_ENV_FILE"
|
|
else
|
|
echo "ALLOWED_ORIGINS=$allowed_origins" >> "$MAP_ENV_FILE"
|
|
fi
|
|
|
|
# Also update the NOCODB URLs if they contain domain references
|
|
sed -i "s|example\.org|$new_domain|g" "$MAP_ENV_FILE"
|
|
sed -i "s|changeme\.org|$new_domain|g" "$MAP_ENV_FILE"
|
|
sed -i "s|albertademocracytaskforce\.org|$new_domain|g" "$MAP_ENV_FILE"
|
|
|
|
echo "✅ Updated map .env file with:"
|
|
echo " - COOKIE_DOMAIN=.$new_domain"
|
|
echo " - ALLOWED_ORIGINS=$allowed_origins"
|
|
echo " - Updated all NocoDB URLs to use $new_domain"
|
|
return 0
|
|
}
|
|
|
|
# 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
|
|
|
|
# For existing .env files, also scan ports and suggest alternatives if conflicts exist
|
|
echo ""
|
|
echo "Checking existing port assignments for conflicts..."
|
|
load_env_vars
|
|
check_port_conflicts
|
|
fi
|
|
|
|
# Load existing environment variables
|
|
load_env_vars
|
|
|
|
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 "HOMEPAGE_VAR_BASE_URL" "https://$domain_name"
|
|
update_env_var "LISTMONK_HOSTNAME" "listmonk.$domain_name"
|
|
update_env_var "N8N_HOST" "n8n.$domain_name"
|
|
update_env_var "CF_DOMAIN" "$domain_name"
|
|
update_env_var "GITEA_DOMAIN" "git.$domain_name"
|
|
update_env_var "GITEA_ROOT_URL" "https://git.$domain_name"
|
|
|
|
# Update cookie and CORS settings
|
|
update_env_var "COOKIE_DOMAIN" ".$domain_name"
|
|
update_env_var "ALLOWED_ORIGINS" "https://map.$domain_name,http://localhost:3000"
|
|
|
|
echo "Domain settings updated successfully!"
|
|
|
|
# Update the map's .env file
|
|
echo -e "\nUpdating map configuration..."
|
|
update_map_env "$domain_name"
|
|
|
|
# Cloudflare Configuration
|
|
echo -e "\n---- Cloudflare Configuration ----"
|
|
get_cloudflare_credentials
|
|
|
|
read -p "Do you want to configure Cloudflare settings now? [Y/n]: " configure_cf
|
|
|
|
if [[ ! "$configure_cf" =~ ^[Nn]$ ]]; then
|
|
# Get Cloudflare API token
|
|
read -p "Enter your Cloudflare API Token: " cf_api_token
|
|
if [ -z "$cf_api_token" ] || [ "$cf_api_token" = "your_cloudflare_api_token" ]; then
|
|
echo "Warning: API token is required for Cloudflare integration"
|
|
cf_api_token="your_cloudflare_api_token"
|
|
fi
|
|
update_env_var "CF_API_TOKEN" "$cf_api_token"
|
|
|
|
# Get Cloudflare Zone ID
|
|
read -p "Enter your Cloudflare Zone ID: " cf_zone_id
|
|
if [ -z "$cf_zone_id" ] || [ "$cf_zone_id" = "your_cloudflare_zone_id" ]; then
|
|
echo "Warning: Zone ID is required for DNS configuration"
|
|
cf_zone_id="your_cloudflare_zone_id"
|
|
fi
|
|
update_env_var "CF_ZONE_ID" "$cf_zone_id"
|
|
|
|
# Get Cloudflare Account ID
|
|
read -p "Enter your Cloudflare Account ID: " cf_account_id
|
|
if [ -z "$cf_account_id" ] || [ "$cf_account_id" = "your_cloudflare_account_id" ]; then
|
|
echo "Warning: Account ID is required for tunnel operations"
|
|
cf_account_id="your_cloudflare_account_id"
|
|
fi
|
|
update_env_var "CF_ACCOUNT_ID" "$cf_account_id"
|
|
|
|
# Note: CF_TUNNEL_ID will be set by start-production.sh when the tunnel is created
|
|
update_env_var "CF_TUNNEL_ID" "will_be_set_by_start_production"
|
|
|
|
echo ""
|
|
echo "Cloudflare configuration saved to .env file."
|
|
echo ""
|
|
echo "To complete the setup and deploy your services:"
|
|
echo "1. Start your services with: docker compose up -d"
|
|
echo "2. Run ./start-production.sh to configure the Cloudflare tunnel"
|
|
echo ""
|
|
else
|
|
echo "Skipping Cloudflare configuration."
|
|
echo "You'll need to configure Cloudflare settings manually before running start-production.sh."
|
|
fi
|
|
|
|
# Update the site_url in mkdocs.yml
|
|
echo -e "\nUpdating site_url in mkdocs.yml..."
|
|
update_mkdocs_yml "$domain_name"
|
|
|
|
# Update service URLs in services.yaml
|
|
echo -e "\nUpdating service URLs in services.yaml..."
|
|
update_services_yaml "$domain_name"
|
|
|
|
# Update the login URL in main.html
|
|
echo -e "\nUpdating login URL in main.html..."
|
|
update_main_html "$domain_name"
|
|
|
|
# Listmonk Admin Credentials configuration
|
|
echo -e "\n---- Listmonk Admin Credentials ----"
|
|
read -p "Enter Listmonk admin email/username [default: admin@example.com]: " listmonk_user
|
|
read -sp "Enter Listmonk admin password [default: changeMe]: " listmonk_password
|
|
echo # Add new line after password input
|
|
|
|
if [ -z "$listmonk_user" ]; then
|
|
listmonk_user="admin@example.com"
|
|
fi
|
|
|
|
if [ -z "$listmonk_password" ]; then
|
|
listmonk_password="changeMe"
|
|
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."
|
|
|
|
# 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"
|
|
|
|
# Generate and update Gitea passwords (these should already exist in the file)
|
|
gitea_db_password=$(generate_password 20)
|
|
update_env_var "GITEA_DB_PASSWD" "$gitea_db_password"
|
|
|
|
gitea_db_root_password=$(generate_password 20)
|
|
update_env_var "GITEA_DB_ROOT_PASSWORD" "$gitea_db_root_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 "- Cookie Domain: .$domain_name"
|
|
echo "- Allowed Origins: https://map.$domain_name,http://localhost:3000"
|
|
echo "- Map .env updated with domain settings"
|
|
echo "- Listmonk Admin: $listmonk_user"
|
|
echo "- N8N Admin Email: $n8n_email"
|
|
echo "- Secure random passwords for database, encryption, and NocoDB"
|
|
echo "- Tunnel configuration updated at: $TUNNEL_CONFIG_FILE"
|
|
echo -e "\nYour .env file is located at: $ENV_FILE"
|
|
echo "A backup of your original .env file was created before modifications."
|
|
|
|
echo ""
|
|
echo "======================================"
|
|
echo "Next Steps:"
|
|
echo "======================================"
|
|
echo ""
|
|
echo "1. Start services locally:"
|
|
echo " docker compose up -d"
|
|
echo ""
|
|
echo "2. Test all services at:"
|
|
echo " - Homepage: http://localhost:${HOMEPAGE_PORT:-3010}"
|
|
echo " - Code Server: http://localhost:${CODE_SERVER_PORT:-8888}"
|
|
echo " - Listmonk: http://localhost:${LISTMONK_PORT:-9000}"
|
|
echo " - Documentation: http://localhost:${MKDOCS_PORT:-4000}"
|
|
echo " - n8n: http://localhost:${N8N_PORT:-5678}"
|
|
echo " - NocoDB: http://localhost:${NOCODB_PORT:-8090}"
|
|
echo " - Gitea: http://localhost:${GITEA_WEB_PORT:-3030}"
|
|
echo " - Map: http://localhost:${MAP_PORT:-3000}"
|
|
echo " - Mini QR: http://localhost:${MINI_QR_PORT:-8089}"
|
|
echo ""
|
|
echo "3. When ready for production:"
|
|
echo " ./start-production.sh"
|
|
echo ""
|
|
echo "======================================" |