#!/bin/bash set -e # Colors GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[1;33m' NC='\033[0m' # No Color log_info() { echo -e "${YELLOW}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # ----------------------------------------------------------------------------- # Input Framework # ----------------------------------------------------------------------------- # Ensure we have a tty for input if [ ! -e /dev/tty ]; then echo "Error: Script must be run in an interactive terminal (cannot find /dev/tty)." >&2 exit 1 fi # Function to prompt for user input # Usage: get_input "VARIABLE_NAME" "Prompt Text" "Default Value" "is_secret(true/false)" get_input() { local var_name="$1" local prompt_text="$2" local default_value="$3" local is_secret="$4" local input_val="" local prompt_full="${GREEN}${prompt_text}${NC}" if [ -n "$default_value" ]; then prompt_full+=" [$default_value]" fi prompt_full+=": " while true; do # Print prompt to stderr so it shows up even if stdout is redirected if [ "$is_secret" == "true" ]; then echo -ne "$prompt_full" >&2 read -s input_val < /dev/tty echo "" >&2 # Newline after secret input else echo -ne "$prompt_full" >&2 read input_val < /dev/tty fi # Use default if input is empty if [ -z "$input_val" ] && [ -n "$default_value" ]; then input_val="$default_value" fi # Validation: Require input if no default exists if [ -z "$input_val" ]; then echo -e "${RED}Error: This value is required.${NC}" >&2 else break fi done # Set the variable dynamically in the parent scope printf -v "$var_name" "%s" "$input_val" export "$var_name=$input_val" } # Function to confirm collected inputs # Usage: confirm_inputs "VAR1" "VAR2" "VAR3" ... confirm_inputs() { echo "" >&2 echo -e "${GREEN}=== Configuration Summary ===${NC}" >&2 for var in "$@"; do local val="${!var}" # Mask secrets in summary if needed, or just show length # For now, just printing value. # To improve: pass a list of secret vars to mask them. echo -e "${YELLOW}$var:${NC} $val" >&2 done echo "" >&2 get_input "CONFIRM" "Is this correct? (y/n)" "y" "false" if [[ "${CONFIRM,,}" != "y" ]]; then echo -e "${RED}Aborted by user.${NC}" >&2 exit 1 fi } install_unit() { local template_url=$1 local filename=$(basename "$template_url") local dest_path=/etc/systemd/system/"$filename" log_info "Installing $filename..." curl -sL $template_url | envsubst > "$dest_path" log_success "$filename installed to $dest_path" } # ----------------------------------------------------------------------------- # Script Logic # ----------------------------------------------------------------------------- echo "Starting Interactive Setup..." echo "-----------------------------" # 1. Collect Inputs # Example: get_input "HOST_NAME" "Enter Hostname" "$(hostname)" "false" get_input "CERT_DIR" "Enter directory for certificates" "$(step path)/certs" "false" get_input "CERT_LOCATION" "Enter specific path for cert" "${CERT_DIR}/${HOSTNAME}.crt" "false" get_input "KEY_LOCATION" "Enter specific path for private key" "${CERT_DIR}/${HOSTNAME}.key" "false" export CERT_LOCATION=$(readlink -f $CERT_LOCATION) export KEY_LOCATION=$(readlink -f $KEY_LOCATION) # 2. Confirm confirm_inputs "CERT_LOCATION" "KEY_LOCATION" # 3. Configure REPO_URL_BASE=https://gitea.john-stream.com/john/soteria/raw/branch/main/ SERVICE_TEMPLATE_URL="${REPO_URL_BASE}systemd/cert-renewer.service" TIMER_TEMPLATE_URL="${REPO_URL_BASE}systemd/cert-renewer.timer" # 3. Execute # echo "Configuring $HOST_NAME..." install_unit ${SERVICE_TEMPLATE_URL} install_unit ${TIMER_TEMPLATE_URL} systemctl daemon-reload systemctl enable --now "$(basename "${TIMER_TEMPLATE_URL}")" systemctl status "$(basename "${SERVICE_TEMPLATE_URL}")" --no-pager systemctl status "$(basename "${TIMER_TEMPLATE_URL}")" --no-pager