#!/bin/bash # Define color codes if command -v tput >/dev/null && [ -t 1 ]; then RED=$(tput setaf 1) GREEN=$(tput setaf 2) YELLOW=$(tput setaf 3) BLUE=$(tput setaf 4) NC=$(tput sgr0) # No Color else RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color fi dotenv_replace() { local env_var_name=$1 local new_value=$2 local file_path=$3 local sed_option="" # Check if running on macOS and adjust sed_option accordingly if [[ "$OSTYPE" == "darwin"* ]]; then sed_option="-i ''" else sed_option="-i" fi # Use eval to correctly handle the dynamic insertion of the sed option delimiter="#" eval sed $sed_option "s$delimiter^${env_var_name}=.*$delimiter${env_var_name}=${new_value}$delimiter" $file_path } echo -e "${YELLOW}Creating .env...${NC}" # If .env exists, ask user if they want to overwrite it if [ -f .env ]; then read -p "A .env file already exists. Do you want to overwrite it? (y/n) " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then echo -e "${YELLOW}Exiting...${NC}" exit 0 fi fi # Create .env file if [ ! -e ".env.example" ] ; then echo "${RED}No .env.example file found in current directory: $(pwd). Please download .env.example from the Tracecat GitHub repo and rerun the env.sh script." exit 1 fi env_file=".env" if ! openssl --help &> /dev/null then echo -e "${RED}Could not run openssl. Please check if openssl is correctly installed." exit 1 fi echo -e "${YELLOW}Generating new service key and signing secret...${NC}" service_key=$(openssl rand -hex 32) signing_secret=$(openssl rand -hex 32) user_auth_secret=$(openssl rand -hex 32) echo -e "${YELLOW}Generating a Fernet encryption key for the database...${NC}" # Use a cross-platform base64 command (works on both Linux and macOS) db_fernet_key=$(openssl rand 32 | base64 | tr -d '\n' | tr '+/' '-_') echo -e "${YELLOW}Creating new .env from .env.example...${NC}" cp .env.example .env # Replace existing values of TRACECAT__SERVICE_KEY and TRACECAT__SIGNING_SECRET dotenv_replace "TRACECAT__SERVICE_KEY" "$service_key" "$env_file" dotenv_replace "TRACECAT__SIGNING_SECRET" "$signing_secret" "$env_file" dotenv_replace "TRACECAT__DB_ENCRYPTION_KEY" "$db_fernet_key" "$env_file" dotenv_replace "USER_AUTH_SECRET" "$user_auth_secret" "$env_file" # Prompt user for environment mode while true; do read -p "Use production mode? (y/n, default: y): " prod_mode prod_mode=${prod_mode:-y} case $prod_mode in [Yy]* ) env_mode="production" break ;; [Nn]* ) env_mode="development" break ;; * ) echo -e "${RED}Please answer y or n.${NC}";; esac done # Prompt user for new IP address and strip http:// or https:// while true; do read -p "Set \`PUBLIC_APP_URL\` environment variable to (default: localhost): " new_ip new_ip=$(sed -E 's/^\s*.*:\/\///g' <<< $new_ip) new_ip=${new_ip:-localhost} if [ "$new_ip" != "0.0.0.0" ]; then break fi echo -e "${RED}Cannot use 0.0.0.0 as address.\nSee https://docs.tracecat.com/self-hosting/docker-compose#faq ${NC}" done # Extract hostname and port from the input # Handle formats like: localhost, localhost:8080, 127.0.0.1:8080 if [[ "$new_ip" =~ ^([^:]+)(:([0-9]+))?$ ]]; then hostname="${BASH_REMATCH[1]}" port="${BASH_REMATCH[3]}" # If port is specified, update PUBLIC_APP_PORT if [ -n "$port" ]; then app_port="$port" base_url="http://${hostname}:${port}" else # No port specified, use default port 80 (or keep existing PUBLIC_APP_PORT) app_port="" base_url="http://${hostname}" fi else # Fallback if regex doesn't match hostname="$new_ip" app_port="" base_url="http://${hostname}" fi public_app_url="$base_url" public_api_url="${base_url}/api" # Prompt user for PostgreSQL SSL mode while true; do read -p "Require PostgreSQL SSL mode? (y/n, default: n): " postgres_ssl postgres_ssl=${postgres_ssl:-n} case $postgres_ssl in [Yy]* ) ssl_mode="require" break ;; [Nn]* ) ssl_mode="disable" break ;; * ) echo -e "${RED}Please answer y or n.${NC}";; esac done # Prompt user for superadmin email echo -e "${YELLOW}Setting up first user (superadmin)...${NC}" while true; do read -p "Enter email address for the first user (superadmin): " superadmin_email if [[ -z "$superadmin_email" ]]; then echo -e "${RED}Email address cannot be empty. Please enter a valid email address.${NC}" continue fi # Basic email validation if [[ "$superadmin_email" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then break else echo -e "${RED}Please enter a valid email address.${NC}" fi done # Update environment variables dotenv_replace "TRACECAT__APP_ENV" "$env_mode" "$env_file" dotenv_replace "NODE_ENV" "$env_mode" "$env_file" dotenv_replace "NEXT_PUBLIC_APP_ENV" "$env_mode" "$env_file" dotenv_replace "PUBLIC_API_URL" "$public_api_url" "$env_file" dotenv_replace "PUBLIC_APP_URL" "$public_app_url" "$env_file" # Update PUBLIC_APP_PORT if port was specified if [ -n "$app_port" ]; then dotenv_replace "PUBLIC_APP_PORT" "$app_port" "$env_file" fi dotenv_replace "TRACECAT__DB_SSLMODE" "$ssl_mode" "$env_file" dotenv_replace "TRACECAT__AUTH_SUPERADMIN_EMAIL" "$superadmin_email" "$env_file" # Remove duplicate entries and leading/trailing commas new_origins=$(echo "$new_origins" | tr ',' '\n' | sort -u | tr '\n' ',' | sed 's/^,//;s/,$//') dotenv_replace "TRACECAT__ALLOW_ORIGINS" "$new_origins" "$env_file" echo -e "${GREEN}Environment file created successfully.${NC}" echo -e "${GREEN}First user (superadmin) email set to: ${superadmin_email}${NC}"