#!/bin/bash set -eo pipefail # WebsiteBox Setup Wizard # Generates .env file and creates data directories SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" cd "$SCRIPT_DIR" # --- Colors and formatting --- BOLD='\033[1m' DIM='\033[2m' RESET='\033[0m' RED='\033[1;31m' GREEN='\033[1;32m' YELLOW='\033[1;33m' ORANGE='\033[1;38;5;208m' CYAN='\033[1;36m' BLUE='\033[1;34m' WHITE='\033[1;37m' printf "\n${WHITE}═══════════════════════════════════════════════════════════${RESET}\n" printf " ${BOLD}WebsiteBox Setup Wizard${RESET}\n" printf "${WHITE}═══════════════════════════════════════════════════════════${RESET}\n\n" # --- Prerequisite Checks --- check_command() { if ! command -v "$1" &>/dev/null; then printf "${RED} ✗ $1 is not installed.${RESET}\n" printf "${RED} $2${RESET}\n" exit 1 fi } check_command docker "Install Docker: https://docs.docker.com/engine/install/" if ! docker compose version &>/dev/null; then printf "${RED} ✗ Docker Compose (v2) is not available.${RESET}\n" printf "${RED} Install it: https://docs.docker.com/compose/install/${RESET}\n" exit 1 fi # Check if Docker is accessible if ! docker info &>/dev/null; then printf "${RED} ✗ Cannot connect to Docker daemon.${RESET}\n" printf "${RED} Make sure Docker is running and your user has permission.${RESET}\n" printf "${RED} You may need to: sudo usermod -aG docker \$USER && newgrp docker${RESET}\n" exit 1 fi # Check ports for port in 80 443; do if ss -tlnp 2>/dev/null | grep -q ":${port} " || netstat -tlnp 2>/dev/null | grep -q ":${port} "; then printf "${YELLOW} ⚠ Port ${port} is already in use.${RESET}\n" printf "${YELLOW} Another service may need to be stopped first.${RESET}\n" read -rp "Continue anyway? (y/N) " cont if [ "$cont" != "y" ] && [ "$cont" != "Y" ]; then exit 1 fi fi done # --- Generate Random Strings --- generate_password() { local length="${1:-32}" openssl rand -base64 48 | tr -dc 'a-zA-Z0-9' | head -c "$length" } generate_salt() { openssl rand -base64 48 | head -c 64 } # --- Collect Configuration --- printf "Please provide the following configuration:\n\n" # Domain while true; do printf "${BLUE}Domain name${RESET} (e.g., example.com): " read -r DOMAIN if [[ "$DOMAIN" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z]{2,})+$ ]]; then break fi printf "${RED} Invalid domain format. Please enter a valid domain (e.g., example.com)${RESET}\n" done # Site title printf "${BLUE}Site title${RESET} [My Portfolio]: " read -r SITE_TITLE SITE_TITLE="${SITE_TITLE:-My Portfolio}" # Admin username while true; do printf "${BLUE}WordPress admin username${RESET}: " read -r ADMIN_USER if [ -z "$ADMIN_USER" ]; then printf "${RED} Username cannot be empty.${RESET}\n" continue fi if [ "$ADMIN_USER" = "admin" ]; then printf "${YELLOW} For security, please choose a username other than 'admin'.${RESET}\n" continue fi break done # Admin email while true; do printf "${BLUE}Admin email${RESET} (used for SSL & WordPress): " read -r ADMIN_EMAIL if [[ "$ADMIN_EMAIL" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then break fi printf "${RED} Please enter a valid email address.${RESET}\n" done # Admin password echo "" printf "${BLUE}Set your WordPress admin password.${RESET}\n" printf "${DIM} Press Enter to auto-generate a secure 20-character password.${RESET}\n" printf "${DIM} Note: your password won't appear on screen as you type — that's normal.${RESET}\n" while true; do printf "${BLUE}Admin password${RESET}: " read -rs ADMIN_PASSWORD echo "" if [ -z "$ADMIN_PASSWORD" ]; then ADMIN_PASSWORD=$(generate_password 20) PASSWORD_AUTO_GENERATED=true printf "${GREEN} ✓ Password auto-generated.${RESET}\n" break fi if [ ${#ADMIN_PASSWORD} -lt 12 ]; then printf "${RED} Password must be at least 12 characters.${RESET}\n" continue fi printf "${BLUE}Confirm password${RESET}: " read -rs ADMIN_PASSWORD_CONFIRM echo "" if [ "$ADMIN_PASSWORD" != "$ADMIN_PASSWORD_CONFIRM" ]; then printf "${RED} Passwords do not match. Try again.${RESET}\n" continue fi PASSWORD_AUTO_GENERATED=false printf "${GREEN} ✓ Password set.${RESET}\n" break done # Age Gate echo "" printf "${BLUE}Enable age verification gate?${RESET} (Y/n): " read -r AGE_GATE_INPUT if [ "$AGE_GATE_INPUT" = "n" ] || [ "$AGE_GATE_INPUT" = "N" ]; then AGE_GATE_ENABLED=false AGE_GATE_MIN_AGE=18 else AGE_GATE_ENABLED=true printf "${BLUE}Minimum age${RESET} (18-21) [18]: " read -r AGE_GATE_MIN_AGE AGE_GATE_MIN_AGE="${AGE_GATE_MIN_AGE:-18}" if [ "$AGE_GATE_MIN_AGE" -lt 18 ] 2>/dev/null || [ "$AGE_GATE_MIN_AGE" -gt 21 ] 2>/dev/null; then printf "${YELLOW} Invalid age. Using default: 18${RESET}\n" AGE_GATE_MIN_AGE=18 fi fi # SMTP (optional) echo "" printf "${BLUE}SMTP server${RESET} (if you don't know what this is, press Enter to skip): " read -r SMTP_HOST SMTP_PORT=587 SMTP_USER="" SMTP_PASS="" SMTP_FROM="" if [ -n "$SMTP_HOST" ]; then printf "${BLUE}SMTP port${RESET} [587]: " read -r SMTP_PORT_INPUT SMTP_PORT="${SMTP_PORT_INPUT:-587}" printf "${BLUE}SMTP username${RESET}: " read -r SMTP_USER printf "${BLUE}SMTP password${RESET}: " read -rs SMTP_PASS echo "" printf "${BLUE}SMTP from address${RESET} [${ADMIN_EMAIL}]: " read -r SMTP_FROM_INPUT SMTP_FROM="${SMTP_FROM_INPUT:-$ADMIN_EMAIL}" fi # Backup retention printf "${BLUE}Days to keep local backups${RESET} (1-365) [30]: " read -r BACKUP_RETENTION_DAYS BACKUP_RETENTION_DAYS="${BACKUP_RETENTION_DAYS:-30}" # --- Auto-generated Values --- DB_NAME="websitebox" DB_USER="websitebox" DB_PASSWORD=$(generate_password 32) DB_ROOT_PASSWORD=$(generate_password 32) AUTH_KEY=$(generate_salt) SECURE_AUTH_KEY=$(generate_salt) LOGGED_IN_KEY=$(generate_salt) NONCE_KEY=$(generate_salt) AUTH_SALT=$(generate_salt) SECURE_AUTH_SALT=$(generate_salt) LOGGED_IN_SALT=$(generate_salt) NONCE_SALT=$(generate_salt) # --- Write .env File --- cat > .env < .credentials </dev/null || curl -s -4 icanhazip.com 2>/dev/null || echo "YOUR_SERVER_IP") # --- Print Summary --- printf "\n${WHITE}═══════════════════════════════════════════════════════════${RESET}\n" printf " ${GREEN}${BOLD}WebsiteBox Setup Complete!${RESET}\n" printf "${WHITE}═══════════════════════════════════════════════════════════${RESET}\n\n" printf " ${GREEN}✓${RESET} Configuration saved to ${BOLD}.env${RESET}\n\n" printf " ${BOLD}Next steps:${RESET}\n\n" printf " ${BLUE}1.${RESET} ${BOLD}Point your domain's A record to this server${RESET}\n" printf " Log in to your domain registrar and add a DNS record:\n" printf " ${DIM}Type:${RESET} A\n" printf " ${DIM}Name:${RESET} @ ${DIM}(this means the root domain, e.g., ${DOMAIN})${RESET}\n" printf " ${DIM}Value:${RESET} ${BOLD}${SERVER_IP}${RESET} ${DIM}(your server's IP address)${RESET}\n" printf " ${DIM}TTL:${RESET} Auto ${DIM}(or the lowest option available)${RESET}\n\n" printf " ${BLUE}2.${RESET} ${BOLD}Wait for DNS propagation, then verify it's working${RESET}\n" printf " Copy this command into the server terminal:\n\n" printf " ${CYAN}dig ${DOMAIN} +short${RESET}\n\n" printf " ${GREEN}✓ Success looks like:${RESET} ${BOLD}${SERVER_IP}${RESET}\n" printf " ${RED}✗ Not ready yet:${RESET} ${DIM}(blank output or a different IP — wait a few minutes and try again)${RESET}\n\n" printf " ${BLUE}3.${RESET} ${BOLD}Launch your website${RESET}\n" printf " Once DNS is working, copy this command into the server terminal:\n\n" printf " ${CYAN}websitebox up -d${RESET}\n\n" printf " ${BLUE}4.${RESET} ${BOLD}Visit your site${RESET}\n" printf " Your website: ${CYAN}https://${DOMAIN}${RESET}\n" printf " Admin login: ${CYAN}https://${DOMAIN}/wp-admin${RESET}\n" printf " Username: ${BOLD}${ADMIN_USER}${RESET}\n" if [ "$PASSWORD_AUTO_GENERATED" = true ]; then printf " Password: ${BOLD}${ADMIN_PASSWORD}${RESET}\n\n" printf " ${YELLOW}⚠${RESET} Your auto-generated password has also been saved to: ${BOLD}.credentials${RESET}\n" printf " Delete this file after recording your password somewhere secure.\n" else printf " Password: ${DIM}(the password you set during setup)${RESET}\n" fi printf "\n${WHITE}═══════════════════════════════════════════════════════════${RESET}\n"