203 lines
5.8 KiB
Bash
Executable File
203 lines
5.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# scripts/generate_env.sh
|
|
# Interactive generator for .env from .env.example
|
|
# Usage: ./scripts/generate_env.sh [--yes] [--production]
|
|
|
|
BASE_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
EXAMPLE="$BASE_DIR/.env.example"
|
|
TARGET="$BASE_DIR/.env"
|
|
|
|
confirm=false
|
|
production=false
|
|
|
|
# Parse arguments
|
|
for arg in "$@"; do
|
|
case $arg in
|
|
--yes)
|
|
confirm=true
|
|
;;
|
|
--production)
|
|
production=true
|
|
;;
|
|
*)
|
|
echo "Usage: $0 [--yes] [--production]"
|
|
echo " --yes Non-interactive mode, use defaults or environment variables"
|
|
echo " --production Setup for production environment"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ ! -f "$EXAMPLE" ]]; then
|
|
echo "Error: .env.example not found at $EXAMPLE"
|
|
exit 1
|
|
fi
|
|
|
|
echo "🔧 Generating $TARGET from $EXAMPLE"
|
|
|
|
if [[ -f "$TARGET" && "$confirm" = false ]]; then
|
|
read -p "$TARGET exists. Overwrite? (y/N): " ans
|
|
case "$ans" in
|
|
[Yy]*) ;;
|
|
*) echo "Aborted"; exit 0;;
|
|
esac
|
|
fi
|
|
|
|
# Function to generate secure passwords
|
|
generate_password() {
|
|
openssl rand -base64 32 | tr -d "=+/" | cut -c1-25
|
|
}
|
|
|
|
# Function to generate Django secret key
|
|
generate_secret_key() {
|
|
python3 -c "
|
|
from django.core.management.utils import get_random_secret_key
|
|
print(get_random_secret_key())
|
|
" 2>/dev/null || openssl rand -base64 50 | tr -d "=+/"
|
|
}
|
|
|
|
# Function to safely update env variable
|
|
update_env_var() {
|
|
local key="$1"
|
|
local value="$2"
|
|
local file="$3"
|
|
|
|
# Remove existing line and add new one
|
|
grep -v "^${key}=" "$file" > "${file}.tmp" 2>/dev/null || true
|
|
echo "${key}=${value}" >> "${file}.tmp"
|
|
mv "${file}.tmp" "$file"
|
|
}
|
|
|
|
# Copy example first
|
|
cp "$EXAMPLE" "$TARGET"
|
|
|
|
# Production mode adjustments
|
|
if [[ "$production" = true ]]; then
|
|
echo "🚀 Setting up for production environment..."
|
|
|
|
# Generate secure values
|
|
SECRET_KEY=$(generate_secret_key)
|
|
DB_PASSWORD=$(generate_password)
|
|
|
|
# Set production values
|
|
update_env_var "DJANGO_SECRET_KEY" "$SECRET_KEY" "$TARGET"
|
|
update_env_var "DJANGO_DEBUG" "False" "$TARGET"
|
|
update_env_var "DATABASE_PASSWORD" "$DB_PASSWORD" "$TARGET"
|
|
update_env_var "POSTGRES_PASSWORD" "$DB_PASSWORD" "$TARGET"
|
|
update_env_var "DJANGO_SECURE_SSL_REDIRECT" "True" "$TARGET"
|
|
update_env_var "DJANGO_SECURE_HSTS_SECONDS" "31536000" "$TARGET"
|
|
update_env_var "DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS" "True" "$TARGET"
|
|
update_env_var "DJANGO_SECURE_HSTS_PRELOAD" "True" "$TARGET"
|
|
|
|
# Prompt for domain
|
|
if [[ "$confirm" = false ]]; then
|
|
read -p "Enter your domain (e.g., example.com): " domain
|
|
read -p "Enter your email for SSL certificate: " email
|
|
|
|
if [[ -n "$domain" ]]; then
|
|
update_env_var "DOMAIN" "$domain" "$TARGET"
|
|
update_env_var "DJANGO_ALLOWED_HOSTS" "${domain},localhost,127.0.0.1" "$TARGET"
|
|
update_env_var "DJANGO_CSRF_TRUSTED_ORIGINS" "https://${domain}" "$TARGET"
|
|
update_env_var "CORS_ALLOWED_ORIGINS" "https://${domain}" "$TARGET"
|
|
update_env_var "NEXT_PUBLIC_API_URL" "https://${domain}" "$TARGET"
|
|
fi
|
|
|
|
if [[ -n "$email" ]]; then
|
|
update_env_var "EMAIL" "$email" "$TARGET"
|
|
fi
|
|
fi
|
|
|
|
echo "✅ Production configuration generated with secure passwords"
|
|
echo "📝 Database password: $DB_PASSWORD"
|
|
echo "⚠️ Save this password securely!"
|
|
fi
|
|
|
|
# For each variable in example, prompt the user to keep or change
|
|
while IFS= read -r line; do
|
|
if [[ "$line" =~ ^# ]] || [[ -z "$line" ]]; then
|
|
continue
|
|
fi
|
|
key=$(echo "$line" | cut -d= -f1)
|
|
val=$(echo "$line" | cut -d= -f2-)
|
|
# Trim
|
|
key=$(echo "$key" | xargs)
|
|
val=$(echo "$val" | xargs)
|
|
|
|
current=$(grep -E "^$key=" "$TARGET" || true)
|
|
current_val=""
|
|
if [[ -n "$current" ]]; then
|
|
current_val=$(echo "$current" | cut -d= -f2-)
|
|
fi
|
|
|
|
if [[ "$confirm" = true ]]; then
|
|
# non-interactive: keep example defaults or environment overrides
|
|
env_val=""
|
|
if [[ -n "${!key:-}" ]]; then
|
|
env_val="${!key}"
|
|
fi
|
|
if [[ -n "$env_val" ]]; then
|
|
update_env_var "$key" "$env_val" "$TARGET"
|
|
fi
|
|
continue
|
|
fi
|
|
|
|
# Skip if production mode already set the value
|
|
if [[ "$production" = true ]]; then
|
|
case "$key" in
|
|
DJANGO_SECRET_KEY|DATABASE_PASSWORD|POSTGRES_PASSWORD|DJANGO_DEBUG|DJANGO_SECURE_*|DOMAIN|EMAIL)
|
|
continue
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
# Interactive mode: prompt user for each variable
|
|
if read -t 1 -n 0 2>/dev/null; then
|
|
# Special prompts for certain variables
|
|
case "$key" in
|
|
DJANGO_SECRET_KEY)
|
|
if [[ -z "$current_val" ]]; then
|
|
read -p "$key (press Enter to generate): " new_val || true
|
|
if [[ -z "$new_val" ]]; then
|
|
new_val=$(generate_secret_key)
|
|
fi
|
|
else
|
|
read -p "$key [HIDDEN]: " new_val || true
|
|
fi
|
|
;;
|
|
DATABASE_PASSWORD|POSTGRES_PASSWORD)
|
|
if [[ -z "$current_val" ]]; then
|
|
read -p "$key (press Enter to generate): " new_val || true
|
|
if [[ -z "$new_val" ]]; then
|
|
new_val=$(generate_password)
|
|
fi
|
|
else
|
|
read -p "$key [HIDDEN]: " new_val || true
|
|
fi
|
|
;;
|
|
*)
|
|
read -p "$key [$current_val]: " new_val || true
|
|
;;
|
|
esac
|
|
else
|
|
# no stdin available, skip prompting
|
|
new_val=""
|
|
fi
|
|
|
|
if [[ -n "$new_val" ]]; then
|
|
update_env_var "$key" "$new_val" "$TARGET"
|
|
fi
|
|
|
|
done < <(grep -E '^[A-Z0-9_]+=.*' "$EXAMPLE")
|
|
|
|
echo "✅ Written $TARGET"
|
|
|
|
if [[ "$production" = false ]]; then
|
|
echo ""
|
|
echo "💡 Tips:"
|
|
echo " - Run with --production for production setup with secure defaults"
|
|
echo " - Run with --yes to auto-fill from environment variables"
|
|
echo " - Check the generated .env file and adjust values as needed"
|
|
fi
|